From 1157111fcf3717cc5bee9809e5c7354ddc375988 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 29 Jun 2014 17:23:06 +0300 Subject: [PATCH 1/3] More bugfixing: - Fixed compile in VCAI (precompiled headers should not include VCMI headers) - Fixed crash on visiting observatories, including shroud of darkness --- AI/VCAI/AIUtility.cpp | 1 + AI/VCAI/StdInc.h | 2 -- AI/VCAI/VCAI.cpp | 2 ++ lib/mapObjects/MiscObjects.cpp | 2 +- server/CGameHandler.cpp | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/AI/VCAI/AIUtility.cpp b/AI/VCAI/AIUtility.cpp index 37ad79386..887f4757a 100644 --- a/AI/VCAI/AIUtility.cpp +++ b/AI/VCAI/AIUtility.cpp @@ -1,6 +1,7 @@ #include "StdInc.h" #include "AIUtility.h" #include "VCAI.h" +#include "Fuzzy.h" #include "../../lib/UnlockGuard.h" #include "../../lib/CConfigHandler.h" diff --git a/AI/VCAI/StdInc.h b/AI/VCAI/StdInc.h index 6448c2288..e0eeaf0aa 100644 --- a/AI/VCAI/StdInc.h +++ b/AI/VCAI/StdInc.h @@ -1,4 +1,2 @@ #pragma once #include "../../Global.h" - -#include "Fuzzy.h" diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index fbf9f1831..b0477fcf8 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -1,6 +1,8 @@ #include "StdInc.h" #include "VCAI.h" #include "Goals.h" +#include "Fuzzy.h" + #include "../../lib/UnlockGuard.h" #include "../../lib/mapObjects/MapObjects.h" #include "../../lib/CConfigHandler.h" diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index d5e9fa2d8..fcd7071db 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -1061,7 +1061,7 @@ void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const case Obj::COVER_OF_DARKNESS: { iw.text.addTxt (MetaString::ADVOB_TXT, 31); - for (auto player : cb->gameState()->players) + for (auto & player : cb->gameState()->players) { if (cb->getPlayerStatus(player.first) == EPlayerStatus::INGAME && cb->getPlayerRelations(player.first, h->tempOwner) == PlayerRelations::ENEMIES) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 93bcbc02b..7684404e4 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1351,7 +1351,7 @@ void CGameHandler::newTurn() } if (t->hasBonusOfType (Bonus::DARKNESS)) { - for (auto player : gameState()->players) + for (auto & player : gameState()->players) { if (getPlayerStatus(player.first) == EPlayerStatus::INGAME && getPlayerRelations(player.first, t->tempOwner) == PlayerRelations::ENEMIES) From f01ab0d48fa146abe6fafb262984cf7f7a98264d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 29 Jun 2014 20:13:25 +0300 Subject: [PATCH 2/3] Fixed rest of reported on forums bugs in rewardables --- lib/mapObjects/CRewardableObject.cpp | 44 +++++++++++++++++++--------- lib/mapObjects/CRewardableObject.h | 2 +- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp index 482d82bfa..d0ca8e293 100644 --- a/lib/mapObjects/CRewardableObject.cpp +++ b/lib/mapObjects/CRewardableObject.cpp @@ -76,7 +76,8 @@ std::vector CRewardableObject::getAvailableRewards(const CGHeroInstance * { const CVisitInfo & visit = info[i]; - if (visit.numOfGrants < visit.limiter.numOfGrants && visit.limiter.heroAllowed(hero)) + if ((visit.limiter.numOfGrants == 0 || visit.numOfGrants < visit.limiter.numOfGrants) // reward has unlimited uses or some are still available + && visit.limiter.heroAllowed(hero)) { logGlobal->debugStream() << "Reward " << i << " is allowed"; ret.push_back(i); @@ -270,7 +271,10 @@ void CRewardableObject::grantRewardAfterLevelup(const CVisitInfo & info, const C for (const Bonus & bonus : info.reward.bonuses) { + assert(bonus.source == Bonus::OBJECT); + assert(bonus.sid == ID); GiveBonus gb; + gb.who = GiveBonus::HERO; gb.bonus = bonus; gb.id = hero->id.getNum(); cb->giveHeroBonus(&gb); @@ -306,7 +310,7 @@ bool CRewardableObject::wasVisited (PlayerColor player) const { case VISIT_UNLIMITED: return false; - case VISIT_ONCE: + case VISIT_ONCE: // FIXME: hide this info deeper and return same as player? for (auto & visit : info) { if (visit.numOfGrants != 0) @@ -315,7 +319,7 @@ bool CRewardableObject::wasVisited (PlayerColor player) const case VISIT_HERO: return false; case VISIT_PLAYER: - return vstd::contains(cb->getPlayer(player)->visitedObjects, ObjectInstanceID(ID)); + return vstd::contains(cb->getPlayer(player)->visitedObjects, ObjectInstanceID(id)); default: return false; } @@ -325,8 +329,10 @@ bool CRewardableObject::wasVisited (const CGHeroInstance * h) const { switch (visitMode) { + case VISIT_UNLIMITED: + return h->hasBonusFrom(Bonus::OBJECT, ID); case VISIT_HERO: - return vstd::contains(h->visitedObjects, ObjectInstanceID(ID)) || h->hasBonusFrom(Bonus::OBJECT, ID); + return h->visitedObjects.count(ObjectInstanceID(id)); default: return wasVisited(h->tempOwner); } @@ -337,12 +343,6 @@ void CRewardInfo::loadComponents(std::vector & comps) const for (auto comp : extraComponents) comps.push_back(comp); - for (size_t i=0; i & comps) const for (auto & entry : creatures) comps.push_back(Component(Component::CREATURE, entry.type->idNumber, entry.count, 0)); + + for (size_t i=0; i creatures; CRewardLimiter(): - numOfGrants(1), + numOfGrants(0), dayOfWeek(0), minLevel(0), primary(4, 0) From a1fff864e618ea9d234341307fa92401b3eddf3f Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 30 Jun 2014 00:16:45 +0300 Subject: [PATCH 3/3] Fixed missing names for dwellings and creature banks --- lib/mapObjects/CBank.cpp | 10 ++--- lib/mapObjects/CObjectClassesHandler.cpp | 47 ++++++++++++++++++++++-- lib/mapObjects/CObjectClassesHandler.h | 18 +++++++-- lib/mapObjects/CObjectHandler.cpp | 2 +- lib/mapObjects/CRewardableObject.cpp | 3 +- lib/mapObjects/CommonConstructors.cpp | 7 +++- 6 files changed, 68 insertions(+), 19 deletions(-) diff --git a/lib/mapObjects/CBank.cpp b/lib/mapObjects/CBank.cpp index a653dcbfd..f80d740b9 100644 --- a/lib/mapObjects/CBank.cpp +++ b/lib/mapObjects/CBank.cpp @@ -45,10 +45,8 @@ void CBank::initObj() std::string CBank::getHoverText(PlayerColor player) const { - // TODO: USE BANK_SPECIFIC NAMES // TODO: record visited players - bool visited = (bc == nullptr); - return visitedTxt(visited); + return getObjectName() + " " + visitedTxt(bc == nullptr); } void CBank::setConfig(const BankConfig & config) @@ -128,8 +126,8 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const bd.player = h->getOwner(); bd.soundID = soundID; bd.text.addTxt(MetaString::ADVOB_TXT, banktext); - //if (ID == Obj::CREATURE_BANK) - // bd.text.addReplacement(VLC->objh->creBanksNames[index]); // FIXME: USE BANK SPECIFIC NAMES + if (ID == Obj::CREATURE_BANK) + bd.text.addReplacement(getObjectName()); cb->showBlockingDialog (&bd); } else @@ -149,7 +147,7 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const else { iw.text << VLC->generaltexth->advobtxt[33];// This was X, now is completely empty - //iw.text.addReplacement(VLC->objh->creBanksNames[index]); // FIXME: USE BANK SPECIFIC NAMES + iw.text.addReplacement(getObjectName()); } cb->showInfoDialog(&iw); } diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index 2720226a5..1e1ccc4f5 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -117,6 +117,17 @@ std::vector CObjectClassesHandler::loadLegacyData(size_t dataSize) ret[i]["name"].String() = namesParser.readString(); namesParser.endLine(); } + + CLegacyConfigParser cregen1Parser("data/crgen1"); + do + customNames[Obj::CREATURE_GENERATOR1].push_back(cregen1Parser.readString()); + while(cregen1Parser.endLine()); + + CLegacyConfigParser cregen4Parser("data/crgen4"); + do + customNames[Obj::CREATURE_GENERATOR4].push_back(cregen4Parser.readString()); + while(cregen4Parser.endLine()); + return ret; } @@ -142,12 +153,16 @@ void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContai logGlobal->errorStream() << "Handler with name " << obj->handlerName << " was not found!"; return; } - auto handler = handlerConstructors.at(obj->handlerName)(); - handler->init(entry); - si32 id = selectNextID(entry["index"], obj->objects, 1000); + + auto handler = handlerConstructors.at(obj->handlerName)(); handler->setType(obj->id, id); + if (customNames.count(obj->id) && customNames.at(obj->id).size() > id) + handler->init(entry, customNames.at(obj->id).at(id)); + else + handler->init(entry); + if (handler->getTemplates().empty()) { auto range = legacyTemplates.equal_range(std::make_pair(obj->id, id)); @@ -208,6 +223,7 @@ void CObjectClassesHandler::loadSubObject(std::string name, JsonNode config, si3 std::string oldMeta = config.meta; // FIXME: move into inheritNode? JsonUtils::inherit(config, objects.at(ID)->base); config.setMeta(oldMeta); + loadObjectEntry(config, objects[ID]); } @@ -290,6 +306,17 @@ std::string CObjectClassesHandler::getObjectName(si32 type) const return ""; } +std::string CObjectClassesHandler::getObjectName(si32 type, si32 subtype) const +{ + if (knownSubObjects(type).count(subtype)) + { + auto name = getHandlerFor(type, subtype)->getCustomName(); + if (name) + return name.get(); + } + return getObjectName(type); +} + void AObjectTypeHandler::setType(si32 type, si32 subtype) { this->type = type; @@ -304,7 +331,7 @@ static ui32 loadJsonOrMax(const JsonNode & input) return input.Float(); } -void AObjectTypeHandler::init(const JsonNode & input) +void AObjectTypeHandler::init(const JsonNode & input, boost::optional name) { base = input["base"]; @@ -328,6 +355,12 @@ void AObjectTypeHandler::init(const JsonNode & input) tmpl.readJson(entry.second); templates.push_back(tmpl); } + + if (input["name"].isNull()) + objectName = name; + else + objectName.reset(input["name"].String()); + initTypeData(input); } @@ -338,6 +371,12 @@ bool AObjectTypeHandler::objectFilter(const CGObjectInstance *, const ObjectTemp void AObjectTypeHandler::initTypeData(const JsonNode & input) { + // empty implementation for overrides +} + +boost::optional AObjectTypeHandler::getCustomName() const +{ + return objectName; } void AObjectTypeHandler::addTemplate(ObjectTemplate templ) diff --git a/lib/mapObjects/CObjectClassesHandler.h b/lib/mapObjects/CObjectClassesHandler.h index a16fb0ba4..30a4ef88f 100644 --- a/lib/mapObjects/CObjectClassesHandler.h +++ b/lib/mapObjects/CObjectClassesHandler.h @@ -98,6 +98,9 @@ class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable { RandomMapInfo rmgInfo; + /// Human-readable name of this object, used for objects like banks and dwellings, if set + boost::optional objectName; + si32 type; si32 subtype; @@ -116,7 +119,10 @@ public: void setType(si32 type, si32 subtype); /// loads generic data from Json structure and passes it towards type-specific constructors - void init(const JsonNode & input); + void init(const JsonNode & input, boost::optional name = boost::optional()); + + /// Returns object-specific name, if set + boost::optional getCustomName() const; void addTemplate(ObjectTemplate templ); void addTemplate(JsonNode config); @@ -148,7 +154,7 @@ public: template void serialize(Handler &h, const int version) { - h & type & subtype & templates & rmgInfo; + h & type & subtype & templates & rmgInfo & objectName; } }; @@ -174,8 +180,6 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase } }; - typedef std::multimap, ObjectTemplate> TTemplatesContainer; - /// list of object handlers, each of them handles only one type std::map objects; @@ -183,8 +187,13 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase std::map > handlerConstructors; /// container with H3 templates, used only during loading, no need to serialize it + typedef std::multimap, ObjectTemplate> TTemplatesContainer; TTemplatesContainer legacyTemplates; + /// contains list of custom names for H3 objects (e.g. Dwellings), used to load H3 data + /// format: customNames[primaryID][secondaryID] -> name + std::map> customNames; + void loadObjectEntry(const JsonNode & entry, ObjectContainter * obj); ObjectContainter * loadFromJson(const JsonNode & json); public: @@ -211,6 +220,7 @@ public: TObjectTypeHandler getHandlerFor(si32 type, si32 subtype) const; std::string getObjectName(si32 type) const; + std::string getObjectName(si32 type, si32 subtype) const; template void serialize(Handler &h, const int version) { diff --git a/lib/mapObjects/CObjectHandler.cpp b/lib/mapObjects/CObjectHandler.cpp index b03980f8c..583193216 100644 --- a/lib/mapObjects/CObjectHandler.cpp +++ b/lib/mapObjects/CObjectHandler.cpp @@ -272,7 +272,7 @@ void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) con std::string CGObjectInstance::getObjectName() const { - return VLC->objtypeh->getObjectName(ID); + return VLC->objtypeh->getObjectName(ID, subID); } std::string CGObjectInstance::getHoverText(PlayerColor player) const diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp index d0ca8e293..6a4786ced 100644 --- a/lib/mapObjects/CRewardableObject.cpp +++ b/lib/mapObjects/CRewardableObject.cpp @@ -184,7 +184,6 @@ void CRewardableObject::blockingDialogAnswered(const CGHeroInstance *hero, ui32 if (answer > 0 && answer-1 < info.size()) { - //NOTE: this relies on assumption that there won't be any changes in player/hero during blocking dialog auto list = getAvailableRewards(hero); grantReward(list[answer - 1], hero); } @@ -470,7 +469,7 @@ void CGPickable::initObj() blockVisit = true; switch(ID) { - case Obj::CAMPFIRE: //FIXME: campfire is not functioning correctly in game (no visible message) + case Obj::CAMPFIRE: { soundID = soundBase::experience; int givenRes = cb->gameState()->getRandomGenerator().nextInt(5); diff --git a/lib/mapObjects/CommonConstructors.cpp b/lib/mapObjects/CommonConstructors.cpp index af259e564..7fb4ce5ff 100644 --- a/lib/mapObjects/CommonConstructors.cpp +++ b/lib/mapObjects/CommonConstructors.cpp @@ -195,8 +195,11 @@ void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CR if (guards.getType() == JsonNode::DATA_BOOL) { - const CCreature * crea = availableCreatures.at(0).at(0); - dwelling->putStack(SlotID(0), new CStackInstance(crea->idNumber, crea->growth * 3 )); + if (guards.Bool()) + { + const CCreature * crea = availableCreatures.at(0).at(0); + dwelling->putStack(SlotID(0), new CStackInstance(crea->idNumber, crea->growth * 3 )); + } } else for (auto & stack : JsonRandom::loadCreatures(guards, rng)) {