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

Merge branch 'develop' into SDL2

Conflicts:
	client/CPlayerInterface.cpp
This commit is contained in:
AlexVinS 2014-07-02 17:15:12 +04:00
commit 195eae48ca
98 changed files with 1629 additions and 1143 deletions

View File

@ -1,6 +1,7 @@
#include "StdInc.h"
#include "AIUtility.h"
#include "VCAI.h"
#include "Fuzzy.h"
#include "../../lib/UnlockGuard.h"
#include "../../lib/CConfigHandler.h"

View File

@ -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<std::string>(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))

View File

@ -1,4 +1,2 @@
#pragma once
#include "../../Global.h"
#include "Fuzzy.h"

View File

@ -1,10 +1,13 @@
#include "StdInc.h"
#include "VCAI.h"
#include "Goals.h"
#include "Fuzzy.h"
#include "../../lib/UnlockGuard.h"
#include "../../lib/mapObjects/MapObjects.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/CModHandler.h"
/*
@ -81,7 +84,7 @@ struct ObjInfo
ObjInfo(){}
ObjInfo(const CGObjectInstance *obj):
pos(obj->pos),
name(obj->getHoverText())
name(obj->getObjectName())
{
}
};
@ -195,7 +198,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 +244,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 +783,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 +1437,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 +1471,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)

View File

@ -14,7 +14,7 @@ endif()
# VCMI version
set(VCMI_VERSION_MAJOR 0)
set(VCMI_VERSION_MINOR 95)
set(VCMI_VERSION_MINOR 96)
set(VCMI_VERSION_PATCH 0)
option(ENABLE_ERM "Enable compilation of ERM scripting module" OFF)

View File

@ -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 <modname>/Mods directory
* Mods may provide their own changelogs and screenshots that will be visible in Launcher

View File

@ -152,9 +152,11 @@ typedef boost::lock_guard<boost::recursive_mutex> TLockGuardRec;
# else
# define DLL_EXPORT __declspec(dllexport)
# endif
# define ELF_VISIBILITY
#else
# ifdef __GNUC__
# define DLL_EXPORT __attribute__ ((visibility("default")))
# define ELF_VISIBILITY __attribute__ ((visibility("default")))
# endif
#endif
@ -164,9 +166,11 @@ typedef boost::lock_guard<boost::recursive_mutex> 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

View File

View File

@ -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):

View File

@ -1130,17 +1130,19 @@ void CAdvMapInt::endingTurn()
LOCPLINT->cb->endTurn();
}
const CGObjectInstance* CAdvMapInt::getBlockingObject(const int3 &mapPos)
const CGObjectInstance* CAdvMapInt::getActiveObject(const int3 &mapPos)
{
std::vector < const CGObjectInstance * > bobjs = LOCPLINT->cb->getBlockingObjs(mapPos); //blocking objects at tile
if (bobjs.empty())
return nullptr;
return *boost::range::max_element(bobjs, &CMapHandler::compareObjectBlitOrder);
/*
if (bobjs.back()->ID == Obj::HERO)
return bobjs.back();
else
return bobjs.front();
return bobjs.front();*/
}
void CAdvMapInt::tileLClicked(const int3 &mapPos)
@ -1150,7 +1152,7 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
const TerrainTile *tile = LOCPLINT->cb->getTile(mapPos);
const CGObjectInstance *topBlocking = getBlockingObject(mapPos);
const CGObjectInstance *topBlocking = getActiveObject(mapPos);
int3 selPos = selection->getSightCenter();
if(spellBeingCasted && isInScreenRange(selPos, mapPos))
@ -1235,12 +1237,11 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
statusbar.clear();
return;
}
const CGObjectInstance *objAtTile = getBlockingObject(mapPos);
const CGObjectInstance *objAtTile = getActiveObject(mapPos);
//std::vector<std::string> 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);
}
@ -1436,7 +1437,7 @@ void CAdvMapInt::tileRClicked(const int3 &mapPos)
return;
}
const CGObjectInstance * obj = getBlockingObject(mapPos);
const CGObjectInstance * obj = getActiveObject(mapPos);
if(!obj)
{
// Bare or undiscovered terrain

View File

@ -85,8 +85,8 @@ public:
/// can get to the towns and heroes.
class CAdvMapInt : public CIntObject
{
//get top selectable object at tile
const CGObjectInstance *getBlockingObject(const int3 &tile);
//Return object that must be active at this tile (=clickable)
const CGObjectInstance *getActiveObject(const int3 &tile);
public:
CAdvMapInt();

View File

@ -500,7 +500,7 @@ void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInst
OwnedObjectInfo &info = visibleObjects[object->subID];
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::vector<const CGObjectInst
OwnedObjectInfo &info = visibleObjects[iter->second];
if (info.count++ == 0)
{
info.hoverText = object->hoverName;
info.hoverText = object->getObjectName();
info.imageID = iter->second;
}
}

View File

@ -627,7 +627,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";

View File

@ -91,15 +91,10 @@ CondSh<EMoveState> stillMoveHero; //used during hero movement
int CPlayerInterface::howManyPeople = 0;
struct OCM_HLP_CGIN
static bool objectBlitOrderSorter(const std::pair<const CGObjectInstance*,SDL_Rect> & a, const std::pair<const CGObjectInstance*,SDL_Rect> & b)
{
bool inline operator ()(const std::pair<const CGObjectInstance*,SDL_Rect> & a, const std::pair<const CGObjectInstance*,SDL_Rect> & b) const
{
return (*a.first)<(*b.first);
}
} ocmptwo_cgin ;
return CMapHandler::compareObjectBlitOrder(a.first, b.first);
}
CPlayerInterface::CPlayerInterface(PlayerColor Player)
{
@ -1645,14 +1640,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
{
@ -1670,9 +1665,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
{
@ -1693,14 +1688,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
{
@ -1716,9 +1711,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
{
@ -1739,14 +1734,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
{
@ -1764,9 +1759,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
{
@ -1787,14 +1782,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
{
@ -1810,9 +1805,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);
}
}
@ -2042,13 +2037,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 )

View File

@ -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);

View File

@ -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<int3, ShashInt3> &tiles, PlayerColor player, bool hide) override {}
//////////////////////////////////////////////////////////////////////////
friend class CCallback; //handling players actions
friend class CBattleCallback; //handling players actions

View File

@ -1848,7 +1848,7 @@ CObjectListWindow::CObjectListWindow(const std::vector<int> &_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();
}
}
@ -4573,7 +4573,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();
}
@ -5636,7 +5636,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);
@ -6183,7 +6183,12 @@ void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EA
if(iWin)
GH.pushInt(iWin);
else
CRClickPopup::createAndPush(obj->getHoverText());
{
if (adventureInt->curHero())
CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero()));
else
CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID));
}
}
CRClickPopup::CRClickPopup()

View File

@ -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"

View File

@ -152,7 +152,6 @@
<Unit filename="CPreGame.h" />
<Unit filename="CQuestLog.cpp" />
<Unit filename="CQuestLog.h" />
<Unit filename="CSoundBase.h" />
<Unit filename="CSpellWindow.cpp" />
<Unit filename="CSpellWindow.h" />
<Unit filename="CVideoHandler.cpp" />

View File

@ -229,7 +229,6 @@
<ClInclude Include="CPlayerInterface.h" />
<ClInclude Include="CPreGame.h" />
<ClInclude Include="CQuestLog.h" />
<ClInclude Include="CSoundBase.h" />
<ClInclude Include="CSpellWindow.h" />
<ClInclude Include="CVideoHandler.h" />
<ClInclude Include="FontBase.h" />

View File

@ -78,7 +78,6 @@
<ClInclude Include="CMusicHandler.h" />
<ClInclude Include="CPlayerInterface.h" />
<ClInclude Include="CPreGame.h" />
<ClInclude Include="CSoundBase.h" />
<ClInclude Include="CSpellWindow.h" />
<ClInclude Include="CVideoHandler.h" />
<ClInclude Include="FontBase.h" />

View File

@ -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"

View File

@ -75,21 +75,10 @@ std::string nameFromType (int typ)
return std::string();
}
struct OCM_HLP
static bool objectBlitOrderSorter(const std::pair<const CGObjectInstance*,SDL_Rect> & a, const std::pair<const CGObjectInstance*,SDL_Rect> & b)
{
bool operator ()(const std::pair<const CGObjectInstance*, SDL_Rect> & a, const std::pair<const CGObjectInstance*, SDL_Rect> & b)
{
return (*a.first)<(*b.first);
}
} ocmptwo ;
// void alphaTransformDef(CGDefInfo * defInfo)
// {
// for(int yy=0; yy<defInfo->handler->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; iz<ttiles[0][0].size(); ++iz)
{
stable_sort(ttiles[ix][iy][iz].objects.begin(), ttiles[ix][iy][iz].objects.end(), ocmptwo);
stable_sort(ttiles[ix][iy][iz].objects.begin(), ttiles[ix][iy][iz].objects.end(), objectBlitOrderSorter);
}
}
}
@ -860,7 +849,7 @@ bool CMapHandler::printObject(const CGObjectInstance *obj)
auto i = curt.objects.begin();
for(; i != curt.objects.end(); i++)
{
if(ocmptwo(toAdd, *i))
if(objectBlitOrderSorter(toAdd, *i))
{
curt.objects.insert(i, toAdd);
i = curt.objects.begin(); //to validate and avoid adding it second time
@ -1065,7 +1054,7 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
{
if(elem.first->ID == 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;
}

View File

@ -108,7 +108,6 @@ public:
std::pair<SDL_Surface *, bool> getVisBitmap(const int3 & pos, const std::vector< std::vector< std::vector<ui8> > > & 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);
};

View File

@ -526,7 +526,7 @@
"combat_value": 154,
"reward" : {
"value": 3200,
"creatures": [ { "amount": 4, "type": "vyvern" } ]
"creatures": [ { "amount": 4, "type": "wyvern" } ]
}
},
{
@ -541,7 +541,7 @@
"combat_value": 230,
"reward" : {
"value": 4800,
"creatures": [ { "amount": 6, "type": "vyvern" } ]
"creatures": [ { "amount": 6, "type": "wyvern" } ]
}
},
{
@ -556,7 +556,7 @@
"combat_value": 307,
"reward" : {
"value": 6400,
"creatures": [ { "amount": 8, "type": "vyvern" } ]
"creatures": [ { "amount": 8, "type": "wyvern" } ]
}
},
{
@ -571,7 +571,7 @@
"combat_value": 461,
"reward" : {
"value": 9600,
"creatures": [ { "amount": 12, "type": "vyvern" } ]
"creatures": [ { "amount": 12, "type": "wyvern" } ]
}
}
]

View File

@ -9,125 +9,298 @@
}
},
"altarOfSacrifice" : { "index" :2, "handler": "market" },
"tradingPost" : { "index" :221, "handler": "market" },
"tradingPostDUPLICATE" : { "index" :99, "handler": "market" },
"freelancersGuild" : { "index" :213, "handler": "market" },
"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" },
"blackMarket" : { "index" :7, "handler": "blackMarket", "types" : { "object" : { "index" : 0} } },
"pandoraBox" : { "index" :6, "handler": "pandora" },
"event" : { "index" :26, "handler": "event" },
"pandoraBox" : { "index" :6, "handler": "pandora", "types" : { "object" : { "index" : 0} } },
"event" : { "index" :26, "handler": "event", "types" : { "object" : { "index" : 0} } },
"redwoodObservatory" : { "index" :58, "handler": "observatory" },
"pillarOfFire" : { "index" :60, "handler": "observatory" },
"coverOfDarkness" : { "index" :15, "handler": "observatory" },
"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} } },
"subterraneanGate" : { "index" :103, "handler": "teleport" },
"whirlpool" : { "index" :111, "handler": "teleport" },
"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
}
},
"refugeeCamp" : { "index" :78, "handler": "dwelling" },
"warMachineFactory" : { "index" :106, "handler": "dwelling" },
"refugeeCamp" : { "index" :78, "handler": "dwelling", "types" : { "object" : { "index" : 0} } },
"warMachineFactory" : { "index" :106, "handler": "dwelling", "types" : { "object" : { "index" : 0} } },
"shrineOfMagicLevel1" : { "index" :88, "handler": "shrine" },
"shrineOfMagicLevel2" : { "index" :89, "handler": "shrine" },
"shrineOfMagicLevel3" : { "index" :90, "handler": "shrine" },
"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} } },
"eyeOfTheMagi" : { "index" :27, "handler": "magi" },
"hutOfTheMagi" : { "index" :37, "handler": "magi" },
"eyeOfTheMagi" : { "index" :27, "handler": "magi", "types" : { "object" : { "index" : 0} } },
"hutOfTheMagi" : { "index" :37, "handler": "magi", "types" : { "object" : { "index" : 0} } },
"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" },
"randomTown" : { "index" :77, "handler": "randomTown", "types" : { "object" : { "index" : 0} } },
"randomHero" : { "index" :70, "handler": "randomHero", "types" : { "object" : { "index" : 0} } },
"randomDwelling" : { "index" :216, "handler": "randomDwelling", "types" : { "object" : { "index" : 0} } },
"randomDwelling" : { "index" :216, "handler": "dwelling" },
"randomResource" : {
"index" :76,
"handler": "randomResource",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVTrndm0", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"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": "randomArtifact",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVArand", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomArtifactTreasure" : {
"index" :66,
"handler": "randomArtifact",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVArnd1", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomArtifactMinor" : {
"index" :67,
"handler": "randomArtifact",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVArnd2", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomArtifactMajor" : {
"index" :68,
"handler": "randomArtifact",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVArnd3", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomArtifactRelic" : {
"index" :69,
"handler": "randomArtifact",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVArnd4", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"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" },
"randomMonster" : {
"index" :71,
"handler": "randomMonster",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVWmrnd0", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomMonsterLevel1" : {
"index" :72,
"handler": "randomMonster",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVWmon1", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomMonsterLevel2" : {
"index" :73,
"handler": "randomMonster",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVWmon2", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomMonsterLevel3" : {
"index" :74,
"handler": "randomMonster",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVWmon3", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomMonsterLevel4" : {
"index" :75,
"handler": "randomMonster",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVWmon4", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomMonsterLevel5" : {
"index" :162,
"handler": "randomMonster",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVWmon5", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomMonsterLevel6" : {
"index" :163,
"handler": "randomMonster",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVWmon6", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
"randomMonsterLevel7" : {
"index" :164,
"handler": "randomMonster",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "AVWmon7", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
}
}
},
/// 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} } }
}

View File

@ -189,20 +189,99 @@
"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" },
// subtype: level
"randomDwellingLvl" : { "index" :217, "handler": "dwelling" },
"randomDwellingLvl" : {
"index" :217, "handler": "randomDwelling",
"types" : {
"objectLvl1" : { "index" : 0},
"objectLvl2" : { "index" : 1},
"objectLvl3" : { "index" : 2},
"objectLvl4" : { "index" : 3},
"objectLvl5" : { "index" : 4},
"objectLvl6" : { "index" : 5},
"objectLvl7" : { "index" : 6}
}
},
// subtype: faction ID
"randomDwellingFaction" : { "index" :218, "handler": "dwelling" },
"randomDwellingFaction" : {
"index" :218,
"handler": "randomDwelling",
"types" : {
"objectCastle" : { "index" : 0},
"objectRampart" : { "index" : 1},
"objectTower" : { "index" : 2},
"objectInferno" : { "index" : 3},
"objectNecropolis" : { "index" : 4},
"objectDungeon" : { "index" : 5},
"objectStronghold" : { "index" : 6},
"objectFortress" : { "index" : 7},
"objectConflux" : { "index" : 8},
}
},
// don't have subtypes (at least now), but closely connected to this objects
"spellScroll" : { "index" :93, "handler": "artifact" },
"heroPlaceholder" : { "index" :214, "handler": "heroPlaceholder" }
"spellScroll" : {
"index" :93,
"handler": "artifact",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : {
"visitableFrom" : [ "+++", "+-+", "+++" ],
"mask" : [ "VA" ],
"animation" : "AVA0001.def"
}
}
}
}
},
"heroPlaceholder" : { "index" :214, "handler": "heroPlaceholder", "types" : { "object" : { "index" : 0 } } }
}

View File

@ -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" },
"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" },
"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" },
"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} } }
}

View File

@ -63,7 +63,7 @@
},
"Upgrade" :
{
"minSize" : "m", "maxSize" : "m",
"minSize" : "s", "maxSize" : "m",
"players" : "2",
"zones" :
{
@ -126,7 +126,7 @@
},
"Golden Ring" :
{
"minSize" : "m", "maxSize" : "m",
"minSize" : "m", "maxSize" : "l",
"players" : "3",
"zones" :
{

View File

@ -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",

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
vcmi (0.96) trusty; urgency=low
* New upstream release
-- Ivan Savenko <saven.ivan@gmail.com> Tue, 01 Jul 2014 20:57:29 +0300
vcmi (0.95) precise; urgency=low
* New upstream release

View File

@ -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);

View File

@ -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<SideInBattle, 2> 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<CStack*> stacks;
std::vector<shared_ptr<CObstacleInstance> > obstacles;
@ -99,7 +98,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
template <typename Handler> 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<CBonusSystemNode&>(*this);

View File

@ -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"

View File

@ -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);

View File

@ -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));

View File

@ -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<boost::shared_mutex> lock(*gs->mx);
return gs->getDate(mode);
}
std::vector < std::string > CGameInfoCallback::getObjDescriptions(int3 pos) const
{
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
std::vector<std::string> 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<PlayerColor> Player) const
{

View File

@ -83,7 +83,6 @@ public:
std::vector <const CGObjectInstance * > getVisitableObjs(int3 pos, bool verbose = true)const;
std::vector <const CGObjectInstance * > getFlaggableObjects(int3 pos) const;
const CGObjectInstance * getTopObj (int3 pos) const;
std::vector <std::string > 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)

View File

@ -256,7 +256,7 @@ DLL_LINKAGE void MetaString::toString(std::string &dst) const
boost::replace_first(dst, "%+d", '+' + boost::lexical_cast<std::string>(numbers[nums++]));
break;
default:
logGlobal->errorStream() << "MetaString processing error!";
logGlobal->errorStream() << "MetaString processing error! Received message of type " << int(elem);
break;
}
}
@ -313,7 +313,7 @@ DLL_LINKAGE std::string MetaString::buildList () const
lista.replace (lista.find("%d"), 2, boost::lexical_cast<std::string>(numbers[nums++]));
break;
default:
logGlobal->errorStream() << "MetaString processing error!";
logGlobal->errorStream() << "MetaString processing error! Received message of type " << int(message[i]);
}
}
@ -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<int3, ShashInt3> 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;
@ -1900,6 +1899,13 @@ void CGameState::initVisitingAndGarrisonedHeroes()
}
}
}
for (auto hero : map->heroesOnMap)
{
if (hero->visitedTown)
{
assert (hero->visitedTown->visitingHero == hero);
}
}
}
BFieldType CGameState::battleGetBattlefieldType(int3 tile)
@ -2980,7 +2986,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 +3516,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;

View File

@ -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 <typename Handler> 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<std::string> > texts //allow additional info for quest log?
template <typename Handler> void serialize(Handler &h, const int version)
{
h & quest & obj & tile;
}
};

120
lib/CGameStateFwd.h Normal file
View File

@ -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 <typename Handler> 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<std::string> > texts //allow additional info for quest log?
template <typename Handler> void serialize(Handler &h, const int version)
{
h & quest & obj & tile;
}
};

View File

@ -199,7 +199,7 @@ void CHeroClassHandler::loadObject(std::string scope, std::string name, const Js
VLC->modh->identifiers.requestIdentifier(scope, "object", "hero", [=](si32 index)
{
JsonNode classConf;
JsonNode classConf = data["mapObject"];
classConf["heroClass"].String() = name;
classConf.setMeta(scope);
VLC->objtypeh->loadSubObject(name, classConf, index, object->id);

View File

@ -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

View File

@ -310,6 +310,7 @@ bool CContentHandler::ContentTypeHandler::preloadModData(std::string modName, st
if (remoteName == modName)
logGlobal->warnStream() << "Redundant namespace definition for " << objectName;
logGlobal->traceStream() << "Patching object " << objectName << " (" << remoteName << ") from " << modName;
JsonNode & remoteConf = modData[remoteName].patches[objectName];
JsonUtils::merge(remoteConf, entry.second);

View File

@ -688,7 +688,19 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
JsonNode config = data["town"]["mapObject"];
config["faction"].String() = object->identifier;
config["faction"].meta = scope;
if (config.meta.empty())// MODS COMPATIBILITY FOR 0.96
config.meta = scope;
VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
// MODS COMPATIBILITY FOR 0.96
auto & advMap = data["town"]["adventureMap"];
if (!advMap.isNull())
{
logGlobal->warnStream() << "Outdated town mod. Will try to generate valid templates out of fort";
JsonNode config;
config["animation"] = advMap["castle"];
VLC->objtypeh->getHandlerFor(index, object->index)->addTemplate(config);
}
});
}
@ -717,15 +729,6 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
config["faction"].String() = object->identifier;
config["faction"].meta = scope;
VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
// MODS COMPATIBILITY FOR 0.96
auto & advMap = data["town"]["adventureMap"];
if (!advMap["fort"].isNull())
{
JsonNode config;
config["appearance"] = advMap["fort"];
VLC->objtypeh->getHandlerFor(index, object->index)->addTemplate(config);
}
});
}

View File

@ -27,7 +27,7 @@
#include "mapping/CCampaignHandler.h" //for CCampaignState
#include "rmg/CMapGenerator.h" // for CMapGenOptions
const ui32 version = 749;
const ui32 version = 750;
const ui32 minSupportedVersion = version;
class CConnection;

View File

@ -14,7 +14,7 @@
namespace GameConstants
{
const std::string VCMI_VERSION = "VCMI 0.95b";
const std::string VCMI_VERSION = "VCMI 0.96";
const int BFIELD_WIDTH = 17;
const int BFIELD_HEIGHT = 11;

View File

@ -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<int3> &tiles) const
{

View File

@ -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<int3, ShashInt3> &tiles, PlayerColor player, bool hide) = 0;
};
class DLL_LINKAGE CNonConstInfoCallback : public CPrivilagedInfoCallback

19
lib/IHandlerBase.cpp Normal file
View File

@ -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);
}

View File

@ -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 _ObjectID, class _Object> 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);
}

View File

@ -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
@ -1046,21 +1049,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 <typename Handler> void serialize(Handler &h, const int version)
{
h & id & name;
}
};
struct ChangeObjectVisitors : public CPackForClient // 1003
{
enum VisitMode
@ -1528,7 +1516,8 @@ struct ObstaclesRemoved : public CPackForClient //3014
}
};
struct CatapultAttack : public CPackForClient //3015
struct ELF_VISIBILITY CatapultAttack : public CPackForClient //3015
{
struct AttackInfo
{
@ -2137,26 +2126,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
@ -2167,28 +2144,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 <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -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;
@ -126,6 +163,7 @@ DLL_LINKAGE void HeroVisitCastle::applyGs( CGameState *gs )
assert(h);
assert(t);
if(start())
t->setVisitingHero(h);
else
@ -177,7 +215,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 +340,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 +646,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 +1049,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);
@ -1507,7 +1539,7 @@ 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)
{

View File

@ -149,6 +149,7 @@
<Unit filename="CRandomGenerator.cpp" />
<Unit filename="CRandomGenerator.h" />
<Unit filename="CScriptingModule.h" />
<Unit filename="CSoundBase.h" />
<Unit filename="CSpellHandler.cpp" />
<Unit filename="CSpellHandler.h" />
<Unit filename="CStopWatch.h" />
@ -169,6 +170,7 @@
<Unit filename="IGameCallback.cpp" />
<Unit filename="IGameCallback.h" />
<Unit filename="IGameEventsReceiver.h" />
<Unit filename="IHandlerBase.cpp" />
<Unit filename="IHandlerBase.h" />
<Unit filename="Interprocess.h" />
<Unit filename="JsonDetail.cpp" />

View File

@ -135,8 +135,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
<ClCompile>
<AdditionalOptions>/Oy- %(AdditionalOptions) /bigobj
/Zm150</AdditionalOptions>
<AdditionalOptions>/Oy- /bigobj /Zm150 </AdditionalOptions>
<PreprocessorDefinitions>VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
<PrecompiledHeader>Use</PrecompiledHeader>
@ -177,13 +176,11 @@
<ClCompile Include="CConsoleHandler.cpp" />
<ClCompile Include="CCreatureHandler.cpp" />
<ClCompile Include="CCreatureSet.cpp" />
<ClCompile Include="CDefObjInfoHandler.cpp" />
<ClCompile Include="CGameInterface.cpp" />
<ClCompile Include="CGameState.cpp" />
<ClCompile Include="CGeneralTextHandler.cpp" />
<ClCompile Include="CHeroHandler.cpp" />
<ClCompile Include="CModHandler.cpp" />
<ClCompile Include="CObjectHandler.cpp" />
<ClCompile Include="CObstacleInstance.cpp" />
<ClCompile Include="Connection.cpp" />
<ClCompile Include="CSpellHandler.cpp" />
@ -202,8 +199,24 @@
<ClCompile Include="filesystem\Filesystem.cpp" />
<ClCompile Include="filesystem\ResourceID.cpp" />
<ClCompile Include="GameConstants.cpp" />
<ClCompile Include="IHandlerBase.cpp" />
<ClCompile Include="JsonDetail.cpp" />
<ClCompile Include="LogicalExpression.cpp" />
<ClCompile Include="mapObjects\CArmedInstance.cpp" />
<ClCompile Include="mapObjects\CBank.cpp" />
<ClCompile Include="mapObjects\CGHeroInstance.cpp" />
<ClCompile Include="mapObjects\CGMarket.cpp" />
<ClCompile Include="mapObjects\CGPandoraBox.cpp" />
<ClCompile Include="mapObjects\CGTownInstance.cpp" />
<ClCompile Include="mapObjects\CObjectClassesHandler.cpp" />
<ClCompile Include="mapObjects\CObjectHandler.cpp" />
<ClCompile Include="mapObjects\CommonConstructors.cpp" />
<ClCompile Include="mapObjects\CQuest.cpp" />
<ClCompile Include="mapObjects\CRewardableConstructor.cpp" />
<ClCompile Include="mapObjects\CRewardableObject.cpp" />
<ClCompile Include="mapObjects\JsonRandom.cpp" />
<ClCompile Include="mapObjects\MiscObjects.cpp" />
<ClCompile Include="mapObjects\ObjectTemplate.cpp" />
<ClCompile Include="mapping\CCampaignHandler.cpp" />
<ClCompile Include="mapping\CMap.cpp" />
<ClCompile Include="mapping\CMapInfo.cpp" />
@ -216,6 +229,7 @@
<ClCompile Include="registerTypes\TypesClientPacks2.cpp" />
<ClCompile Include="registerTypes\TypesMapObjects1.cpp" />
<ClCompile Include="registerTypes\TypesMapObjects2.cpp" />
<ClCompile Include="registerTypes\TypesMapObjects3.cpp" />
<ClCompile Include="registerTypes\TypesPregamePacks.cpp" />
<ClCompile Include="registerTypes\TypesServerPacks.cpp" />
<ClCompile Include="rmg\CMapGenerator.cpp" />
@ -259,13 +273,12 @@
<ClInclude Include="CConsoleHandler.h" />
<ClInclude Include="CCreatureHandler.h" />
<ClInclude Include="CCreatureSet.h" />
<ClInclude Include="CDefObjInfoHandler.h" />
<ClInclude Include="CGameInterface.h" />
<ClInclude Include="CGameState.h" />
<ClInclude Include="CGameStateFwd.h" />
<ClInclude Include="CGeneralTextHandler.h" />
<ClInclude Include="CHeroHandler.h" />
<ClInclude Include="CModHandler.h" />
<ClInclude Include="CObjectHandler.h" />
<ClInclude Include="CObstacleInstance.h" />
<ClInclude Include="CondSh.h" />
<ClInclude Include="Connection.h" />
@ -293,6 +306,22 @@
<ClInclude Include="IBonusTypeHandler.h" />
<ClInclude Include="JsonDetail.h" />
<ClInclude Include="LogicalExpression.h" />
<ClInclude Include="mapObjects\CArmedInstance.h" />
<ClInclude Include="mapObjects\CBank.h" />
<ClInclude Include="mapObjects\CGHeroInstance.h" />
<ClInclude Include="mapObjects\CGMarket.h" />
<ClInclude Include="mapObjects\CGPandoraBox.h" />
<ClInclude Include="mapObjects\CGTownInstance.h" />
<ClInclude Include="mapObjects\CObjectClassesHandler.h" />
<ClInclude Include="mapObjects\CObjectHandler.h" />
<ClInclude Include="mapObjects\CommonConstructors.h" />
<ClInclude Include="mapObjects\CQuest.h" />
<ClInclude Include="mapObjects\CRewardableConstructor.h" />
<ClInclude Include="mapObjects\CRewardableObject.h" />
<ClInclude Include="mapObjects\JsonRandom.h" />
<ClInclude Include="mapObjects\MapObjects.h" />
<ClInclude Include="mapObjects\MiscObjects.h" />
<ClInclude Include="mapObjects\ObjectTemplate.h" />
<ClInclude Include="mapping\CCampaignHandler.h" />
<ClInclude Include="mapping\CMap.h" />
<ClInclude Include="mapping\CMapInfo.h" />

View File

@ -23,6 +23,9 @@
<Filter Include="registerTypes">
<UniqueIdentifier>{927d9b6e-3dc5-4370-b603-1b9887095509}</UniqueIdentifier>
</Filter>
<Filter Include="mapObjects">
<UniqueIdentifier>{ee24c7f7-f4e2-4d35-b994-94a6e29ea92f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BattleAction.cpp" />
@ -30,10 +33,8 @@
<ClCompile Include="CArtHandler.cpp" />
<ClCompile Include="CBuildingHandler.cpp" />
<ClCompile Include="CCreatureHandler.cpp" />
<ClCompile Include="CDefObjInfoHandler.cpp" />
<ClCompile Include="CGeneralTextHandler.cpp" />
<ClCompile Include="CHeroHandler.cpp" />
<ClCompile Include="CObjectHandler.cpp" />
<ClCompile Include="CSpellHandler.cpp" />
<ClCompile Include="CTownHandler.cpp" />
<ClCompile Include="CCreatureSet.cpp" />
@ -157,6 +158,53 @@
</ClCompile>
<ClCompile Include="registerTypes\TypesMapObjects1.cpp" />
<ClCompile Include="registerTypes\TypesMapObjects2.cpp" />
<ClCompile Include="mapObjects\CArmedInstance.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CBank.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CGHeroInstance.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CGMarket.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CGPandoraBox.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CGTownInstance.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CObjectClassesHandler.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CObjectHandler.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CommonConstructors.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CQuest.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CRewardableConstructor.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\CRewardableObject.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\JsonRandom.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\MiscObjects.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="mapObjects\ObjectTemplate.cpp">
<Filter>mapObjects</Filter>
</ClCompile>
<ClCompile Include="registerTypes\TypesMapObjects3.cpp" />
<ClCompile Include="IHandlerBase.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="CCreatureSet.h">
@ -201,18 +249,12 @@
<ClInclude Include="CCreatureHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CDefObjInfoHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CGeneralTextHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CHeroHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CObjectHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ConstTransitivePtr.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -399,5 +441,56 @@
<ClInclude Include="rmg\float3.h">
<Filter>rmg</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CArmedInstance.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CBank.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CGHeroInstance.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CGMarket.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CGPandoraBox.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CGTownInstance.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CObjectClassesHandler.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CObjectHandler.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CommonConstructors.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CQuest.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CRewardableConstructor.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\CRewardableObject.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\JsonRandom.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\MapObjects.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\MiscObjects.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="mapObjects\ObjectTemplate.h">
<Filter>mapObjects</Filter>
</ClInclude>
<ClInclude Include="CGameStateFwd.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -156,3 +156,21 @@ struct ShashInt3
static const int3 dirs[] = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0),
int3(1,1,0),int3(-1,1,0),int3(1,-1,0),int3(-1,-1,0) };
//FIXME: make sure it's <int3> container and not just any
template<typename Container>
int3 findClosestTile (Container & container, int3 dest)
{
int3 result(-1,-1,-1);
ui32 distance = std::numeric_limits<ui32>::max();
for (int3 tile : container)
{
ui32 currentDistance = dest.dist2dSQ(tile);
if (currentDistance < distance)
{
result = tile;
distance = currentDistance;
}
}
return result;
}

View File

@ -1,4 +1,4 @@
/*
/*
* CArmedInstance.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "CObjectHandler.h"
#include "../CCreatureSet.h"
@ -13,6 +13,9 @@
*
*/
class BattleInfo;
class CGameState;
class DLL_LINKAGE CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet
{
public:

View File

@ -1,4 +1,4 @@
/*
/*
* CBank.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
@ -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,10 @@ 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
{
bool visited = (bc == nullptr);
hoverName = visitedTxt(visited); // FIXME: USE BANK_SPECIFIC NAMES
return hoverName;
// TODO: record visited players
return getObjectName() + " " + visitedTxt(bc == nullptr);
}
void CBank::setConfig(const BankConfig & config)
@ -125,8 +126,8 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const
bd.player = h->getOwner();
bd.soundID = soundID;
bd.text.addTxt(MetaString::ADVOB_TXT, banktext);
//if (ID == Obj::CREATURE_BANK)
// bd.text.addReplacement(VLC->objh->creBanksNames[index]); // FIXME: USE BANK SPECIFIC NAMES
if (ID == Obj::CREATURE_BANK)
bd.text.addReplacement(getObjectName());
cb->showBlockingDialog (&bd);
}
else
@ -146,7 +147,7 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const
else
{
iw.text << VLC->generaltexth->advobtxt[33];// This was X, now is completely empty
//iw.text.addReplacement(VLC->objh->creBanksNames[index]); // FIXME: USE BANK SPECIFIC NAMES
iw.text.addReplacement(getObjectName());
}
cb->showInfoDialog(&iw);
}

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "CObjectHandler.h"
#include "CArmedInstance.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;

View File

@ -1,4 +1,4 @@
/*
/*
* CGHeroInstance.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
@ -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
@ -472,9 +473,12 @@ void CGHeroInstance::initObj()
skillsInfo.resetMagicSchoolCounter();
skillsInfo.resetWisdomCounter();
if (ID != Obj::PRISON)
{
auto customApp = VLC->objtypeh->getHandlerFor(ID, type->heroClass->id)->getOverride(cb->gameState()->getTile(visitablePos())->terType, this);
if (customApp)
appearance = customApp.get();
}
for(const auto &spec : type->spec) //TODO: unfity with bonus system
{
@ -999,11 +1003,11 @@ void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedSta
cb->showInfoDialog(&iw);
}
/*
int3 CGHeroInstance::getSightCenter() const
{
return getPosition(false);
}
}*/
int CGHeroInstance::getSightRadious() const
{

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "CObjectHandler.h"
#include "CArmedInstance.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

View File

@ -1,4 +1,4 @@
/*
/*
*
* CGMarket.cpp, part of VCMI engine
*
@ -14,6 +14,9 @@
#include "../NetPacks.h"
#include "../CGeneralTextHandler.h"
#include "../IGameCallback.h"
#include "../CCreatureHandler.h"
#include "../CGameState.h"
using namespace boost::assign;

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "CObjectHandler.h"

View File

@ -1,4 +1,4 @@
/*
/*
* CGPandoraBox.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
@ -15,6 +15,8 @@
#include "../CSoundBase.h"
#include "../CSpellHandler.h"
#include "../StartInfo.h"
#include "../IGameCallback.h"
using namespace boost::assign;

View File

@ -1,7 +1,8 @@
#pragma once
#pragma once
#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:

View File

@ -1,4 +1,4 @@
/*
/*
* CGTownInstance.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
@ -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
@ -520,14 +523,25 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
{
//FIXME: find out why this issue appears on random maps
if (visitingHero == h)
{
cb->stopHeroVisitCastle(this, h);
logGlobal->warnStream() << h->name << " correctly left town " << name;
}
else
logGlobal->warnStream() << "Warning, " << h->name << " tries to leave the town " << name << " but hero is not inside.";
}
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 +658,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<<it.getNum();//allies - add to possible visitors
return mask;
if (cb->getPlayerRelations(tempOwner, color) != PlayerRelations::ENEMIES)
return true;
return false;
}
void CGTownInstance::getOutOffsets( std::vector<int3> &offsets ) const
@ -903,7 +914,13 @@ bool CGTownInstance::addBonusIfBuilt(BuildingID building, Bonus::BonusType type,
void CGTownInstance::setVisitingHero(CGHeroInstance *h)
{
if (!(!!visitingHero == !h))
{
logGlobal->warnStream() << boost::format("Hero visiting town %s is %s ") % name % (visitingHero.get() ? visitingHero->name : "NULL");
logGlobal->warnStream() << boost::format("New hero will be %s ") % (h ? h->name : "NULL");
assert(!!visitingHero == !h);
}
if(h)
{
PlayerState *p = cb->gameState()->getPlayer(h->tempOwner);
@ -1010,7 +1027,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);
}
}

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "CObjectHandler.h"
#include "CGMarket.h" // For IMarket interface
@ -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<int3> &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;
};

View File

@ -1,9 +1,9 @@
#include "StdInc.h"
#include "StdInc.h"
#include "CObjectClassesHandler.h"
#include "../filesystem/Filesystem.h"
#include "../filesystem/CBinaryReader.h"
#include "../lib/VCMI_Lib.h"
#include "../VCMI_Lib.h"
#include "../GameConstants.h"
#include "../StringConstants.h"
#include "../CGeneralTextHandler.h"
@ -40,6 +40,13 @@ CObjectClassesHandler::CObjectClassesHandler()
SET_HANDLER_CLASS("static", CObstacleConstructor);
SET_HANDLER_CLASS("", CObstacleConstructor);
SET_HANDLER("randomArtifact", CGArtifact);
SET_HANDLER("randomHero", CGHeroInstance);
SET_HANDLER("randomResource", CGResource);
SET_HANDLER("randomTown", CGTownInstance);
SET_HANDLER("randomMonster", CGCreature);
SET_HANDLER("randomDwelling", CGDwelling);
SET_HANDLER("generic", CGObjectInstance);
SET_HANDLER("market", CGMarket);
SET_HANDLER("cartographer", CCartographer);
@ -67,6 +74,7 @@ CObjectClassesHandler::CObjectClassesHandler()
SET_HANDLER("pandora", CGPandoraBox);
SET_HANDLER("pickable", CGPickable);
SET_HANDLER("prison", CGHeroInstance);
SET_HANDLER("prison", CGHeroInstance);
SET_HANDLER("questGuard", CGQuestGuard);
SET_HANDLER("resource", CGResource);
SET_HANDLER("scholar", CGScholar);
@ -109,6 +117,17 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
ret[i]["name"].String() = namesParser.readString();
namesParser.endLine();
}
CLegacyConfigParser cregen1Parser("data/crgen1");
do
customNames[Obj::CREATURE_GENERATOR1].push_back(cregen1Parser.readString());
while(cregen1Parser.endLine());
CLegacyConfigParser cregen4Parser("data/crgen4");
do
customNames[Obj::CREATURE_GENERATOR4].push_back(cregen4Parser.readString());
while(cregen4Parser.endLine());
return ret;
}
@ -121,7 +140,7 @@ si32 selectNextID(const JsonNode & fixedID, const Map & map, si32 defaultID)
if (map.empty())
return defaultID; // no objects loaded, keep gap for H3M objects
if (map.rbegin()->first > defaultID)
if (map.rbegin()->first >= defaultID)
return map.rbegin()->first + 1; // some modded objects loaded, return next available
return defaultID; // some H3M objects loaded, first modded found
@ -134,12 +153,16 @@ void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContai
logGlobal->errorStream() << "Handler with name " << obj->handlerName << " was not found!";
return;
}
auto handler = handlerConstructors.at(obj->handlerName)();
handler->init(entry);
si32 id = selectNextID(entry["index"], obj->objects, 1000);
auto handler = handlerConstructors.at(obj->handlerName)();
handler->setType(obj->id, id);
if (customNames.count(obj->id) && customNames.at(obj->id).size() > id)
handler->init(entry, customNames.at(obj->id).at(id));
else
handler->init(entry);
if (handler->getTemplates().empty())
{
auto range = legacyTemplates.equal_range(std::make_pair(obj->id, id));
@ -150,8 +173,9 @@ void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContai
legacyTemplates.erase(range.first, range.second);
}
obj->objects[id] = handler;
logGlobal->debugStream() << "Loaded object " << obj->id << ":" << id;
assert(!obj->objects.count(id)); // DO NOT override
obj->objects[id] = handler;
}
CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(const JsonNode & json)
@ -200,6 +224,7 @@ void CObjectClassesHandler::loadSubObject(std::string name, JsonNode config, si3
std::string oldMeta = config.meta; // FIXME: move into inheritNode?
JsonUtils::inherit(config, objects.at(ID)->base);
config.setMeta(oldMeta);
loadObjectEntry(config, objects[ID]);
}
@ -276,8 +301,21 @@ void CObjectClassesHandler::afterLoadFinalization()
std::string CObjectClassesHandler::getObjectName(si32 type) const
{
assert(objects.count(type));
if (objects.count(type))
return objects.at(type)->name;
logGlobal->errorStream() << "Access to non existing object of type " << type;
return "";
}
std::string CObjectClassesHandler::getObjectName(si32 type, si32 subtype) const
{
if (knownSubObjects(type).count(subtype))
{
auto name = getHandlerFor(type, subtype)->getCustomName();
if (name)
return name.get();
}
return getObjectName(type);
}
void AObjectTypeHandler::setType(si32 type, si32 subtype)
@ -294,7 +332,7 @@ static ui32 loadJsonOrMax(const JsonNode & input)
return input.Float();
}
void AObjectTypeHandler::init(const JsonNode & input)
void AObjectTypeHandler::init(const JsonNode & input, boost::optional<std::string> name)
{
base = input["base"];
@ -318,6 +356,12 @@ void AObjectTypeHandler::init(const JsonNode & input)
tmpl.readJson(entry.second);
templates.push_back(tmpl);
}
if (input["name"].isNull())
objectName = name;
else
objectName.reset(input["name"].String());
initTypeData(input);
}
@ -328,6 +372,12 @@ bool AObjectTypeHandler::objectFilter(const CGObjectInstance *, const ObjectTemp
void AObjectTypeHandler::initTypeData(const JsonNode & input)
{
// empty implementation for overrides
}
boost::optional<std::string> AObjectTypeHandler::getCustomName() const
{
return objectName;
}
void AObjectTypeHandler::addTemplate(ObjectTemplate templ)

View File

@ -1,10 +1,11 @@
#pragma once
#pragma once
#include "ObjectTemplate.h"
#include "../GameConstants.h"
#include "../ConstTransitivePtr.h"
#include "../IHandlerBase.h"
#include "../JsonNode.h"
/*
* CObjectClassesHandler.h, part of VCMI engine
@ -20,7 +21,7 @@ class JsonNode;
class CRandomGenerator;
/// Structure that describes placement rules for this object in random map
struct RandomMapInfo
struct DLL_LINKAGE RandomMapInfo
{
/// How valuable this object is, 1k = worthless, 10k = Utopia-level
ui32 value;
@ -47,7 +48,7 @@ struct RandomMapInfo
}
};
class IObjectInfo
class DLL_LINKAGE IObjectInfo
{
public:
struct CArmyStructure
@ -64,7 +65,7 @@ public:
walkersStrength(0)
{}
bool operator <(const CArmyStructure & other)
bool operator <(const CArmyStructure & other) const
{
return this->totalStrength < other.totalStrength;
}
@ -97,6 +98,9 @@ class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
{
RandomMapInfo rmgInfo;
/// Human-readable name of this object, used for objects like banks and dwellings, if set
boost::optional<std::string> objectName;
si32 type;
si32 subtype;
@ -115,7 +119,10 @@ public:
void setType(si32 type, si32 subtype);
/// loads generic data from Json structure and passes it towards type-specific constructors
void init(const JsonNode & input);
void init(const JsonNode & input, boost::optional<std::string> name = boost::optional<std::string>());
/// Returns object-specific name, if set
boost::optional<std::string> getCustomName() const;
void addTemplate(ObjectTemplate templ);
void addTemplate(JsonNode config);
@ -147,7 +154,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & type & subtype & templates & rmgInfo;
h & type & subtype & templates & rmgInfo & objectName;
}
};
@ -173,8 +180,6 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
}
};
typedef std::multimap<std::pair<si32, si32>, ObjectTemplate> TTemplatesContainer;
/// list of object handlers, each of them handles only one type
std::map<si32, ObjectContainter * > objects;
@ -182,8 +187,13 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;
/// container with H3 templates, used only during loading, no need to serialize it
typedef std::multimap<std::pair<si32, si32>, ObjectTemplate> TTemplatesContainer;
TTemplatesContainer legacyTemplates;
/// contains list of custom names for H3 objects (e.g. Dwellings), used to load H3 data
/// format: customNames[primaryID][secondaryID] -> name
std::map<si32, std::vector<std::string>> customNames;
void loadObjectEntry(const JsonNode & entry, ObjectContainter * obj);
ObjectContainter * loadFromJson(const JsonNode & json);
public:
@ -210,6 +220,7 @@ public:
TObjectTypeHandler getHandlerFor(si32 type, si32 subtype) const;
std::string getObjectName(si32 type) const;
std::string getObjectName(si32 type, si32 subtype) const;
template <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -1,4 +1,4 @@
/*
/*
* CObjectHandler.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
@ -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,20 +134,10 @@ 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;
}
int CGObjectInstance::getWidth() const//returns width of object graphic in tiles
@ -191,39 +178,7 @@ std::set<int3> CGObjectInstance::getBlockedPos() const
std::set<int3> CGObjectInstance::getBlockedOffsets() const
{
std::set<int3> ret;
for(int w=0; w<getWidth(); ++w)
{
for(int h=0; h<getHeight(); ++h)
{
if (appearance.isBlockedAt(w, h))
ret.insert(int3(-w, -h, 0));
}
}
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.x<cmp.pos.x)
return true;
return false;
return appearance.getBlockedOffsets();
}
void CGObjectInstance::setType(si32 ID, si32 subID)
@ -252,6 +207,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 +224,6 @@ void CGObjectInstance::setProperty( ui8 what, ui32 val )
subID = val;
break;
}
setPropertyDer(what, val);
}
void CGObjectInstance::setPropertyDer( ui8 what, ui32 val )
@ -275,41 +231,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<int3, ShashInt3> &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++)
@ -317,21 +246,10 @@ int3 CGObjectInstance::getVisitableOffset() const
if (appearance.isVisitableAt(x, y))
return int3(x,y,0);
logGlobal->warnStream() << "Warning: getVisitableOffset called on non-visitable obj!";
//logGlobal->warnStream() << "Warning: getVisitableOffset called on non-visitable obj!";
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 +261,21 @@ void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) con
cb->giveHeroBonus(&gbonus);
}
std::string CGObjectInstance::getObjectName() const
{
return VLC->objtypeh->getObjectName(ID, subID);
}
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 +299,6 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
}
}
ui8 CGObjectInstance::getPassableness() const
{
return 0;
}
int3 CGObjectInstance::visitablePos() const
{
return pos - getVisitableOffset();
@ -383,7 +311,7 @@ bool CGObjectInstance::isVisitable() const
bool CGObjectInstance::passableFor(PlayerColor color) const
{
return getPassableness() & 1<<color.getNum();
return false;
}
CGObjectInstanceBySubIdFinder::CGObjectInstanceBySubIdFinder(CGObjectInstance * obj) : obj(obj)

View File

@ -1,8 +1,8 @@
#pragma once
#pragma once
#include "ObjectTemplate.h"
#include "../IGameCallback.h"
//#include "../IGameCallback.h"
#include "../int3.h"
#include "../HeroBonus.h"
@ -17,6 +17,9 @@
*/
class CGHeroInstance;
class IGameCallback;
class CGObjectInstance;
class MetaString;
struct BattleResult;
class DLL_LINKAGE IObjectInterface
@ -95,60 +98,82 @@ public:
class DLL_LINKAGE CGObjectInstance : public IObjectInterface
{
public:
mutable std::string hoverName;
int3 pos; //h3m pos
/// Position of bottom-right corner of object on map
int3 pos;
/// Type of object, e.g. town, hero, creature.
Obj ID;
si32 subID; //normal subID (this one from OH3 maps ;])
ObjectInstanceID id;//number of object in map's vector
/// Subtype of object, depends on type
si32 subID;
/// Index of object in map's list of objects
ObjectInstanceID id;
/// Defines appearance of object on map (animation, blocked tiles, blit order, etc)
ObjectTemplate appearance;
/// Current owner of an object (when below PLAYER_LIMIT)
PlayerColor tempOwner;
bool blockVisit; //if non-zero then blocks the tile but is visitable from neighbouring tile
/// If true hero can visit this object only from neighbouring tiles and can't stand on this object
bool blockVisit;
CGObjectInstance();
~CGObjectInstance();
/// "center" tile from which the sight distance is calculated
int3 getSightCenter() const;
virtual 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
virtual int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
virtual int getSightRadious() const; //sight distance (should be used if player-owned structure)
bool passableFor(PlayerColor color) const;
void getSightTiles(std::unordered_set<int3, ShashInt3> &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<int3> getBlockedPos() const; //returns set of positions blocked by this object
std::set<int3> 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 <typename Handler> 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;
};

View File

@ -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)
{
case Obj::SEER_HUT:
if (quest->progress != CQuest::NOT_ACTIVE)
std::string hoverName = getObjectName();
if (ID == Obj::SEER_HUT && 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";
}
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))<<i;
return ret;
return wasMyColorVisited(color);
}

View File

@ -16,6 +16,8 @@
*
*/
class CGCreature;
class DLL_LINKAGE CQuest
{
public:
@ -95,7 +97,7 @@ public:
CGSeerHut() : IQuestObject(){};
void initObj() override;
const std::string & getHoverText() const override;
std::string getHoverText(PlayerColor player) const override;
void newTurn() const override;
void onHeroVisit(const CGHeroInstance * h) const override;
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
@ -138,10 +140,10 @@ public:
static std::map <PlayerColor, std::set <ui8> > 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 <typename Handler> 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 <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -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);

View File

@ -15,7 +15,7 @@
*
*/
class CRandomRewardObjectInfo : public IObjectInfo
class DLL_LINKAGE CRandomRewardObjectInfo : public IObjectInfo
{
JsonNode parameters;
public:
@ -42,7 +42,7 @@ public:
void init(const JsonNode & objectConfig);
};
class CRewardableConstructor : public AObjectTypeHandler
class DLL_LINKAGE CRewardableConstructor : public AObjectTypeHandler
{
CRandomRewardObjectInfo objectInfo;

View File

@ -15,6 +15,8 @@
#include "../CGeneralTextHandler.h"
#include "../CSoundBase.h"
#include "../NetPacks.h"
#include "../IGameCallback.h"
#include "../CGameState.h"
#include "CObjectClassesHandler.h"
@ -74,8 +76,10 @@ std::vector<ui32> CRewardableObject::getAvailableRewards(const CGHeroInstance *
{
const CVisitInfo & visit = info[i];
if (visit.numOfGrants < visit.limiter.numOfGrants && visit.limiter.heroAllowed(hero))
if ((visit.limiter.numOfGrants == 0 || visit.numOfGrants < visit.limiter.numOfGrants) // reward has unlimited uses or some are still available
&& visit.limiter.heroAllowed(hero))
{
logGlobal->debugStream() << "Reward " << i << " is allowed";
ret.push_back(i);
}
}
@ -86,7 +90,7 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
{
auto grantRewardWithMessage = [&](int index) -> void
{
grantReward(index, h);
logGlobal->debugStream() << "Granting reward " << index << ". Message says: " << info[index].message.toString();
// show message only if it is not empty
if (!info[index].message.toString().empty())
{
@ -97,6 +101,8 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
info[index].reward.loadComponents(iw.components);
cb->showInfoDialog(&iw);
}
// grant reward afterwards. Note that it may remove object
grantReward(index, h);
};
auto selectRewardsMessage = [&](std::vector<ui32> rewards) -> void
{
@ -112,6 +118,7 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
if (!wasVisited(h))
{
auto rewards = getAvailableRewards(h);
logGlobal->debugStream() << "Visiting object with " << rewards.size() << " possible rewards";
switch (rewards.size())
{
case 0: // no available rewards, e.g. empty flotsam
@ -153,6 +160,7 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
}
else
{
logGlobal->debugStream() << "Revisiting already visited object";
InfoWindow iw;
iw.player = h->tempOwner;
iw.soundID = soundID;
@ -176,7 +184,6 @@ void CRewardableObject::blockingDialogAnswered(const CGHeroInstance *hero, ui32
if (answer > 0 && answer-1 < info.size())
{
//NOTE: this relies on assumption that there won't be any changes in player/hero during blocking dialog
auto list = getAvailableRewards(hero);
grantReward(list[answer - 1], hero);
}
@ -263,7 +270,10 @@ void CRewardableObject::grantRewardAfterLevelup(const CVisitInfo & info, const C
for (const Bonus & bonus : info.reward.bonuses)
{
assert(bonus.source == Bonus::OBJECT);
assert(bonus.sid == ID);
GiveBonus gb;
gb.who = GiveBonus::HERO;
gb.bonus = bonus;
gb.id = hero->id.getNum();
cb->giveHeroBonus(&gb);
@ -298,8 +308,9 @@ bool CRewardableObject::wasVisited (PlayerColor player) const
switch (visitMode)
{
case VISIT_UNLIMITED:
case VISIT_BONUS:
return false;
case VISIT_ONCE:
case VISIT_ONCE: // FIXME: hide this info deeper and return same as player?
for (auto & visit : info)
{
if (visit.numOfGrants != 0)
@ -308,7 +319,7 @@ bool CRewardableObject::wasVisited (PlayerColor player) const
case VISIT_HERO:
return false;
case VISIT_PLAYER:
return vstd::contains(cb->getPlayer(player)->visitedObjects, ObjectInstanceID(ID));
return vstd::contains(cb->getPlayer(player)->visitedObjects, ObjectInstanceID(id));
default:
return false;
}
@ -318,8 +329,12 @@ bool CRewardableObject::wasVisited (const CGHeroInstance * h) const
{
switch (visitMode)
{
case VISIT_UNLIMITED:
return false;
case VISIT_BONUS:
return h->hasBonusFrom(Bonus::OBJECT, ID);
case VISIT_HERO:
return vstd::contains(h->visitedObjects, ObjectInstanceID(ID)) || h->hasBonusFrom(Bonus::OBJECT, ID);
return h->visitedObjects.count(ObjectInstanceID(id));
default:
return wasVisited(h->tempOwner);
}
@ -330,12 +345,6 @@ void CRewardInfo::loadComponents(std::vector<Component> & comps) const
for (auto comp : extraComponents)
comps.push_back(comp);
for (size_t i=0; i<resources.size(); i++)
{
if (resources[i] !=0)
comps.push_back(Component(Component::RESOURCE, i, resources[i], 0));
}
if (gainedExp) comps.push_back(Component(Component::EXPERIENCE, 0, gainedExp, 0));
if (gainedLevels) comps.push_back(Component(Component::EXPERIENCE, 0, gainedLevels, 0));
@ -358,6 +367,12 @@ void CRewardInfo::loadComponents(std::vector<Component> & comps) const
for (auto & entry : creatures)
comps.push_back(Component(Component::CREATURE, entry.type->idNumber, entry.count, 0));
for (size_t i=0; i<resources.size(); i++)
{
if (resources[i] !=0)
comps.push_back(Component(Component::RESOURCE, i, resources[i], 0));
}
}
Component CRewardInfo::getDisplayedComponent() const
@ -375,19 +390,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);
if(visitMode == VISIT_PLAYER || visitMode == VISIT_ONCE)
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)
@ -458,7 +472,7 @@ void CGPickable::initObj()
blockVisit = true;
switch(ID)
{
case Obj::CAMPFIRE: //FIXME: campfire is not functioning correctly in game (no visible message)
case Obj::CAMPFIRE:
{
soundID = soundBase::experience;
int givenRes = cb->gameState()->getRandomGenerator().nextInt(5);
@ -600,7 +614,7 @@ void CGPickable::initObj()
CGBonusingObject::CGBonusingObject()
{
visitMode = VISIT_UNLIMITED;
visitMode = VISIT_BONUS;
selectMode = SELECT_FIRST;
}
@ -644,7 +658,7 @@ void CGBonusingObject::initObj()
break;
case Obj::FAERIE_RING:
configureMessage(info[0], 49, 50, soundBase::LUCK);
configureBonus(info[0], Bonus::LUCK, 2, 71);
configureBonus(info[0], Bonus::LUCK, 1, 71);
break;
case Obj::FOUNTAIN_OF_FORTUNE:
selectMode = SELECT_RANDOM;
@ -652,8 +666,10 @@ void CGBonusingObject::initObj()
for (int i=0; i<5; i++)
{
configureBonus(info[i], Bonus::LUCK, i-1, 69); //NOTE: description have %d that should be replaced with value
configureMessage(info[i], 55, 56, soundBase::LUCK);
info[i].message.addTxt(MetaString::ADVOB_TXT, 55);
soundID = soundBase::LUCK;
}
onVisited.addTxt(MetaString::ADVOB_TXT, 56);
break;
case Obj::IDOL_OF_FORTUNE:
@ -662,8 +678,10 @@ void CGBonusingObject::initObj()
{
info[i].limiter.dayOfWeek = i+1;
configureBonus(info[i], i%2 ? Bonus::MORALE : Bonus::LUCK, 1, 68);
configureMessage(info[i], 62, 63, soundBase::experience);
info[i].message.addTxt(MetaString::ADVOB_TXT, 62);
soundID = soundBase::experience;
}
onVisited.addTxt(MetaString::ADVOB_TXT, 63);
info.back().limiter.dayOfWeek = 7;
configureBonus(info.back(), Bonus::MORALE, 1, 68); // on last day of week
configureBonus(info.back(), Bonus::LUCK, 1, 68);
@ -692,8 +710,10 @@ void CGBonusingObject::initObj()
configureBonus(info[0], Bonus::MORALE, 2, 96);
configureBonus(info[1], Bonus::MORALE, 1, 97);
configureMessage(info[0], 140, 141, soundBase::temple);
configureMessage(info[1], 140, 141, soundBase::temple);
info[0].message.addTxt(MetaString::ADVOB_TXT, 140);
info[1].message.addTxt(MetaString::ADVOB_TXT, 140);
onVisited.addTxt(MetaString::ADVOB_TXT, 141);
soundID = soundBase::temple;
break;
case Obj::WATERING_HOLE:
configureMessage(info[0], 166, 167, soundBase::MORALE);
@ -918,6 +938,8 @@ void CGVisitableOPH::initObj()
info.resize(2);
info[0].reward.primary[PrimarySkill::SPELL_POWER] = 1;
info[1].reward.primary[PrimarySkill::KNOWLEDGE] = 1;
info[0].reward.resources[Res::GOLD] = -1000;
info[1].reward.resources[Res::GOLD] = -1000;
onSelect.addTxt(MetaString::ADVOB_TXT, 71);
onVisited.addTxt(MetaString::ADVOB_TXT, 72);
onEmpty.addTxt(MetaString::ADVOB_TXT, 73);
@ -928,6 +950,8 @@ void CGVisitableOPH::initObj()
info.resize(2);
info[0].reward.primary[PrimarySkill::ATTACK] = 1;
info[1].reward.primary[PrimarySkill::DEFENSE] = 1;
info[0].reward.resources[Res::GOLD] = -1000;
info[1].reward.resources[Res::GOLD] = -1000;
onSelect.addTxt(MetaString::ADVOB_TXT, 158);
onVisited.addTxt(MetaString::ADVOB_TXT, 159);
onEmpty.addTxt(MetaString::ADVOB_TXT, 160);
@ -937,59 +961,6 @@ void CGVisitableOPH::initObj()
}
}
//TODO: re-enable. Probably in some different form but still necessary
/*
const std::string & CGVisitableOPH::getHoverText() const
{
int pom = -1;
switch(ID)
{
case Obj::ARENA:
pom = -1;
break;
case Obj::MERCENARY_CAMP:
pom = 8;
break;
case Obj::MARLETTO_TOWER:
pom = 7;
break;
case Obj::STAR_AXIS:
pom = 11;
break;
case Obj::GARDEN_OF_REVELATION:
pom = 4;
break;
case Obj::LEARNING_STONE:
pom = 5;
break;
case Obj::TREE_OF_KNOWLEDGE:
pom = 18;
break;
case Obj::LIBRARY_OF_ENLIGHTENMENT:
break;
case Obj::SCHOOL_OF_MAGIC:
pom = 9;
break;
case Obj::SCHOOL_OF_WAR:
pom = 10;
break;
default:
throw std::runtime_error("Wrong CGVisitableOPH object ID!\n");
}
hoverName = VLC->objtypeh->getObjectName(ID);
if(pom >= 0)
hoverName += ("\n" + VLC->generaltexth->xtrainfo[pom]);
const CGHeroInstance *h = cb->getSelectedHero (cb->getCurrentPlayer());
if(h)
{
hoverName += "\n\n";
bool visited = vstd::contains (visitors, h->id);
hoverName += visitedTxt (visited);
}
return hoverName;
}
*/
///////////////////////////////////////////////////////////////////////////////////////////////////
CGVisitableOPW::CGVisitableOPW()

View File

@ -4,6 +4,7 @@
#include "CArmedInstance.h"
#include "../NetPacksBase.h"
#include "../ResourceSet.h"
/*
* CRewardableObject.h, part of VCMI engine
@ -47,7 +48,7 @@ public:
std::vector<CStackBasicDescriptor> creatures;
CRewardLimiter():
numOfGrants(1),
numOfGrants(0),
dayOfWeek(0),
minLevel(0),
primary(4, 0)
@ -128,7 +129,7 @@ public:
}
};
class CVisitInfo
class DLL_LINKAGE CVisitInfo
{
public:
CRewardLimiter limiter;
@ -176,6 +177,7 @@ protected:
VISIT_UNLIMITED, // any number of times. Side effect - object hover text won't contain visited/not visited text
VISIT_ONCE, // only once, first to visit get all the rewards
VISIT_HERO, // every hero can visit object once
VISIT_BONUS, // can be visited by any hero that don't have bonus from this object
VISIT_PLAYER // every player can visit object once
};
@ -209,7 +211,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;

View File

@ -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
@ -192,10 +194,13 @@ void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CR
}
if (guards.getType() == JsonNode::DATA_BOOL)
{
if (guards.Bool())
{
const CCreature * crea = availableCreatures.at(0).at(0);
dwelling->putStack(SlotID(0), new CStackInstance(crea->idNumber, crea->growth * 3 ));
}
}
else for (auto & stack : JsonRandom::loadCreatures(guards, rng))
{
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->idNumber, stack.count));

View File

@ -206,7 +206,14 @@ namespace JsonRandom
return ret;
}
std::vector<Bonus> loadBonuses(const JsonNode & value)
//std::vector<Component> loadComponents(const JsonNode & value)
//{
// std::vector<Component> ret;
// return ret;
// //TODO
//}
std::vector<Bonus> DLL_LINKAGE loadBonuses(const JsonNode & value)
{
std::vector<Bonus> ret;
for (const JsonNode & entry : value.Vector())
@ -218,8 +225,4 @@ namespace JsonRandom
return ret;
}
std::vector<Component> loadComponents(const JsonNode & value)
{
//TODO
}
}

View File

@ -46,5 +46,5 @@ namespace JsonRandom
DLL_LINKAGE std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value);
DLL_LINKAGE std::vector<Bonus> loadBonuses(const JsonNode & value);
DLL_LINKAGE std::vector<Component> loadComponents(const JsonNode & value);
//DLL_LINKAGE std::vector<Component> loadComponents(const JsonNode & value);
}

View File

@ -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,14 +98,18 @@ const std::string & CGCreature::getHoverText() const
ms << " " ;
ms.addTxt(MetaString::CRE_PL_NAMES,subID);
ms.toString(hoverName);
return hoverName;
}
std::string CGCreature::getHoverText(const CGHeroInstance * hero) const
{
std::string hoverName = getHoverText(hero->tempOwner);
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());
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;
@ -117,9 +123,9 @@ const std::string & CGCreature::getHoverText() const
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<std::pair<ui32,si32> >::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<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(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<Res::ERes>(subID);
MetaString ms;
ms << std::pair<ui8,ui32>(9,producedResource);
if(tempOwner >= PlayerColor::PLAYER_LIMIT)
tempOwner = PlayerColor::NEUTRAL;
else
ms << " (" << std::pair<ui8,ui32>(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<ui8,ui32>(9,subID) << "\n(" << std::pair<ui8,ui32>(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<<it.getNum(); //allies - add to possible visitors
return mask;
if (cb->getPlayerRelations(tempOwner, player) != PlayerRelations::ENEMIES)
return true;
return false;
}
void CGGarrison::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
@ -1326,10 +1348,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
@ -1500,11 +1521,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 )
@ -1554,11 +1573,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

View File

@ -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<si32> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CArmedInstance&>(*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 <typename Handler> 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 <typename Handler> 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 <typename Handler> 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 <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -3,7 +3,7 @@
#include "../filesystem/Filesystem.h"
#include "../filesystem/CBinaryReader.h"
#include "../lib/VCMI_Lib.h"
#include "../VCMI_Lib.h"
#include "../GameConstants.h"
#include "../StringConstants.h"
#include "../CGeneralTextHandler.h"
@ -308,6 +308,33 @@ bool ObjectTemplate::isBlockedAt(si32 X, si32 Y) const
return false;
}
std::set<int3> ObjectTemplate::getBlockedOffsets() const
{
std::set<int3> ret;
for(int w = 0; w < getWidth(); ++w)
{
for(int h = 0; h < getHeight(); ++h)
{
if (isBlockedAt(w, h))
ret.insert(int3(-w, -h, 0));
}
}
return ret;
}
int3 ObjectTemplate::getBlockMapOffset() const
{
for(int w = 0; w < getWidth(); ++w)
{
for(int h = 0; h < getHeight(); ++h)
{
if (isBlockedAt(w, h))
return int3(-w, -h, 0);
}
}
return int3(-1,-1,-1);
}
bool ObjectTemplate::isVisitableFrom(si8 X, si8 Y) const
{
// visitDir uses format

View File

@ -15,6 +15,7 @@
class CBinaryReader;
class CLegacyConfigParser;
class JsonNode;
class int3;
class DLL_LINKAGE ObjectTemplate
{
@ -56,6 +57,8 @@ public:
bool isVisitableAt(si32 X, si32 Y) const;
bool isVisibleAt(si32 X, si32 Y) const;
bool isBlockedAt(si32 X, si32 Y) const;
std::set<int3> getBlockedOffsets() const;
int3 getBlockMapOffset() const; //bottom-right corner when firts blocked tile is
// Checks if object is visitable from certain direction. X and Y must be between -1..+1
bool isVisitableFrom(si8 X, si8 Y) const;

View File

@ -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;
}

View File

@ -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
{
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;
}
}

View File

@ -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
@ -96,6 +97,7 @@ void registerTypesMapObjectTypes(Serializer &s)
REGISTER_GENERIC_HANDLER(CGBorderGuard);
REGISTER_GENERIC_HANDLER(CGCreature);
REGISTER_GENERIC_HANDLER(CGDenOfthieves);
REGISTER_GENERIC_HANDLER(CGDwelling);
REGISTER_GENERIC_HANDLER(CGEvent);
REGISTER_GENERIC_HANDLER(CGGarrison);
REGISTER_GENERIC_HANDLER(CGHeroPlaceholder);
@ -121,6 +123,7 @@ void registerTypesMapObjectTypes(Serializer &s)
REGISTER_GENERIC_HANDLER(CGSignBottle);
REGISTER_GENERIC_HANDLER(CGSirens);
REGISTER_GENERIC_HANDLER(CGTeleport);
REGISTER_GENERIC_HANDLER(CGTownInstance);
REGISTER_GENERIC_HANDLER(CGUniversity);
REGISTER_GENERIC_HANDLER(CGVisitableOPH);
REGISTER_GENERIC_HANDLER(CGVisitableOPW);
@ -234,7 +237,6 @@ void registerTypesClientPacks1(Serializer &s)
s.template registerType<CPackForClient, NewTurn>();
s.template registerType<CPackForClient, InfoWindow>();
s.template registerType<CPackForClient, SetObjectProperty>();
s.template registerType<CPackForClient, SetHoverName>();
s.template registerType<CPackForClient, ShowInInfobox>();
s.template registerType<CPackForClient, AdvmapSpellCast>();
s.template registerType<CPackForClient, OpenWindow>();

View File

@ -23,8 +23,8 @@ void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3&
}
CMapGenerator::CMapGenerator(shared_ptr<CMapGenOptions> mapGenOptions, int randomSeed /*= std::time(nullptr)*/) :
mapGenOptions(mapGenOptions), randomSeed(randomSeed), monolithIndex(0)
CMapGenerator::CMapGenerator(shared_ptr<CMapGenOptions> mapGenOptions, int RandomSeed /*= std::time(nullptr)*/) :
mapGenOptions(mapGenOptions), randomSeed(RandomSeed), monolithIndex(0)
{
rand.setSeed(randomSeed);
}
@ -50,12 +50,13 @@ void CMapGenerator::initTiles()
CMapGenerator::~CMapGenerator()
{
//FIXME: what if map is not present anymore?
if (tiles && map)
if (tiles)
{
for (int i=0; i < map->width; i++)
int width = mapGenOptions->getWidth();
int height = mapGenOptions->getHeight();
for (int i=0; i < width; i++)
{
for(int j=0; j < map->height; j++)
for(int j=0; j < height; j++)
{
delete [] tiles[i][j];
}
@ -80,6 +81,7 @@ std::unique_ptr<CMap> CMapGenerator::generate()
genZones();
map->calculateGuardingGreaturePositions(); //clear map so that all tiles are unguarded
fillZones();
//updated fuarded tiles will be calculated in CGameState::initMapObjects()
}
catch (rmgException &e)
{
@ -251,8 +253,8 @@ void CMapGenerator::createConnections()
setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template
//zones can make paths only in their own area
zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId()); //make connection towards our zone center
zoneB->crunchPath (this, guardPos, zoneB->getPos(), zoneB->getId()); //make connection towards other zone center
zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId(), zoneA->getFreePaths()); //make connection towards our zone center
zoneB->crunchPath (this, guardPos, zoneB->getPos(), zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center
break; //we're done with this connection
}
}

View File

@ -51,7 +51,7 @@ public:
class DLL_LINKAGE CMapGenerator
{
public:
explicit CMapGenerator(shared_ptr<CMapGenOptions> mapGenOptions, int randomSeed = std::time(nullptr));
explicit CMapGenerator(shared_ptr<CMapGenOptions> mapGenOptions, int RandomSeed = std::time(nullptr));
~CMapGenerator(); // required due to unique_ptr
std::unique_ptr<CMap> generate();

View File

@ -314,6 +314,11 @@ std::vector<CTreasureInfo> CRmgTemplateZone::getTreasureInfo()
return treasureInfo;
}
std::set<int3>* CRmgTemplateZone::getFreePaths()
{
return &freePaths;
}
float3 CRmgTemplateZone::getCenter() const
{
return center;
@ -756,7 +761,7 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
playerInfo.allowedFactions.clear();
playerInfo.allowedFactions.insert (townType);
playerInfo.hasMainTown = true;
playerInfo.posOfMainTown = town->pos - int3(2, 0, 0);
playerInfo.posOfMainTown = town->pos - town->getVisitableOffset();
playerInfo.generateHeroAtMainTown = true;
//now create actual towns
@ -957,20 +962,49 @@ void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
void CRmgTemplateZone::createObstacles(CMapGenerator* gen)
{
//get all possible obstacles for this terrain
for (auto primaryID : VLC->objtypeh->knownObjects())
{
for (auto secondaryID : VLC->objtypeh->knownSubObjects(primaryID))
{
auto handler = VLC->objtypeh->getHandlerFor(primaryID, secondaryID);
if (handler->isStaticObject())
{
for (auto temp : handler->getTemplates())
{
if (temp.canBePlacedAt(terrainType) && temp.getBlockMapOffset().valid())
possibleObstacles.push_back(temp);
}
}
}
}
auto sel = gen->editManager->getTerrainSelection();
sel.clearSelection();
auto tryToPlaceObstacleHere = [this, gen](int3& tile)-> bool
{
auto temp = *RandomGeneratorUtil::nextItem(possibleObstacles, gen->rand);
int3 obstaclePos = tile + temp.getBlockMapOffset();
if (canObstacleBePlacedHere(gen, temp, obstaclePos)) //can be placed here
{
auto obj = VLC->objtypeh->getHandlerFor(temp.id, temp.subid)->create(temp);
placeObject(gen, obj, obstaclePos);
return true;
}
return false;
};
for (auto tile : tileinfo)
{
//test code - block all the map to show paths clearly
//if (gen->isPossible(tile))
// gen->setOccupied(tile, ETileType::BLOCKED);
if (gen->shouldBeBlocked(tile)) //fill tiles that should be blocked with obstacles
{
auto obj = new CGObjectInstance();
obj->ID = static_cast<Obj>(130);
obj->subID = 0;
placeObject(gen, obj, tile);
while (!tryToPlaceObstacleHere(tile));
}
else if (gen->isPossible(tile))
{
//try to place random obstacle once - if not possible, leave it clear
tryToPlaceObstacleHere(tile);
}
}
}
@ -1026,6 +1060,23 @@ bool CRmgTemplateZone::findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dis
return result;
}
bool CRmgTemplateZone::canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos)
{
auto tilesBlockedByObject = temp.getBlockedOffsets();
bool allTilesAvailable = true;
for (auto blockingTile : tilesBlockedByObject)
{
int3 t = pos + blockingTile;
if (!gen->map->isInTheMap(t) || !(gen->isPossible(t) || gen->shouldBeBlocked(t)))
{
allTilesAvailable = false; //if at least one tile is not possible, object can't be placed here
break;
}
}
return allTilesAvailable;
}
bool CRmgTemplateZone::findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos)
{
//we need object apperance to deduce free tiles
@ -1213,8 +1264,11 @@ bool CRmgTemplateZone::guardObject(CMapGenerator* gen, CGObjectInstance* object,
gen->setOccupied (guardTile, ETileType::USED);
}
else
gen->setOccupied (guardTile, ETileType::FREE);
else //allow no guard or other object in front of this object
{
for (auto tile : tiles)
gen->setOccupied (tile, ETileType::FREE);
}
return true;
}

View File

@ -21,6 +21,7 @@ class CMapGenerator;
class CTileInfo;
class int3;
class CGObjectInstance;
class ObjectTemplate;
namespace ETemplateZoneType
{
@ -149,6 +150,7 @@ public:
std::vector<TRmgTemplateZoneId> getConnections() const;
void addTreasureInfo(CTreasureInfo & info);
std::vector<CTreasureInfo> getTreasureInfo();
std::set<int3>* getFreePaths();
ObjectInfo getRandomObject (CMapGenerator* gen, ui32 value);
@ -172,6 +174,7 @@ private:
ui16 totalDensity;
std::vector<CTreasureInfo> treasureInfo;
std::vector<ObjectInfo> possibleObjects;
std::vector<ObjectTemplate> possibleObstacles;
//content info
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
@ -182,12 +185,13 @@ private:
float3 center;
std::set<int3> tileinfo; //irregular area assined to zone
std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
std::map<TRmgTemplateZoneId, bool> alreadyConnected; //TODO: allow multiple connections between two zones?
std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to
bool pointIsIn(int x, int y);
void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects
bool findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos);
bool findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dist, int3 &pos);
bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos);
void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str);

View File

@ -48,7 +48,7 @@
<Add option="-lboost_thread$(#boost.libsuffix)" />
<Add option="-lboost_chrono$(#boost.libsuffix)" />
<Add option="-lVCMI_lib" />
<Add directory="$(#boost.lib)" />
<Add directory="$(#boost.lib32)" />
<Add directory="../.." />
</Linker>
<Unit filename="ERMInterpreter.cpp" />
@ -58,7 +58,6 @@
<Unit filename="ERMScriptModule.cpp" />
<Unit filename="ERMScriptModule.h" />
<Unit filename="StdInc.h">
<Option compile="1" />
<Option weight="0" />
</Unit>
<Extensions>

View File

@ -2,11 +2,14 @@
#include "ERMInterpreter.h"
#include <cctype>
#include "../../lib/CObjectHandler.h"
#include "../../lib/mapObjects/CObjectHandler.h"
#include "../../lib/mapObjects/MapObjects.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/CCreatureHandler.h"
#include "../../lib/VCMIDirs.h"
#include "../../lib/IGameCallback.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/MiscObjects.h"
/*
* ERMInterpreter.cpp, part of VCMI engine

View File

@ -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<CBlockingDialogQuery>(*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<CObjectVisitQuery>(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,37 @@ 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<int3, ShashInt3> tiles;
getTilesInRange(tiles, center, radius, player, hide? -1 : 1);
if (hide)
{
std::unordered_set<int3, ShashInt3> observedTiles; //do not hide tiles observed by heroes. May lead to disastrous AI problems
auto p = gs->getPlayer(player);
for (auto h : p->heroes)
{
getTilesInRange(observedTiles, h->getSightCenter(), h->getSightRadious(), h->tempOwner, -1);
}
for (auto t : p->towns)
{
getTilesInRange(observedTiles, t->getSightCenter(), t->getSightRadious(), t->tempOwner, -1);
}
for (auto tile : observedTiles)
vstd::erase_if_present (tiles, tile);
}
changeFogOfWar(tiles, player, hide);
}
void CGameHandler::changeFogOfWar(std::unordered_set<int3, ShashInt3> &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()))

View File

@ -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<int3, ShashInt3> &tiles, PlayerColor player, bool hide) override;
bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) override;
@ -289,7 +290,7 @@ public:
private:
std::list<PlayerColor> 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);

View File

@ -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]);
}