diff --git a/AI/VCAI/Goals.cpp b/AI/VCAI/Goals.cpp index adb4e35bb..b4929f180 100644 --- a/AI/VCAI/Goals.cpp +++ b/AI/VCAI/Goals.cpp @@ -66,7 +66,7 @@ std::string Goals::AbstractGoal::name() const //TODO: virtualize { auto obj = cb->getObjInstance(ObjectInstanceID(objid)); if (obj) - desc = "GET OBJ " + obj->getHoverText(); + desc = "GET OBJ " + obj->getObjectName(); } case FIND_OBJ: desc = "FIND OBJ " + boost::lexical_cast(objid); @@ -75,7 +75,7 @@ std::string Goals::AbstractGoal::name() const //TODO: virtualize { auto obj = cb->getObjInstance(ObjectInstanceID(objid)); if (obj) - desc = "VISIT HERO " + obj->getHoverText(); + desc = "VISIT HERO " + obj->getObjectName(); } break; case GET_ART_TYPE: @@ -493,7 +493,7 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals() if (topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES) if (topObj != hero.get(true)) //the hero we want to free - logAi->errorStream() << boost::format("%s stands in the way of %s") % topObj->getHoverText() % h->getHoverText(); + logAi->errorStream() << boost::format("%s stands in the way of %s") % topObj->getObjectName() % h->getObjectName(); if (topObj->ID == Obj::QUEST_GUARD || topObj->ID == Obj::BORDERGUARD) { if (shouldVisit(h, topObj)) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index ba857730b..fbf9f1831 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -5,6 +5,7 @@ #include "../../lib/mapObjects/MapObjects.h" #include "../../lib/CConfigHandler.h" #include "../../lib/CHeroHandler.h" +#include "../../lib/CModHandler.h" /* @@ -81,7 +82,7 @@ struct ObjInfo ObjInfo(){} ObjInfo(const CGObjectInstance *obj): pos(obj->pos), - name(obj->getHoverText()) + name(obj->getObjectName()) { } }; @@ -195,7 +196,7 @@ void VCAI::showShipyardDialog(const IShipyard *obj) void VCAI::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) { - LOG_TRACE_PARAMS(logAi, "victoryLossCheckResult '%s'", victoryLossCheckResult); + LOG_TRACE_PARAMS(logAi, "victoryLossCheckResult '%s'", victoryLossCheckResult.messageToSelf); NET_EVENT_HANDLER; logAi->debugStream() << boost::format("Player %d: I heard that player %d %s.") % playerID % player.getNum() % (victoryLossCheckResult.victory() ? "won" : "lost"); if(player == playerID) @@ -241,7 +242,7 @@ void VCAI::artifactDisassembled(const ArtifactLocation &al) void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) { - LOG_TRACE_PARAMS(logAi, "start '%i'; obj '%s'", start % (visitedObj ? visitedObj->hoverName : std::string("n/a"))); + LOG_TRACE_PARAMS(logAi, "start '%i'; obj '%s'", start % (visitedObj ? visitedObj->getObjectName() : std::string("n/a"))); NET_EVENT_HANDLER; if(start) { @@ -780,13 +781,13 @@ void VCAI::makeTurnInternal() bool VCAI::goVisitObj(const CGObjectInstance * obj, HeroPtr h) { int3 dst = obj->visitablePos(); - logAi->debugStream() << boost::format("%s will try to visit %s at (%s)") % h->name % obj->getHoverText() % strFromInt3(dst); + logAi->debugStream() << boost::format("%s will try to visit %s at (%s)") % h->name % obj->getObjectName() % strFromInt3(dst); return moveHeroToTile(dst, h); } void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h) { - LOG_TRACE_PARAMS(logAi, "Hero %s and object %s at %s", h->name % obj->getHoverText() % obj->pos); + LOG_TRACE_PARAMS(logAi, "Hero %s and object %s at %s", h->name % obj->getObjectName() % obj->pos); switch (obj->ID) { case Obj::CREATURE_GENERATOR1: @@ -1434,7 +1435,7 @@ void VCAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int assert(playerID > PlayerColor::PLAYER_LIMIT || status.getBattle() == UPCOMING_BATTLE); status.setBattle(ONGOING_BATTLE); const CGObjectInstance *presumedEnemy = backOrNull(cb->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit - battlename = boost::str(boost::format("Starting battle of %s attacking %s at %s") % (hero1 ? hero1->name : "a army") % (presumedEnemy ? presumedEnemy->hoverName : "unknown enemy") % tile); + battlename = boost::str(boost::format("Starting battle of %s attacking %s at %s") % (hero1 ? hero1->name : "a army") % (presumedEnemy ? presumedEnemy->getObjectName() : "unknown enemy") % tile); CAdventureAI::battleStart(army1, army2, tile, hero1, hero2, side); } @@ -1468,7 +1469,7 @@ void VCAI::reserveObject(HeroPtr h, const CGObjectInstance *obj) { reservedObjs.insert(obj); reservedHeroesMap[h].insert(obj); - logAi->debugStream() << "reserved object id=" << obj->id << "; address=" << (intptr_t)obj << "; name=" << obj->getHoverText(); + logAi->debugStream() << "reserved object id=" << obj->id << "; address=" << (intptr_t)obj << "; name=" << obj->getObjectName(); } void VCAI::unreserveObject(HeroPtr h, const CGObjectInstance *obj) diff --git a/CMakeLists.txt b/CMakeLists.txt index 420bf163c..9a06161a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,9 +100,14 @@ endif() if(CMAKE_COMPILER_IS_GNUCXX OR NOT WIN32) #so far all *nix compilers support such parameters if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(CLANG_SPECIFIC_FLAGS "-Wno-mismatched-tags") + set(CLANG_SPECIFIC_FLAGS "-Wno-mismatched-tags") endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wextra -Wpointer-arith -Wno-switch -Wno-sign-compare -Wno-unused-parameter -Wuninitialized -Wno-overloaded-virtual ${CLANG_SPECIFIC_FLAGS}") + + if(UNIX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") + endif() + endif() if(WIN32) # on Win everything goes into H3 root directory diff --git a/ChangeLog b/ChangeLog index 1be4238e5..64ba175f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ GENERAL: * (linux) now VCMI follows XDG specifications. See http://forum.vcmi.eu/viewtopic.php?t=858 ADVENTURE AI: +* Optimized speed and removed various bottlenecks. ADVENTURE MAP: * Heroes auto-level primary and secondary skill levels according to experience @@ -13,6 +14,14 @@ BATTLES: SPELLS: * New configuration format: http://wiki.vcmi.eu/index.php?title=Spell_Format +RANDOM MAP GENERATOR +* Towns form mods cna be used +* Reading connections, terrains, towns and mines from template +* Zone placement +* Zone borders and connections, fractalized paths inside zones +* Guard generation +* Treasue piles generation (so far only few removable objects) + MODS: * Support for submods - mod may have their own "submods" located in /Mods directory * Mods may provide their own changelogs and screenshots that will be visible in Launcher diff --git a/Global.h b/Global.h index a9c81fe59..def02d647 100644 --- a/Global.h +++ b/Global.h @@ -152,9 +152,11 @@ typedef boost::lock_guard TLockGuardRec; # else # define DLL_EXPORT __declspec(dllexport) # endif +# define ELF_VISIBILITY #else # ifdef __GNUC__ -# define DLL_EXPORT __attribute__ ((visibility("default"))) +# define DLL_EXPORT __attribute__ ((visibility("default"))) +# define ELF_VISIBILITY __attribute__ ((visibility("default"))) # endif #endif @@ -164,9 +166,11 @@ typedef boost::lock_guard TLockGuardRec; # else # define DLL_IMPORT __declspec(dllimport) # endif +# define ELF_VISIBILITY #else # ifdef __GNUC__ # define DLL_IMPORT __attribute__ ((visibility("default"))) +# define ELF_VISIBILITY __attribute__ ((visibility("default"))) # endif #endif diff --git a/client/AdventureMapClasses.cpp b/client/AdventureMapClasses.cpp index 31960805f..515a519ff 100644 --- a/client/AdventureMapClasses.cpp +++ b/client/AdventureMapClasses.cpp @@ -317,7 +317,7 @@ void CTownList::CTownItem::showTooltip() std::string CTownList::CTownItem::getHoverText() { - return town->hoverName; + return town->getObjectName(); } CTownList::CTownList(int size, Point position, std::string btnUp, std::string btnDown): diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index 4dfba348d..ea075bcf7 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -1234,10 +1234,9 @@ void CAdvMapInt::tileHovered(const int3 &mapPos) } const CGObjectInstance *objAtTile = getBlockingObject(mapPos); - //std::vector temp = LOCPLINT->cb->getObjDescriptions(mapPos); if (objAtTile) { - std::string text = objAtTile->getHoverText(); + std::string text = curHero() ? objAtTile->getHoverText(curHero()) : objAtTile->getHoverText(LOCPLINT->playerID); boost::replace_all(text,"\n"," "); statusbar.setText(text); } diff --git a/client/CKingdomInterface.cpp b/client/CKingdomInterface.cpp index 83f730515..2c6dfb235 100644 --- a/client/CKingdomInterface.cpp +++ b/client/CKingdomInterface.cpp @@ -500,7 +500,7 @@ void CKingdomInterface::generateObjectsList(const std::vectorsubID]; if (info.count++ == 0) { - info.hoverText = object->getHoverText(); + info.hoverText = object->getObjectName(); info.imageID = object->subID; } } @@ -511,7 +511,7 @@ void CKingdomInterface::generateObjectsList(const std::vectorsecond]; if (info.count++ == 0) { - info.hoverText = object->hoverName; + info.hoverText = object->getObjectName(); info.imageID = iter->second; } } diff --git a/client/CMT.cpp b/client/CMT.cpp index 070b2cce1..6fed20903 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -589,7 +589,7 @@ void processCommand(const std::string &message) } else if(cn == "bonuses") { - std::cout << "Bonuses of " << adventureInt->selection->getHoverText() << std::endl + std::cout << "Bonuses of " << adventureInt->selection->getObjectName() << std::endl << adventureInt->selection->getBonusList() << std::endl; std::cout << "\nInherited bonuses:\n"; diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 68d53d1ca..5654b867e 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -91,16 +91,10 @@ CondSh stillMoveHero; //used during hero movement int CPlayerInterface::howManyPeople = 0; - -struct OCM_HLP_CGIN +static bool objectBlitOrderSorter(const std::pair & a, const std::pair & b) { - bool inline operator ()(const std::pair & a, const std::pair & b) const - { - return (*a.first)<(*b.first); - } -} ocmptwo_cgin ; - - + return CMapHandler::compareObjectBlitOrder(a.first, b.first); +} CPlayerInterface::CPlayerInterface(PlayerColor Player) { @@ -1708,14 +1702,14 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 33), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 33), ho->id); - std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), objectBlitOrderSorter); } else if(details.end.x == details.start.x && details.end.y+1 == details.start.y) //t { @@ -1733,9 +1727,9 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 32, 33), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 64, 33), ho->id); - std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); } else if(details.end.x-1 == details.start.x && details.end.y+1 == details.start.y) //tr { @@ -1756,14 +1750,14 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 33), ho->id); CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 33))); - std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), objectBlitOrderSorter); } else if(details.end.x-1 == details.start.x && details.end.y == details.start.y) //r { @@ -1779,9 +1773,9 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 32), ho->id); CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 32))); - std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), objectBlitOrderSorter); } else if(details.end.x-1 == details.start.x && details.end.y-1 == details.start.y) //br { @@ -1802,14 +1796,14 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 63, 63))); CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 95, 63))); - std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); } else if(details.end.x == details.start.x && details.end.y-1 == details.start.y) //b { @@ -1827,9 +1821,9 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 32, 63))); CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 64, 63))); - std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); } else if(details.end.x+1 == details.start.x && details.end.y-1 == details.start.y) //bl { @@ -1850,14 +1844,14 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 33, 63))); CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(std::make_pair(ho, genRect(32, 32, 65, 63))); - std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter); } else if(details.end.x+1 == details.start.x && details.end.y == details.start.y) //l { @@ -1873,9 +1867,9 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 32), ho->id); subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 32), ho->id); - std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), objectBlitOrderSorter); } } @@ -2105,13 +2099,13 @@ void CPlayerInterface::finishMovement( const TryMoveHero &details, const int3 &h subRect(details.end.x, details.end.y, details.end.z, genRect(32, 32, 64, 32), ho->id); //restoring good order of objects - std::stable_sort(CGI->mh->ttiles[details.end.x-2][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-2][details.end.y-1][details.end.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[details.end.x-1][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-1][details.end.y-1][details.end.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[details.end.x][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x][details.end.y-1][details.end.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[details.end.x-2][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-2][details.end.y-1][details.end.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[details.end.x-1][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-1][details.end.y-1][details.end.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[details.end.x][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x][details.end.y-1][details.end.z].objects.end(), objectBlitOrderSorter); - std::stable_sort(CGI->mh->ttiles[details.end.x-2][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-2][details.end.y][details.end.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[details.end.x-1][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-1][details.end.y][details.end.z].objects.end(), ocmptwo_cgin); - std::stable_sort(CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.end(), ocmptwo_cgin); + std::stable_sort(CGI->mh->ttiles[details.end.x-2][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-2][details.end.y][details.end.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[details.end.x-1][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-1][details.end.y][details.end.z].objects.end(), objectBlitOrderSorter); + std::stable_sort(CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.end(), objectBlitOrderSorter); } void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult ) diff --git a/client/CQuestLog.cpp b/client/CQuestLog.cpp index 1eb621ce4..05cf409c4 100644 --- a/client/CQuestLog.cpp +++ b/client/CQuestLog.cpp @@ -140,7 +140,7 @@ void CQuestLog::init() MetaString text; quests[i].quest->getRolloverText (text, false); if (quests[i].obj) - text.addReplacement (quests[i].obj->getHoverText()); //get name of the object + text.addReplacement (quests[i].obj->getObjectName()); //get name of the object CQuestLabel * label = new CQuestLabel (Rect(28, 199 + i * 24, 172,30), FONT_SMALL, TOPLEFT, Colors::WHITE, text.toString()); label->callback = boost::bind(&CQuestLog::selectQuest, this, i); labels.push_back(label); diff --git a/client/Client.h b/client/Client.h index 8ebb49d98..ed16a87c6 100644 --- a/client/Client.h +++ b/client/Client.h @@ -170,7 +170,6 @@ public: bool removeObject(const CGObjectInstance * obj) override {return false;}; void setBlockVis(ObjectInstanceID objid, bool bv) override {}; void setOwner(const CGObjectInstance * obj, PlayerColor owner) override {}; - void setHoverName(const CGObjectInstance * obj, MetaString * name) override {}; void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) override {}; void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) override {}; @@ -218,6 +217,9 @@ public: void sendAndApply(CPackForClient * info) override {}; void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override {}; + void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override {} + void changeFogOfWar(std::unordered_set &tiles, PlayerColor player, bool hide) override {} + ////////////////////////////////////////////////////////////////////////// friend class CCallback; //handling players actions friend class CBattleCallback; //handling players actions diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 3ffa2bd1e..b2d824fb6 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -1848,7 +1848,7 @@ CObjectListWindow::CObjectListWindow(const std::vector &_items, CIntObject items.reserve(_items.size()); for(int id : _items) { - items.push_back(std::make_pair(id, CGI->mh->map->objects[id]->hoverName)); + items.push_back(std::make_pair(id, CGI->mh->map->objects[id]->getObjectName())); } init(titlePic, _title, _descr); @@ -2614,7 +2614,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan break; case Obj::BLACK_MARKET: title = CGI->generaltexth->allTexts[349]; break; case Obj::TRADING_POST: title = CGI->generaltexth->allTexts[159]; break; case Obj::TRADING_POST_SNOW: title = CGI->generaltexth->allTexts[159]; - break; default: title = market->o->getHoverText(); + break; default: title = market->o->getObjectName(); } } @@ -4571,7 +4571,7 @@ void CHeroArea::clickRight(tribool down, bool previousState) void CHeroArea::hover(bool on) { if (on && hero) - GH.statusbar->setText(hero->hoverName); + GH.statusbar->setText(hero->getObjectName()); else GH.statusbar->clear(); } @@ -5634,7 +5634,7 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance *visitor, const CGObjectIn slotsCount=7; resources = CDefHandler::giveDefEss("SMALRES.DEF"); - new CLabel(325, 32, FONT_BIG, CENTER, Colors::YELLOW, fort->hoverName);//Hill Fort + new CLabel(325, 32, FONT_BIG, CENTER, Colors::YELLOW, fort->getObjectName());//Hill Fort heroPic = new CHeroArea(30, 60, hero); @@ -6181,7 +6181,7 @@ void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EA if(iWin) GH.pushInt(iWin); else - CRClickPopup::createAndPush(obj->getHoverText()); + CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID)); } CRClickPopup::CRClickPopup() diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 7f6f5028c..29d36f43f 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -15,6 +15,7 @@ #include "../lib/VCMIDirs.h" #include "../lib/CSpellHandler.h" #include "../lib/CSoundBase.h" +#include "../lib/StartInfo.h" #include "mapHandler.h" #include "GUIClasses.h" #include "../lib/CConfigHandler.h" diff --git a/client/battle/CBattleInterfaceClasses.cpp b/client/battle/CBattleInterfaceClasses.cpp index fcf3d878e..cbfa489bc 100644 --- a/client/battle/CBattleInterfaceClasses.cpp +++ b/client/battle/CBattleInterfaceClasses.cpp @@ -17,6 +17,7 @@ #include "../../lib/NetPacks.h" #include "../../lib/CCreatureHandler.h" #include "../../lib/BattleState.h" +#include "../../lib/StartInfo.h" #include "../CMusicHandler.h" #include "../CVideoHandler.h" #include "../../lib/CTownHandler.h" diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index 84496ea4b..3080f5a11 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -75,21 +75,10 @@ std::string nameFromType (int typ) return std::string(); } -struct OCM_HLP +static bool objectBlitOrderSorter(const std::pair & a, const std::pair & b) { - bool operator ()(const std::pair & a, const std::pair & b) - { - return (*a.first)<(*b.first); - } -} ocmptwo ; - -// void alphaTransformDef(CGDefInfo * defInfo) -// { -// for(int yy=0; yyhandler->ourImages.size(); ++yy) -// { -// CSDL_Ext::alphaTransform(defInfo->handler->ourImages[yy].bitmap); -// } -// } + return CMapHandler::compareObjectBlitOrder(a.first, b.first); +} void CMapHandler::prepareFOWDefs() { @@ -308,7 +297,7 @@ void CMapHandler::initObjectRects() { for(int iz=0; izID == Obj::HOLE) //Hole { - out = elem.first->hoverName; + out = elem.first->getObjectName(); return; } } @@ -1092,3 +1081,25 @@ ui8 CMapHandler::getPhaseShift(const CGObjectInstance *object) const TerrainTile2::TerrainTile2() :terbitmap(nullptr) {} + +bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b) +{ + if (a->appearance.printPriority != b->appearance.printPriority) + return a->appearance.printPriority > b->appearance.printPriority; + + if(a->pos.y != b->pos.y) + return a->pos.y < b->pos.y; + + if(b->ID==Obj::HERO && a->ID!=Obj::HERO) + return true; + if(b->ID!=Obj::HERO && a->ID==Obj::HERO) + return false; + + if(!a->isVisitable() && b->isVisitable()) + return true; + if(!b->isVisitable() && a->isVisitable()) + return false; + if(a->pos.x < b->pos.x) + return true; + return false; +} diff --git a/client/mapHandler.h b/client/mapHandler.h index 09d4eaae9..7700c47a5 100644 --- a/client/mapHandler.h +++ b/client/mapHandler.h @@ -108,7 +108,6 @@ public: std::pair getVisBitmap(const int3 & pos, const std::vector< std::vector< std::vector > > & visibilityMap) const; //returns appropriate bitmap and info if alpha blitting is necessary ui8 getPhaseShift(const CGObjectInstance *object) const; - std::vector< std::string > getObjDescriptions(int3 pos); //returns desriptions of objects blocking given position void getTerrainDescr(const int3 &pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear CGObjectInstance * createObject(int id, int subid, int3 pos, int owner=254); //creates a new object with a certain id and subid bool printObject(const CGObjectInstance * obj); //puts appropriate things to ttiles, so obj will be visible on map @@ -127,4 +126,6 @@ public: void validateRectTerr(SDL_Rect * val, const SDL_Rect * ext); //terrainRect helper static ui8 getDir(const int3 & a, const int3 & b); //returns direction number in range 0 - 7 (0 is left top, clockwise) [direction: form a to b] + static bool compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b); + }; diff --git a/config/objects/generic.json b/config/objects/generic.json index bc1e1dcf8..f916b5be0 100644 --- a/config/objects/generic.json +++ b/config/objects/generic.json @@ -8,126 +8,145 @@ "prison" : { "index" : 0 } } }, + + "altarOfSacrifice" : { "index" :2, "handler": "market", "types" : { "object" : { "index" : 0} } }, + "tradingPost" : { "index" :221, "handler": "market", "types" : { "object" : { "index" : 0} } }, + "tradingPostDUPLICATE" : { "index" :99, "handler": "market", "types" : { "object" : { "index" : 0} } }, + "freelancersGuild" : { "index" :213, "handler": "market", "types" : { "object" : { "index" : 0} } }, + + "blackMarket" : { "index" :7, "handler": "blackMarket", "types" : { "object" : { "index" : 0} } }, + + "pandoraBox" : { "index" :6, "handler": "pandora", "types" : { "object" : { "index" : 0} } }, + "event" : { "index" :26, "handler": "event", "types" : { "object" : { "index" : 0} } }, + + "redwoodObservatory" : { "index" :58, "handler": "observatory", "types" : { "object" : { "index" : 0} } }, + "pillarOfFire" : { "index" :60, "handler": "observatory", "types" : { "object" : { "index" : 0} } }, + "coverOfDarkness" : { "index" :15, "handler": "observatory", "types" : { "object" : { "index" : 0} } }, - "altarOfSacrifice" : { "index" :2, "handler": "market" }, - "tradingPost" : { "index" :221, "handler": "market" }, - "tradingPostDUPLICATE" : { "index" :99, "handler": "market" }, - "freelancersGuild" : { "index" :213, "handler": "market" }, + "whirlpool" : { "index" :111, "handler": "teleport", "types" : { "object" : { "index" : 0} } }, + "subterraneanGate" : { + "index" :103, + "handler": "teleport", + "types" : { + "object" : { "index" : 0 }, + "objectWoG" : { "index" : 1 } // WoG object? Present on VCMI Test 2011b + } + }, - "blackMarket" : { "index" :7, "handler": "blackMarket" }, + "refugeeCamp" : { "index" :78, "handler": "dwelling", "types" : { "object" : { "index" : 0} } }, + "warMachineFactory" : { "index" :106, "handler": "dwelling", "types" : { "object" : { "index" : 0} } }, - "pandoraBox" : { "index" :6, "handler": "pandora" }, - "event" : { "index" :26, "handler": "event" }, + "shrineOfMagicLevel1" : { "index" :88, "handler": "shrine", "types" : { "object" : { "index" : 0} } }, + "shrineOfMagicLevel2" : { "index" :89, "handler": "shrine", "types" : { "object" : { "index" : 0} } }, + "shrineOfMagicLevel3" : { "index" :90, "handler": "shrine", "types" : { "object" : { "index" : 0} } }, - "redwoodObservatory" : { "index" :58, "handler": "observatory" }, - "pillarOfFire" : { "index" :60, "handler": "observatory" }, - "coverOfDarkness" : { "index" :15, "handler": "observatory" }, - - "subterraneanGate" : { "index" :103, "handler": "teleport" }, - "whirlpool" : { "index" :111, "handler": "teleport" }, + "eyeOfTheMagi" : { "index" :27, "handler": "magi", "types" : { "object" : { "index" : 0} } }, + "hutOfTheMagi" : { "index" :37, "handler": "magi", "types" : { "object" : { "index" : 0} } }, - "refugeeCamp" : { "index" :78, "handler": "dwelling" }, - "warMachineFactory" : { "index" :106, "handler": "dwelling" }, - - "shrineOfMagicLevel1" : { "index" :88, "handler": "shrine" }, - "shrineOfMagicLevel2" : { "index" :89, "handler": "shrine" }, - "shrineOfMagicLevel3" : { "index" :90, "handler": "shrine" }, - - "eyeOfTheMagi" : { "index" :27, "handler": "magi" }, - "hutOfTheMagi" : { "index" :37, "handler": "magi" }, - - "lighthouse" : { "index" :42, "handler": "lighthouse" }, - "magicWell" : { "index" :49, "handler": "magicWell" }, - "obelisk" : { "index" :57, "handler": "obelisk" }, - "oceanBottle" : { "index" :59, "handler": "sign" }, - "scholar" : { "index" :81, "handler": "scholar" }, - "shipyard" : { "index" :87, "handler": "shipyard" }, - "sign" : { "index" :91, "handler": "sign" }, - "sirens" : { "index" :92, "handler": "siren" }, - "denOfThieves" : { "index" :97, "handler": "denOfThieves" }, - "university" : { "index" :104, "handler": "university" }, - "witchHut" : { "index" :113, "handler": "witch" }, - "questGuard" : { "index" :215, "handler": "questGuard" }, + "lighthouse" : { "index" :42, "handler": "lighthouse", "types" : { "object" : { "index" : 0} } }, + "obelisk" : { "index" :57, "handler": "obelisk", "types" : { "object" : { "index" : 0} } }, + "oceanBottle" : { "index" :59, "handler": "sign", "types" : { "object" : { "index" : 0} } }, + "scholar" : { "index" :81, "handler": "scholar", "types" : { "object" : { "index" : 0} } }, + "shipyard" : { "index" :87, "handler": "shipyard", "types" : { "object" : { "index" : 0} } }, + "sign" : { "index" :91, "handler": "sign", "types" : { "object" : { "index" : 0} } }, + "sirens" : { "index" :92, "handler": "siren", "types" : { "object" : { "index" : 0} } }, + "denOfThieves" : { "index" :97, "handler": "denOfThieves", "types" : { "object" : { "index" : 0} } }, + "university" : { "index" :104, "handler": "university", "types" : { "object" : { "index" : 0} } }, + "witchHut" : { "index" :113, "handler": "witch", "types" : { "object" : { "index" : 0} } }, + "questGuard" : { "index" :215, "handler": "questGuard", "types" : { "object" : { "index" : 0} } }, + "magicWell" : { + "index" :49, + "handler": "magicWell", + "types" : { + "object" : { "index" : 0}, + "objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Test 2011b + } + }, /// Random objects - "randomResource" : { "index" :76, "handler": "resource" }, - "randomTown" : { "index" :77, "handler": "town" }, - "randomHero" : { "index" :70, "handler": "hero" }, + "randomResource" : { "index" :76, "handler": "resource" }, + "randomTown" : { "index" :77, "handler": "town" }, + "randomHero" : { "index" :70, "handler": "hero" }, "randomDwelling" : { "index" :216, "handler": "dwelling" }, - "randomArtifact" : { "index" :65, "handler": "artifact" }, - "randomArtifactTreasure" : { "index" :66, "handler": "artifact" }, - "randomArtifactMinor" : { "index" :67, "handler": "artifact" }, - "randomArtifactMajor" : { "index" :68, "handler": "artifact" }, - "randomArtifactRelic" : { "index" :69, "handler": "artifact" }, + "randomArtifact" : { "index" :65, "handler": "artifact" }, + "randomArtifactTreasure" : { "index" :66, "handler": "artifact" }, + "randomArtifactMinor" : { "index" :67, "handler": "artifact" }, + "randomArtifactMajor" : { "index" :68, "handler": "artifact" }, + "randomArtifactRelic" : { "index" :69, "handler": "artifact" }, - "randomMonster" : { "index" :71, "handler": "monster" }, - "randomMonsterLevel1" : { "index" :72, "handler": "monster" }, - "randomMonsterLevel2" : { "index" :73, "handler": "monster" }, - "randomMonsterLevel3" : { "index" :74, "handler": "monster" }, - "randomMonsterLevel4" : { "index" :75, "handler": "monster" }, + "randomMonster" : { "index" :71, "handler": "monster" }, + "randomMonsterLevel1" : { "index" :72, "handler": "monster" }, + "randomMonsterLevel2" : { "index" :73, "handler": "monster" }, + "randomMonsterLevel3" : { "index" :74, "handler": "monster" }, + "randomMonsterLevel4" : { "index" :75, "handler": "monster" }, "randomMonsterLevel5" : { "index" :162, "handler": "monster" }, "randomMonsterLevel6" : { "index" :163, "handler": "monster" }, "randomMonsterLevel7" : { "index" :164, "handler": "monster" }, /// Classes without dedicated object - "hillFort" : { "index" :35, "handler": "generic" }, - "grail" : { "index" :36, "handler": "generic" }, - "tavern" : { "index" :95, "handler": "generic" }, - "sanctuary" : { "index" :80, "handler": "generic" }, + "hillFort" : { "index" :35, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "grail" : { "index" :36, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "tavern" : { "index" :95, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "sanctuary" : { "index" :80, "handler": "generic", "types" : { "object" : { "index" : 0} } }, /// Passive objects, terrain overlays - "cursedGround" : { "index" :21, "handler": "generic" }, - "magicPlains" : { "index" :46, "handler": "generic" }, - "swampFoliage" : { "index" :211, "handler": "generic" }, - "cloverField" : { "index" :222, "handler": "generic" }, - "cursedGroundDUPLICATE" : { "index" :223, "handler": "generic" }, - "evilFog" : { "index" :224, "handler": "generic" }, - "favorableWinds" : { "index" :225, "handler": "generic" }, - "fieryFields" : { "index" :226, "handler": "generic" }, - "holyGround" : { "index" :227, "handler": "generic" }, - "lucidPools" : { "index" :228, "handler": "generic" }, - "magicClouds" : { "index" :229, "handler": "generic" }, - "magicPlainsDUPLICATE" : { "index" :230, "handler": "generic" }, - "rocklands" : { "index" :231, "handler": "generic" }, + "cursedGround" : { "index" :21, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "magicPlains" : { "index" :46, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "swampFoliage" : { "index" :211, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "cloverField" : { "index" :222, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "cursedGroundDUPLICATE" : { "index" :223, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "evilFog" : { "index" :224, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "favorableWinds" : { "index" :225, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "fieryFields" : { "index" :226, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "holyGround" : { "index" :227, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "lucidPools" : { "index" :228, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "magicClouds" : { "index" :229, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "magicPlainsDUPLICATE" : { "index" :230, "handler": "generic", "types" : { "object" : { "index" : 0} } }, + "rocklands" : { "index" :231, "handler": "generic", "types" : { "object" : { "index" : 0} } }, /// Decorations - "cactus" : { "index" :116, "handler": "static" }, - "canyon" : { "index" :117, "handler": "static" }, - "crater" : { "index" :118, "handler": "static" }, - "deadVegetation" : { "index" :119, "handler": "static" }, - "flowers" : { "index" :120, "handler": "static" }, - "frozenLake" : { "index" :121, "handler": "static" }, - "hole" : { "index" :124, "handler": "static" }, - "kelp" : { "index" :125, "handler": "static" }, - "lake" : { "index" :126, "handler": "static" }, - "lavaFlow" : { "index" :127, "handler": "static" }, - "lavaLake" : { "index" :128, "handler": "static" }, - "mushrooms" : { "index" :129, "handler": "static" }, - "log" : { "index" :130, "handler": "static" }, - "mandrake" : { "index" :131, "handler": "static" }, - "moss" : { "index" :132, "handler": "static" }, - "mound" : { "index" :133, "handler": "static" }, - "mountain" : { "index" :134, "handler": "static" }, - "oakTrees" : { "index" :135, "handler": "static" }, - "outcropping" : { "index" :136, "handler": "static" }, - "pineTrees" : { "index" :137, "handler": "static" }, - "riverDelta" : { "index" :143, "handler": "static" }, - "rock" : { "index" :147, "handler": "static" }, - "sandDune" : { "index" :148, "handler": "static" }, - "sandPit" : { "index" :149, "handler": "static" }, - "shrub" : { "index" :150, "handler": "static" }, - "skull" : { "index" :151, "handler": "static" }, - "stump" : { "index" :153, "handler": "static" }, - "trees" : { "index" :155, "handler": "static" }, - "volcano" : { "index" :158, "handler": "static" }, - "reef" : { "index" :161, "handler": "static" }, - "lakeDUPLICATE" : { "index" :177, "handler": "static" }, - "treesDUPLICATE" : { "index" :199, "handler": "static" }, - "desertHills" : { "index" :206, "handler": "static" }, - "dirtHills" : { "index" :207, "handler": "static" }, - "grassHills" : { "index" :208, "handler": "static" }, - "roughHills" : { "index" :209, "handler": "static" }, - "subterraneanRocks" : { "index" :210, "handler": "static" } + "cactus" : { "index" :116, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "canyon" : { "index" :117, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "crater" : { "index" :118, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "deadVegetation" : { "index" :119, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "flowers" : { "index" :120, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "frozenLake" : { "index" :121, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "hole" : { "index" :124, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "kelp" : { "index" :125, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "lake" : { "index" :126, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "lavaFlow" : { "index" :127, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "lavaLake" : { "index" :128, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "mushrooms" : { "index" :129, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "log" : { "index" :130, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "mandrake" : { "index" :131, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "moss" : { "index" :132, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "mound" : { "index" :133, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "mountain" : { "index" :134, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "oakTrees" : { "index" :135, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "outcropping" : { "index" :136, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "pineTrees" : { "index" :137, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "riverDelta" : { "index" :143, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "rock" : { "index" :147, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "sandDune" : { "index" :148, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "sandPit" : { "index" :149, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "shrub" : { "index" :150, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "skull" : { "index" :151, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "stump" : { "index" :153, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "trees" : { "index" :155, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "volcano" : { "index" :158, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "reef" : { "index" :161, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "lakeDUPLICATE" : { "index" :177, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "treesDUPLICATE" : { "index" :199, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "desertHills" : { "index" :206, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "dirtHills" : { "index" :207, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "grassHills" : { "index" :208, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "roughHills" : { "index" :209, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "subterraneanRocks" : { "index" :210, "handler": "static", "types" : { "object" : { "index" : 0} } }, + + //These are WoG objects? They are not available in H3 + "frozenLakeDUPLICATE" : { "index" :172, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "oakTreesDUPLICATE" : { "index" :186, "handler": "static", "types" : { "object" : { "index" : 0} } }, + "plant" : { "index" :189, "handler": "static", "types" : { "object" : { "index" : 0} } } } diff --git a/config/objects/moddables.json b/config/objects/moddables.json index b03c5f6a5..51268b93c 100644 --- a/config/objects/moddables.json +++ b/config/objects/moddables.json @@ -189,9 +189,48 @@ "garrisonVertical" : { "index" :219, "handler": "garrison" }, // Subtype: paired monoliths - "monolithOneWayEntrance" : { "index" :43, "handler": "teleport" }, - "monolithOneWayExit" : { "index" :44, "handler": "teleport" }, - "monolithTwoWay" : { "index" :45, "handler": "teleport" }, + "monolithOneWayEntrance" : { + "index" :43, + "handler": "teleport", + "types" : { + "monolith1" : { "index" : 0 }, + "monolith2" : { "index" : 1 }, + "monolith3" : { "index" : 2 }, + "monolith4" : { "index" : 3 }, + "monolith5" : { "index" : 4 }, + "monolith6" : { "index" : 5 }, + "monolith7" : { "index" : 6 }, + "monolith8" : { "index" : 7 } + } + }, + "monolithOneWayExit" : { + "index" :44, + "handler": "teleport", + "types" : { + "monolith1" : { "index" : 0 }, + "monolith2" : { "index" : 1 }, + "monolith3" : { "index" : 2 }, + "monolith4" : { "index" : 3 }, + "monolith5" : { "index" : 4 }, + "monolith6" : { "index" : 5 }, + "monolith7" : { "index" : 6 }, + "monolith8" : { "index" : 7 } + } + }, + "monolithTwoWay" : { + "index" :45, + "handler": "teleport", + "types" : { + "monolith1" : { "index" : 0 }, + "monolith2" : { "index" : 1 }, + "monolith3" : { "index" : 2 }, + "monolith4" : { "index" : 3 }, + "monolith5" : { "index" : 4 }, + "monolith6" : { "index" : 5 }, + "monolith7" : { "index" : 6 }, + "monolith8" : { "index" : 7 } + } + }, // subtype: different appearance. That's all? "seerHut" : { "index" :83, "handler": "seerHut" }, diff --git a/config/objects/rewardable.json b/config/objects/rewardable.json index 7b6a06984..b0847471e 100644 --- a/config/objects/rewardable.json +++ b/config/objects/rewardable.json @@ -1,44 +1,51 @@ { /// These are objects that covered by concept of "configurable object" /// Most or even all of their configuration located in this file - "magicSpring" : { "index" :48, "handler": "magicSpring" }, + "magicSpring" : { "index" :48, "handler": "magicSpring", "types" : { "object" : { "index" : 0} } }, - "mysticalGarden" : { "index" :55, "handler": "oncePerWeek" }, - "windmill" : { "index" :112, "handler": "oncePerWeek" }, - "waterWheel" : { "index" :109, "handler": "oncePerWeek" }, + "mysticalGarden" : { "index" :55, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } }, + "windmill" : { "index" :112, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } }, + "waterWheel" : { "index" :109, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } }, - "leanTo" : { "index" :39, "handler": "onceVisitable" }, - "corpse" : { "index" :22, "handler": "onceVisitable" }, - "wagon" : { "index" :105, "handler": "onceVisitable" }, - "warriorTomb" : { "index" :108, "handler": "onceVisitable" }, + "leanTo" : { "index" :39, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } }, + "corpse" : { "index" :22, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } }, + "wagon" : { "index" :105, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } }, + "warriorTomb" : { "index" :108, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } }, - "campfire" : { "index" :12, "handler": "pickable" }, - "flotsam" : { "index" :29, "handler": "pickable" }, - "seaChest" : { "index" :82, "handler": "pickable" }, - "shipwreckSurvivor" : { "index" :86, "handler": "pickable" }, - "treasureChest" : { "index" :101, "handler": "pickable" }, + "campfire" : { "index" :12, "handler": "pickable", "types" : { "object" : { "index" : 0} } }, + "flotsam" : { "index" :29, "handler": "pickable", "types" : { "object" : { "index" : 0} } }, + "seaChest" : { "index" :82, "handler": "pickable", "types" : { "object" : { "index" : 0} } }, + "shipwreckSurvivor" : { "index" :86, "handler": "pickable", "types" : { "object" : { "index" : 0} } }, + "treasureChest" : { "index" :101, "handler": "pickable", "types" : { "object" : { "index" : 0} } }, - "arena" : { "index" :4, "handler": "oncePerHero" }, - "marlettoTower" : { "index" :23, "handler": "oncePerHero" }, - "gardenOfRevelation" : { "index" :32, "handler": "oncePerHero" }, - "libraryOfEnlightenment" : { "index" :41, "handler": "oncePerHero" }, - "mercenaryCamp" : { "index" :51, "handler": "oncePerHero" }, - "starAxis" : { "index" :61, "handler": "oncePerHero" }, - "learningStone" : { "index" :100, "handler": "oncePerHero" }, - "treeOfKnowledge" : { "index" :102, "handler": "oncePerHero" }, - "schoolOfMagic" : { "index" :47, "handler": "oncePerHero" }, - "schoolOfWar" : { "index" :107, "handler": "oncePerHero" }, - - "buoy" : { "index" :11, "handler": "bonusingObject" }, - "swanPond" : { "index" :14, "handler": "bonusingObject" }, - "faerieRing" : { "index" :28, "handler": "bonusingObject" }, - "fountainOfFortune" : { "index" :30, "handler": "bonusingObject" }, - "fountainOfYouth" : { "index" :31, "handler": "bonusingObject" }, - "idolOfFortune" : { "index" :38, "handler": "bonusingObject" }, - "mermaids" : { "index" :52, "handler": "bonusingObject" }, - "oasis" : { "index" :56, "handler": "bonusingObject" }, - "stables" : { "index" :94, "handler": "bonusingObject" }, - "temple" : { "index" :96, "handler": "bonusingObject" }, - "rallyFlag" : { "index" :64, "handler": "bonusingObject" }, - "wateringHole" : { "index" :110, "handler": "bonusingObject" }, + "arena" : { "index" :4, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "marlettoTower" : { "index" :23, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "gardenOfRevelation" : { "index" :32, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "libraryOfEnlightenment" : { "index" :41, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "mercenaryCamp" : { "index" :51, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "starAxis" : { "index" :61, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "treeOfKnowledge" : { "index" :102, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "schoolOfMagic" : { "index" :47, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "schoolOfWar" : { "index" :107, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } }, + "learningStone" : { + "index" :100, + "handler": "oncePerHero", + "types" : { + "object" : { "index" : 0}, + "objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Tests 2011 + } + }, + + "buoy" : { "index" :11, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "swanPond" : { "index" :14, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "faerieRing" : { "index" :28, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "fountainOfFortune" : { "index" :30, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "fountainOfYouth" : { "index" :31, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "idolOfFortune" : { "index" :38, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "mermaids" : { "index" :52, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "oasis" : { "index" :56, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "stables" : { "index" :94, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "temple" : { "index" :96, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "rallyFlag" : { "index" :64, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, + "wateringHole" : { "index" :110, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } } } diff --git a/config/schemas/mod.json b/config/schemas/mod.json index be0e5b9fd..8206b04d0 100644 --- a/config/schemas/mod.json +++ b/config/schemas/mod.json @@ -87,6 +87,11 @@ "description": "List of configuration files for heroes", "items": { "type":"string", "format" : "textFile" } }, + "objects": { + "type":"array", + "description": "List of configuration files for objects", + "items": { "type":"string", "format" : "textFile" } + }, "spells": { "type":"array", "description": "List of configuration files for spells", diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index 8b8395157..fb2b1eeff 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -365,13 +365,11 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp if(town) { curB->town = town; - curB->siege = town->fortLevel(); curB->terrainType = VLC->townh->factions[town->subID]->nativeTerrain; } else { curB->town = nullptr; - curB->siege = CGTownInstance::NONE; curB->terrainType = terrain; } @@ -574,13 +572,13 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp } - if (curB->siege == CGTownInstance::CITADEL || curB->siege == CGTownInstance::CASTLE) + if (curB->town && curB->town->fortLevel() >= CGTownInstance::CITADEL) { // keep tower CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -2); stacks.push_back(stack); - if (curB->siege == CGTownInstance::CASTLE) + if (curB->town->fortLevel() >= CGTownInstance::CASTLE) { // lower tower + upper tower CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -4); diff --git a/lib/BattleState.h b/lib/BattleState.h index 3d8ac4587..4eb774f4d 100644 --- a/lib/BattleState.h +++ b/lib/BattleState.h @@ -4,8 +4,8 @@ #include "BattleHex.h" #include "HeroBonus.h" #include "CCreatureSet.h" -#include "mapObjects/CGTownInstance.h" -#include "mapObjects/CGHeroInstance.h" +#include "mapObjects/CArmedInstance.h" // for army serialization +#include "mapObjects/CGHeroInstance.h" // for commander serialization #include "CCreatureHandler.h" #include "CObstacleInstance.h" #include "ConstTransitivePtr.h" @@ -83,8 +83,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb { std::array sides; //sides[0] - attacker, sides[1] - defender si32 round, activeStack, selectedStack; - CGTownInstance::EFortLevel siege; - const CGTownInstance * town; //used during town siege - id of attacked town; -1 if not town defence + const CGTownInstance * town; //used during town siege, nullptr if this is not a siege (note that fortless town IS also a siege) int3 tile; //for background and bonuses std::vector stacks; std::vector > obstacles; @@ -99,7 +98,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb template void serialize(Handler &h, const int version) { h & sides; - h & round & activeStack & selectedStack & siege & town & tile & stacks & obstacles + h & round & activeStack & selectedStack & town & tile & stacks & obstacles & si & battlefieldType & terrainType; h & tacticsSide & tacticDistance; h & static_cast(*this); diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 592e1de58..805cc6aeb 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -2,8 +2,8 @@ #include "../lib/HeroBonus.h" -#include "../lib/ConstTransitivePtr.h" -#include "JsonNode.h" +//#include "../lib/ConstTransitivePtr.h" +//#include "JsonNode.h" #include "GameConstants.h" #include "IHandlerBase.h" diff --git a/lib/CBattleCallback.cpp b/lib/CBattleCallback.cpp index 1744ca27a..10692aa8d 100644 --- a/lib/CBattleCallback.cpp +++ b/lib/CBattleCallback.cpp @@ -409,7 +409,7 @@ ui8 CBattleInfoEssentials::playerToSide(PlayerColor player) const ui8 CBattleInfoEssentials::battleGetSiegeLevel() const { RETURN_IF_NOT_BATTLE(0); - return getBattle()->siege; + return getBattle()->town ? getBattle()->town->fortLevel() : CGTownInstance::NONE; } bool CBattleInfoEssentials::battleCanSurrender(PlayerColor player) const @@ -429,7 +429,7 @@ bool CBattleInfoEssentials::battleHasHero(ui8 side) const si8 CBattleInfoEssentials::battleGetWallState(int partOfWall) const { RETURN_IF_NOT_BATTLE(0); - if(getBattle()->siege == CGTownInstance::NONE) + if(getBattle()->town == nullptr || getBattle()->town->fortLevel() == CGTownInstance::NONE) return EWallState::NONE; assert(partOfWall >= 0 && partOfWall < EWallPart::PARTS_COUNT); diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index f33019a81..7dea9f9f0 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -224,6 +224,7 @@ ui64 CCreatureSet::getPower (SlotID slot) const { return getStack(slot).getPower(); } + std::string CCreatureSet::getRoughAmount (SlotID slot) const { int quantity = CCreature::getQuantityID(getStackCount(slot)); diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index eb62696ff..2f249dec8 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -16,6 +16,7 @@ #include "StartInfo.h" // for StartInfo #include "BattleState.h" // for BattleInfo #include "NetPacks.h" // for InfoWindow +#include "CModHandler.h" //TODO make clean #define ERROR_VERBOSE_OR_NOT_RET_VAL_IF(cond, verbose, txt, retVal) do {if(cond){if(verbose)logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0) @@ -260,18 +261,6 @@ int CGameInfoCallback::getDate(Date::EDateType mode) const //boost::shared_lock lock(*gs->mx); return gs->getDate(mode); } -std::vector < std::string > CGameInfoCallback::getObjDescriptions(int3 pos) const -{ - //boost::shared_lock lock(*gs->mx); - std::vector ret; - const TerrainTile *t = getTile(pos); - ERROR_RET_VAL_IF(!t, "Not a valid tile given!", ret); - - - for(const CGObjectInstance * obj : t->blockingObjects) - ret.push_back(obj->getHoverText()); - return ret; -} bool CGameInfoCallback::isVisible(int3 pos, boost::optional Player) const { diff --git a/lib/CGameInfoCallback.h b/lib/CGameInfoCallback.h index aeade6a56..ae740b29d 100644 --- a/lib/CGameInfoCallback.h +++ b/lib/CGameInfoCallback.h @@ -83,7 +83,6 @@ public: std::vector getVisitableObjs(int3 pos, bool verbose = true)const; std::vector getFlaggableObjects(int3 pos) const; const CGObjectInstance * getTopObj (int3 pos) const; - std::vector getObjDescriptions(int3 pos)const; //returns descriptions of objects at pos in order from the lowest to the highest PlayerColor getOwner(ObjectInstanceID heroID) const; const CGObjectInstance *getObjByQuestIdentifier(int identifier) const; //nullptr if object has been removed (eg. killed) diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 45b1510a0..a5fe9923b 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -1053,7 +1053,6 @@ void CGameState::randomizeMapObjects() if(!obj) continue; randomizeObject(obj); - obj->hoverName = VLC->objtypeh->getObjectName(obj->ID); //handle Favouring Winds - mark tiles under it if(obj->ID == Obj::FAVORABLE_WINDS) @@ -1637,7 +1636,7 @@ void CGameState::initFogOfWar() if(!obj || !vstd::contains(elem.second.players, obj->tempOwner)) continue; //not a flagged object std::unordered_set tiles; - obj->getSightTiles(tiles); + getTilesInRange(tiles, obj->getSightCenter(), obj->getSightRadious(), obj->tempOwner, 1); for(int3 tile : tiles) { elem.second.fogOfWarMap[tile.x][tile.y][tile.z] = 1; @@ -2980,7 +2979,7 @@ void InfoAboutArmy::initFromArmy(const CArmedInstance *Army, bool detailed) { army = ArmyDescriptor(Army, detailed); owner = Army->tempOwner; - name = Army->getHoverText(); + name = Army->getObjectName(); } void InfoAboutHero::assign(const InfoAboutHero & iah) @@ -3510,59 +3509,6 @@ CPathfinder::CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance allowEmbarkAndDisembark = true; } -EVictoryLossCheckResult::EVictoryLossCheckResult() : - intValue(0) -{ -} - -EVictoryLossCheckResult::EVictoryLossCheckResult(si32 intValue, std::string toSelf, std::string toOthers) : - messageToSelf(toSelf), - messageToOthers(toOthers), - intValue(intValue) -{ -} - -bool EVictoryLossCheckResult::operator==(EVictoryLossCheckResult const & other) const -{ - return intValue == other.intValue; -} - -bool EVictoryLossCheckResult::operator!=(EVictoryLossCheckResult const & other) const -{ - return intValue != other.intValue; -} - -bool EVictoryLossCheckResult::victory() const -{ - return intValue == VICTORY; -} - -bool EVictoryLossCheckResult::loss() const -{ - return intValue == DEFEAT; -} - -EVictoryLossCheckResult EVictoryLossCheckResult::invert() -{ - return EVictoryLossCheckResult(-intValue, messageToOthers, messageToSelf); -} - -EVictoryLossCheckResult EVictoryLossCheckResult::victory(std::string toSelf, std::string toOthers) -{ - return EVictoryLossCheckResult(VICTORY, toSelf, toOthers); -} - -EVictoryLossCheckResult EVictoryLossCheckResult::defeat(std::string toSelf, std::string toOthers) -{ - return EVictoryLossCheckResult(DEFEAT, toSelf, toOthers); -} - -std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult) -{ - os << victoryLossCheckResult.messageToSelf; - return os; -} - CRandomGenerator & CGameState::getRandomGenerator() { return rand; diff --git a/lib/CGameState.h b/lib/CGameState.h index 0d8a8c8f2..222e9ce76 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -15,6 +15,7 @@ #include "ResourceSet.h" #include "int3.h" #include "CRandomGenerator.h" +#include "CGameStateFwd.h" /* * CGameState.h, part of VCMI engine @@ -355,39 +356,6 @@ public: struct BattleInfo; -class DLL_LINKAGE EVictoryLossCheckResult -{ -public: - static EVictoryLossCheckResult victory(std::string toSelf, std::string toOthers); - static EVictoryLossCheckResult defeat(std::string toSelf, std::string toOthers); - - EVictoryLossCheckResult(); - bool operator==(EVictoryLossCheckResult const & other) const; - bool operator!=(EVictoryLossCheckResult const & other) const; - bool victory() const; - bool loss() const; - - EVictoryLossCheckResult invert(); - - std::string messageToSelf; - std::string messageToOthers; - - template void serialize(Handler &h, const int version) - { - h & intValue & messageToSelf & messageToOthers; - } -private: - enum EResult - { - DEFEAT = -1, - INGAME = 0, - VICTORY= +1 - }; - - EVictoryLossCheckResult(si32 intValue, std::string toSelf, std::string toOthers); - si32 intValue; // uses EResult -}; - DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult); class DLL_LINKAGE CGameState : public CNonConstInfoCallback @@ -533,35 +501,3 @@ private: friend class CMapHandler; friend class CGameHandler; }; - -struct DLL_LINKAGE QuestInfo //universal interface for human and AI -{ - const CQuest * quest; - const CGObjectInstance * obj; //related object, most likely Seer Hut - int3 tile; - - QuestInfo(){}; - QuestInfo (const CQuest * Quest, const CGObjectInstance * Obj, int3 Tile) : - quest (Quest), obj (Obj), tile (Tile){}; - - //FIXME: assignment operator should return QuestInfo & - bool operator= (const QuestInfo &qi) - { - quest = qi.quest; - obj = qi.obj; - tile = qi.tile; - return true; - } - - bool operator== (const QuestInfo & qi) const - { - return (quest == qi.quest && obj == qi.obj); - } - - //std::vector > texts //allow additional info for quest log? - - template void serialize(Handler &h, const int version) - { - h & quest & obj & tile; - } -}; diff --git a/lib/CGameStateFwd.h b/lib/CGameStateFwd.h new file mode 100644 index 000000000..b284373e3 --- /dev/null +++ b/lib/CGameStateFwd.h @@ -0,0 +1,120 @@ +#pragma once + +/* + * CGameStateFwd.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ + +class CQuest; +class CGObjectInstance; + +class DLL_LINKAGE EVictoryLossCheckResult +{ +public: + static EVictoryLossCheckResult victory(std::string toSelf, std::string toOthers) + { + return EVictoryLossCheckResult(VICTORY, toSelf, toOthers); + } + + static EVictoryLossCheckResult defeat(std::string toSelf, std::string toOthers) + { + return EVictoryLossCheckResult(DEFEAT, toSelf, toOthers); + } + + EVictoryLossCheckResult(): + intValue(0) + { + } + + bool operator==(EVictoryLossCheckResult const & other) const + { + return intValue == other.intValue; + } + + bool operator!=(EVictoryLossCheckResult const & other) const + { + return intValue != other.intValue; + } + + bool victory() const + { + return intValue == VICTORY; + } + bool loss() const + { + return intValue == DEFEAT; + } + + EVictoryLossCheckResult invert() + { + return EVictoryLossCheckResult(-intValue, messageToOthers, messageToSelf); + } + + std::string messageToSelf; + std::string messageToOthers; + + template void serialize(Handler &h, const int version) + { + h & intValue & messageToSelf & messageToOthers; + } +private: + enum EResult + { + DEFEAT = -1, + INGAME = 0, + VICTORY= +1 + }; + + EVictoryLossCheckResult(si32 intValue, std::string toSelf, std::string toOthers): + messageToSelf(toSelf), + messageToOthers(toOthers), + intValue(intValue) + { + } + + si32 intValue; // uses EResult +}; + +/*static std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult) +{ + os << victoryLossCheckResult.messageToSelf; + return os; +}*/ + +struct DLL_LINKAGE QuestInfo //universal interface for human and AI +{ + const CQuest * quest; + const CGObjectInstance * obj; //related object, most likely Seer Hut + int3 tile; + + QuestInfo(){}; + QuestInfo (const CQuest * Quest, const CGObjectInstance * Obj, int3 Tile) : + quest (Quest), obj (Obj), tile (Tile){}; + + //FIXME: assignment operator should return QuestInfo & + bool operator= (const QuestInfo &qi) + { + quest = qi.quest; + obj = qi.obj; + tile = qi.tile; + return true; + } + + bool operator== (const QuestInfo & qi) const + { + return (quest == qi.quest && obj == qi.obj); + } + + //std::vector > texts //allow additional info for quest log? + + template void serialize(Handler &h, const int version) + { + h & quest & obj & tile; + } +}; + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f426a13a6..62764080e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -82,6 +82,7 @@ set(lib_SRCS ResourceSet.cpp VCMI_Lib.cpp VCMIDirs.cpp + IHandlerBase.cpp IGameCallback.cpp CGameInfoCallback.cpp @@ -118,8 +119,8 @@ set(lib_HEADERS GameConstants.h StringConstants.h IGameEventsReceiver.h - IHandlerBase.h int3.h + CGameStateFwd.h Interprocess.h NetPacks.h NetPacksBase.h diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index 98bcf2c4a..7712b192b 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -15,9 +15,12 @@ #include "CSpellHandler.h" // for CSpell #include "NetPacks.h" #include "CBonusTypeHandler.h" +#include "CModHandler.h" #include "Connection.h" // for SAVEGAME_MAGIC #include "mapObjects/CObjectClassesHandler.h" +#include "StartInfo.h" +#include "CGameState.h" void CPrivilagedInfoCallback::getFreeTiles (std::vector &tiles) const { diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index e6183e2b2..abbb5d64b 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -48,7 +48,6 @@ public: virtual bool removeObject(const CGObjectInstance * obj)=0; virtual void setBlockVis(ObjectInstanceID objid, bool bv)=0; virtual void setOwner(const CGObjectInstance * objid, PlayerColor owner)=0; - virtual void setHoverName(const CGObjectInstance * obj, MetaString * name)=0; virtual void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false)=0; virtual void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false)=0; virtual void showBlockingDialog(BlockingDialog *iw) =0; @@ -93,6 +92,8 @@ public: virtual void sendAndApply(CPackForClient * info)=0; virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map virtual void addQuest(int player, QuestInfo & quest){}; + virtual void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) = 0; + virtual void changeFogOfWar(std::unordered_set &tiles, PlayerColor player, bool hide) = 0; }; class DLL_LINKAGE CNonConstInfoCallback : public CPrivilagedInfoCallback diff --git a/lib/IHandlerBase.cpp b/lib/IHandlerBase.cpp new file mode 100644 index 000000000..bddbae3ba --- /dev/null +++ b/lib/IHandlerBase.cpp @@ -0,0 +1,19 @@ +/* + * IHandlerBase.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ + +#include "StdInc.h" +#include "IHandlerBase.h" +#include "CModHandler.h" + + +void IHandlerBase::registerObject(std::string scope, std::string type_name, std::string name, si32 index) +{ + return VLC->modh->identifiers.registerObject(scope, type_name, name, index); +} diff --git a/lib/IHandlerBase.h b/lib/IHandlerBase.h index 2ae74235e..c26b6f944 100644 --- a/lib/IHandlerBase.h +++ b/lib/IHandlerBase.h @@ -11,7 +11,7 @@ */ #include "../lib/ConstTransitivePtr.h" #include "VCMI_Lib.h" - #include "CModHandler.h" + //#include "CModHandler.h" class JsonNode; @@ -22,6 +22,9 @@ class DLL_LINKAGE IHandlerBase // Object * loadFromJson(const JsonNode & json); // where Object is type of data loaded by handler // primary used in loadObject methods +protected: + /// Calls modhandler. Mostly needed to avoid large number of includes in headers + void registerObject(std::string scope, std::string type_name, std::string name, si32 index); public: /// loads all original game data in vector of json nodes @@ -48,7 +51,6 @@ public: virtual ~IHandlerBase(){} }; - template class CHandlerBase: public IHandlerBase { public: @@ -68,7 +70,7 @@ public: objects.push_back(object); - VLC->modh->identifiers.registerObject(scope, type_name, name, object->id); + registerObject(scope, type_name, name, object->id); } void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override { @@ -80,7 +82,7 @@ public: assert(objects[index] == nullptr); // ensure that this id was not loaded before objects[index] = object; - VLC->modh->identifiers.registerObject(scope,type_name, name, object->id); + registerObject(scope,type_name, name, object->id); } diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 5f8c0d666..61cfedba6 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -3,16 +3,18 @@ #include "NetPacksBase.h" #include "BattleAction.h" -#include "HeroBonus.h" +//#include "HeroBonus.h" #include "mapObjects/CGHeroInstance.h" -#include "CCreatureSet.h" -#include "mapping/CMapInfo.h" -#include "StartInfo.h" +//#include "CCreatureSet.h" +//#include "mapping/CMapInfo.h" +//#include "StartInfo.h" #include "ConstTransitivePtr.h" #include "int3.h" #include "ResourceSet.h" +//#include "CObstacleInstance.h" +#include "CGameStateFwd.h" +#include "mapping/CMap.h" #include "CObstacleInstance.h" -#include "CGameState.h" /* * NetPacks.h, part of VCMI engine @@ -37,7 +39,8 @@ class CArtifactInstance; struct StackLocation; struct ArtSlotInfo; struct QuestInfo; - +class CMapInfo; +class StartInfo; struct CPackForClient : public CPack @@ -1045,21 +1048,6 @@ struct SetObjectProperty : public CPackForClient//1001 } }; -struct SetHoverName : public CPackForClient//1002 -{ - DLL_LINKAGE void applyGs(CGameState *gs); - - ObjectInstanceID id; - MetaString name; - SetHoverName(){type = 1002;} - SetHoverName(ObjectInstanceID ID, MetaString& Name):id(ID),name(Name){type = 1002;} - - template void serialize(Handler &h, const int version) - { - h & id & name; - } -}; - struct ChangeObjectVisitors : public CPackForClient // 1003 { enum VisitMode @@ -1527,7 +1515,8 @@ struct ObstaclesRemoved : public CPackForClient //3014 } }; -struct CatapultAttack : public CPackForClient //3015 +struct ELF_VISIBILITY CatapultAttack : public CPackForClient //3015 + { struct AttackInfo { @@ -2136,26 +2125,14 @@ struct PlayerJoined : public CPregamePackToHost } }; -struct SelectMap : public CPregamePackToPropagate +struct ELF_VISIBILITY SelectMap : public CPregamePackToPropagate { const CMapInfo *mapInfo; - bool free; + bool free;//local flag, do not serialize - SelectMap(const CMapInfo &src) - { - mapInfo = &src; - free = false; - } - SelectMap() - { - mapInfo = nullptr; - free = true; - } - ~SelectMap() - { - if(free) - delete mapInfo; - } + DLL_LINKAGE SelectMap(const CMapInfo &src); + DLL_LINKAGE SelectMap(); + DLL_LINKAGE ~SelectMap(); void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp @@ -2166,28 +2143,16 @@ struct SelectMap : public CPregamePackToPropagate }; -struct UpdateStartOptions : public CPregamePackToPropagate +struct ELF_VISIBILITY UpdateStartOptions : public CPregamePackToPropagate { StartInfo *options; - bool free; + bool free;//local flag, do not serialize void apply(CSelectionScreen *selScreen); //that functions are implemented in CPreGame.cpp - UpdateStartOptions(StartInfo &src) - { - options = &src; - free = false; - } - UpdateStartOptions() - { - options = nullptr; - free = true; - } - ~UpdateStartOptions() - { - if(free) - delete options; - } + DLL_LINKAGE UpdateStartOptions(StartInfo &src); + DLL_LINKAGE UpdateStartOptions(); + DLL_LINKAGE ~UpdateStartOptions(); template void serialize(Handler &h, const int version) { diff --git a/lib/NetPacksBase.h b/lib/NetPacksBase.h index aca2fd62d..6e63d7c36 100644 --- a/lib/NetPacksBase.h +++ b/lib/NetPacksBase.h @@ -25,7 +25,7 @@ struct ArtSlotInfo; #include "GameConstants.h" -struct CPack +struct DLL_LINKAGE CPack { ui16 type; @@ -197,4 +197,4 @@ struct ArtifactLocation { h & artHolder & slot; } -}; \ No newline at end of file +}; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 479a9311d..2c700b101 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -14,6 +14,8 @@ #include "CGameState.h" #include "BattleState.h" #include "CTownHandler.h" +#include "mapping/CMapInfo.h" +#include "StartInfo.h" /* * NetPacksLib.cpp, part of VCMI engine @@ -60,6 +62,41 @@ DLL_LINKAGE void SetSecSkill::applyGs( CGameState *gs ) hero->setSecSkillLevel(which, val, abs); } + +DLL_LINKAGE SelectMap::SelectMap(const CMapInfo &src) +{ + mapInfo = &src; + free = false; +} +DLL_LINKAGE SelectMap::SelectMap() +{ + mapInfo = nullptr; + free = true; +} + +DLL_LINKAGE SelectMap::~SelectMap() +{ + if(free) + delete mapInfo; +} + +DLL_LINKAGE UpdateStartOptions::UpdateStartOptions(StartInfo &src) +{ + options = &src; + free = false; +} +DLL_LINKAGE UpdateStartOptions::UpdateStartOptions() +{ + options = nullptr; + free = true; +} + +DLL_LINKAGE UpdateStartOptions::~UpdateStartOptions() +{ + if(free) + delete options; +} + DLL_LINKAGE void SetCommanderProperty::applyGs(CGameState *gs) { CCommanderInstance * commander = gs->getHero(heroid)->commander; @@ -177,7 +214,7 @@ DLL_LINKAGE void FoWChange::applyGs( CGameState *gs ) case Obj::TOWN: case Obj::ABANDONED_MINE: if(vstd::contains(team->players, o->tempOwner)) //check owned observators - o->getSightTiles(tilesRevealed); + gs->getTilesInRange(tiles, o->getSightCenter(), o->getSightRadious(), o->tempOwner, 1); break; } } @@ -302,7 +339,7 @@ DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs ) { CGObjectInstance *obj = gs->getObjInstance(id); - logGlobal->debugStream() << "removing object id=" << id << "; address=" << (intptr_t)obj << "; name=" << obj->getHoverText(); + logGlobal->debugStream() << "removing object id=" << id << "; address=" << (intptr_t)obj << "; name=" << obj->getObjectName(); //unblock tiles gs->map->removeBlockVisTiles(obj); @@ -608,14 +645,13 @@ DLL_LINKAGE void NewObject::applyGs( CGameState *gs ) const TerrainTile &t = gs->map->getTile(pos); o->appearance = VLC->objtypeh->getHandlerFor(o->ID, o->subID)->getTemplates(t.terType).front(); id = o->id = ObjectInstanceID(gs->map->objects.size()); - o->hoverName = VLC->objtypeh->getObjectName(ID); gs->map->objects.push_back(o); gs->map->addBlockVisTiles(o); o->initObj(); gs->map->calculateGuardingGreaturePositions(); - logGlobal->debugStream() << "added object id=" << id << "; address=" << (intptr_t)o << "; name=" << o->getHoverText(); + logGlobal->debugStream() << "added object id=" << id << "; address=" << (intptr_t)o << "; name=" << o->getObjectName(); } DLL_LINKAGE void NewArtifact::applyGs( CGameState *gs ) @@ -1012,11 +1048,6 @@ DLL_LINKAGE void SetObjectProperty::applyGs( CGameState *gs ) } } -DLL_LINKAGE void SetHoverName::applyGs( CGameState *gs ) -{ - name.toString(gs->getObj(id)->hoverName); -} - DLL_LINKAGE void HeroLevelUp::applyGs( CGameState *gs ) { CGHeroInstance * h = gs->getHero(hero->id); @@ -1495,6 +1526,7 @@ DLL_LINKAGE void ObstaclesRemoved::applyGs( CGameState *gs ) } } + DLL_LINKAGE CatapultAttack::CatapultAttack() { type = 3015; @@ -1502,12 +1534,11 @@ DLL_LINKAGE CatapultAttack::CatapultAttack() DLL_LINKAGE CatapultAttack::~CatapultAttack() { - } DLL_LINKAGE void CatapultAttack::applyGs( CGameState *gs ) { - if(gs->curB && gs->curB->siege != CGTownInstance::NONE) //if there is a battle and it's a siege + if(gs->curB && gs->curB->town && gs->curB->town->fortLevel() != CGTownInstance::NONE) //if there is a battle and it's a siege { for(const auto &it :attackedParts) { diff --git a/lib/VCMI_lib.cbp b/lib/VCMI_lib.cbp index aaff61c72..a1cdd70e0 100644 --- a/lib/VCMI_lib.cbp +++ b/lib/VCMI_lib.cbp @@ -128,6 +128,7 @@ + diff --git a/lib/VCMI_lib.vcxproj b/lib/VCMI_lib.vcxproj index f35fbb138..5e7da453f 100644 --- a/lib/VCMI_lib.vcxproj +++ b/lib/VCMI_lib.vcxproj @@ -199,6 +199,7 @@ + @@ -274,6 +275,7 @@ + diff --git a/lib/VCMI_lib.vcxproj.filters b/lib/VCMI_lib.vcxproj.filters index 321e9a652..9e1ec4ec5 100644 --- a/lib/VCMI_lib.vcxproj.filters +++ b/lib/VCMI_lib.vcxproj.filters @@ -204,6 +204,7 @@ mapObjects + @@ -488,5 +489,8 @@ mapObjects + + Header Files + \ No newline at end of file diff --git a/lib/mapObjects/CArmedInstance.h b/lib/mapObjects/CArmedInstance.h index bb771fc4e..9b58332ca 100644 --- a/lib/mapObjects/CArmedInstance.h +++ b/lib/mapObjects/CArmedInstance.h @@ -13,6 +13,9 @@ * */ +class BattleInfo; +class CGameState; + class DLL_LINKAGE CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet { public: diff --git a/lib/mapObjects/CBank.cpp b/lib/mapObjects/CBank.cpp index 1c74a4fad..a653dcbfd 100644 --- a/lib/mapObjects/CBank.cpp +++ b/lib/mapObjects/CBank.cpp @@ -16,6 +16,8 @@ #include "../CSoundBase.h" #include "CommonConstructors.h" #include "../CSpellHandler.h" +#include "../IGameCallback.h" +#include "../CGameState.h" using namespace boost::assign; @@ -41,11 +43,12 @@ void CBank::initObj() VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, cb->gameState()->getRandomGenerator()); } -const std::string & CBank::getHoverText() const +std::string CBank::getHoverText(PlayerColor player) const { + // TODO: USE BANK_SPECIFIC NAMES + // TODO: record visited players bool visited = (bc == nullptr); - hoverName = visitedTxt(visited); // FIXME: USE BANK_SPECIFIC NAMES - return hoverName; + return visitedTxt(visited); } void CBank::setConfig(const BankConfig & config) diff --git a/lib/mapObjects/CBank.h b/lib/mapObjects/CBank.h index a08cb9874..cfecdf20c 100644 --- a/lib/mapObjects/CBank.h +++ b/lib/mapObjects/CBank.h @@ -32,7 +32,7 @@ public: void setConfig(const BankConfig & bc); void initObj() override; - const std::string & getHoverText() const override; + std::string getHoverText(PlayerColor player) const override; void newTurn() const override; bool wasVisited (PlayerColor player) const override; void onHeroVisit(const CGHeroInstance * h) const override; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 20fe4e870..10464505b 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -14,10 +14,13 @@ #include "../NetPacks.h" #include "../CGeneralTextHandler.h" #include "../CHeroHandler.h" +#include "../CModHandler.h" #include "../CSoundBase.h" #include "../CSpellHandler.h" #include "CObjectClassesHandler.h" - +#include "../IGameCallback.h" +#include "../CGameState.h" +#include "../CCreatureHandler.h" using namespace boost::assign; @@ -418,19 +421,17 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const } } -const std::string & CGHeroInstance::getHoverText() const +std::string CGHeroInstance::getObjectName() const { if(ID != Obj::PRISON) { - hoverName = VLC->generaltexth->allTexts[15]; + std::string hoverName = VLC->generaltexth->allTexts[15]; boost::algorithm::replace_first(hoverName,"%s",name); boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name); return hoverName; } else - hoverName = VLC->objtypeh->getObjectName(ID); - - return hoverName; + return CGObjectInstance::getObjectName(); } const std::string & CGHeroInstance::getBiography() const @@ -999,11 +1000,11 @@ void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedSta cb->showInfoDialog(&iw); } - +/* int3 CGHeroInstance::getSightCenter() const { return getPosition(false); -} +}*/ int CGHeroInstance::getSightRadious() const { diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 602342a20..87abc77c7 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -18,6 +18,8 @@ class CHero; class CGBoat; +class CGTownInstance; +class TerrainTile; class CGHeroPlaceholder : public CGObjectInstance { @@ -113,7 +115,7 @@ public: } } skillsInfo; - int3 getSightCenter() const; //"center" tile from which the sight distance is calculated + //int3 getSightCenter() const; //"center" tile from which the sight distance is calculated int getSightRadious() const; //sight distance (should be used if player-owned structure) ////////////////////////////////////////////////////////////////////////// @@ -205,7 +207,7 @@ public: void initObj() override; void onHeroVisit(const CGHeroInstance * h) const override; - const std::string & getHoverText() const override; + std::string getObjectName() const override; protected: void setPropertyDer(ui8 what, ui32 val) override;//synchr diff --git a/lib/mapObjects/CGMarket.cpp b/lib/mapObjects/CGMarket.cpp index 4968f9594..13fdfea11 100644 --- a/lib/mapObjects/CGMarket.cpp +++ b/lib/mapObjects/CGMarket.cpp @@ -14,6 +14,9 @@ #include "../NetPacks.h" #include "../CGeneralTextHandler.h" +#include "../IGameCallback.h" +#include "../CCreatureHandler.h" +#include "../CGameState.h" using namespace boost::assign; diff --git a/lib/mapObjects/CGPandoraBox.cpp b/lib/mapObjects/CGPandoraBox.cpp index ed368c63c..b4fa8c98d 100644 --- a/lib/mapObjects/CGPandoraBox.cpp +++ b/lib/mapObjects/CGPandoraBox.cpp @@ -15,6 +15,8 @@ #include "../CSoundBase.h" #include "../CSpellHandler.h" +#include "../StartInfo.h" +#include "../IGameCallback.h" using namespace boost::assign; diff --git a/lib/mapObjects/CGPandoraBox.h b/lib/mapObjects/CGPandoraBox.h index 828ce4697..c2ad87dde 100644 --- a/lib/mapObjects/CGPandoraBox.h +++ b/lib/mapObjects/CGPandoraBox.h @@ -2,6 +2,7 @@ #include "CObjectHandler.h" #include "CArmedInstance.h" +#include "../ResourceSet.h" /* * CGPandoraBox.h, part of VCMI engine @@ -13,6 +14,8 @@ * */ +class InfoWindow; + class DLL_LINKAGE CGPandoraBox : public CArmedInstance { public: diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index c01e1755d..9cb8b05a5 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -14,6 +14,9 @@ #include "../NetPacks.h" #include "../CGeneralTextHandler.h" +#include "../CModHandler.h" +#include "../IGameCallback.h" +#include "../CGameState.h" using namespace boost::assign; @@ -55,7 +58,7 @@ void CGDwelling::initObj() } } -void CGDwelling::setProperty(ui8 what, ui32 val) +void CGDwelling::setPropertyDer(ui8 what, ui32 val) { switch (what) { @@ -77,8 +80,8 @@ void CGDwelling::setProperty(ui8 what, ui32 val) creatures[0].second[0] = CreatureID(val); break; } - CGObjectInstance::setProperty(what,val); } + void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const { if(ID == Obj::REFUGEE_CAMP && !creatures[0].first) //Refugee Camp, no available cres @@ -523,11 +526,15 @@ void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const cb->stopHeroVisitCastle(this, h); } +std::string CGTownInstance::getObjectName() const +{ + return name + ", " + town->faction->name; +} + void CGTownInstance::initObj() ///initialize town structures { blockVisit = true; - hoverName = name + ", " + town->faction->name; if (subID == ETownType::DUNGEON) creatures.resize(GameConstants::CREATURES_PER_TOWN+1);//extra dwelling for Dungeon @@ -644,25 +651,22 @@ void CGTownInstance::newTurn() const } } } - +/* int3 CGTownInstance::getSightCenter() const { return pos - int3(2,0,0); } - -ui8 CGTownInstance::getPassableness() const +*/ +bool CGTownInstance::passableFor(PlayerColor color) const { if (!armedGarrison())//empty castle - anyone can visit - return GameConstants::ALL_PLAYERS; + return true; if ( tempOwner == PlayerColor::NEUTRAL )//neutral guarded - no one can visit - return 0; + return false; - ui8 mask = 0; - TeamState * ts = cb->gameState()->getPlayerTeam(tempOwner); - for(PlayerColor it : ts->players) - mask |= 1<getPlayerRelations(tempOwner, color) != PlayerRelations::ENEMIES) + return true; + return false; } void CGTownInstance::getOutOffsets( std::vector &offsets ) const @@ -1010,7 +1014,7 @@ void CGTownInstance::battleFinished(const CGHeroInstance *hero, const BattleResu FoWChange fw; fw.player = hero->tempOwner; fw.mode = 1; - getSightTiles (fw.tiles); //update visibility for castle structures + cb->getTilesInRange(fw.tiles, getSightCenter(), getSightRadious(), tempOwner, 1); cb->sendAndApply (&fw); } } diff --git a/lib/mapObjects/CGTownInstance.h b/lib/mapObjects/CGTownInstance.h index 1b56fc99b..fd105365f 100644 --- a/lib/mapObjects/CGTownInstance.h +++ b/lib/mapObjects/CGTownInstance.h @@ -17,6 +17,7 @@ */ class CCastleEvent; +class CGTownInstance; class DLL_LINKAGE CSpecObjInfo { @@ -59,7 +60,7 @@ public: void initObj() override; void onHeroVisit(const CGHeroInstance * h) const override; void newTurn() const override; - void setProperty(ui8 what, ui32 val) override; + void setPropertyDer(ui8 what, ui32 val) override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; @@ -200,8 +201,8 @@ public: ////////////////////////////////////////////////////////////////////////// - ui8 getPassableness() const; //bitmap - if the bit is set the corresponding player can pass through the visitable tiles of object, even if it's blockvis; if not set - default properties from definfo are used - int3 getSightCenter() const override; //"center" tile from which the sight distance is calculated + bool passableFor(PlayerColor color) const; + //int3 getSightCenter() const override; //"center" tile from which the sight distance is calculated int getSightRadious() const override; //returns sight distance int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral void getOutOffsets(std::vector &offsets) const; //offsets to obj pos when we boat can be placed @@ -243,6 +244,7 @@ public: void onHeroLeave(const CGHeroInstance * h) const override; void initObj() override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; + std::string getObjectName() const override; protected: void setPropertyDer(ui8 what, ui32 val) override; }; diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index b02d8c174..990137a50 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -276,8 +276,10 @@ void CObjectClassesHandler::afterLoadFinalization() std::string CObjectClassesHandler::getObjectName(si32 type) const { - assert(objects.count(type)); - return objects.at(type)->name; + if (objects.count(type)) + return objects.at(type)->name; + logGlobal->errorStream() << "Access to non existing object of type " << type; + return ""; } void AObjectTypeHandler::setType(si32 type, si32 subtype) diff --git a/lib/mapObjects/CObjectClassesHandler.h b/lib/mapObjects/CObjectClassesHandler.h index 5da326c20..a16fb0ba4 100644 --- a/lib/mapObjects/CObjectClassesHandler.h +++ b/lib/mapObjects/CObjectClassesHandler.h @@ -5,6 +5,7 @@ #include "../GameConstants.h" #include "../ConstTransitivePtr.h" #include "../IHandlerBase.h" +#include "../JsonNode.h" /* * CObjectClassesHandler.h, part of VCMI engine @@ -64,7 +65,7 @@ public: walkersStrength(0) {} - bool operator <(const CArmyStructure & other) + bool operator <(const CArmyStructure & other) const { return this->totalStrength < other.totalStrength; } diff --git a/lib/mapObjects/CObjectHandler.cpp b/lib/mapObjects/CObjectHandler.cpp index a74eaaf74..b03980f8c 100644 --- a/lib/mapObjects/CObjectHandler.cpp +++ b/lib/mapObjects/CObjectHandler.cpp @@ -15,6 +15,9 @@ #include "../CGeneralTextHandler.h" #include "../CHeroHandler.h" #include "../CSoundBase.h" +#include "../filesystem/ResourceID.h" +#include "../IGameCallback.h" +#include "../CGameState.h" #include "CObjectClassesHandler.h" @@ -53,12 +56,6 @@ static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 showInfoDialog(playerID,txtID,soundID); } -static std::string & visitedTxt(const bool visited) -{ - int id = visited ? 352 : 353; - return VLC->generaltexth->allTexts[id]; -} - ///IObjectInterface void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const {} @@ -137,21 +134,11 @@ CGObjectInstance::CGObjectInstance(): } CGObjectInstance::~CGObjectInstance() { - //if (state) - // delete state; - //state=nullptr; } -const std::string & CGObjectInstance::getHoverText() const -{ - return hoverName; -} void CGObjectInstance::setOwner(PlayerColor ow) { - //if (state) - // state->owner = ow; - //else - tempOwner = ow; + tempOwner = ow; } int CGObjectInstance::getWidth() const//returns width of object graphic in tiles { @@ -203,29 +190,6 @@ std::set CGObjectInstance::getBlockedOffsets() const return ret; } - -bool CGObjectInstance::operator<(const CGObjectInstance & cmp) const //screen printing priority comparing -{ - if (appearance.printPriority != cmp.appearance.printPriority) - return appearance.printPriority > cmp.appearance.printPriority; - - if(pos.y != cmp.pos.y) - return pos.y < cmp.pos.y; - - if(cmp.ID==Obj::HERO && ID!=Obj::HERO) - return true; - if(cmp.ID!=Obj::HERO && ID==Obj::HERO) - return false; - - if(!isVisitable() && cmp.isVisitable()) - return true; - if(!cmp.isVisitable() && isVisitable()) - return false; - if(this->pos.xgameState()->map->getTile(visitablePos()); @@ -252,6 +216,8 @@ void CGObjectInstance::initObj() void CGObjectInstance::setProperty( ui8 what, ui32 val ) { + setPropertyDer(what, val); // call this before any actual changes (needed at least for dwellings) + switch(what) { case ObjProperty::OWNER: @@ -267,7 +233,6 @@ void CGObjectInstance::setProperty( ui8 what, ui32 val ) subID = val; break; } - setPropertyDer(what, val); } void CGObjectInstance::setPropertyDer( ui8 what, ui32 val ) @@ -275,41 +240,14 @@ void CGObjectInstance::setPropertyDer( ui8 what, ui32 val ) int3 CGObjectInstance::getSightCenter() const { - //return vistiable tile if possible - for(int i=0; i < 8; i++) - for(int j=0; j < 6; j++) - if(visitableAt(i,j)) - return(pos + int3(i-7, j-5, 0)); - return pos; + return visitablePos(); } int CGObjectInstance::getSightRadious() const { return 3; } -void CGObjectInstance::getSightTiles(std::unordered_set &tiles) const //returns reference to the set -{ - cb->getTilesInRange(tiles, getSightCenter(), getSightRadious(), tempOwner, 1); -} -void CGObjectInstance::hideTiles(PlayerColor ourplayer, int radius) const -{ - for (auto i = cb->gameState()->teams.begin(); i != cb->gameState()->teams.end(); i++) - { - if ( !vstd::contains(i->second.players, ourplayer ))//another team - { - for (auto & elem : i->second.players) - if ( cb->getPlayer(elem)->status == EPlayerStatus::INGAME )//seek for living player (if any) - { - FoWChange fw; - fw.mode = 0; - fw.player = elem; - cb->getTilesInRange (fw.tiles, pos, radius, (elem), -1); - cb->sendAndApply (&fw); - break; - } - } - } -} + int3 CGObjectInstance::getVisitableOffset() const { for(int y = 0; y < appearance.getHeight(); y++) @@ -321,17 +259,6 @@ int3 CGObjectInstance::getVisitableOffset() const return int3(0,0,0); } -void CGObjectInstance::getNameVis( std::string &hname ) const -{ - const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer()); - hname = VLC->objtypeh->getObjectName(ID); - if(h) - { - const bool visited = h->hasBonusFrom(Bonus::OBJECT,ID); - hname + " " + visitedTxt(visited); - } -} - void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) const { GiveBonus gbonus; @@ -343,6 +270,21 @@ void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) con cb->giveHeroBonus(&gbonus); } +std::string CGObjectInstance::getObjectName() const +{ + return VLC->objtypeh->getObjectName(ID); +} + +std::string CGObjectInstance::getHoverText(PlayerColor player) const +{ + return getObjectName(); +} + +std::string CGObjectInstance::getHoverText(const CGHeroInstance * hero) const +{ + return getHoverText(hero->tempOwner); +} + void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const { switch(ID) @@ -366,11 +308,6 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const } } -ui8 CGObjectInstance::getPassableness() const -{ - return 0; -} - int3 CGObjectInstance::visitablePos() const { return pos - getVisitableOffset(); @@ -383,7 +320,7 @@ bool CGObjectInstance::isVisitable() const bool CGObjectInstance::passableFor(PlayerColor color) const { - return getPassableness() & 1< &tiles) const; //returns reference to the set PlayerColor getOwner() const; void setOwner(PlayerColor ow); + + /** APPEARANCE ACCESSORS **/ + int getWidth() const; //returns width of object graphic in tiles int getHeight() const; //returns height of object graphic in tiles - virtual bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) (h3m pos) - virtual int3 getVisitableOffset() const; //returns (x,y,0) offset to first visitable tile from bottom right obj tile (0,0,0) (h3m pos) + bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) (h3m pos) int3 visitablePos() const; bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) (h3m pos) bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) (h3m pos) std::set getBlockedPos() const; //returns set of positions blocked by this object std::set getBlockedOffsets() const; //returns set of relative positions blocked by this object bool isVisitable() const; //returns true if object is visitable - bool operator<(const CGObjectInstance & cmp) const; //screen printing priority comparing - void hideTiles(PlayerColor ourplayer, int radius) const; - CGObjectInstance(); - virtual ~CGObjectInstance(); - //CGObjectInstance(const CGObjectInstance & right); - //CGObjectInstance& operator=(const CGObjectInstance & right); - virtual const std::string & getHoverText() const; + /** VIRTUAL METHODS **/ + + /// Returns true if player can pass through visitable tiles of this object + virtual bool passableFor(PlayerColor color) const; + /// Range of revealed map around this object, counting from getSightCenter() + virtual int getSightRadious() const; + /// returns (x,y,0) offset to a visitable tile of object + virtual int3 getVisitableOffset() const; + /// Called mostly during map randomization to turn random object into a regular one (e.g. "Random Monster" into "Pikeman") virtual void setType(si32 ID, si32 subID); - ///IObjectInterface + /// returns text visible in status bar with specific hero/player active. + + /// Returns generic name of object, without any player-specific info + virtual std::string getObjectName() const; + + /// Returns hover name for situation when there are no selected heroes. Default = object name + virtual std::string getHoverText(PlayerColor player) const; + /// Returns hero-specific hover name, including visited/not visited info. Default = player-specific name + virtual std::string getHoverText(const CGHeroInstance * hero) const; + + /** OVERRIDES OF IObjectInterface **/ + void initObj() override; void onHeroVisit(const CGHeroInstance * h) const override; - void setProperty(ui8 what, ui32 val) override;//synchr - - friend class CGameHandler; + /// method for synchronous update. Note: For new properties classes should override setPropertyDer instead + void setProperty(ui8 what, ui32 val) override final; + //friend class CGameHandler; template void serialize(Handler &h, const int version) { - h & hoverName & pos & ID & subID & id & tempOwner & blockVisit & appearance; + h & pos & ID & subID & id & tempOwner & blockVisit & appearance; //definfo is handled by map serializer } protected: - virtual void setPropertyDer(ui8 what, ui32 val);//synchr + /// virtual method that allows synchronously update object state on server and all clients + virtual void setPropertyDer(ui8 what, ui32 val); - void getNameVis(std::string &hname) const; + /// Gives dummy bonus from this object to hero. Can be used to track visited state void giveDummyBonus(ObjectInstanceID heroID, ui8 duration = Bonus::ONE_DAY) const; }; diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index c899b4071..ad301eb61 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -17,6 +17,8 @@ #include "../CGeneralTextHandler.h" #include "../CHeroHandler.h" #include "CObjectClassesHandler.h" +#include "../IGameCallback.h" +#include "../CGameState.h" using namespace boost::assign; @@ -434,25 +436,15 @@ void CGSeerHut::getRolloverText (MetaString &text, bool onHover) const text.addReplacement(seerName); } -const std::string & CGSeerHut::getHoverText() const +std::string CGSeerHut::getHoverText(PlayerColor player) const { - switch (ID) + std::string hoverName = getObjectName(); + if (ID == Obj::SEER_HUT && quest->progress != CQuest::NOT_ACTIVE) { - case Obj::SEER_HUT: - if (quest->progress != CQuest::NOT_ACTIVE) - { - hoverName = VLC->generaltexth->allTexts[347]; - boost::algorithm::replace_first(hoverName,"%s", seerName); - } - else //just seer hut - hoverName = VLC->objtypeh->getObjectName(ID); - break; - case Obj::QUEST_GUARD: - hoverName = VLC->objtypeh->getObjectName(ID); - break; - default: - logGlobal->debugStream() << "unrecognized quest object"; + hoverName = VLC->generaltexth->allTexts[347]; + boost::algorithm::replace_first(hoverName,"%s", seerName); } + if (quest->progress & quest->missionType) //rollover when the quest is active { MetaString ms; @@ -757,19 +749,14 @@ bool CGKeys::wasMyColorVisited (PlayerColor player) const return false; } -const std::string& CGKeys::getHoverText() const +std::string CGKeys::getHoverText(PlayerColor player) const { - bool visited = wasMyColorVisited (cb->getLocalPlayer()); - hoverName = getName() + "\n" + visitedTxt(visited); - return hoverName; + return getObjectName() + "\n" + visitedTxt(wasMyColorVisited(player)); } - -const std::string CGKeys::getName() const +std::string CGKeys::getObjectName() const { - std::string name; - name = VLC->generaltexth->tentColors[subID] + " " + VLC->objtypeh->getObjectName(ID); - return name; + return VLC->generaltexth->tentColors[subID] + " " + CGObjectInstance::getObjectName(); } bool CGKeymasterTent::wasVisited (PlayerColor player) const @@ -853,10 +840,7 @@ void CGBorderGate::onHeroVisit( const CGHeroInstance * h ) const //TODO: passabi } } -ui8 CGBorderGate::getPassableness() const +bool CGBorderGate::passableFor(PlayerColor color) const { - ui8 ret = 0; - for (int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++) - ret |= wasMyColorVisited(PlayerColor(i))< > playerKeyMap; //[players][keysowned] //SubID 0 - lightblue, 1 - green, 2 - red, 3 - darkblue, 4 - brown, 5 - purple, 6 - white, 7 - black - const std::string getName() const; //depending on color bool wasMyColorVisited (PlayerColor player) const; - const std::string & getHoverText() const override; + std::string getObjectName() const override; //depending on color + std::string getHoverText(PlayerColor player) const override; template void serialize(Handler &h, const int version) { @@ -189,7 +191,7 @@ public: CGBorderGate() : CGBorderGuard(){}; void onHeroVisit(const CGHeroInstance * h) const override; - ui8 getPassableness() const override; + bool passableFor(PlayerColor color) const override; template void serialize(Handler &h, const int version) { diff --git a/lib/mapObjects/CRewardableConstructor.cpp b/lib/mapObjects/CRewardableConstructor.cpp index e5b02e0c9..3835733b7 100644 --- a/lib/mapObjects/CRewardableConstructor.cpp +++ b/lib/mapObjects/CRewardableConstructor.cpp @@ -5,6 +5,7 @@ #include "../StringConstants.h" #include "../CCreatureHandler.h" #include "JsonRandom.h" +#include "../IGameCallback.h" /* * CRewardableConstructor.cpp, part of VCMI engine @@ -95,7 +96,8 @@ void CRandomRewardObjectInfo::configureObject(CRewardableObject * object, CRando info.reward.movePoints = JsonRandom::loadValue(reward["movePoints"], rng); info.reward.movePercentage = JsonRandom::loadValue(reward["movePercentage"], rng, -1); - info.reward.bonuses = JsonRandom::loadBonuses(reward["bonuses"]); + //FIXME: compile this line on Visual + //info.reward.bonuses = JsonRandom::loadBonuses(reward["bonuses"]); info.reward.primary = JsonRandom::loadPrimary(reward["primary"], rng); info.reward.secondary = JsonRandom::loadSecondary(reward["secondary"], rng); diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp index 5fc3731ff..4b8561e48 100644 --- a/lib/mapObjects/CRewardableObject.cpp +++ b/lib/mapObjects/CRewardableObject.cpp @@ -15,6 +15,8 @@ #include "../CGeneralTextHandler.h" #include "../CSoundBase.h" #include "../NetPacks.h" +#include "../IGameCallback.h" +#include "../CGameState.h" #include "CObjectClassesHandler.h" @@ -375,19 +377,18 @@ static std::string & visitedTxt(const bool visited) return VLC->generaltexth->allTexts[id]; } -const std::string & CRewardableObject::getHoverText() const +std::string CRewardableObject::getHoverText(PlayerColor player) const { - const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer()); - hoverName = VLC->objtypeh->getObjectName(ID); if(visitMode != VISIT_UNLIMITED) - { - bool visited = wasVisited(cb->getCurrentPlayer()); - if (h) - visited |= wasVisited(h); + return getObjectName() + " " + visitedTxt(wasVisited(player)); + return getObjectName(); +} - hoverName += " " + visitedTxt(visited); - } - return hoverName; +std::string CRewardableObject::getHoverText(const CGHeroInstance * hero) const +{ + if(visitMode != VISIT_UNLIMITED) + return getObjectName() + " " + visitedTxt(wasVisited(hero)); + return getObjectName(); } void CRewardableObject::setPropertyDer(ui8 what, ui32 val) diff --git a/lib/mapObjects/CRewardableObject.h b/lib/mapObjects/CRewardableObject.h index 8592f8a39..6ebc89b44 100644 --- a/lib/mapObjects/CRewardableObject.h +++ b/lib/mapObjects/CRewardableObject.h @@ -4,6 +4,7 @@ #include "CArmedInstance.h" #include "../NetPacksBase.h" +#include "../ResourceSet.h" /* * CRewardableObject.h, part of VCMI engine @@ -209,7 +210,8 @@ protected: public: void setPropertyDer(ui8 what, ui32 val) override; - const std::string & getHoverText() const override; + std::string getHoverText(PlayerColor player) const override; + std::string getHoverText(const CGHeroInstance * hero) const override; /// Visitability checks. Note that hero check includes check for hero owner (returns true if object was visited by player) bool wasVisited (PlayerColor player) const override; diff --git a/lib/mapObjects/CommonConstructors.cpp b/lib/mapObjects/CommonConstructors.cpp index 14f45fd9c..af259e564 100644 --- a/lib/mapObjects/CommonConstructors.cpp +++ b/lib/mapObjects/CommonConstructors.cpp @@ -8,6 +8,8 @@ #include "../CHeroHandler.h" #include "../CCreatureHandler.h" #include "JsonRandom.h" +#include "../CModHandler.h" +#include "../IGameCallback.h" /* * CommonConstructors.cpp, part of VCMI engine diff --git a/lib/mapObjects/JsonRandom.cpp b/lib/mapObjects/JsonRandom.cpp index 0e10fdbe5..88a5577d0 100644 --- a/lib/mapObjects/JsonRandom.cpp +++ b/lib/mapObjects/JsonRandom.cpp @@ -206,10 +206,12 @@ namespace JsonRandom return ret; } - std::vector loadComponents(const JsonNode & value) - { - //TODO - } + //std::vector loadComponents(const JsonNode & value) + //{ + // std::vector ret; + // return ret; + // //TODO + //} std::vector DLL_LINKAGE loadBonuses(const JsonNode & value) { diff --git a/lib/mapObjects/JsonRandom.h b/lib/mapObjects/JsonRandom.h index c809477d8..dad95988d 100644 --- a/lib/mapObjects/JsonRandom.h +++ b/lib/mapObjects/JsonRandom.h @@ -23,28 +23,28 @@ class CStackBasicDescriptor; namespace JsonRandom { - struct RandomStackInfo + struct DLL_LINKAGE RandomStackInfo { std::vector allowedCreatures; si32 minAmount; si32 maxAmount; }; - si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0); - TResources loadResources(const JsonNode & value, CRandomGenerator & rng); - std::vector loadPrimary(const JsonNode & value, CRandomGenerator & rng); - std::map loadSecondary(const JsonNode & value, CRandomGenerator & rng); + DLL_LINKAGE si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0); + DLL_LINKAGE TResources loadResources(const JsonNode & value, CRandomGenerator & rng); + DLL_LINKAGE std::vector loadPrimary(const JsonNode & value, CRandomGenerator & rng); + DLL_LINKAGE std::map loadSecondary(const JsonNode & value, CRandomGenerator & rng); - ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng); - std::vector loadArtifacts(const JsonNode & value, CRandomGenerator & rng); + DLL_LINKAGE ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng); + DLL_LINKAGE std::vector loadArtifacts(const JsonNode & value, CRandomGenerator & rng); - SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, std::vector spells); - std::vector loadSpells(const JsonNode & value, CRandomGenerator & rng, std::vector spells); + DLL_LINKAGE SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, std::vector spells); + DLL_LINKAGE std::vector loadSpells(const JsonNode & value, CRandomGenerator & rng, std::vector spells); - CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng); - std::vector loadCreatures(const JsonNode & value, CRandomGenerator & rng); - std::vector evaluateCreatures(const JsonNode & value); + DLL_LINKAGE CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng); + DLL_LINKAGE std::vector loadCreatures(const JsonNode & value, CRandomGenerator & rng); + DLL_LINKAGE std::vector evaluateCreatures(const JsonNode & value); - std::vector DLL_LINKAGE loadBonuses(const JsonNode & value); - std::vector loadComponents(const JsonNode & value); + DLL_LINKAGE std::vector loadBonuses(const JsonNode & value); + //DLL_LINKAGE std::vector loadComponents(const JsonNode & value); } diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 4fbfade1b..d5e9fa2d8 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -14,9 +14,12 @@ #include "../NetPacks.h" #include "../CGeneralTextHandler.h" #include "../CSoundBase.h" +#include "../CModHandler.h" #include "CObjectClassesHandler.h" #include "../CSpellHandler.h" +#include "../IGameCallback.h" +#include "../CGameState.h" using namespace boost::assign; @@ -78,17 +81,16 @@ bool CPlayersVisited::wasVisited( TeamID team ) const return false; } -const std::string & CGCreature::getHoverText() const +std::string CGCreature::getHoverText(PlayerColor player) const { if(stacks.empty()) { - static const std::string errorValue("!!!INVALID_STACK!!!"); - //should not happen... logGlobal->errorStream() << "Invalid stack at tile " << pos << ": subID=" << subID << "; id=" << id; - return errorValue; // references to temporary are illegal - use pre-constructed string + return "!!!INVALID_STACK!!!"; } + std::string hoverName; MetaString ms; int pom = stacks.begin()->second->getQuantityID(); pom = 172 + 3*pom; @@ -96,30 +98,34 @@ const std::string & CGCreature::getHoverText() const ms << " " ; ms.addTxt(MetaString::CRE_PL_NAMES,subID); ms.toString(hoverName); - - if(const CGHeroInstance *selHero = cb->getSelectedHero(cb->getCurrentPlayer())) - { - const JsonNode & texts = VLC->generaltexth->localizedTexts["adventureMap"]["monsterThreat"]; - - hoverName += texts["title"].String(); - int choice; - double ratio = ((double)getArmyStrength() / selHero->getTotalStrength()); - if (ratio < 0.1) choice = 0; - else if (ratio < 0.25) choice = 1; - else if (ratio < 0.6) choice = 2; - else if (ratio < 0.9) choice = 3; - else if (ratio < 1.1) choice = 4; - else if (ratio < 1.3) choice = 5; - else if (ratio < 1.8) choice = 6; - else if (ratio < 2.5) choice = 7; - else if (ratio < 4) choice = 8; - else if (ratio < 8) choice = 9; - else if (ratio < 20) choice = 10; - else choice = 11; - hoverName += texts["levels"].Vector()[choice].String(); - } return hoverName; } + +std::string CGCreature::getHoverText(const CGHeroInstance * hero) const +{ + std::string hoverName = getHoverText(hero->tempOwner); + + const JsonNode & texts = VLC->generaltexth->localizedTexts["adventureMap"]["monsterThreat"]; + + hoverName += texts["title"].String(); + int choice; + double ratio = ((double)getArmyStrength() / hero->getTotalStrength()); + if (ratio < 0.1) choice = 0; + else if (ratio < 0.25) choice = 1; + else if (ratio < 0.6) choice = 2; + else if (ratio < 0.9) choice = 3; + else if (ratio < 1.1) choice = 4; + else if (ratio < 1.3) choice = 5; + else if (ratio < 1.8) choice = 6; + else if (ratio < 2.5) choice = 7; + else if (ratio < 4) choice = 8; + else if (ratio < 8) choice = 9; + else if (ratio < 20) choice = 10; + else choice = 11; + hoverName += texts["levels"].Vector()[choice].String(); + return hoverName; +} + void CGCreature::onHeroVisit( const CGHeroInstance * h ) const { int action = takenAction(h); @@ -443,21 +449,6 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult & } else { - //int killedAmount=0; - //for(std::set >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++) - // if(i->first == subID) - // killedAmount += i->second; - //cb->setAmount(id, slots.find(0)->second.second - killedAmount); - - /* - MetaString ms; - int pom = slots.find(0)->second.getQuantityID(); - pom = 174 + 3*pom + 1; - ms << std::pair(6,pom) << " " << std::pair(7,subID); - cb->setHoverName(id,&ms); - cb->setObjProperty(id, 11, slots.begin()->second.count * 1000); - */ - //merge stacks into one TSlots::const_iterator i; CCreature * cre = VLC->creh->creatures[formation.basicType]; @@ -554,38 +545,48 @@ void CGMine::initObj() assert(!possibleResources.empty()); producedResource = *RandomGeneratorUtil::nextItem(possibleResources, cb->gameState()->getRandomGenerator()); tempOwner = PlayerColor::NEUTRAL; - hoverName = VLC->generaltexth->mines[7].first + "\n" + VLC->generaltexth->allTexts[202] + " " + troglodytes->getQuantityTXT(false) + " " + troglodytes->type->namePl; } else { producedResource = static_cast(subID); - - MetaString ms; - ms << std::pair(9,producedResource); if(tempOwner >= PlayerColor::PLAYER_LIMIT) tempOwner = PlayerColor::NEUTRAL; - else - ms << " (" << std::pair(6,23+tempOwner.getNum()) << ")"; - ms.toString(hoverName); } producedQuantity = defaultResProduction(); } +std::string CGMine::getObjectName() const +{ + return VLC->generaltexth->mines.at(subID).first; +} + +std::string CGMine::getHoverText(PlayerColor player) const +{ + + std::string hoverName = getObjectName(); // Sawmill + + if (tempOwner != PlayerColor::NEUTRAL) + { + hoverName += "\n"; + hoverName += VLC->generaltexth->arraytxt[23 + tempOwner.getNum()]; // owned by Red Player + hoverName += "\n(" + VLC->generaltexth->restypes[producedResource] + ")"; + } + + for (auto & slot : Slots()) // guarded by a few Pikeman + { + hoverName += "\n"; + hoverName += getRoughAmount(slot.first); + hoverName += getCreature(slot.first)->namePl; + } + return hoverName; +} + void CGMine::flagMine(PlayerColor player) const { assert(tempOwner != player); cb->setOwner(this, player); //not ours? flag it! - MetaString ms; - ms << std::pair(9,subID) << "\n(" << std::pair(6,23+player.getNum()) << ")"; - if(subID == 7) - { - ms << "(%s)"; - ms.addReplacement(MetaString::RES_NAMES, producedResource); - } - cb->setHoverName(this,&ms); - InfoWindow iw; iw.soundID = soundBase::FLAGMINE; iw.text.addTxt(MetaString::MINE_EVNTS,producedResource); //not use subID, abandoned mines uses default mine texts @@ -626,10 +627,14 @@ void CGMine::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) con cb->startBattleI(hero, this); } +std::string CGResource::getHoverText(PlayerColor player) const +{ + return VLC->generaltexth->restypes[subID]; +} + void CGResource::initObj() { blockVisit = true; - hoverName = VLC->generaltexth->restypes[subID]; if(!amount) { @@ -866,7 +871,6 @@ void CGArtifact::initObj() blockVisit = true; if(ID == Obj::ARTIFACT) { - hoverName = VLC->arth->artifacts[subID]->Name(); if(!storedArtifact->artType) storedArtifact->setType(VLC->arth->artifacts[subID]); } @@ -879,6 +883,11 @@ void CGArtifact::initObj() //assert(storedArtifact->artType->id == subID); //this does not stop desync } +std::string CGArtifact::getObjectName() const +{ + return VLC->arth->artifacts[subID]->Name(); +} + void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const { if(!stacksCount()) @@ -985,20 +994,25 @@ void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const cb->showInfoDialog(&iw); } -const std::string & CGWitchHut::getHoverText() const +std::string CGWitchHut::getHoverText(PlayerColor player) const { - hoverName = VLC->objtypeh->getObjectName(ID); - if(wasVisited(cb->getLocalPlayer())) + std::string hoverName = getObjectName(); + if(wasVisited(player)) { hoverName += "\n" + VLC->generaltexth->allTexts[356]; // + (learn %s) boost::algorithm::replace_first(hoverName,"%s",VLC->generaltexth->skillName[ability]); - const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer()); - if(h && h->getSecSkillLevel(SecondarySkill(ability))) //hero knows that ability - hoverName += "\n\n" + VLC->generaltexth->allTexts[357]; // (Already learned) } return hoverName; } +std::string CGWitchHut::getHoverText(const CGHeroInstance * hero) const +{ + std::string hoverName = getHoverText(hero->tempOwner); + if(hero->getSecSkillLevel(SecondarySkill(ability))) //hero knows that ability + hoverName += "\n\n" + VLC->generaltexth->allTexts[357]; // (Already learned) + return hoverName; +} + void CGMagicWell::onHeroVisit( const CGHeroInstance * h ) const { int message; @@ -1020,10 +1034,9 @@ void CGMagicWell::onHeroVisit( const CGHeroInstance * h ) const showInfoDialog(h,message,soundBase::faerie); } -const std::string & CGMagicWell::getHoverText() const +std::string CGMagicWell::getHoverText(const CGHeroInstance * hero) const { - getNameVis(hoverName); - return hoverName; + return getObjectName() + " " + visitedTxt(hero->hasBonusFrom(Bonus::OBJECT,ID)); } void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const @@ -1048,7 +1061,12 @@ void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const case Obj::COVER_OF_DARKNESS: { iw.text.addTxt (MetaString::ADVOB_TXT, 31); - hideTiles(h->tempOwner, 20); + for (auto player : cb->gameState()->players) + { + if (cb->getPlayerStatus(player.first) == EPlayerStatus::INGAME && + cb->getPlayerRelations(player.first, h->tempOwner) == PlayerRelations::ENEMIES) + cb->changeFogOfWar(visitablePos(), 20, player.first, true); + } break; } } @@ -1115,20 +1133,25 @@ void CGShrine::initObj() } } -const std::string & CGShrine::getHoverText() const +std::string CGShrine::getHoverText(PlayerColor player) const { - hoverName = VLC->objtypeh->getObjectName(ID); - if(wasVisited(cb->getCurrentPlayer())) //TODO: use local player, not current + std::string hoverName = getObjectName(); + if(wasVisited(player)) { hoverName += "\n" + VLC->generaltexth->allTexts[355]; // + (learn %s) boost::algorithm::replace_first(hoverName,"%s", spell.toSpell()->name); - const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer()); - if(h && vstd::contains(h->spells,spell)) //hero knows that ability - hoverName += "\n\n" + VLC->generaltexth->allTexts[354]; // (Already learned) } return hoverName; } +std::string CGShrine::getHoverText(const CGHeroInstance * hero) const +{ + std::string hoverName = getHoverText(hero->tempOwner); + if(vstd::contains(hero->spells, spell)) //hero knows that spell + hoverName += "\n\n" + VLC->generaltexth->allTexts[354]; // (Already learned) + return hoverName; +} + void CGSignBottle::initObj() { //if no text is set than we pick random from the predefined ones @@ -1250,19 +1273,18 @@ void CGGarrison::onHeroVisit (const CGHeroInstance *h) const cb->showGarrisonDialog(id, h->id, removableUnits); } -ui8 CGGarrison::getPassableness() const +bool CGGarrison::passableFor(PlayerColor player) const { + //FIXME: identical to same method in CGTownInstance + if ( !stacksCount() )//empty - anyone can visit - return GameConstants::ALL_PLAYERS; + return true; if ( tempOwner == PlayerColor::NEUTRAL )//neutral guarded - no one can visit - return 0; + return false; - ui8 mask = 0; - TeamState * ts = cb->gameState()->getPlayerTeam(tempOwner); - for(PlayerColor it : ts->players) - mask |= 1<getPlayerRelations(tempOwner, player) != PlayerRelations::ENEMIES) + return true; + return false; } void CGGarrison::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const @@ -1325,10 +1347,9 @@ void CGSirens::initObj() blockVisit = true; } -const std::string & CGSirens::getHoverText() const +std::string CGSirens::getHoverText(const CGHeroInstance * hero) const { - getNameVis(hoverName); - return hoverName; + return getObjectName() + " " + visitedTxt(hero->hasBonusFrom(Bonus::OBJECT,ID)); } void CGSirens::onHeroVisit( const CGHeroInstance * h ) const @@ -1499,11 +1520,9 @@ void CGObelisk::initObj() obeliskCount++; } -const std::string & CGObelisk::getHoverText() const +std::string CGObelisk::getHoverText(PlayerColor player) const { - bool visited = wasVisited(cb->getLocalPlayer()); - hoverName = VLC->objtypeh->getObjectName(ID) + " " + visitedTxt(visited); - return hoverName; + return getObjectName() + " " + visitedTxt(wasVisited(player)); } void CGObelisk::setPropertyDer( ui8 what, ui32 val ) @@ -1553,11 +1572,10 @@ void CGLighthouse::initObj() } } -const std::string & CGLighthouse::getHoverText() const +std::string CGLighthouse::getHoverText(PlayerColor player) const { - hoverName = VLC->objtypeh->getObjectName(ID); //TODO: owned by %s player - return hoverName; + return getObjectName(); } void CGLighthouse::giveBonusTo( PlayerColor player ) const diff --git a/lib/mapObjects/MiscObjects.h b/lib/mapObjects/MiscObjects.h index c53db75d7..ca1601c6a 100644 --- a/lib/mapObjects/MiscObjects.h +++ b/lib/mapObjects/MiscObjects.h @@ -2,6 +2,7 @@ #include "CObjectHandler.h" #include "CArmedInstance.h" +#include "../ResourceSet.h" /* * MiscObjects.h, part of VCMI engine @@ -48,7 +49,8 @@ public: bool refusedJoining; void onHeroVisit(const CGHeroInstance * h) const override; - const std::string & getHoverText() const override; + std::string getHoverText(PlayerColor player) const override; + std::string getHoverText(const CGHeroInstance * hero) const override; void initObj() override; void newTurn() const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; @@ -106,7 +108,8 @@ public: std::vector allowedAbilities; ui32 ability; - const std::string & getHoverText() const override; + std::string getHoverText(PlayerColor player) const override; + std::string getHoverText(const CGHeroInstance * hero) const override; void onHeroVisit(const CGHeroInstance * h) const override; void initObj() override; template void serialize(Handler &h, const int version) @@ -138,7 +141,7 @@ class DLL_LINKAGE CGGarrison : public CArmedInstance public: bool removableUnits; - ui8 getPassableness() const; + bool passableFor(PlayerColor color) const override; void onHeroVisit(const CGHeroInstance * h) const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; @@ -159,6 +162,8 @@ public: void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; + std::string getObjectName() const override; + void pick( const CGHeroInstance * h ) const; void initObj() override; @@ -179,6 +184,7 @@ public: void initObj() override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; + std::string getHoverText(PlayerColor player) const override; void collectRes(PlayerColor player) const; @@ -195,7 +201,8 @@ public: SpellID spell; //id of spell or NONE if random void onHeroVisit(const CGHeroInstance * h) const override; void initObj() override; - const std::string & getHoverText() const override; + std::string getHoverText(PlayerColor player) const override; + std::string getHoverText(const CGHeroInstance * hero) const override; template void serialize(Handler &h, const int version) { @@ -217,6 +224,10 @@ public: void flagMine(PlayerColor player) const; void newTurn() const override; void initObj() override; + + std::string getObjectName() const override; + std::string getHoverText(PlayerColor player) const override; + template void serialize(Handler &h, const int version) { h & static_cast(*this); @@ -245,7 +256,7 @@ class DLL_LINKAGE CGMagicWell : public CGObjectInstance //objects giving bonuses { public: void onHeroVisit(const CGHeroInstance * h) const override; - const std::string & getHoverText() const override; + std::string getHoverText(const CGHeroInstance * hero) const override; template void serialize(Handler &h, const int version) { @@ -257,7 +268,7 @@ class DLL_LINKAGE CGSirens : public CGObjectInstance { public: void onHeroVisit(const CGHeroInstance * h) const override; - const std::string & getHoverText() const override; + std::string getHoverText(const CGHeroInstance * hero) const override; void initObj() override; template void serialize(Handler &h, const int version) @@ -352,7 +363,7 @@ public: void onHeroVisit(const CGHeroInstance * h) const override; void initObj() override; - const std::string & getHoverText() const override; + std::string getHoverText(PlayerColor player) const override; template void serialize(Handler &h, const int version) { @@ -367,7 +378,7 @@ class DLL_LINKAGE CGLighthouse : public CGObjectInstance public: void onHeroVisit(const CGHeroInstance * h) const override; void initObj() override; - const std::string & getHoverText() const override; + std::string getHoverText(PlayerColor player) const override; template void serialize(Handler &h, const int version) { diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 15e66c26e..1d53f8d88 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -432,7 +432,7 @@ const CGObjectInstance * CMap::getObjectiveObjectFrom(int3 pos, Obj::EObj type) } assert(bestMatch != nullptr); // if this happens - victory conditions or map itself is very, very broken - logGlobal->errorStream() << "Will use " << bestMatch->getHoverText() << " from " << bestMatch->pos; + logGlobal->errorStream() << "Will use " << bestMatch->getObjectName() << " from " << bestMatch->pos; return bestMatch; } diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index f064cc70a..5e7694528 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -1063,56 +1063,6 @@ void CMapLoaderH3M::readObjects() nobj = readHero(idToBeGiven); break; } - case Obj::ARENA: - case Obj::MERCENARY_CAMP: - case Obj::MARLETTO_TOWER: - case Obj::STAR_AXIS: - case Obj::GARDEN_OF_REVELATION: - case Obj::LEARNING_STONE: - case Obj::TREE_OF_KNOWLEDGE: - case Obj::LIBRARY_OF_ENLIGHTENMENT: - case Obj::SCHOOL_OF_MAGIC: - case Obj::SCHOOL_OF_WAR: - { - nobj = new CGVisitableOPH(); - break; - } - case Obj::MYSTICAL_GARDEN: - case Obj::WINDMILL: - case Obj::WATER_WHEEL: - { - nobj = new CGVisitableOPW(); - break; - } - case Obj::MONOLITH_ONE_WAY_ENTRANCE: - case Obj::MONOLITH_ONE_WAY_EXIT: - case Obj::MONOLITH_TWO_WAY: - case Obj::SUBTERRANEAN_GATE: - case Obj::WHIRLPOOL: - { - nobj = new CGTeleport(); - break; - } - case Obj::CAMPFIRE: - case Obj::FLOTSAM: - case Obj::SEA_CHEST: - case Obj::SHIPWRECK_SURVIVOR: - { - nobj = new CGPickable(); - break; - } - case Obj::TREASURE_CHEST: - if(objTempl.subid == 0) - { - nobj = new CGPickable(); - } - else - { - //WoG pickable object - //TODO: possible special handling - nobj = new CGObjectInstance(); - } - break; case Obj::MONSTER: //Monster case Obj::RANDOM_MONSTER: case Obj::RANDOM_MONSTER_L1: @@ -1330,12 +1280,6 @@ void CMapLoaderH3M::readObjects() reader.skip(3); break; } - case Obj::REFUGEE_CAMP: - case Obj::WAR_MACHINE_FACTORY: - { - nobj = new CGDwelling(); - break; - } case Obj::SHRINE_OF_MAGIC_INCANTATION: case Obj::SHRINE_OF_MAGIC_GESTURE: case Obj::SHRINE_OF_MAGIC_THOUGHT: @@ -1458,52 +1402,6 @@ void CMapLoaderH3M::readObjects() nobj = guard; break; } - case Obj::FAERIE_RING: - case Obj::SWAN_POND: - case Obj::IDOL_OF_FORTUNE: - case Obj::FOUNTAIN_OF_FORTUNE: - case Obj::RALLY_FLAG: - case Obj::OASIS: - case Obj::TEMPLE: - case Obj::WATERING_HOLE: - case Obj::FOUNTAIN_OF_YOUTH: - case Obj::BUOY: - case Obj::MERMAID: - case Obj::STABLES: - { - nobj = new CGBonusingObject(); - break; - } - case Obj::MAGIC_WELL: - { - nobj = new CGMagicWell(); - break; - } - case Obj::COVER_OF_DARKNESS: - case Obj::REDWOOD_OBSERVATORY: - case Obj::PILLAR_OF_FIRE: - { - nobj = new CGObservatory(); - break; - } - case Obj::CORPSE: - case Obj::LEAN_TO: - case Obj::WAGON: - case Obj::WARRIORS_TOMB: - { - nobj = new CGOnceVisitable(); - break; - } - case Obj::BOAT: - { - nobj = new CGBoat(); - break; - } - case Obj::SIRENS: - { - nobj = new CGSirens(); - break; - } case Obj::SHIPYARD: { nobj = new CGShipyard(); @@ -1531,11 +1429,6 @@ void CMapLoaderH3M::readObjects() hp->power = 0; } - break; - } - case Obj::KEYMASTER: - { - nobj = new CGKeymasterTent(); break; } case Obj::BORDERGUARD: @@ -1550,21 +1443,6 @@ void CMapLoaderH3M::readObjects() map->addQuest (nobj); break; } - case Obj::EYE_OF_MAGI: - case Obj::HUT_OF_MAGI: - { - nobj = new CGMagi(); - break; - } - case Obj::CREATURE_BANK: - case Obj::DERELICT_SHIP: - case Obj::DRAGON_UTOPIA: - case Obj::CRYPT: - case Obj::SHIPWRECK: - { - nobj = new CBank(); - break; - } case Obj::PYRAMID: //Pyramid of WoG object { if(objTempl.subid == 0) @@ -1579,53 +1457,24 @@ void CMapLoaderH3M::readObjects() } break; } - case Obj::CARTOGRAPHER: - { - nobj = new CCartographer(); - break; - } - case Obj::MAGIC_SPRING: - { - nobj = new CGMagicSpring(); - break; - } - case Obj::DEN_OF_THIEVES: - { - nobj = new CGDenOfthieves(); - break; - } - case Obj::OBELISK: - { - nobj = new CGObelisk(); - break; - } case Obj::LIGHTHOUSE: //Lighthouse { nobj = new CGLighthouse(); nobj->tempOwner = PlayerColor(reader.readUInt32()); break; } - case Obj::ALTAR_OF_SACRIFICE: - case Obj::TRADING_POST: - case Obj::FREELANCERS_GUILD: - case Obj::TRADING_POST_SNOW: - { - nobj = new CGMarket(); - break; - } - case Obj::UNIVERSITY: - { - nobj = new CGUniversity(); - break; - } - case Obj::BLACK_MARKET: - { - nobj = new CGBlackMarket(); - break; - } default: //any other object { - nobj = new CGObjectInstance(); + if (VLC->objtypeh->knownSubObjects(objTempl.id).count(objTempl.subid)) + { + nobj = VLC->objtypeh->getHandlerFor(objTempl.id, objTempl.subid)->create(objTempl); + } + else + { + logGlobal->warnStream() << "Unrecognized object: " << objTempl.id << ":" << objTempl.subid << " at " << objPos + << " on map " << map->name; + nobj = new CGObjectInstance(); + } break; } } diff --git a/lib/registerTypes/RegisterTypes.h b/lib/registerTypes/RegisterTypes.h index dd7467108..8bf37da4d 100644 --- a/lib/registerTypes/RegisterTypes.h +++ b/lib/registerTypes/RegisterTypes.h @@ -12,6 +12,7 @@ #include "../mapObjects/CRewardableConstructor.h" #include "../mapObjects/CommonConstructors.h" #include "../mapObjects/MapObjects.h" +#include "../CObstacleInstance.h" /* * RegisterTypes.h, part of VCMI engine @@ -234,7 +235,6 @@ void registerTypesClientPacks1(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); - s.template registerType(); s.template registerType(); s.template registerType(); s.template registerType(); diff --git a/scripting/erm/ERMInterpreter.cpp b/scripting/erm/ERMInterpreter.cpp index 8abd3096d..fde6c8a13 100644 --- a/scripting/erm/ERMInterpreter.cpp +++ b/scripting/erm/ERMInterpreter.cpp @@ -2,8 +2,8 @@ #include "ERMInterpreter.h" #include -#include "../../lib/mapObjects/CObjectHandler.h" -#include "../../lib/mapObjects/MapObjects.h" +#include "../../lib/mapObjects/CObjectHandler.h" +#include "../../lib/mapObjects/MapObjects.h" #include "../../lib/CHeroHandler.h" #include "../../lib/CCreatureHandler.h" #include "../../lib/VCMIDirs.h" diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 98255ea42..93bcbc02b 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1351,9 +1351,13 @@ void CGameHandler::newTurn() } if (t->hasBonusOfType (Bonus::DARKNESS)) { - t->hideTiles(t->getOwner(), t->getBonusLocalFirst(Selector::type(Bonus::DARKNESS))->val); + for (auto player : gameState()->players) + { + if (getPlayerStatus(player.first) == EPlayerStatus::INGAME && + getPlayerRelations(player.first, t->tempOwner) == PlayerRelations::ENEMIES) + changeFogOfWar(t->visitablePos(), t->getBonusLocalFirst(Selector::type(Bonus::DARKNESS))->val, player.first, true); + } } - //unhiding what shouldn't be hidden? //that's handled in netpacks client } if(newMonth) @@ -1845,12 +1849,6 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, PlayerColor owner) } } -void CGameHandler::setHoverName(const CGObjectInstance * obj, MetaString* name) -{ - SetHoverName shn(obj->id, *name); - sendAndApply(&shn); -} - void CGameHandler::showBlockingDialog( BlockingDialog *iw ) { auto dialogQuery = make_shared(*iw); @@ -2523,7 +2521,7 @@ bool CGameHandler::buildStructure( ObjectInstanceID tid, BuildingID requestedID, FoWChange fw; fw.player = t->tempOwner; fw.mode = 1; - t->getSightTiles(fw.tiles); + getTilesInRange(fw.tiles, t->getSightCenter(), t->getSightRadious(), t->tempOwner, 1); sendAndApply(&fw); if(t->visitingHero) @@ -4988,7 +4986,7 @@ bool CGameHandler::isAllowedExchange( ObjectInstanceID id1, ObjectInstanceID id2 void CGameHandler::objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h ) { - logGlobal->traceStream() << h->nodeName() << " visits " << obj->getHoverText(); + logGlobal->debugStream() << h->nodeName() << " visits " << obj->getObjectName() << "(" << obj->ID << ":" << obj->subID << ")"; auto visitQuery = make_shared(obj, h, obj->visitablePos()); queries.addQuery(visitQuery); //TODO real visit pos @@ -5227,7 +5225,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player) } } -void CGameHandler::getVictoryLossMessage(PlayerColor player, EVictoryLossCheckResult victoryLossCheckResult, InfoWindow & out) const +void CGameHandler::getVictoryLossMessage(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult, InfoWindow & out) const { out.player = player; out.text.clear(); @@ -6252,6 +6250,22 @@ void CGameHandler::removeAfterVisit(const CGObjectInstance *object) assert("This function needs to be called during the object visit!"); } +void CGameHandler::changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) +{ + std::unordered_set tiles; + getTilesInRange(tiles, center, radius, player, hide? -1 : 1); + changeFogOfWar(tiles, player, hide); +} + +void CGameHandler::changeFogOfWar(std::unordered_set &tiles, PlayerColor player, bool hide) +{ + FoWChange fow; + fow.tiles = tiles; + fow.player = player; + fow.mode = hide? 0 : 1; + sendAndApply(&fow); +} + bool CGameHandler::isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) { if(auto topQuery = queries.topQuery(hero->getOwner())) diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 36798d519..1a3791522 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -127,7 +127,6 @@ public: bool removeObject(const CGObjectInstance * obj) override; void setBlockVis(ObjectInstanceID objid, bool bv) override; void setOwner(const CGObjectInstance * obj, PlayerColor owner) override; - void setHoverName(const CGObjectInstance * objid, MetaString * name) override; void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs=false) override; void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) override; //void showInfoDialog(InfoWindow *iw) override; @@ -174,6 +173,8 @@ public: void changeObjPos(ObjectInstanceID objid, int3 newPos, ui8 flags) override; void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override; + void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override; + void changeFogOfWar(std::unordered_set &tiles, PlayerColor player, bool hide) override; bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) override; @@ -289,7 +290,7 @@ public: private: std::list generatePlayerTurnOrder() const; void makeStackDoNothing(const CStack * next); - void getVictoryLossMessage(PlayerColor player, EVictoryLossCheckResult victoryLossCheckResult, InfoWindow & out) const; + void getVictoryLossMessage(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult, InfoWindow & out) const; // Check for victory and loss conditions void checkVictoryLossConditionsForPlayer(PlayerColor player); diff --git a/server/CQuery.cpp b/server/CQuery.cpp index e7ecb0355..45bffae79 100644 --- a/server/CQuery.cpp +++ b/server/CQuery.cpp @@ -322,7 +322,7 @@ CHeroLevelUpDialogQuery::CHeroLevelUpDialogQuery(const HeroLevelUp &Hlu) void CHeroLevelUpDialogQuery::onRemoval(CGameHandler *gh, PlayerColor color) { assert(answer); - logGlobal->traceStream() << "Completing hero level-up query. " << hlu.hero->getHoverText() << " gains skill " << *answer; + logGlobal->traceStream() << "Completing hero level-up query. " << hlu.hero->getObjectName() << " gains skill " << *answer; gh->levelUpHero(hlu.hero, hlu.skills[*answer]); } @@ -340,7 +340,7 @@ CCommanderLevelUpDialogQuery::CCommanderLevelUpDialogQuery(const CommanderLevelU void CCommanderLevelUpDialogQuery::onRemoval(CGameHandler *gh, PlayerColor color) { assert(answer); - logGlobal->traceStream() << "Completing commander level-up query. Commander of hero " << clu.hero->getHoverText() << " gains skill " << *answer; + logGlobal->traceStream() << "Completing commander level-up query. Commander of hero " << clu.hero->getObjectName() << " gains skill " << *answer; gh->levelUpCommander(clu.hero->commander, clu.skills[*answer]); }