mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-17 01:32:21 +02:00
Merge pull request #2209 from IvanSavenko/map_object_configuration
Support for json configuration of some map objects
This commit is contained in:
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "../../../lib/mapObjectConstructors/CommonConstructors.h"
|
#include "../../../lib/mapObjectConstructors/CBankInstanceConstructor.h"
|
||||||
|
|
||||||
namespace NKAI
|
namespace NKAI
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "Nullkiller.h"
|
#include "Nullkiller.h"
|
||||||
#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "../../../lib/mapObjectConstructors/CommonConstructors.h"
|
#include "../../../lib/mapObjectConstructors/CBankInstanceConstructor.h"
|
||||||
#include "../../../lib/mapObjects/MapObjects.h"
|
#include "../../../lib/mapObjects/MapObjects.h"
|
||||||
#include "../../../lib/CCreatureHandler.h"
|
#include "../../../lib/CCreatureHandler.h"
|
||||||
#include "../../../lib/CPathfinder.h"
|
#include "../../../lib/CPathfinder.h"
|
||||||
|
@ -23,7 +23,7 @@ using namespace Goals;
|
|||||||
|
|
||||||
bool BuildBoat::operator==(const BuildBoat & other) const
|
bool BuildBoat::operator==(const BuildBoat & other) const
|
||||||
{
|
{
|
||||||
return shipyard->o->id == other.shipyard->o->id;
|
return shipyard == other.shipyard;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//TSubgoal BuildBoat::decomposeSingle() const
|
//TSubgoal BuildBoat::decomposeSingle() const
|
||||||
@ -54,7 +54,7 @@ void BuildBoat::accept(AIGateway * ai)
|
|||||||
throw cannotFulfillGoalException("Can not afford boat");
|
throw cannotFulfillGoalException("Can not afford boat");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cb->getPlayerRelations(ai->playerID, shipyard->o->tempOwner) == PlayerRelations::ENEMIES)
|
if(cb->getPlayerRelations(ai->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
throw cannotFulfillGoalException("Can not build boat in enemy shipyard");
|
throw cannotFulfillGoalException("Can not build boat in enemy shipyard");
|
||||||
}
|
}
|
||||||
@ -65,9 +65,8 @@ void BuildBoat::accept(AIGateway * ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Building boat at shipyard %s located at %s, estimated boat position %s",
|
"Building boat at shipyard located at %s, estimated boat position %s",
|
||||||
shipyard->o->getObjectName(),
|
shipyard->getObject()->visitablePos().toString(),
|
||||||
shipyard->o->visitablePos().toString(),
|
|
||||||
shipyard->bestLocation().toString());
|
shipyard->bestLocation().toString());
|
||||||
|
|
||||||
cb->buildBoat(shipyard);
|
cb->buildBoat(shipyard);
|
||||||
|
@ -32,9 +32,9 @@ namespace AIPathfinding
|
|||||||
|
|
||||||
Goals::TSubgoal BuildBoatAction::decompose(const CGHeroInstance * hero) const
|
Goals::TSubgoal BuildBoatAction::decompose(const CGHeroInstance * hero) const
|
||||||
{
|
{
|
||||||
if(cb->getPlayerRelations(ai->playerID, shipyard->o->tempOwner) == PlayerRelations::ENEMIES)
|
if(cb->getPlayerRelations(ai->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
return Goals::sptr(Goals::CaptureObject(shipyard->o));
|
return Goals::sptr(Goals::CaptureObject(targetObject()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Goals::sptr(Goals::Invalid());
|
return Goals::sptr(Goals::Invalid());
|
||||||
@ -44,7 +44,7 @@ namespace AIPathfinding
|
|||||||
{
|
{
|
||||||
auto hero = source->actor->hero;
|
auto hero = source->actor->hero;
|
||||||
|
|
||||||
if(cb->getPlayerRelations(hero->tempOwner, shipyard->o->tempOwner) == PlayerRelations::ENEMIES)
|
if(cb->getPlayerRelations(hero->tempOwner, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
#if NKAI_TRACE_LEVEL > 1
|
#if NKAI_TRACE_LEVEL > 1
|
||||||
logAi->trace("Can not build a boat. Shipyard is enemy.");
|
logAi->trace("Can not build a boat. Shipyard is enemy.");
|
||||||
@ -70,7 +70,7 @@ namespace AIPathfinding
|
|||||||
|
|
||||||
const CGObjectInstance * BuildBoatAction::targetObject() const
|
const CGObjectInstance * BuildBoatAction::targetObject() const
|
||||||
{
|
{
|
||||||
return shipyard->o;
|
return dynamic_cast<const CGObjectInstance*>(shipyard);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChainActor * BuildBoatAction::getActor(const ChainActor * sourceActor) const
|
const ChainActor * BuildBoatAction::getActor(const ChainActor * sourceActor) const
|
||||||
@ -101,7 +101,7 @@ namespace AIPathfinding
|
|||||||
|
|
||||||
std::string BuildBoatAction::toString() const
|
std::string BuildBoatAction::toString() const
|
||||||
{
|
{
|
||||||
return "Build Boat at " + shipyard->o->getObjectName();
|
return "Build Boat at " + shipyard->getObject()->visitablePos().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SummonBoatAction::canAct(const AIPathNode * source) const
|
bool SummonBoatAction::canAct(const AIPathNode * source) const
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include "../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
#include "../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
#include "../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "../../lib/mapObjectConstructors/CommonConstructors.h"
|
#include "../../lib/mapObjectConstructors/CBankInstanceConstructor.h"
|
||||||
#include "../../lib/mapObjects/CBank.h"
|
#include "../../lib/mapObjects/CBank.h"
|
||||||
#include "../../lib/mapObjects/CGDwelling.h"
|
#include "../../lib/mapObjects/CGDwelling.h"
|
||||||
|
|
||||||
|
@ -22,14 +22,14 @@ using namespace Goals;
|
|||||||
|
|
||||||
bool BuildBoat::operator==(const BuildBoat & other) const
|
bool BuildBoat::operator==(const BuildBoat & other) const
|
||||||
{
|
{
|
||||||
return shipyard->o->id == other.shipyard->o->id;
|
return shipyard == other.shipyard;
|
||||||
}
|
}
|
||||||
|
|
||||||
TSubgoal BuildBoat::whatToDoToAchieve()
|
TSubgoal BuildBoat::whatToDoToAchieve()
|
||||||
{
|
{
|
||||||
if(cb->getPlayerRelations(ai->playerID, shipyard->o->tempOwner) == PlayerRelations::ENEMIES)
|
if(cb->getPlayerRelations(ai->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
return fh->chooseSolution(ai->ah->howToVisitObj(shipyard->o));
|
return fh->chooseSolution(ai->ah->howToVisitObj(dynamic_cast<const CGObjectInstance*>(shipyard)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(shipyard->shipyardStatus() != IShipyard::GOOD)
|
if(shipyard->shipyardStatus() != IShipyard::GOOD)
|
||||||
@ -53,7 +53,7 @@ void BuildBoat::accept(VCAI * ai)
|
|||||||
throw cannotFulfillGoalException("Can not afford boat");
|
throw cannotFulfillGoalException("Can not afford boat");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cb->getPlayerRelations(ai->playerID, shipyard->o->tempOwner) == PlayerRelations::ENEMIES)
|
if(cb->getPlayerRelations(ai->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
throw cannotFulfillGoalException("Can not build boat in enemy shipyard");
|
throw cannotFulfillGoalException("Can not build boat in enemy shipyard");
|
||||||
}
|
}
|
||||||
@ -64,9 +64,8 @@ void BuildBoat::accept(VCAI * ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Building boat at shipyard %s located at %s, estimated boat position %s",
|
"Building boat at shipyard located at %s, estimated boat position %s",
|
||||||
shipyard->o->getObjectName(),
|
shipyard->getObject()->visitablePos().toString(),
|
||||||
shipyard->o->visitablePos().toString(),
|
|
||||||
shipyard->bestLocation().toString());
|
shipyard->bestLocation().toString());
|
||||||
|
|
||||||
cb->buildBoat(shipyard);
|
cb->buildBoat(shipyard);
|
||||||
@ -81,5 +80,5 @@ std::string BuildBoat::name() const
|
|||||||
|
|
||||||
std::string BuildBoat::completeMessage() const
|
std::string BuildBoat::completeMessage() const
|
||||||
{
|
{
|
||||||
return "Boat have been built at " + shipyard->o->visitablePos().toString();
|
return "Boat have been built at " + shipyard->getObject()->visitablePos().toString();
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,7 @@ void CCallback::sendMessage(const std::string &mess, const CGObjectInstance * cu
|
|||||||
void CCallback::buildBoat( const IShipyard *obj )
|
void CCallback::buildBoat( const IShipyard *obj )
|
||||||
{
|
{
|
||||||
BuildBoat bb;
|
BuildBoat bb;
|
||||||
bb.objid = obj->o->id;
|
bb.objid = dynamic_cast<const CGObjectInstance*>(obj)->id;
|
||||||
sendRequest(&bb);
|
sendRequest(&bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,7 +906,7 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
|||||||
case EOpenWindowMode::SHIPYARD_WINDOW:
|
case EOpenWindowMode::SHIPYARD_WINDOW:
|
||||||
{
|
{
|
||||||
const IShipyard *sy = IShipyard::castFrom(cl.getObj(ObjectInstanceID(pack.id1)));
|
const IShipyard *sy = IShipyard::castFrom(cl.getObj(ObjectInstanceID(pack.id1)));
|
||||||
callInterfaceIfPresent(cl, sy->o->tempOwner, &IGameEventsReceiver::showShipyardDialog, sy);
|
callInterfaceIfPresent(cl, sy->getObject()->getOwner(), &IGameEventsReceiver::showShipyardDialog, sy);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EOpenWindowMode::THIEVES_GUILD:
|
case EOpenWindowMode::THIEVES_GUILD:
|
||||||
|
@ -45,6 +45,9 @@
|
|||||||
|
|
||||||
#include "../../CCallback.h"
|
#include "../../CCallback.h"
|
||||||
|
|
||||||
|
#include "../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
|
#include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
|
#include "../lib/mapObjectConstructors/CommonConstructors.h"
|
||||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||||
#include "../lib/mapObjects/CGMarket.h"
|
#include "../lib/mapObjects/CGMarket.h"
|
||||||
#include "../lib/ArtifactUtils.h"
|
#include "../lib/ArtifactUtils.h"
|
||||||
@ -1093,11 +1096,20 @@ CShipyardWindow::CShipyardWindow(const TResources & cost, int state, BoatId boat
|
|||||||
|
|
||||||
bgWater = std::make_shared<CPicture>("TPSHIPBK", 100, 69);
|
bgWater = std::make_shared<CPicture>("TPSHIPBK", 100, 69);
|
||||||
|
|
||||||
std::string boatFilenames[3] = {"AB01_", "AB02_", "AB03_"};
|
auto handler = CGI->objtypeh->getHandlerFor(Obj::BOAT, boatType);
|
||||||
|
|
||||||
|
auto boatConstructor = std::dynamic_pointer_cast<const BoatInstanceConstructor>(handler);
|
||||||
|
|
||||||
|
assert(boatConstructor);
|
||||||
|
|
||||||
|
if (boatConstructor)
|
||||||
|
{
|
||||||
|
std::string boatFilename = boatConstructor->getBoatAnimationName();
|
||||||
|
|
||||||
Point waterCenter = Point(bgWater->pos.x+bgWater->pos.w/2, bgWater->pos.y+bgWater->pos.h/2);
|
Point waterCenter = Point(bgWater->pos.x+bgWater->pos.w/2, bgWater->pos.y+bgWater->pos.h/2);
|
||||||
bgShip = std::make_shared<CAnimImage>(boatFilenames[boatType.getNum()], 0, 7, 120, 96, 0);
|
bgShip = std::make_shared<CAnimImage>(boatFilename, 0, 7, 120, 96, 0);
|
||||||
bgShip->center(waterCenter);
|
bgShip->center(waterCenter);
|
||||||
|
}
|
||||||
|
|
||||||
// Create resource icons and costs.
|
// Create resource icons and costs.
|
||||||
std::string goldValue = std::to_string(cost[EGameResID::GOLD]);
|
std::string goldValue = std::to_string(cost[EGameResID::GOLD]);
|
||||||
|
@ -66,9 +66,14 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
${MAIN_LIB_DIR}/logging/CLogger.cpp
|
${MAIN_LIB_DIR}/logging/CLogger.cpp
|
||||||
|
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/AObjectTypeHandler.cpp
|
${MAIN_LIB_DIR}/mapObjectConstructors/AObjectTypeHandler.cpp
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/CBankInstanceConstructor.cpp
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/CObjectClassesHandler.cpp
|
${MAIN_LIB_DIR}/mapObjectConstructors/CObjectClassesHandler.cpp
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/CommonConstructors.cpp
|
${MAIN_LIB_DIR}/mapObjectConstructors/CommonConstructors.cpp
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/CRewardableConstructor.cpp
|
${MAIN_LIB_DIR}/mapObjectConstructors/CRewardableConstructor.cpp
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/DwellingInstanceConstructor.cpp
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/HillFortInstanceConstructor.cpp
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/ShipyardInstanceConstructor.cpp
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/ShrineInstanceConstructor.cpp
|
||||||
|
|
||||||
${MAIN_LIB_DIR}/mapObjects/CArmedInstance.cpp
|
${MAIN_LIB_DIR}/mapObjects/CArmedInstance.cpp
|
||||||
${MAIN_LIB_DIR}/mapObjects/CBank.cpp
|
${MAIN_LIB_DIR}/mapObjects/CBank.cpp
|
||||||
@ -369,11 +374,17 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
${MAIN_LIB_DIR}/logging/CLogger.h
|
${MAIN_LIB_DIR}/logging/CLogger.h
|
||||||
|
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/AObjectTypeHandler.h
|
${MAIN_LIB_DIR}/mapObjectConstructors/AObjectTypeHandler.h
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/CBankInstanceConstructor.h
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/CDefaultObjectTypeHandler.h
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/CObjectClassesHandler.h
|
${MAIN_LIB_DIR}/mapObjectConstructors/CObjectClassesHandler.h
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/CommonConstructors.h
|
${MAIN_LIB_DIR}/mapObjectConstructors/CommonConstructors.h
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/CRewardableConstructor.h
|
${MAIN_LIB_DIR}/mapObjectConstructors/CRewardableConstructor.h
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/DwellingInstanceConstructor.h
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/HillFortInstanceConstructor.h
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/IObjectInfo.h
|
${MAIN_LIB_DIR}/mapObjectConstructors/IObjectInfo.h
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/RandomMapInfo.h
|
${MAIN_LIB_DIR}/mapObjectConstructors/RandomMapInfo.h
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/ShipyardInstanceConstructor.h
|
||||||
|
${MAIN_LIB_DIR}/mapObjectConstructors/ShrineInstanceConstructor.h
|
||||||
${MAIN_LIB_DIR}/mapObjectConstructors/SObjectSounds.h
|
${MAIN_LIB_DIR}/mapObjectConstructors/SObjectSounds.h
|
||||||
|
|
||||||
${MAIN_LIB_DIR}/mapObjects/CArmedInstance.h
|
${MAIN_LIB_DIR}/mapObjects/CArmedInstance.h
|
||||||
|
@ -148,6 +148,7 @@
|
|||||||
"mageGuild" : 4,
|
"mageGuild" : 4,
|
||||||
"warMachine" : "ballista",
|
"warMachine" : "ballista",
|
||||||
"moatAbility" : "castleMoat",
|
"moatAbility" : "castleMoat",
|
||||||
|
"boat" : "boatCastle",
|
||||||
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
||||||
|
|
||||||
"buildings" :
|
"buildings" :
|
||||||
|
@ -153,6 +153,7 @@
|
|||||||
"primaryResource" : "mercury",
|
"primaryResource" : "mercury",
|
||||||
"warMachine" : "ballista",
|
"warMachine" : "ballista",
|
||||||
"moatAbility" : "castleMoat",
|
"moatAbility" : "castleMoat",
|
||||||
|
"boat" : "boatNecropolis",
|
||||||
|
|
||||||
"buildings" :
|
"buildings" :
|
||||||
{
|
{
|
||||||
|
@ -148,6 +148,7 @@
|
|||||||
"mageGuild" : 3,
|
"mageGuild" : 3,
|
||||||
"warMachine" : "firstAidTent",
|
"warMachine" : "firstAidTent",
|
||||||
"moatAbility" : "fortressMoat",
|
"moatAbility" : "fortressMoat",
|
||||||
|
"boat" : "boatFortress",
|
||||||
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
||||||
|
|
||||||
"buildings" :
|
"buildings" :
|
||||||
|
@ -153,6 +153,7 @@
|
|||||||
"mageGuild" : 5,
|
"mageGuild" : 5,
|
||||||
"warMachine" : "firstAidTent",
|
"warMachine" : "firstAidTent",
|
||||||
"moatAbility" : "necropolisMoat",
|
"moatAbility" : "necropolisMoat",
|
||||||
|
"boat" : "boatNecropolis",
|
||||||
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
||||||
|
|
||||||
"buildings" :
|
"buildings" :
|
||||||
|
@ -310,6 +310,10 @@
|
|||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 500,
|
"value" : 500,
|
||||||
"rarity" : 100
|
"rarity" : 100
|
||||||
|
},
|
||||||
|
"visitText" : 127,
|
||||||
|
"spell" : {
|
||||||
|
"level" : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,6 +334,10 @@
|
|||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 2000,
|
"value" : 2000,
|
||||||
"rarity" : 100
|
"rarity" : 100
|
||||||
|
},
|
||||||
|
"visitText" : 128,
|
||||||
|
"spell" : {
|
||||||
|
"level" : 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,6 +358,10 @@
|
|||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 3000,
|
"value" : 3000,
|
||||||
"rarity" : 100
|
"rarity" : 100
|
||||||
|
},
|
||||||
|
"visitText" : 129,
|
||||||
|
"spell" : {
|
||||||
|
"level" : 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -476,7 +488,8 @@
|
|||||||
"index" : 0,
|
"index" : 0,
|
||||||
"aiValue" : 1000,
|
"aiValue" : 1000,
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
}
|
},
|
||||||
|
"boat" : "boatCastle"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -640,19 +653,6 @@
|
|||||||
},
|
},
|
||||||
"randomDwelling" : { "index" :216, "handler": "randomDwelling", "types" : { "object" : { "index" : 0} } },
|
"randomDwelling" : { "index" :216, "handler": "randomDwelling", "types" : { "object" : { "index" : 0} } },
|
||||||
|
|
||||||
"randomResource" : {
|
|
||||||
"index" :76,
|
|
||||||
"handler": "randomResource",
|
|
||||||
"types" : {
|
|
||||||
"object" : {
|
|
||||||
"index" : 0,
|
|
||||||
"templates" : {
|
|
||||||
"normal" : { "animation" : "AVTrndm0", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"randomArtifact" : {
|
"randomArtifact" : {
|
||||||
"index" :65,
|
"index" :65,
|
||||||
"handler": "randomArtifact",
|
"handler": "randomArtifact",
|
||||||
@ -830,7 +830,7 @@
|
|||||||
/// Classes without dedicated object
|
/// Classes without dedicated object
|
||||||
"hillFort" : {
|
"hillFort" : {
|
||||||
"index" :35,
|
"index" :35,
|
||||||
"handler": "generic",
|
"handler": "hillFort",
|
||||||
"base" : {
|
"base" : {
|
||||||
"sounds" : {
|
"sounds" : {
|
||||||
"ambient" : ["LOOPSWAR"],
|
"ambient" : ["LOOPSWAR"],
|
||||||
@ -845,7 +845,14 @@
|
|||||||
"zoneLimit" : 1,
|
"zoneLimit" : 1,
|
||||||
"value" : 7000,
|
"value" : 7000,
|
||||||
"rarity" : 20
|
"rarity" : 20
|
||||||
}
|
},
|
||||||
|
"upgradeCostFactor" : [
|
||||||
|
0, // level 1
|
||||||
|
25,
|
||||||
|
50,
|
||||||
|
75,
|
||||||
|
100 // level 5+
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -861,7 +868,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"marketOfTime" : { // Unused/not implemented H3 object present on some maps RoE maps
|
"marketOfTime" : { // Unused/not implemented H3 object present on some RoE maps
|
||||||
"index" :50,
|
"index" :50,
|
||||||
"handler": "generic"
|
"handler": "generic"
|
||||||
},
|
},
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
"randomResource":
|
"randomResource":
|
||||||
{
|
{
|
||||||
"index" :76,
|
"index" :76,
|
||||||
"handler": "resource",
|
"handler": "randomResource",
|
||||||
"base" : {
|
"base" : {
|
||||||
"base" : {
|
"base" : {
|
||||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||||
@ -69,9 +69,10 @@
|
|||||||
},
|
},
|
||||||
"templates" :
|
"templates" :
|
||||||
{
|
{
|
||||||
"res" :
|
"normal" : {
|
||||||
{
|
"animation" : "AVTrndm0",
|
||||||
"animation" : "AVTrndm0.def"
|
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||||
|
"mask" : [ "VV", "VA"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,21 +147,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"types" : {
|
"types" : {
|
||||||
"evil" : // Necropolis
|
"boatNecropolis" : {
|
||||||
{
|
|
||||||
"index" : 0,
|
"index" : 0,
|
||||||
"actualAnimation" : "AB01_.def",
|
"actualAnimation" : "AB01_.def",
|
||||||
"overlayAnimation" : "ABM01_.def",
|
"overlayAnimation" : "ABM01_.def",
|
||||||
"flagAnimations" : ["ABF01L", "ABF01G", "ABF01R", "ABF01D", "ABF01B", "ABF01P", "ABF01W", "ABF01K"]
|
"flagAnimations" : ["ABF01L", "ABF01G", "ABF01R", "ABF01D", "ABF01B", "ABF01P", "ABF01W", "ABF01K"]
|
||||||
},
|
},
|
||||||
"good" : // Castle
|
"boatCastle" : {
|
||||||
{
|
|
||||||
"index" : 1,
|
"index" : 1,
|
||||||
"actualAnimation" : "AB02_.def",
|
"actualAnimation" : "AB02_.def",
|
||||||
"overlayAnimation" : "ABM02_.def",
|
"overlayAnimation" : "ABM02_.def",
|
||||||
"flagAnimations" : ["ABF02L", "ABF02G", "ABF02R", "ABF02D", "ABF02B", "ABF02P", "ABF02W", "ABF02K"]
|
"flagAnimations" : ["ABF02L", "ABF02G", "ABF02R", "ABF02D", "ABF02B", "ABF02P", "ABF02W", "ABF02K"]
|
||||||
},
|
},
|
||||||
"neutral" : { // Fortress
|
"boatFortress" : {
|
||||||
"index" : 2,
|
"index" : 2,
|
||||||
"actualAnimation" : "AB03_.def",
|
"actualAnimation" : "AB03_.def",
|
||||||
"overlayAnimation" : "ABM03_.def",
|
"overlayAnimation" : "ABM03_.def",
|
||||||
|
@ -124,6 +124,10 @@
|
|||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Identifier of war machine produced by blacksmith in town"
|
"description" : "Identifier of war machine produced by blacksmith in town"
|
||||||
},
|
},
|
||||||
|
"boat" : {
|
||||||
|
"type" : "string",
|
||||||
|
"description" : "Identifier of boat type that is produced by shipyard in town, if any"
|
||||||
|
},
|
||||||
"horde" : {
|
"horde" : {
|
||||||
"type" : "array",
|
"type" : "array",
|
||||||
"maxItems" : 2,
|
"maxItems" : 2,
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class SpellID;
|
class SpellID;
|
||||||
|
enum class ESpellSchool: int8_t;
|
||||||
|
|
||||||
namespace spells
|
namespace spells
|
||||||
{
|
{
|
||||||
@ -43,6 +44,7 @@ public:
|
|||||||
virtual bool isSpecial() const = 0;
|
virtual bool isSpecial() const = 0;
|
||||||
virtual bool isMagical() const = 0; //Should this spell considered as magical effect or as ability (like dendroid's bind)
|
virtual bool isMagical() const = 0; //Should this spell considered as magical effect or as ability (like dendroid's bind)
|
||||||
|
|
||||||
|
virtual bool hasSchool(ESpellSchool school) const = 0;
|
||||||
virtual void forEachSchool(const SchoolCallback & cb) const = 0;
|
virtual void forEachSchool(const SchoolCallback & cb) const = 0;
|
||||||
virtual const std::string & getCastSound() const = 0;
|
virtual const std::string & getCastSound() const = 0;
|
||||||
virtual int32_t getCost(const int32_t skillLevel) const = 0;
|
virtual int32_t getCost(const int32_t skillLevel) const = 0;
|
||||||
|
@ -621,7 +621,7 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
|||||||
auto dwellingIDs = VLC->objtypeh->knownSubObjects(primaryID);
|
auto dwellingIDs = VLC->objtypeh->knownSubObjects(primaryID);
|
||||||
for (si32 entry : dwellingIDs)
|
for (si32 entry : dwellingIDs)
|
||||||
{
|
{
|
||||||
const auto * handler = dynamic_cast<const CDwellingInstanceConstructor *>(VLC->objtypeh->getHandlerFor(primaryID, entry).get());
|
const auto * handler = dynamic_cast<const DwellingInstanceConstructor *>(VLC->objtypeh->getHandlerFor(primaryID, entry).get());
|
||||||
|
|
||||||
if (handler->producesCreature(VLC->creh->objects[cid]))
|
if (handler->producesCreature(VLC->creh->objects[cid]))
|
||||||
result = std::make_pair(primaryID, entry);
|
result = std::make_pair(primaryID, entry);
|
||||||
@ -2018,54 +2018,28 @@ UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance &stack) const
|
|||||||
UpgradeInfo ret;
|
UpgradeInfo ret;
|
||||||
const CCreature *base = stack.type;
|
const CCreature *base = stack.type;
|
||||||
|
|
||||||
const CGHeroInstance * h = stack.armyObj->ID == Obj::HERO ? dynamic_cast<const CGHeroInstance *>(stack.armyObj) : nullptr;
|
if (stack.armyObj->ID == Obj::HERO)
|
||||||
const CGTownInstance *t = nullptr;
|
{
|
||||||
|
auto hero = dynamic_cast<const CGHeroInstance *>(stack.armyObj);
|
||||||
|
hero->fillUpgradeInfo(ret, stack);
|
||||||
|
|
||||||
if(stack.armyObj->ID == Obj::TOWN)
|
if (hero->visitedTown)
|
||||||
t = dynamic_cast<const CGTownInstance *>(stack.armyObj);
|
|
||||||
else if(h)
|
|
||||||
{ //hero specialty
|
|
||||||
TConstBonusListPtr lista = h->getBonuses(Selector::typeSubtype(BonusType::SPECIAL_UPGRADE, base->getId()));
|
|
||||||
for(const auto & it : *lista)
|
|
||||||
{
|
{
|
||||||
auto nid = CreatureID(it->additionalInfo[0]);
|
hero->visitedTown->fillUpgradeInfo(ret, stack);
|
||||||
if (nid != base->getId()) //in very specific case the upgrade is available by default (?)
|
|
||||||
{
|
|
||||||
ret.newID.push_back(nid);
|
|
||||||
ret.cost.push_back(nid.toCreature()->getFullRecruitCost() - base->getFullRecruitCost());
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
t = h->visitedTown;
|
|
||||||
}
|
|
||||||
if(t)
|
|
||||||
{
|
{
|
||||||
for(const CGTownInstance::TCreaturesSet::value_type & dwelling : t->creatures)
|
auto object = vstd::frontOrNull(getVisitableObjs(hero->visitablePos()));
|
||||||
{
|
auto upgradeSource = dynamic_cast<const ICreatureUpgrader*>(object);
|
||||||
if (vstd::contains(dwelling.second, base->getId())) //Dwelling with our creature
|
if (object != hero && upgradeSource != nullptr)
|
||||||
{
|
upgradeSource->fillUpgradeInfo(ret, stack);
|
||||||
for(const auto & upgrID : dwelling.second)
|
|
||||||
{
|
|
||||||
if(vstd::contains(base->upgrades, upgrID)) //possible upgrade
|
|
||||||
{
|
|
||||||
ret.newID.push_back(upgrID);
|
|
||||||
ret.cost.push_back(upgrID.toCreature()->getFullRecruitCost() - base->getFullRecruitCost());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//hero is visiting Hill Fort
|
if (stack.armyObj->ID == Obj::TOWN)
|
||||||
if(h && map->getTile(h->visitablePos()).visitableObjects.front()->ID == Obj::HILL_FORT)
|
|
||||||
{
|
{
|
||||||
static const int costModifiers[] = {0, 25, 50, 75, 100}; //we get cheaper upgrades depending on level
|
auto town = dynamic_cast<const CGTownInstance *>(stack.armyObj);
|
||||||
const int costModifier = costModifiers[std::min<int>(std::max((int)base->getLevel() - 1, 0), std::size(costModifiers) - 1)];
|
town->fillUpgradeInfo(ret, stack);
|
||||||
|
|
||||||
for(const auto & nid : base->upgrades)
|
|
||||||
{
|
|
||||||
ret.newID.push_back(nid);
|
|
||||||
ret.cost.push_back((nid.toCreature()->getFullRecruitCost() - base->getFullRecruitCost()) * costModifier / 100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ret.newID.empty())
|
if(!ret.newID.empty())
|
||||||
|
@ -893,6 +893,16 @@ void CTownHandler::loadTown(CTown * town, const JsonNode & source)
|
|||||||
|
|
||||||
warMachinesToLoad[town] = source["warMachine"];
|
warMachinesToLoad[town] = source["warMachine"];
|
||||||
|
|
||||||
|
|
||||||
|
town->shipyardBoat = EBoatId::NONE;
|
||||||
|
if (!source["boat"].isNull())
|
||||||
|
{
|
||||||
|
VLC->modh->identifiers.requestIdentifier("core:boat", source["boat"], [=](int32_t boatTypeID)
|
||||||
|
{
|
||||||
|
town->shipyardBoat = BoatId(boatTypeID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
town->mageLevel = static_cast<ui32>(source["mageGuild"].Float());
|
town->mageLevel = static_cast<ui32>(source["mageGuild"].Float());
|
||||||
|
|
||||||
town->namesCount = 0;
|
town->namesCount = 0;
|
||||||
@ -1148,6 +1158,25 @@ void CTownHandler::afterLoadFinalization()
|
|||||||
initializeRequirements();
|
initializeRequirements();
|
||||||
initializeOverridden();
|
initializeOverridden();
|
||||||
initializeWarMachines();
|
initializeWarMachines();
|
||||||
|
|
||||||
|
for(auto & faction : objects)
|
||||||
|
{
|
||||||
|
if (!faction->town)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool hasBoat = faction->town->shipyardBoat != EBoatId::NONE;
|
||||||
|
bool hasShipyard = faction->town->buildings.count(BuildingID::SHIPYARD);
|
||||||
|
|
||||||
|
if ( hasBoat && !hasShipyard )
|
||||||
|
logMod->warn("Town %s has boat but has no shipyard!", faction->getJsonKey());
|
||||||
|
|
||||||
|
if ( !hasBoat && hasShipyard )
|
||||||
|
{
|
||||||
|
logMod->warn("Town %s has shipyard but has no boat set!", faction->getJsonKey());
|
||||||
|
// Mod compatibility for 1.3
|
||||||
|
faction->town->shipyardBoat = EBoatId::CASTLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTownHandler::initializeRequirements()
|
void CTownHandler::initializeRequirements()
|
||||||
|
@ -281,6 +281,9 @@ public:
|
|||||||
GameResID primaryRes;
|
GameResID primaryRes;
|
||||||
ArtifactID warMachine;
|
ArtifactID warMachine;
|
||||||
SpellID moatAbility;
|
SpellID moatAbility;
|
||||||
|
|
||||||
|
/// boat that will be built by town shipyard, if exists
|
||||||
|
BoatId shipyardBoat;
|
||||||
// default chance for hero of specific class to appear in tavern, if field "tavern" was not set
|
// default chance for hero of specific class to appear in tavern, if field "tavern" was not set
|
||||||
// resulting chance = sqrt(town.chance * heroClass.chance)
|
// resulting chance = sqrt(town.chance * heroClass.chance)
|
||||||
ui32 defaultTavernChance;
|
ui32 defaultTavernChance;
|
||||||
@ -346,6 +349,7 @@ public:
|
|||||||
h & mageLevel;
|
h & mageLevel;
|
||||||
h & primaryRes;
|
h & primaryRes;
|
||||||
h & warMachine;
|
h & warMachine;
|
||||||
|
h & shipyardBoat;
|
||||||
h & clientInfo;
|
h & clientInfo;
|
||||||
h & moatAbility;
|
h & moatAbility;
|
||||||
h & defaultTavernChance;
|
h & defaultTavernChance;
|
||||||
|
@ -1285,9 +1285,9 @@ class BattleField : public BaseForID<BattleField, si32>
|
|||||||
enum class EBoatId
|
enum class EBoatId
|
||||||
{
|
{
|
||||||
NONE = -1,
|
NONE = -1,
|
||||||
BOAT_EVIL = 0,
|
NECROPOLIS = 0,
|
||||||
BOAT_GOOD,
|
CASTLE,
|
||||||
BOAT_NEUTRAL
|
FORTRESS
|
||||||
};
|
};
|
||||||
|
|
||||||
using BoatId = Identifier<EBoatId>;
|
using BoatId = Identifier<EBoatId>;
|
||||||
|
@ -170,18 +170,21 @@ void CPrivilegedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact *>
|
|||||||
out.push_back(VLC->arth->objects[VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MAJOR)]);
|
out.push_back(VLC->arth->objects[VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MAJOR)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPrivilegedInfoCallback::getAllowedSpells(std::vector<SpellID> & out, ui16 level)
|
void CPrivilegedInfoCallback::getAllowedSpells(std::vector<SpellID> & out, std::optional<ui16> level)
|
||||||
{
|
{
|
||||||
for (ui32 i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?)
|
for (ui32 i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?)
|
||||||
{
|
{
|
||||||
|
|
||||||
const spells::Spell * spell = SpellID(i).toSpell();
|
const spells::Spell * spell = SpellID(i).toSpell();
|
||||||
if(isAllowed(0, spell->getIndex()) && spell->getLevel() == level)
|
|
||||||
{
|
if (!isAllowed(0, spell->getIndex()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (level.has_value() && spell->getLevel() != level)
|
||||||
|
continue;
|
||||||
|
|
||||||
out.push_back(spell->getId());
|
out.push_back(spell->getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CGameState * CPrivilegedInfoCallback::gameState()
|
CGameState * CPrivilegedInfoCallback::gameState()
|
||||||
{
|
{
|
||||||
|
@ -71,7 +71,7 @@ public:
|
|||||||
|
|
||||||
//gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
//gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
||||||
void pickAllowedArtsSet(std::vector<const CArtifact *> & out, CRandomGenerator & rand) const;
|
void pickAllowedArtsSet(std::vector<const CArtifact *> & out, CRandomGenerator & rand) const;
|
||||||
void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
|
void getAllowedSpells(std::vector<SpellID> &out, std::optional<ui16> level = std::nullopt);
|
||||||
|
|
||||||
template<typename Saver>
|
template<typename Saver>
|
||||||
void saveCommonState(Saver &out) const; //stores GS and VLC
|
void saveCommonState(Saver &out) const; //stores GS and VLC
|
||||||
|
@ -243,21 +243,36 @@ namespace JsonRandom
|
|||||||
if (value.getType() == JsonNode::JsonType::DATA_STRING)
|
if (value.getType() == JsonNode::JsonType::DATA_STRING)
|
||||||
return SpellID(VLC->modh->identifiers.getIdentifier("spell", value).value());
|
return SpellID(VLC->modh->identifiers.getIdentifier("spell", value).value());
|
||||||
|
|
||||||
|
if (!value["level"].isNull())
|
||||||
|
{
|
||||||
|
int32_t spellLevel = value["level"].Float();
|
||||||
|
|
||||||
vstd::erase_if(spells, [=](const SpellID & spell)
|
vstd::erase_if(spells, [=](const SpellID & spell)
|
||||||
{
|
{
|
||||||
return VLC->spellh->getById(spell)->getLevel() != si32(value["level"].Float());
|
return VLC->spellh->getById(spell)->getLevel() != spellLevel;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value["school"].isNull())
|
||||||
|
{
|
||||||
|
int32_t schoolID = VLC->modh->identifiers.getIdentifier("spellSchool", value["school"]).value();
|
||||||
|
|
||||||
|
vstd::erase_if(spells, [=](const SpellID & spell)
|
||||||
|
{
|
||||||
|
return !VLC->spellh->getById(spell)->hasSchool(ESpellSchool(schoolID));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spells.empty())
|
||||||
|
{
|
||||||
|
logMod->warn("Failed to select suitable random spell!");
|
||||||
|
return SpellID::NONE;
|
||||||
|
}
|
||||||
return SpellID(*RandomGeneratorUtil::nextItem(spells, rng));
|
return SpellID(*RandomGeneratorUtil::nextItem(spells, rng));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const std::vector<SpellID> & spells)
|
std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const std::vector<SpellID> & spells)
|
||||||
{
|
{
|
||||||
// possible extensions: (taken from spell json config)
|
|
||||||
// "type": "adventure",//"adventure", "combat", "ability"
|
|
||||||
// "school": {"air":true, "earth":true, "fire":true, "water":true},
|
|
||||||
// "level": 1,
|
|
||||||
|
|
||||||
std::vector<SpellID> ret;
|
std::vector<SpellID> ret;
|
||||||
for (const JsonNode & entry : value.Vector())
|
for (const JsonNode & entry : value.Vector())
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,15 @@ class DLL_LINKAGE TerrainType : public EntityT<TerrainId>
|
|||||||
TerrainId id;
|
TerrainId id;
|
||||||
ui8 passabilityType;
|
ui8 passabilityType;
|
||||||
|
|
||||||
|
enum PassabilityType : ui8
|
||||||
|
{
|
||||||
|
LAND = 1,
|
||||||
|
WATER = 2,
|
||||||
|
SURFACE = 4,
|
||||||
|
SUBTERRANEAN = 8,
|
||||||
|
ROCK = 16
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int32_t getIndex() const override { return id.getNum(); }
|
int32_t getIndex() const override { return id.getNum(); }
|
||||||
int32_t getIconIndex() const override { return 0; }
|
int32_t getIconIndex() const override { return 0; }
|
||||||
@ -37,15 +46,6 @@ public:
|
|||||||
std::string getNameTextID() const override;
|
std::string getNameTextID() const override;
|
||||||
std::string getNameTranslated() const override;
|
std::string getNameTranslated() const override;
|
||||||
|
|
||||||
enum PassabilityType : ui8
|
|
||||||
{
|
|
||||||
LAND = 1,
|
|
||||||
WATER = 2,
|
|
||||||
SURFACE = 4,
|
|
||||||
SUBTERRANEAN = 8,
|
|
||||||
ROCK = 16
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<BattleField> battleFields;
|
std::vector<BattleField> battleFields;
|
||||||
std::vector<TerrainId> prohibitTransitions;
|
std::vector<TerrainId> prohibitTransitions;
|
||||||
ColorRGBA minimapBlocked;
|
ColorRGBA minimapBlocked;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "AObjectTypeHandler.h"
|
#include "AObjectTypeHandler.h"
|
||||||
|
|
||||||
|
#include "IObjectInfo.h"
|
||||||
#include "../CGeneralTextHandler.h"
|
#include "../CGeneralTextHandler.h"
|
||||||
#include "../VCMI_Lib.h"
|
#include "../VCMI_Lib.h"
|
||||||
#include "../mapObjects/CGObjectInstance.h"
|
#include "../mapObjects/CGObjectInstance.h"
|
||||||
@ -221,5 +222,9 @@ void AObjectTypeHandler::afterLoadFinalization()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<IObjectInfo> AObjectTypeHandler::getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -107,7 +107,7 @@ public:
|
|||||||
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const = 0;
|
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const = 0;
|
||||||
|
|
||||||
/// Returns object configuration, if available. Otherwise returns NULL
|
/// Returns object configuration, if available. Otherwise returns NULL
|
||||||
virtual std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const = 0;
|
virtual std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
248
lib/mapObjectConstructors/CBankInstanceConstructor.cpp
Normal file
248
lib/mapObjectConstructors/CBankInstanceConstructor.cpp
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* CBankInstanceConstructor.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 "CBankInstanceConstructor.h"
|
||||||
|
|
||||||
|
#include "../JsonRandom.h"
|
||||||
|
#include "../CGeneralTextHandler.h"
|
||||||
|
#include "../IGameCallback.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
bool CBankInstanceConstructor::hasNameTextID() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBankInstanceConstructor::initTypeData(const JsonNode & input)
|
||||||
|
{
|
||||||
|
if (input.Struct().count("name") == 0)
|
||||||
|
logMod->warn("Bank %s missing name!", getJsonKey());
|
||||||
|
|
||||||
|
VLC->generaltexth->registerString(input.meta, getNameTextID(), input["name"].String());
|
||||||
|
|
||||||
|
levels = input["levels"].Vector();
|
||||||
|
bankResetDuration = static_cast<si32>(input["resetDuration"].Float());
|
||||||
|
}
|
||||||
|
|
||||||
|
BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const
|
||||||
|
{
|
||||||
|
BankConfig bc;
|
||||||
|
|
||||||
|
bc.chance = static_cast<ui32>(level["chance"].Float());
|
||||||
|
|
||||||
|
bc.guards = JsonRandom::loadCreatures(level["guards"], rng);
|
||||||
|
bc.upgradeChance = static_cast<ui32>(level["upgrade_chance"].Float());
|
||||||
|
bc.combatValue = static_cast<ui32>(level["combat_value"].Float());
|
||||||
|
|
||||||
|
std::vector<SpellID> spells;
|
||||||
|
IObjectInterface::cb->getAllowedSpells(spells);
|
||||||
|
|
||||||
|
bc.resources = ResourceSet(level["reward"]["resources"]);
|
||||||
|
bc.creatures = JsonRandom::loadCreatures(level["reward"]["creatures"], rng);
|
||||||
|
bc.artifacts = JsonRandom::loadArtifacts(level["reward"]["artifacts"], rng);
|
||||||
|
bc.spells = JsonRandom::loadSpells(level["reward"]["spells"], rng, spells);
|
||||||
|
|
||||||
|
bc.value = static_cast<ui32>(level["value"].Float());
|
||||||
|
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBankInstanceConstructor::randomizeObject(CBank * bank, CRandomGenerator & rng) const
|
||||||
|
{
|
||||||
|
bank->resetDuration = bankResetDuration;
|
||||||
|
|
||||||
|
si32 totalChance = 0;
|
||||||
|
for(const auto & node : levels)
|
||||||
|
totalChance += static_cast<si32>(node["chance"].Float());
|
||||||
|
|
||||||
|
assert(totalChance != 0);
|
||||||
|
|
||||||
|
si32 selectedChance = rng.nextInt(totalChance - 1);
|
||||||
|
|
||||||
|
int cumulativeChance = 0;
|
||||||
|
for(const auto & node : levels)
|
||||||
|
{
|
||||||
|
cumulativeChance += static_cast<int>(node["chance"].Float());
|
||||||
|
if(selectedChance < cumulativeChance)
|
||||||
|
{
|
||||||
|
bank->setConfig(generateConfig(node, rng));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CBankInfo::CBankInfo(const JsonVector & Config) :
|
||||||
|
config(Config)
|
||||||
|
{
|
||||||
|
assert(!Config.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount)
|
||||||
|
{
|
||||||
|
army.totalStrength += crea->getFightValue() * amount;
|
||||||
|
|
||||||
|
bool walker = true;
|
||||||
|
if(crea->hasBonusOfType(BonusType::SHOOTER))
|
||||||
|
{
|
||||||
|
army.shootersStrength += crea->getFightValue() * amount;
|
||||||
|
walker = false;
|
||||||
|
}
|
||||||
|
if(crea->hasBonusOfType(BonusType::FLYING))
|
||||||
|
{
|
||||||
|
army.flyersStrength += crea->getFightValue() * amount;
|
||||||
|
walker = false;
|
||||||
|
}
|
||||||
|
if(walker)
|
||||||
|
army.walkersStrength += crea->getFightValue() * amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
IObjectInfo::CArmyStructure CBankInfo::minGuards() const
|
||||||
|
{
|
||||||
|
std::vector<IObjectInfo::CArmyStructure> armies;
|
||||||
|
for(auto configEntry : config)
|
||||||
|
{
|
||||||
|
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"]);
|
||||||
|
IObjectInfo::CArmyStructure army;
|
||||||
|
for(auto & stack : stacks)
|
||||||
|
{
|
||||||
|
assert(!stack.allowedCreatures.empty());
|
||||||
|
auto weakest = boost::range::min_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b)
|
||||||
|
{
|
||||||
|
return a->getFightValue() < b->getFightValue();
|
||||||
|
});
|
||||||
|
addStackToArmy(army, *weakest, stack.minAmount);
|
||||||
|
}
|
||||||
|
armies.push_back(army);
|
||||||
|
}
|
||||||
|
return *boost::range::min_element(armies);
|
||||||
|
}
|
||||||
|
|
||||||
|
IObjectInfo::CArmyStructure CBankInfo::maxGuards() const
|
||||||
|
{
|
||||||
|
std::vector<IObjectInfo::CArmyStructure> armies;
|
||||||
|
for(auto configEntry : config)
|
||||||
|
{
|
||||||
|
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"]);
|
||||||
|
IObjectInfo::CArmyStructure army;
|
||||||
|
for(auto & stack : stacks)
|
||||||
|
{
|
||||||
|
assert(!stack.allowedCreatures.empty());
|
||||||
|
auto strongest = boost::range::max_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b)
|
||||||
|
{
|
||||||
|
return a->getFightValue() < b->getFightValue();
|
||||||
|
});
|
||||||
|
addStackToArmy(army, *strongest, stack.maxAmount);
|
||||||
|
}
|
||||||
|
armies.push_back(army);
|
||||||
|
}
|
||||||
|
return *boost::range::max_element(armies);
|
||||||
|
}
|
||||||
|
|
||||||
|
TPossibleGuards CBankInfo::getPossibleGuards() const
|
||||||
|
{
|
||||||
|
TPossibleGuards out;
|
||||||
|
|
||||||
|
for(const JsonNode & configEntry : config)
|
||||||
|
{
|
||||||
|
const JsonNode & guardsInfo = configEntry["guards"];
|
||||||
|
auto stacks = JsonRandom::evaluateCreatures(guardsInfo);
|
||||||
|
IObjectInfo::CArmyStructure army;
|
||||||
|
|
||||||
|
|
||||||
|
for(auto stack : stacks)
|
||||||
|
{
|
||||||
|
army.totalStrength += stack.allowedCreatures.front()->getAIValue() * (stack.minAmount + stack.maxAmount) / 2;
|
||||||
|
//TODO: add fields for flyers, walkers etc...
|
||||||
|
}
|
||||||
|
|
||||||
|
ui8 chance = static_cast<ui8>(configEntry["chance"].Float());
|
||||||
|
out.push_back(std::make_pair(chance, army));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PossibleReward<TResources>> CBankInfo::getPossibleResourcesReward() const
|
||||||
|
{
|
||||||
|
std::vector<PossibleReward<TResources>> result;
|
||||||
|
|
||||||
|
for(const JsonNode & configEntry : config)
|
||||||
|
{
|
||||||
|
const JsonNode & resourcesInfo = configEntry["reward"]["resources"];
|
||||||
|
|
||||||
|
if(!resourcesInfo.isNull())
|
||||||
|
{
|
||||||
|
result.emplace_back(configEntry["chance"].Integer(), TResources(resourcesInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PossibleReward<CStackBasicDescriptor>> CBankInfo::getPossibleCreaturesReward() const
|
||||||
|
{
|
||||||
|
std::vector<PossibleReward<CStackBasicDescriptor>> aproximateReward;
|
||||||
|
|
||||||
|
for(const JsonNode & configEntry : config)
|
||||||
|
{
|
||||||
|
const JsonNode & guardsInfo = configEntry["reward"]["creatures"];
|
||||||
|
auto stacks = JsonRandom::evaluateCreatures(guardsInfo);
|
||||||
|
|
||||||
|
for(auto stack : stacks)
|
||||||
|
{
|
||||||
|
const auto * creature = stack.allowedCreatures.front();
|
||||||
|
|
||||||
|
aproximateReward.emplace_back(configEntry["chance"].Integer(), CStackBasicDescriptor(creature, (stack.minAmount + stack.maxAmount) / 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aproximateReward;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBankInfo::givesResources() const
|
||||||
|
{
|
||||||
|
for(const JsonNode & node : config)
|
||||||
|
if(!node["reward"]["resources"].isNull())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBankInfo::givesArtifacts() const
|
||||||
|
{
|
||||||
|
for(const JsonNode & node : config)
|
||||||
|
if(!node["reward"]["artifacts"].isNull())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBankInfo::givesCreatures() const
|
||||||
|
{
|
||||||
|
for(const JsonNode & node : config)
|
||||||
|
if(!node["reward"]["creatures"].isNull())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBankInfo::givesSpells() const
|
||||||
|
{
|
||||||
|
for(const JsonNode & node : config)
|
||||||
|
if(!node["reward"]["spells"].isNull())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<IObjectInfo> CBankInstanceConstructor::getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const
|
||||||
|
{
|
||||||
|
return std::unique_ptr<IObjectInfo>(new CBankInfo(levels));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
104
lib/mapObjectConstructors/CBankInstanceConstructor.h
Normal file
104
lib/mapObjectConstructors/CBankInstanceConstructor.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* CBankInstanceConstructor.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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CDefaultObjectTypeHandler.h"
|
||||||
|
#include "IObjectInfo.h"
|
||||||
|
|
||||||
|
#include "../CCreatureSet.h"
|
||||||
|
#include "../ResourceSet.h"
|
||||||
|
#include "../mapObjects/CBank.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct BankConfig
|
||||||
|
{
|
||||||
|
ui32 value = 0; //overall value of given things
|
||||||
|
ui32 chance = 0; //chance for this level being chosen
|
||||||
|
ui32 upgradeChance = 0; //chance for creatures to be in upgraded versions
|
||||||
|
ui32 combatValue = 0; //how hard are guards of this level
|
||||||
|
std::vector<CStackBasicDescriptor> guards; //creature ID, amount
|
||||||
|
ResourceSet resources; //resources given in case of victory
|
||||||
|
std::vector<CStackBasicDescriptor> creatures; //creatures granted in case of victory (creature ID, amount)
|
||||||
|
std::vector<ArtifactID> artifacts; //artifacts given in case of victory
|
||||||
|
std::vector<SpellID> spells; // granted spell(s), for Pyramid
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & chance;
|
||||||
|
h & upgradeChance;
|
||||||
|
h & guards;
|
||||||
|
h & combatValue;
|
||||||
|
h & resources;
|
||||||
|
h & creatures;
|
||||||
|
h & artifacts;
|
||||||
|
h & value;
|
||||||
|
h & spells;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using TPossibleGuards = std::vector<std::pair<ui8, IObjectInfo::CArmyStructure>>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct DLL_LINKAGE PossibleReward
|
||||||
|
{
|
||||||
|
int chance;
|
||||||
|
T data;
|
||||||
|
|
||||||
|
PossibleReward(int chance, const T & data) : chance(chance), data(data) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE CBankInfo : public IObjectInfo
|
||||||
|
{
|
||||||
|
const JsonVector & config;
|
||||||
|
public:
|
||||||
|
CBankInfo(const JsonVector & Config);
|
||||||
|
|
||||||
|
TPossibleGuards getPossibleGuards() const;
|
||||||
|
std::vector<PossibleReward<TResources>> getPossibleResourcesReward() const;
|
||||||
|
std::vector<PossibleReward<CStackBasicDescriptor>> getPossibleCreaturesReward() const;
|
||||||
|
|
||||||
|
// These functions should try to evaluate minimal possible/max possible guards to give provide information on possible thread to AI
|
||||||
|
CArmyStructure minGuards() const override;
|
||||||
|
CArmyStructure maxGuards() const override;
|
||||||
|
|
||||||
|
bool givesResources() const override;
|
||||||
|
bool givesArtifacts() const override;
|
||||||
|
bool givesCreatures() const override;
|
||||||
|
bool givesSpells() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBankInstanceConstructor : public CDefaultObjectTypeHandler<CBank>
|
||||||
|
{
|
||||||
|
BankConfig generateConfig(const JsonNode & conf, CRandomGenerator & rng) const;
|
||||||
|
|
||||||
|
JsonVector levels;
|
||||||
|
protected:
|
||||||
|
void initTypeData(const JsonNode & input) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// all banks of this type will be reset N days after clearing,
|
||||||
|
si32 bankResetDuration = 0;
|
||||||
|
|
||||||
|
void randomizeObject(CBank * object, CRandomGenerator & rng) const override;
|
||||||
|
|
||||||
|
bool hasNameTextID() const override;
|
||||||
|
|
||||||
|
std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & levels;
|
||||||
|
h & bankResetDuration;
|
||||||
|
h & static_cast<CDefaultObjectTypeHandler<CBank>&>(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
53
lib/mapObjectConstructors/CDefaultObjectTypeHandler.h
Normal file
53
lib/mapObjectConstructors/CDefaultObjectTypeHandler.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* CDefaultObjectTypeHandler.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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AObjectTypeHandler.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/// Class that is used as base for multiple object constructors
|
||||||
|
template<class ObjectType>
|
||||||
|
class CDefaultObjectTypeHandler : public AObjectTypeHandler
|
||||||
|
{
|
||||||
|
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const final
|
||||||
|
{
|
||||||
|
ObjectType * castedObject = dynamic_cast<ObjectType*>(object);
|
||||||
|
|
||||||
|
if(castedObject == nullptr)
|
||||||
|
throw std::runtime_error("Unexpected object type!");
|
||||||
|
|
||||||
|
randomizeObject(castedObject, rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const final
|
||||||
|
{
|
||||||
|
ObjectType * result = createObject();
|
||||||
|
|
||||||
|
preInitObject(result);
|
||||||
|
|
||||||
|
if(tmpl)
|
||||||
|
result->appearance = tmpl;
|
||||||
|
|
||||||
|
initializeObject(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void initializeObject(ObjectType * object) const {}
|
||||||
|
virtual void randomizeObject(ObjectType * object, CRandomGenerator & rng) const {}
|
||||||
|
virtual ObjectType * createObject() const
|
||||||
|
{
|
||||||
|
return new ObjectType();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -21,11 +21,21 @@
|
|||||||
#include "../JsonNode.h"
|
#include "../JsonNode.h"
|
||||||
#include "../CSoundBase.h"
|
#include "../CSoundBase.h"
|
||||||
|
|
||||||
|
#include "../mapObjectConstructors/CBankInstanceConstructor.h"
|
||||||
#include "../mapObjectConstructors/CRewardableConstructor.h"
|
#include "../mapObjectConstructors/CRewardableConstructor.h"
|
||||||
#include "../mapObjectConstructors/CommonConstructors.h"
|
#include "../mapObjectConstructors/CommonConstructors.h"
|
||||||
#include "../mapObjects/CQuest.h"
|
#include "../mapObjectConstructors/DwellingInstanceConstructor.h"
|
||||||
|
#include "../mapObjectConstructors/HillFortInstanceConstructor.h"
|
||||||
|
#include "../mapObjectConstructors/ShipyardInstanceConstructor.h"
|
||||||
|
#include "../mapObjectConstructors/ShrineInstanceConstructor.h"
|
||||||
#include "../mapObjects/CGPandoraBox.h"
|
#include "../mapObjects/CGPandoraBox.h"
|
||||||
|
#include "../mapObjects/CQuest.h"
|
||||||
#include "../mapObjects/ObjectTemplate.h"
|
#include "../mapObjects/ObjectTemplate.h"
|
||||||
|
#include "../mapObjects/CGMarket.h"
|
||||||
|
#include "../mapObjects/MiscObjects.h"
|
||||||
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../mapObjects/CGTownInstance.h"
|
||||||
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -37,12 +47,15 @@ CObjectClassesHandler::CObjectClassesHandler()
|
|||||||
// list of all known handlers, hardcoded for now since the only way to add new objects is via C++ code
|
// list of all known handlers, hardcoded for now since the only way to add new objects is via C++ code
|
||||||
//Note: should be in sync with registerTypesMapObjectTypes function
|
//Note: should be in sync with registerTypesMapObjectTypes function
|
||||||
SET_HANDLER_CLASS("configurable", CRewardableConstructor);
|
SET_HANDLER_CLASS("configurable", CRewardableConstructor);
|
||||||
SET_HANDLER_CLASS("dwelling", CDwellingInstanceConstructor);
|
SET_HANDLER_CLASS("dwelling", DwellingInstanceConstructor);
|
||||||
SET_HANDLER_CLASS("hero", CHeroInstanceConstructor);
|
SET_HANDLER_CLASS("hero", CHeroInstanceConstructor);
|
||||||
SET_HANDLER_CLASS("town", CTownInstanceConstructor);
|
SET_HANDLER_CLASS("town", CTownInstanceConstructor);
|
||||||
SET_HANDLER_CLASS("bank", CBankInstanceConstructor);
|
SET_HANDLER_CLASS("bank", CBankInstanceConstructor);
|
||||||
SET_HANDLER_CLASS("boat", BoatInstanceConstructor);
|
SET_HANDLER_CLASS("boat", BoatInstanceConstructor);
|
||||||
SET_HANDLER_CLASS("market", MarketInstanceConstructor);
|
SET_HANDLER_CLASS("market", MarketInstanceConstructor);
|
||||||
|
SET_HANDLER_CLASS("shrine", ShrineInstanceConstructor);
|
||||||
|
SET_HANDLER_CLASS("hillFort", HillFortInstanceConstructor);
|
||||||
|
SET_HANDLER_CLASS("shipyard", ShipyardInstanceConstructor);
|
||||||
|
|
||||||
SET_HANDLER_CLASS("static", CObstacleConstructor);
|
SET_HANDLER_CLASS("static", CObstacleConstructor);
|
||||||
SET_HANDLER_CLASS("", CObstacleConstructor);
|
SET_HANDLER_CLASS("", CObstacleConstructor);
|
||||||
@ -76,8 +89,6 @@ CObjectClassesHandler::CObjectClassesHandler()
|
|||||||
SET_HANDLER("resource", CGResource);
|
SET_HANDLER("resource", CGResource);
|
||||||
SET_HANDLER("scholar", CGScholar);
|
SET_HANDLER("scholar", CGScholar);
|
||||||
SET_HANDLER("seerHut", CGSeerHut);
|
SET_HANDLER("seerHut", CGSeerHut);
|
||||||
SET_HANDLER("shipyard", CGShipyard);
|
|
||||||
SET_HANDLER("shrine", CGShrine);
|
|
||||||
SET_HANDLER("sign", CGSignBottle);
|
SET_HANDLER("sign", CGSignBottle);
|
||||||
SET_HANDLER("siren", CGSirens);
|
SET_HANDLER("siren", CGSirens);
|
||||||
SET_HANDLER("monolith", CGMonolith);
|
SET_HANDLER("monolith", CGMonolith);
|
||||||
|
@ -10,19 +10,23 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CommonConstructors.h"
|
#include "CommonConstructors.h"
|
||||||
|
|
||||||
#include "../CCreatureHandler.h"
|
|
||||||
#include "../CGeneralTextHandler.h"
|
#include "../CGeneralTextHandler.h"
|
||||||
#include "../CHeroHandler.h"
|
#include "../CHeroHandler.h"
|
||||||
#include "../CModHandler.h"
|
#include "../CModHandler.h"
|
||||||
|
#include "../CTownHandler.h"
|
||||||
#include "../IGameCallback.h"
|
#include "../IGameCallback.h"
|
||||||
|
#include "../JsonRandom.h"
|
||||||
#include "../StringConstants.h"
|
#include "../StringConstants.h"
|
||||||
#include "../TerrainHandler.h"
|
#include "../TerrainHandler.h"
|
||||||
#include "../mapObjects/CBank.h"
|
#include "../VCMI_Lib.h"
|
||||||
|
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../mapObjects/CGMarket.h"
|
||||||
#include "../mapObjects/CGTownInstance.h"
|
#include "../mapObjects/CGTownInstance.h"
|
||||||
|
#include "../mapObjects/MiscObjects.h"
|
||||||
#include "../mapObjects/ObjectTemplate.h"
|
#include "../mapObjects/ObjectTemplate.h"
|
||||||
|
|
||||||
#include "../mapping/CMapDefines.h"
|
#include "../mapping/CMapDefines.h"
|
||||||
#include "JsonRandom.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -69,15 +73,13 @@ bool CTownInstanceConstructor::objectFilter(const CGObjectInstance * object, std
|
|||||||
return filters.count(templ->stringID) != 0 && filters.at(templ->stringID).test(buildTest);
|
return filters.count(templ->stringID) != 0 && filters.at(templ->stringID).test(buildTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGObjectInstance * CTownInstanceConstructor::create(std::shared_ptr<const ObjectTemplate> tmpl) const
|
void CTownInstanceConstructor::initializeObject(CGTownInstance * obj) const
|
||||||
{
|
{
|
||||||
CGTownInstance * obj = createTyped(tmpl);
|
|
||||||
obj->town = faction->town;
|
obj->town = faction->town;
|
||||||
obj->tempOwner = PlayerColor::NEUTRAL;
|
obj->tempOwner = PlayerColor::NEUTRAL;
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTownInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
|
void CTownInstanceConstructor::randomizeObject(CGTownInstance * object, CRandomGenerator & rng) const
|
||||||
{
|
{
|
||||||
auto templ = getOverride(CGObjectInstance::cb->getTile(object->pos)->terType->getId(), object);
|
auto templ = getOverride(CGObjectInstance::cb->getTile(object->pos)->terType->getId(), object);
|
||||||
if(templ)
|
if(templ)
|
||||||
@ -121,144 +123,16 @@ bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, std
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGObjectInstance * CHeroInstanceConstructor::create(std::shared_ptr<const ObjectTemplate> tmpl) const
|
void CHeroInstanceConstructor::initializeObject(CGHeroInstance * obj) const
|
||||||
{
|
{
|
||||||
CGHeroInstance * obj = createTyped(tmpl);
|
|
||||||
obj->type = nullptr; //FIXME: set to valid value. somehow.
|
obj->type = nullptr; //FIXME: set to valid value. somehow.
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHeroInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
|
void CHeroInstanceConstructor::randomizeObject(CGHeroInstance * object, CRandomGenerator & rng) const
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDwellingInstanceConstructor::hasNameTextID() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDwellingInstanceConstructor::initTypeData(const JsonNode & input)
|
|
||||||
{
|
|
||||||
if (input.Struct().count("name") == 0)
|
|
||||||
logMod->warn("Dwelling %s missing name!", getJsonKey());
|
|
||||||
|
|
||||||
VLC->generaltexth->registerString( input.meta, getNameTextID(), input["name"].String());
|
|
||||||
|
|
||||||
const JsonVector & levels = input["creatures"].Vector();
|
|
||||||
const auto totalLevels = levels.size();
|
|
||||||
|
|
||||||
availableCreatures.resize(totalLevels);
|
|
||||||
for(auto currentLevel = 0; currentLevel < totalLevels; currentLevel++)
|
|
||||||
{
|
|
||||||
const JsonVector & creaturesOnLevel = levels[currentLevel].Vector();
|
|
||||||
const auto creaturesNumber = creaturesOnLevel.size();
|
|
||||||
availableCreatures[currentLevel].resize(creaturesNumber);
|
|
||||||
|
|
||||||
for(auto currentCreature = 0; currentCreature < creaturesNumber; currentCreature++)
|
|
||||||
{
|
|
||||||
VLC->modh->identifiers.requestIdentifier("creature", creaturesOnLevel[currentCreature], [=] (si32 index)
|
|
||||||
{
|
|
||||||
availableCreatures[currentLevel][currentCreature] = VLC->creh->objects[index];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
assert(!availableCreatures[currentLevel].empty());
|
|
||||||
}
|
|
||||||
guards = input["guards"];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDwellingInstanceConstructor::objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGObjectInstance * CDwellingInstanceConstructor::create(std::shared_ptr<const ObjectTemplate> tmpl) const
|
|
||||||
{
|
|
||||||
CGDwelling * obj = createTyped(tmpl);
|
|
||||||
|
|
||||||
obj->creatures.resize(availableCreatures.size());
|
|
||||||
for(const auto & entry : availableCreatures)
|
|
||||||
{
|
|
||||||
for(const CCreature * cre : entry)
|
|
||||||
obj->creatures.back().second.push_back(cre->getId());
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator &rng) const
|
|
||||||
{
|
|
||||||
auto * dwelling = dynamic_cast<CGDwelling *>(object);
|
|
||||||
|
|
||||||
dwelling->creatures.clear();
|
|
||||||
dwelling->creatures.reserve(availableCreatures.size());
|
|
||||||
|
|
||||||
for(const auto & entry : availableCreatures)
|
|
||||||
{
|
|
||||||
dwelling->creatures.resize(dwelling->creatures.size() + 1);
|
|
||||||
for(const CCreature * cre : entry)
|
|
||||||
dwelling->creatures.back().second.push_back(cre->getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool guarded = false; //TODO: serialize for sanity
|
|
||||||
|
|
||||||
if(guards.getType() == JsonNode::JsonType::DATA_BOOL) //simple switch
|
|
||||||
{
|
|
||||||
if(guards.Bool())
|
|
||||||
{
|
|
||||||
guarded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(guards.getType() == JsonNode::JsonType::DATA_VECTOR) //custom guards (eg. Elemental Conflux)
|
|
||||||
{
|
|
||||||
for(auto & stack : JsonRandom::loadCreatures(guards, rng))
|
|
||||||
{
|
|
||||||
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->getId(), stack.count));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //default condition - creatures are of level 5 or higher
|
|
||||||
{
|
|
||||||
for(auto creatureEntry : availableCreatures)
|
|
||||||
{
|
|
||||||
if(creatureEntry.at(0)->getLevel() >= 5)
|
|
||||||
{
|
|
||||||
guarded = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(guarded)
|
|
||||||
{
|
|
||||||
for(auto creatureEntry : availableCreatures)
|
|
||||||
{
|
|
||||||
const CCreature * crea = creatureEntry.at(0);
|
|
||||||
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(crea->getId(), crea->getGrowth() * 3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDwellingInstanceConstructor::producesCreature(const CCreature * crea) const
|
|
||||||
{
|
|
||||||
for(const auto & entry : availableCreatures)
|
|
||||||
{
|
|
||||||
for(const CCreature * cre : entry)
|
|
||||||
if(crea == cre)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<const CCreature *> CDwellingInstanceConstructor::getProducedCreatures() const
|
|
||||||
{
|
|
||||||
std::vector<const CCreature *> creatures; //no idea why it's 2D, to be honest
|
|
||||||
for(const auto & entry : availableCreatures)
|
|
||||||
{
|
|
||||||
for(const CCreature * cre : entry)
|
|
||||||
creatures.push_back(cre);
|
|
||||||
}
|
|
||||||
return creatures;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BoatInstanceConstructor::initTypeData(const JsonNode & input)
|
void BoatInstanceConstructor::initTypeData(const JsonNode & input)
|
||||||
{
|
{
|
||||||
layer = EPathfindingLayer::SAIL;
|
layer = EPathfindingLayer::SAIL;
|
||||||
@ -274,9 +148,8 @@ void BoatInstanceConstructor::initTypeData(const JsonNode & input)
|
|||||||
bonuses = JsonRandom::loadBonuses(input["bonuses"]);
|
bonuses = JsonRandom::loadBonuses(input["bonuses"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGObjectInstance * BoatInstanceConstructor::create(std::shared_ptr<const ObjectTemplate> tmpl) const
|
void BoatInstanceConstructor::initializeObject(CGBoat * boat) const
|
||||||
{
|
{
|
||||||
CGBoat * boat = createTyped(tmpl);
|
|
||||||
boat->layer = layer;
|
boat->layer = layer;
|
||||||
boat->actualAnimation = actualAnimation;
|
boat->actualAnimation = actualAnimation;
|
||||||
boat->overlayAnimation = overlayAnimation;
|
boat->overlayAnimation = overlayAnimation;
|
||||||
@ -285,13 +158,20 @@ CGObjectInstance * BoatInstanceConstructor::create(std::shared_ptr<const ObjectT
|
|||||||
boat->onboardVisitAllowed = onboardVisitAllowed;
|
boat->onboardVisitAllowed = onboardVisitAllowed;
|
||||||
for(auto & b : bonuses)
|
for(auto & b : bonuses)
|
||||||
boat->addNewBonus(std::make_shared<Bonus>(b));
|
boat->addNewBonus(std::make_shared<Bonus>(b));
|
||||||
|
|
||||||
return boat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoatInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
|
std::string BoatInstanceConstructor::getBoatAnimationName() const
|
||||||
{
|
{
|
||||||
|
return actualAnimation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoatInstanceConstructor::afterLoadFinalization()
|
||||||
|
{
|
||||||
|
if (layer == EPathfindingLayer::SAIL)
|
||||||
|
{
|
||||||
|
if (getTemplates(TerrainId(ETerrainId::WATER)).empty())
|
||||||
|
logMod->warn("Boat of type %s has no templates suitable for water!", getJsonKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarketInstanceConstructor::initTypeData(const JsonNode & input)
|
void MarketInstanceConstructor::initTypeData(const JsonNode & input)
|
||||||
@ -309,31 +189,25 @@ void MarketInstanceConstructor::initTypeData(const JsonNode & input)
|
|||||||
speech = input["speech"].String();
|
speech = input["speech"].String();
|
||||||
}
|
}
|
||||||
|
|
||||||
CGObjectInstance * MarketInstanceConstructor::create(std::shared_ptr<const ObjectTemplate> tmpl) const
|
CGMarket * MarketInstanceConstructor::createObject() const
|
||||||
{
|
{
|
||||||
CGMarket * market = nullptr;
|
|
||||||
if(marketModes.size() == 1)
|
if(marketModes.size() == 1)
|
||||||
{
|
{
|
||||||
switch(*marketModes.begin())
|
switch(*marketModes.begin())
|
||||||
{
|
{
|
||||||
case EMarketMode::ARTIFACT_RESOURCE:
|
case EMarketMode::ARTIFACT_RESOURCE:
|
||||||
case EMarketMode::RESOURCE_ARTIFACT:
|
case EMarketMode::RESOURCE_ARTIFACT:
|
||||||
market = new CGBlackMarket;
|
return new CGBlackMarket;
|
||||||
break;
|
|
||||||
|
|
||||||
case EMarketMode::RESOURCE_SKILL:
|
case EMarketMode::RESOURCE_SKILL:
|
||||||
market = new CGUniversity;
|
return new CGUniversity;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new CGMarket;
|
||||||
|
}
|
||||||
|
|
||||||
if(!market)
|
void MarketInstanceConstructor::initializeObject(CGMarket * market) const
|
||||||
market = new CGMarket;
|
{
|
||||||
|
|
||||||
preInitObject(market);
|
|
||||||
|
|
||||||
if(tmpl)
|
|
||||||
market->appearance = tmpl;
|
|
||||||
market->marketModes = marketModes;
|
market->marketModes = marketModes;
|
||||||
market->marketEfficiency = marketEfficiency;
|
market->marketEfficiency = marketEfficiency;
|
||||||
|
|
||||||
@ -343,11 +217,9 @@ CGObjectInstance * MarketInstanceConstructor::create(std::shared_ptr<const Objec
|
|||||||
|
|
||||||
if (!speech.empty())
|
if (!speech.empty())
|
||||||
market->speech = VLC->generaltexth->translate(speech);
|
market->speech = VLC->generaltexth->translate(speech);
|
||||||
|
|
||||||
return market;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarketInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
|
void MarketInstanceConstructor::randomizeObject(CGMarket * object, CRandomGenerator & rng) const
|
||||||
{
|
{
|
||||||
if(auto * university = dynamic_cast<CGUniversity *>(object))
|
if(auto * university = dynamic_cast<CGUniversity *>(object))
|
||||||
{
|
{
|
||||||
@ -356,241 +228,4 @@ void MarketInstanceConstructor::configureObject(CGObjectInstance * object, CRand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CBankInstanceConstructor::hasNameTextID() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBankInstanceConstructor::initTypeData(const JsonNode & input)
|
|
||||||
{
|
|
||||||
if (input.Struct().count("name") == 0)
|
|
||||||
logMod->warn("Bank %s missing name!", getJsonKey());
|
|
||||||
|
|
||||||
VLC->generaltexth->registerString(input.meta, getNameTextID(), input["name"].String());
|
|
||||||
|
|
||||||
levels = input["levels"].Vector();
|
|
||||||
bankResetDuration = static_cast<si32>(input["resetDuration"].Float());
|
|
||||||
}
|
|
||||||
|
|
||||||
CGObjectInstance *CBankInstanceConstructor::create(std::shared_ptr<const ObjectTemplate> tmpl) const
|
|
||||||
{
|
|
||||||
return createTyped(tmpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const
|
|
||||||
{
|
|
||||||
BankConfig bc;
|
|
||||||
|
|
||||||
bc.chance = static_cast<ui32>(level["chance"].Float());
|
|
||||||
|
|
||||||
bc.guards = JsonRandom::loadCreatures(level["guards"], rng);
|
|
||||||
bc.upgradeChance = static_cast<ui32>(level["upgrade_chance"].Float());
|
|
||||||
bc.combatValue = static_cast<ui32>(level["combat_value"].Float());
|
|
||||||
|
|
||||||
std::vector<SpellID> spells;
|
|
||||||
for (size_t i=0; i<6; i++)
|
|
||||||
IObjectInterface::cb->getAllowedSpells(spells, static_cast<ui16>(i));
|
|
||||||
|
|
||||||
bc.resources = ResourceSet(level["reward"]["resources"]);
|
|
||||||
bc.creatures = JsonRandom::loadCreatures(level["reward"]["creatures"], rng);
|
|
||||||
bc.artifacts = JsonRandom::loadArtifacts(level["reward"]["artifacts"], rng);
|
|
||||||
bc.spells = JsonRandom::loadSpells(level["reward"]["spells"], rng, spells);
|
|
||||||
|
|
||||||
bc.value = static_cast<ui32>(level["value"].Float());
|
|
||||||
|
|
||||||
return bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
|
|
||||||
{
|
|
||||||
auto * bank = dynamic_cast<CBank *>(object);
|
|
||||||
|
|
||||||
bank->resetDuration = bankResetDuration;
|
|
||||||
|
|
||||||
si32 totalChance = 0;
|
|
||||||
for(const auto & node : levels)
|
|
||||||
totalChance += static_cast<si32>(node["chance"].Float());
|
|
||||||
|
|
||||||
assert(totalChance != 0);
|
|
||||||
|
|
||||||
si32 selectedChance = rng.nextInt(totalChance - 1);
|
|
||||||
|
|
||||||
int cumulativeChance = 0;
|
|
||||||
for(const auto & node : levels)
|
|
||||||
{
|
|
||||||
cumulativeChance += static_cast<int>(node["chance"].Float());
|
|
||||||
if(selectedChance < cumulativeChance)
|
|
||||||
{
|
|
||||||
bank->setConfig(generateConfig(node, rng));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CBankInfo::CBankInfo(const JsonVector & Config) :
|
|
||||||
config(Config)
|
|
||||||
{
|
|
||||||
assert(!Config.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount)
|
|
||||||
{
|
|
||||||
army.totalStrength += crea->getFightValue() * amount;
|
|
||||||
|
|
||||||
bool walker = true;
|
|
||||||
if(crea->hasBonusOfType(BonusType::SHOOTER))
|
|
||||||
{
|
|
||||||
army.shootersStrength += crea->getFightValue() * amount;
|
|
||||||
walker = false;
|
|
||||||
}
|
|
||||||
if(crea->hasBonusOfType(BonusType::FLYING))
|
|
||||||
{
|
|
||||||
army.flyersStrength += crea->getFightValue() * amount;
|
|
||||||
walker = false;
|
|
||||||
}
|
|
||||||
if(walker)
|
|
||||||
army.walkersStrength += crea->getFightValue() * amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
IObjectInfo::CArmyStructure CBankInfo::minGuards() const
|
|
||||||
{
|
|
||||||
std::vector<IObjectInfo::CArmyStructure> armies;
|
|
||||||
for(auto configEntry : config)
|
|
||||||
{
|
|
||||||
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"]);
|
|
||||||
IObjectInfo::CArmyStructure army;
|
|
||||||
for(auto & stack : stacks)
|
|
||||||
{
|
|
||||||
assert(!stack.allowedCreatures.empty());
|
|
||||||
auto weakest = boost::range::min_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b)
|
|
||||||
{
|
|
||||||
return a->getFightValue() < b->getFightValue();
|
|
||||||
});
|
|
||||||
addStackToArmy(army, *weakest, stack.minAmount);
|
|
||||||
}
|
|
||||||
armies.push_back(army);
|
|
||||||
}
|
|
||||||
return *boost::range::min_element(armies);
|
|
||||||
}
|
|
||||||
|
|
||||||
IObjectInfo::CArmyStructure CBankInfo::maxGuards() const
|
|
||||||
{
|
|
||||||
std::vector<IObjectInfo::CArmyStructure> armies;
|
|
||||||
for(auto configEntry : config)
|
|
||||||
{
|
|
||||||
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"]);
|
|
||||||
IObjectInfo::CArmyStructure army;
|
|
||||||
for(auto & stack : stacks)
|
|
||||||
{
|
|
||||||
assert(!stack.allowedCreatures.empty());
|
|
||||||
auto strongest = boost::range::max_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b)
|
|
||||||
{
|
|
||||||
return a->getFightValue() < b->getFightValue();
|
|
||||||
});
|
|
||||||
addStackToArmy(army, *strongest, stack.maxAmount);
|
|
||||||
}
|
|
||||||
armies.push_back(army);
|
|
||||||
}
|
|
||||||
return *boost::range::max_element(armies);
|
|
||||||
}
|
|
||||||
|
|
||||||
TPossibleGuards CBankInfo::getPossibleGuards() const
|
|
||||||
{
|
|
||||||
TPossibleGuards out;
|
|
||||||
|
|
||||||
for(const JsonNode & configEntry : config)
|
|
||||||
{
|
|
||||||
const JsonNode & guardsInfo = configEntry["guards"];
|
|
||||||
auto stacks = JsonRandom::evaluateCreatures(guardsInfo);
|
|
||||||
IObjectInfo::CArmyStructure army;
|
|
||||||
|
|
||||||
|
|
||||||
for(auto stack : stacks)
|
|
||||||
{
|
|
||||||
army.totalStrength += stack.allowedCreatures.front()->getAIValue() * (stack.minAmount + stack.maxAmount) / 2;
|
|
||||||
//TODO: add fields for flyers, walkers etc...
|
|
||||||
}
|
|
||||||
|
|
||||||
ui8 chance = static_cast<ui8>(configEntry["chance"].Float());
|
|
||||||
out.push_back(std::make_pair(chance, army));
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<PossibleReward<TResources>> CBankInfo::getPossibleResourcesReward() const
|
|
||||||
{
|
|
||||||
std::vector<PossibleReward<TResources>> result;
|
|
||||||
|
|
||||||
for(const JsonNode & configEntry : config)
|
|
||||||
{
|
|
||||||
const JsonNode & resourcesInfo = configEntry["reward"]["resources"];
|
|
||||||
|
|
||||||
if(!resourcesInfo.isNull())
|
|
||||||
{
|
|
||||||
result.emplace_back(configEntry["chance"].Integer(), TResources(resourcesInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<PossibleReward<CStackBasicDescriptor>> CBankInfo::getPossibleCreaturesReward() const
|
|
||||||
{
|
|
||||||
std::vector<PossibleReward<CStackBasicDescriptor>> aproximateReward;
|
|
||||||
|
|
||||||
for(const JsonNode & configEntry : config)
|
|
||||||
{
|
|
||||||
const JsonNode & guardsInfo = configEntry["reward"]["creatures"];
|
|
||||||
auto stacks = JsonRandom::evaluateCreatures(guardsInfo);
|
|
||||||
|
|
||||||
for(auto stack : stacks)
|
|
||||||
{
|
|
||||||
const auto * creature = stack.allowedCreatures.front();
|
|
||||||
|
|
||||||
aproximateReward.emplace_back(configEntry["chance"].Integer(), CStackBasicDescriptor(creature, (stack.minAmount + stack.maxAmount) / 2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return aproximateReward;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBankInfo::givesResources() const
|
|
||||||
{
|
|
||||||
for(const JsonNode & node : config)
|
|
||||||
if(!node["reward"]["resources"].isNull())
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBankInfo::givesArtifacts() const
|
|
||||||
{
|
|
||||||
for(const JsonNode & node : config)
|
|
||||||
if(!node["reward"]["artifacts"].isNull())
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBankInfo::givesCreatures() const
|
|
||||||
{
|
|
||||||
for(const JsonNode & node : config)
|
|
||||||
if(!node["reward"]["creatures"].isNull())
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBankInfo::givesSpells() const
|
|
||||||
{
|
|
||||||
for(const JsonNode & node : config)
|
|
||||||
if(!node["reward"]["spells"].isNull())
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<IObjectInfo> CBankInstanceConstructor::getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const
|
|
||||||
{
|
|
||||||
return std::unique_ptr<IObjectInfo>(new CBankInfo(levels));
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -9,63 +9,24 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AObjectTypeHandler.h"
|
#include "CDefaultObjectTypeHandler.h"
|
||||||
|
|
||||||
#include "../mapObjects/CGMarket.h"
|
|
||||||
#include "../mapObjects/MiscObjects.h"
|
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
|
||||||
#include "../mapObjects/CGTownInstance.h"
|
|
||||||
#include "../mapObjects/CBank.h"
|
|
||||||
#include "../LogicalExpression.h"
|
#include "../LogicalExpression.h"
|
||||||
#include "IObjectInfo.h"
|
|
||||||
|
#include "../mapObjects/MiscObjects.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class CGArtifact;
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
class CGTownInstance;
|
class CGTownInstance;
|
||||||
class CGHeroInstance;
|
class CGHeroInstance;
|
||||||
class CGDwelling;
|
class CGMarket;
|
||||||
class CHeroClass;
|
class CHeroClass;
|
||||||
class CBank;
|
class CBank;
|
||||||
|
class CGBoat;
|
||||||
class CFaction;
|
class CFaction;
|
||||||
class CStackBasicDescriptor;
|
class CStackBasicDescriptor;
|
||||||
|
|
||||||
/// Class that is used for objects that do not have dedicated handler
|
|
||||||
template<class ObjectType>
|
|
||||||
class CDefaultObjectTypeHandler : public AObjectTypeHandler
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
ObjectType * createTyped(std::shared_ptr<const ObjectTemplate> tmpl /* = nullptr */) const
|
|
||||||
{
|
|
||||||
auto obj = new ObjectType();
|
|
||||||
preInitObject(obj);
|
|
||||||
|
|
||||||
//Set custom template or leave null
|
|
||||||
if (tmpl)
|
|
||||||
{
|
|
||||||
obj->appearance = tmpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
CDefaultObjectTypeHandler() {}
|
|
||||||
|
|
||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override
|
|
||||||
{
|
|
||||||
return createTyped(tmpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CObstacleConstructor : public CDefaultObjectTypeHandler<CGObjectInstance>
|
class CObstacleConstructor : public CDefaultObjectTypeHandler<CGObjectInstance>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -83,8 +44,8 @@ public:
|
|||||||
CFaction * faction = nullptr;
|
CFaction * faction = nullptr;
|
||||||
std::map<std::string, LogicalExpression<BuildingID>> filters;
|
std::map<std::string, LogicalExpression<BuildingID>> filters;
|
||||||
|
|
||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
void initializeObject(CGTownInstance * object) const override;
|
||||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
void randomizeObject(CGTownInstance * object, CRandomGenerator & rng) const override;
|
||||||
void afterLoadFinalization() override;
|
void afterLoadFinalization() override;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@ -107,8 +68,8 @@ public:
|
|||||||
CHeroClass * heroClass = nullptr;
|
CHeroClass * heroClass = nullptr;
|
||||||
std::map<std::string, LogicalExpression<HeroTypeID>> filters;
|
std::map<std::string, LogicalExpression<HeroTypeID>> filters;
|
||||||
|
|
||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
void initializeObject(CGHeroInstance * object) const override;
|
||||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
void randomizeObject(CGHeroInstance * object, CRandomGenerator & rng) const override;
|
||||||
void afterLoadFinalization() override;
|
void afterLoadFinalization() override;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@ -120,34 +81,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling>
|
class DLL_LINKAGE BoatInstanceConstructor : public CDefaultObjectTypeHandler<CGBoat>
|
||||||
{
|
|
||||||
std::vector<std::vector<const CCreature *>> availableCreatures;
|
|
||||||
|
|
||||||
JsonNode guards;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const override;
|
|
||||||
void initTypeData(const JsonNode & input) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool hasNameTextID() const override;
|
|
||||||
|
|
||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
|
||||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
|
||||||
|
|
||||||
bool producesCreature(const CCreature * crea) const;
|
|
||||||
std::vector<const CCreature *> getProducedCreatures() const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & availableCreatures;
|
|
||||||
h & guards;
|
|
||||||
h & static_cast<CDefaultObjectTypeHandler<CGDwelling>&>(*this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class BoatInstanceConstructor : public CDefaultObjectTypeHandler<CGBoat>
|
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
void initTypeData(const JsonNode & config) override;
|
void initTypeData(const JsonNode & config) override;
|
||||||
@ -162,8 +96,11 @@ protected:
|
|||||||
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
|
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
void initializeObject(CGBoat * object) const override;
|
||||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
void afterLoadFinalization() override;
|
||||||
|
|
||||||
|
/// Returns boat preview animation, for use in Shipyards
|
||||||
|
std::string getBoatAnimationName() const;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
@ -178,90 +115,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BankConfig
|
|
||||||
{
|
|
||||||
ui32 value = 0; //overall value of given things
|
|
||||||
ui32 chance = 0; //chance for this level being chosen
|
|
||||||
ui32 upgradeChance = 0; //chance for creatures to be in upgraded versions
|
|
||||||
ui32 combatValue = 0; //how hard are guards of this level
|
|
||||||
std::vector<CStackBasicDescriptor> guards; //creature ID, amount
|
|
||||||
ResourceSet resources; //resources given in case of victory
|
|
||||||
std::vector<CStackBasicDescriptor> creatures; //creatures granted in case of victory (creature ID, amount)
|
|
||||||
std::vector<ArtifactID> artifacts; //artifacts given in case of victory
|
|
||||||
std::vector<SpellID> spells; // granted spell(s), for Pyramid
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & chance;
|
|
||||||
h & upgradeChance;
|
|
||||||
h & guards;
|
|
||||||
h & combatValue;
|
|
||||||
h & resources;
|
|
||||||
h & creatures;
|
|
||||||
h & artifacts;
|
|
||||||
h & value;
|
|
||||||
h & spells;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using TPossibleGuards = std::vector<std::pair<ui8, IObjectInfo::CArmyStructure>>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct DLL_LINKAGE PossibleReward
|
|
||||||
{
|
|
||||||
int chance;
|
|
||||||
T data;
|
|
||||||
|
|
||||||
PossibleReward(int chance, const T & data) : chance(chance), data(data) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLL_LINKAGE CBankInfo : public IObjectInfo
|
|
||||||
{
|
|
||||||
const JsonVector & config;
|
|
||||||
public:
|
|
||||||
CBankInfo(const JsonVector & Config);
|
|
||||||
|
|
||||||
TPossibleGuards getPossibleGuards() const;
|
|
||||||
std::vector<PossibleReward<TResources>> getPossibleResourcesReward() const;
|
|
||||||
std::vector<PossibleReward<CStackBasicDescriptor>> getPossibleCreaturesReward() const;
|
|
||||||
|
|
||||||
// These functions should try to evaluate minimal possible/max possible guards to give provide information on possible thread to AI
|
|
||||||
CArmyStructure minGuards() const override;
|
|
||||||
CArmyStructure maxGuards() const override;
|
|
||||||
|
|
||||||
bool givesResources() const override;
|
|
||||||
bool givesArtifacts() const override;
|
|
||||||
bool givesCreatures() const override;
|
|
||||||
bool givesSpells() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CBankInstanceConstructor : public CDefaultObjectTypeHandler<CBank>
|
|
||||||
{
|
|
||||||
BankConfig generateConfig(const JsonNode & conf, CRandomGenerator & rng) const;
|
|
||||||
|
|
||||||
JsonVector levels;
|
|
||||||
protected:
|
|
||||||
void initTypeData(const JsonNode & input) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// all banks of this type will be reset N days after clearing,
|
|
||||||
si32 bankResetDuration = 0;
|
|
||||||
|
|
||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
|
||||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
|
||||||
|
|
||||||
bool hasNameTextID() const override;
|
|
||||||
|
|
||||||
std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & levels;
|
|
||||||
h & bankResetDuration;
|
|
||||||
h & static_cast<CDefaultObjectTypeHandler<CBank>&>(*this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
|
class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -274,8 +127,9 @@ protected:
|
|||||||
std::string title, speech;
|
std::string title, speech;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
|
CGMarket * createObject() const override;
|
||||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
void initializeObject(CGMarket * object) const override;
|
||||||
|
void randomizeObject(CGMarket * object, CRandomGenerator & rng) const override;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
146
lib/mapObjectConstructors/DwellingInstanceConstructor.cpp
Normal file
146
lib/mapObjectConstructors/DwellingInstanceConstructor.cpp
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* DwellingInstanceConstructor.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 "DwellingInstanceConstructor.h"
|
||||||
|
|
||||||
|
#include "../CCreatureHandler.h"
|
||||||
|
#include "../CGeneralTextHandler.h"
|
||||||
|
#include "../CModHandler.h"
|
||||||
|
#include "../JsonRandom.h"
|
||||||
|
#include "../VCMI_Lib.h"
|
||||||
|
#include "../mapObjects/CGDwelling.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
bool DwellingInstanceConstructor::hasNameTextID() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DwellingInstanceConstructor::initTypeData(const JsonNode & input)
|
||||||
|
{
|
||||||
|
if (input.Struct().count("name") == 0)
|
||||||
|
logMod->warn("Dwelling %s missing name!", getJsonKey());
|
||||||
|
|
||||||
|
VLC->generaltexth->registerString( input.meta, getNameTextID(), input["name"].String());
|
||||||
|
|
||||||
|
const JsonVector & levels = input["creatures"].Vector();
|
||||||
|
const auto totalLevels = levels.size();
|
||||||
|
|
||||||
|
availableCreatures.resize(totalLevels);
|
||||||
|
for(auto currentLevel = 0; currentLevel < totalLevels; currentLevel++)
|
||||||
|
{
|
||||||
|
const JsonVector & creaturesOnLevel = levels[currentLevel].Vector();
|
||||||
|
const auto creaturesNumber = creaturesOnLevel.size();
|
||||||
|
availableCreatures[currentLevel].resize(creaturesNumber);
|
||||||
|
|
||||||
|
for(auto currentCreature = 0; currentCreature < creaturesNumber; currentCreature++)
|
||||||
|
{
|
||||||
|
VLC->modh->identifiers.requestIdentifier("creature", creaturesOnLevel[currentCreature], [=] (si32 index)
|
||||||
|
{
|
||||||
|
availableCreatures[currentLevel][currentCreature] = VLC->creh->objects[index];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
assert(!availableCreatures[currentLevel].empty());
|
||||||
|
}
|
||||||
|
guards = input["guards"];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DwellingInstanceConstructor::objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DwellingInstanceConstructor::initializeObject(CGDwelling * obj) const
|
||||||
|
{
|
||||||
|
obj->creatures.resize(availableCreatures.size());
|
||||||
|
for(const auto & entry : availableCreatures)
|
||||||
|
{
|
||||||
|
for(const CCreature * cre : entry)
|
||||||
|
obj->creatures.back().second.push_back(cre->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DwellingInstanceConstructor::randomizeObject(CGDwelling * object, CRandomGenerator &rng) const
|
||||||
|
{
|
||||||
|
auto * dwelling = dynamic_cast<CGDwelling *>(object);
|
||||||
|
|
||||||
|
dwelling->creatures.clear();
|
||||||
|
dwelling->creatures.reserve(availableCreatures.size());
|
||||||
|
|
||||||
|
for(const auto & entry : availableCreatures)
|
||||||
|
{
|
||||||
|
dwelling->creatures.resize(dwelling->creatures.size() + 1);
|
||||||
|
for(const CCreature * cre : entry)
|
||||||
|
dwelling->creatures.back().second.push_back(cre->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool guarded = false; //TODO: serialize for sanity
|
||||||
|
|
||||||
|
if(guards.getType() == JsonNode::JsonType::DATA_BOOL) //simple switch
|
||||||
|
{
|
||||||
|
if(guards.Bool())
|
||||||
|
{
|
||||||
|
guarded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(guards.getType() == JsonNode::JsonType::DATA_VECTOR) //custom guards (eg. Elemental Conflux)
|
||||||
|
{
|
||||||
|
for(auto & stack : JsonRandom::loadCreatures(guards, rng))
|
||||||
|
{
|
||||||
|
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->getId(), stack.count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //default condition - creatures are of level 5 or higher
|
||||||
|
{
|
||||||
|
for(auto creatureEntry : availableCreatures)
|
||||||
|
{
|
||||||
|
if(creatureEntry.at(0)->getLevel() >= 5)
|
||||||
|
{
|
||||||
|
guarded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(guarded)
|
||||||
|
{
|
||||||
|
for(auto creatureEntry : availableCreatures)
|
||||||
|
{
|
||||||
|
const CCreature * crea = creatureEntry.at(0);
|
||||||
|
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(crea->getId(), crea->getGrowth() * 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DwellingInstanceConstructor::producesCreature(const CCreature * crea) const
|
||||||
|
{
|
||||||
|
for(const auto & entry : availableCreatures)
|
||||||
|
{
|
||||||
|
for(const CCreature * cre : entry)
|
||||||
|
if(crea == cre)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const CCreature *> DwellingInstanceConstructor::getProducedCreatures() const
|
||||||
|
{
|
||||||
|
std::vector<const CCreature *> creatures; //no idea why it's 2D, to be honest
|
||||||
|
for(const auto & entry : availableCreatures)
|
||||||
|
{
|
||||||
|
for(const CCreature * cre : entry)
|
||||||
|
creatures.push_back(cre);
|
||||||
|
}
|
||||||
|
return creatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
45
lib/mapObjectConstructors/DwellingInstanceConstructor.h
Normal file
45
lib/mapObjectConstructors/DwellingInstanceConstructor.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* DwellingInstanceConstructor.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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CDefaultObjectTypeHandler.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class CGDwelling;
|
||||||
|
|
||||||
|
class DwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling>
|
||||||
|
{
|
||||||
|
std::vector<std::vector<const CCreature *>> availableCreatures;
|
||||||
|
|
||||||
|
JsonNode guards;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool objectFilter(const CGObjectInstance * obj, std::shared_ptr<const ObjectTemplate> tmpl) const override;
|
||||||
|
void initTypeData(const JsonNode & input) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool hasNameTextID() const override;
|
||||||
|
|
||||||
|
void initializeObject(CGDwelling * object) const override;
|
||||||
|
void randomizeObject(CGDwelling * object, CRandomGenerator & rng) const override;
|
||||||
|
|
||||||
|
bool producesCreature(const CCreature * crea) const;
|
||||||
|
std::vector<const CCreature *> getProducedCreatures() const;
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & availableCreatures;
|
||||||
|
h & guards;
|
||||||
|
h & static_cast<CDefaultObjectTypeHandler<CGDwelling>&>(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
27
lib/mapObjectConstructors/HillFortInstanceConstructor.cpp
Normal file
27
lib/mapObjectConstructors/HillFortInstanceConstructor.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* HillFortInstanceConstructor.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 "HillFortInstanceConstructor.h"
|
||||||
|
|
||||||
|
#include "../mapObjects/MiscObjects.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
void HillFortInstanceConstructor::initTypeData(const JsonNode & config)
|
||||||
|
{
|
||||||
|
parameters = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HillFortInstanceConstructor::initializeObject(HillFort * fort) const
|
||||||
|
{
|
||||||
|
fort->upgradeCostPercentage = parameters["upgradeCostFactor"].convertTo<std::vector<int>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
34
lib/mapObjectConstructors/HillFortInstanceConstructor.h
Normal file
34
lib/mapObjectConstructors/HillFortInstanceConstructor.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* HillFortInstanceConstructor.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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CDefaultObjectTypeHandler.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class HillFort;
|
||||||
|
|
||||||
|
class HillFortInstanceConstructor final : public CDefaultObjectTypeHandler<HillFort>
|
||||||
|
{
|
||||||
|
JsonNode parameters;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initTypeData(const JsonNode & config) override;
|
||||||
|
void initializeObject(HillFort * object) const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & static_cast<AObjectTypeHandler&>(*this);
|
||||||
|
h & parameters;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
28
lib/mapObjectConstructors/ShipyardInstanceConstructor.cpp
Normal file
28
lib/mapObjectConstructors/ShipyardInstanceConstructor.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* ShipyardInstanceConstructor.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 "ShipyardInstanceConstructor.h"
|
||||||
|
|
||||||
|
#include "../mapObjects/MiscObjects.h"
|
||||||
|
#include "../CModHandler.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
void ShipyardInstanceConstructor::initTypeData(const JsonNode & config)
|
||||||
|
{
|
||||||
|
parameters = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShipyardInstanceConstructor::initializeObject(CGShipyard * shipyard) const
|
||||||
|
{
|
||||||
|
shipyard->createdBoat = BoatId(*VLC->modh->identifiers.getIdentifier("core:boat", parameters["boat"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
34
lib/mapObjectConstructors/ShipyardInstanceConstructor.h
Normal file
34
lib/mapObjectConstructors/ShipyardInstanceConstructor.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* ShipyardInstanceConstructor.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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CDefaultObjectTypeHandler.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class CGShipyard;
|
||||||
|
|
||||||
|
class ShipyardInstanceConstructor final : public CDefaultObjectTypeHandler<CGShipyard>
|
||||||
|
{
|
||||||
|
JsonNode parameters;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initTypeData(const JsonNode & config) override;
|
||||||
|
void initializeObject(CGShipyard * object) const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & static_cast<AObjectTypeHandler&>(*this);
|
||||||
|
h & parameters;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
42
lib/mapObjectConstructors/ShrineInstanceConstructor.cpp
Normal file
42
lib/mapObjectConstructors/ShrineInstanceConstructor.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* ShrineInstanceConstructor.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 "ShrineInstanceConstructor.h"
|
||||||
|
|
||||||
|
#include "../mapObjects/MiscObjects.h"
|
||||||
|
#include "../JsonRandom.h"
|
||||||
|
#include "../IGameCallback.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
void ShrineInstanceConstructor::initTypeData(const JsonNode & config)
|
||||||
|
{
|
||||||
|
parameters = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShrineInstanceConstructor::randomizeObject(CGShrine * shrine, CRandomGenerator & rng) const
|
||||||
|
{
|
||||||
|
auto visitTextParameter = parameters["visitText"];
|
||||||
|
|
||||||
|
if (visitTextParameter.isNumber())
|
||||||
|
shrine->visitText.addTxt(MetaString::ADVOB_TXT, static_cast<ui32>(visitTextParameter.Float()));
|
||||||
|
else
|
||||||
|
shrine->visitText << visitTextParameter.String();
|
||||||
|
|
||||||
|
if(shrine->spell == SpellID::NONE) // shrine has no predefined spell
|
||||||
|
{
|
||||||
|
std::vector<SpellID> possibilities;
|
||||||
|
shrine->cb->getAllowedSpells(possibilities);
|
||||||
|
|
||||||
|
shrine->spell =JsonRandom::loadSpell(parameters["spell"], rng, possibilities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
34
lib/mapObjectConstructors/ShrineInstanceConstructor.h
Normal file
34
lib/mapObjectConstructors/ShrineInstanceConstructor.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* ShrineInstanceConstructor.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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CDefaultObjectTypeHandler.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class CGShrine;
|
||||||
|
|
||||||
|
class ShrineInstanceConstructor final : public CDefaultObjectTypeHandler<CGShrine>
|
||||||
|
{
|
||||||
|
JsonNode parameters;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initTypeData(const JsonNode & config) override;
|
||||||
|
void randomizeObject(CGShrine * object, CRandomGenerator & rng) const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & static_cast<AObjectTypeHandler&>(*this);
|
||||||
|
h & parameters;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -18,7 +18,7 @@
|
|||||||
#include "../CGeneralTextHandler.h"
|
#include "../CGeneralTextHandler.h"
|
||||||
#include "../CSoundBase.h"
|
#include "../CSoundBase.h"
|
||||||
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "../mapObjectConstructors/CommonConstructors.h"
|
#include "../mapObjectConstructors/CBankInstanceConstructor.h"
|
||||||
#include "../IGameCallback.h"
|
#include "../IGameCallback.h"
|
||||||
#include "../CGameState.h"
|
#include "../CGameState.h"
|
||||||
|
|
||||||
|
@ -225,7 +225,6 @@ int CGHeroInstance::maxMovePointsCached(bool onLand, const TurnInfo * ti) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
CGHeroInstance::CGHeroInstance():
|
CGHeroInstance::CGHeroInstance():
|
||||||
IBoatGenerator(this),
|
|
||||||
tacticFormationEnabled(false),
|
tacticFormationEnabled(false),
|
||||||
inTownGarrison(false),
|
inTownGarrison(false),
|
||||||
moveDir(4),
|
moveDir(4),
|
||||||
@ -453,7 +452,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
|
|||||||
//Create a new boat for hero
|
//Create a new boat for hero
|
||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::BOAT;
|
no.ID = Obj::BOAT;
|
||||||
no.subID = BoatId(EBoatId::BOAT_NEUTRAL);
|
no.subID = BoatId(EBoatId::CASTLE);
|
||||||
no.pos = CGBoat::translatePos(boatPos);
|
no.pos = CGBoat::translatePos(boatPos);
|
||||||
|
|
||||||
cb->sendAndApply(&no);
|
cb->sendAndApply(&no);
|
||||||
@ -954,13 +953,8 @@ si32 CGHeroInstance::getManaNewTurn() const
|
|||||||
|
|
||||||
BoatId CGHeroInstance::getBoatType() const
|
BoatId CGHeroInstance::getBoatType() const
|
||||||
{
|
{
|
||||||
switch (type->heroClass->getAlignment())
|
// hero can only generate boat via "Summon Boat" spell which always create same boat as in Necropolis shipyard
|
||||||
{
|
return EBoatId::NECROPOLIS;
|
||||||
case EAlignment::EVIL: return EBoatId::BOAT_EVIL;
|
|
||||||
case EAlignment::GOOD: return EBoatId::BOAT_GOOD;
|
|
||||||
case EAlignment::NEUTRAL: return EBoatId::BOAT_NEUTRAL;
|
|
||||||
default: return EBoatId::NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGHeroInstance::getOutOffsets(std::vector<int3> &offsets) const
|
void CGHeroInstance::getOutOffsets(std::vector<int3> &offsets) const
|
||||||
@ -973,6 +967,11 @@ void CGHeroInstance::getOutOffsets(std::vector<int3> &offsets) const
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IObjectInterface * CGHeroInstance::getObject() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t CGHeroInstance::getSpellCost(const spells::Spell * sp) const
|
int32_t CGHeroInstance::getSpellCost(const spells::Spell * sp) const
|
||||||
{
|
{
|
||||||
return sp->getCost(getSpellSchoolLevel(sp));
|
return sp->getCost(getSpellSchoolLevel(sp));
|
||||||
@ -1715,4 +1714,18 @@ bool CGHeroInstance::isMissionCritical() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGHeroInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const
|
||||||
|
{
|
||||||
|
TConstBonusListPtr lista = getBonuses(Selector::typeSubtype(BonusType::SPECIAL_UPGRADE, stack.type->getId()));
|
||||||
|
for(const auto & it : *lista)
|
||||||
|
{
|
||||||
|
auto nid = CreatureID(it->additionalInfo[0]);
|
||||||
|
if (nid != stack.type->getId()) //in very specific case the upgrade is available by default (?)
|
||||||
|
{
|
||||||
|
info.newID.push_back(nid);
|
||||||
|
info.cost.push_back(nid.toCreature()->getFullRecruitCost() - stack.type->getFullRecruitCost());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -39,7 +39,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public spells::Caster, public AFactionMember
|
class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public spells::Caster, public AFactionMember, public ICreatureUpgrader
|
||||||
{
|
{
|
||||||
// We serialize heroes into JSON for crossover
|
// We serialize heroes into JSON for crossover
|
||||||
friend class CCampaignState;
|
friend class CCampaignState;
|
||||||
@ -133,6 +133,7 @@ public:
|
|||||||
|
|
||||||
BoatId getBoatType() const override; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
BoatId getBoatType() const override; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||||
void getOutOffsets(std::vector<int3> &offsets) const override; //offsets to obj pos when we boat can be placed
|
void getOutOffsets(std::vector<int3> &offsets) const override; //offsets to obj pos when we boat can be placed
|
||||||
|
const IObjectInterface * getObject() const override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -230,6 +231,8 @@ public:
|
|||||||
void recreateSecondarySkillsBonuses();
|
void recreateSecondarySkillsBonuses();
|
||||||
void updateSkillBonus(const SecondarySkill & which, int val);
|
void updateSkillBonus(const SecondarySkill & which, int val);
|
||||||
|
|
||||||
|
void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override;
|
||||||
|
|
||||||
bool hasVisions(const CGObjectInstance * target, const int subtype) const;
|
bool hasVisions(const CGObjectInstance * target, const int subtype) const;
|
||||||
/// If this hero perishes, the scenario is failed
|
/// If this hero perishes, the scenario is failed
|
||||||
bool isMissionCritical() const;
|
bool isMissionCritical() const;
|
||||||
|
@ -254,11 +254,6 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
{
|
{
|
||||||
switch(ID)
|
switch(ID)
|
||||||
{
|
{
|
||||||
case Obj::HILL_FORT:
|
|
||||||
{
|
|
||||||
openWindow(EOpenWindowMode::HILL_FORT_WINDOW,id.getNum(),h->id.getNum());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Obj::SANCTUARY:
|
case Obj::SANCTUARY:
|
||||||
{
|
{
|
||||||
//You enter the sanctuary and immediately feel as if a great weight has been lifted off your shoulders. You feel safe here.
|
//You enter the sanctuary and immediately feel as if a great weight has been lifted off your shoulders. You feel safe here.
|
||||||
|
@ -224,8 +224,6 @@ bool CGTownInstance::hasCapitol() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
CGTownInstance::CGTownInstance():
|
CGTownInstance::CGTownInstance():
|
||||||
IShipyard(this),
|
|
||||||
IMarket(),
|
|
||||||
town(nullptr),
|
town(nullptr),
|
||||||
builded(0),
|
builded(0),
|
||||||
destroyed(0),
|
destroyed(0),
|
||||||
@ -590,6 +588,19 @@ void CGTownInstance::getOutOffsets( std::vector<int3> &offsets ) const
|
|||||||
offsets = {int3(-1,2,0), int3(-3,2,0)};
|
offsets = {int3(-1,2,0), int3(-3,2,0)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGTownInstance::EGeneratorState CGTownInstance::shipyardStatus() const
|
||||||
|
{
|
||||||
|
if (!hasBuilt(BuildingID::SHIPYARD))
|
||||||
|
return EGeneratorState::UNKNOWN;
|
||||||
|
|
||||||
|
return IShipyard::shipyardStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
const IObjectInterface * CGTownInstance::getObject() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
void CGTownInstance::mergeGarrisonOnSiege() const
|
void CGTownInstance::mergeGarrisonOnSiege() const
|
||||||
{
|
{
|
||||||
auto getWeakestStackSlot = [&](ui64 powerLimit)
|
auto getWeakestStackSlot = [&](ui64 powerLimit)
|
||||||
@ -671,13 +682,7 @@ void CGTownInstance::clearArmy() const
|
|||||||
|
|
||||||
BoatId CGTownInstance::getBoatType() const
|
BoatId CGTownInstance::getBoatType() const
|
||||||
{
|
{
|
||||||
switch (town->faction->alignment)
|
return town->shipyardBoat;
|
||||||
{
|
|
||||||
case EAlignment::EVIL : return EBoatId::BOAT_EVIL;
|
|
||||||
case EAlignment::GOOD : return EBoatId::BOAT_GOOD;
|
|
||||||
case EAlignment::NEUTRAL : return EBoatId::BOAT_NEUTRAL;
|
|
||||||
default: return EBoatId::NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CGTownInstance::getMarketEfficiency() const
|
int CGTownInstance::getMarketEfficiency() const
|
||||||
@ -1242,5 +1247,22 @@ int GrowthInfo::totalGrowth() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGTownInstance::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const
|
||||||
|
{
|
||||||
|
for(const CGTownInstance::TCreaturesSet::value_type & dwelling : creatures)
|
||||||
|
{
|
||||||
|
if (vstd::contains(dwelling.second, stack.type->getId())) //Dwelling with our creature
|
||||||
|
{
|
||||||
|
for(const auto & upgrID : dwelling.second)
|
||||||
|
{
|
||||||
|
if(vstd::contains(stack.type->upgrades, upgrID)) //possible upgrade
|
||||||
|
{
|
||||||
|
info.newID.push_back(upgrID);
|
||||||
|
info.cost.push_back(upgrID.toCreature()->getFullRecruitCost() - stack.type->getFullRecruitCost());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -42,10 +42,12 @@ struct DLL_LINKAGE GrowthInfo
|
|||||||
int totalGrowth() const;
|
int totalGrowth() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket, public INativeTerrainProvider
|
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket, public INativeTerrainProvider, public ICreatureUpgrader
|
||||||
{
|
{
|
||||||
std::string name; // name of town
|
std::string name; // name of town
|
||||||
public:
|
public:
|
||||||
|
using CGDwelling::getPosition;
|
||||||
|
|
||||||
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
|
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
|
||||||
|
|
||||||
CTownAndVisitingHero townAndVis;
|
CTownAndVisitingHero townAndVis;
|
||||||
@ -71,7 +73,6 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<CGDwelling&>(*this);
|
h & static_cast<CGDwelling&>(*this);
|
||||||
h & static_cast<IShipyard&>(*this);
|
|
||||||
h & name;
|
h & name;
|
||||||
h & builded;
|
h & builded;
|
||||||
h & destroyed;
|
h & destroyed;
|
||||||
@ -134,6 +135,8 @@ public:
|
|||||||
int getSightRadius() const override; //returns sight distance
|
int getSightRadius() const override; //returns sight distance
|
||||||
BoatId getBoatType() const override; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
BoatId getBoatType() const override; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||||
void getOutOffsets(std::vector<int3> &offsets) const override; //offsets to obj pos when we boat can be placed. Parameter will be cleared
|
void getOutOffsets(std::vector<int3> &offsets) const override; //offsets to obj pos when we boat can be placed. Parameter will be cleared
|
||||||
|
EGeneratorState shipyardStatus() const override;
|
||||||
|
const IObjectInterface * getObject() const override;
|
||||||
int getMarketEfficiency() const override; //=market count
|
int getMarketEfficiency() const override; //=market count
|
||||||
bool allowsTrade(EMarketMode::EMarketMode mode) const override;
|
bool allowsTrade(EMarketMode::EMarketMode mode) const override;
|
||||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
|
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
|
||||||
@ -197,6 +200,8 @@ public:
|
|||||||
void battleFinished(const CGHeroInstance * hero, const BattleResult & result) const override;
|
void battleFinished(const CGHeroInstance * hero, const BattleResult & result) const override;
|
||||||
std::string getObjectName() const override;
|
std::string getObjectName() const override;
|
||||||
|
|
||||||
|
void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override;
|
||||||
|
|
||||||
void afterAddToMap(CMap * map) override;
|
void afterAddToMap(CMap * map) override;
|
||||||
void afterRemoveFromMap(CMap * map) override;
|
void afterRemoveFromMap(CMap * map) override;
|
||||||
static void reset();
|
static void reset();
|
||||||
|
@ -92,10 +92,10 @@ int3 IBoatGenerator::bestLocation() const
|
|||||||
|
|
||||||
for (auto & offset : offsets)
|
for (auto & offset : offsets)
|
||||||
{
|
{
|
||||||
if(const TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offset, false)) //tile is in the map
|
if(const TerrainTile *tile = getObject()->cb->getTile(getObject()->getPosition() + offset, false)) //tile is in the map
|
||||||
{
|
{
|
||||||
if(tile->terType->isWater() && (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat
|
if(tile->terType->isWater() && (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat
|
||||||
return o->pos + offset;
|
return getObject()->getPosition() + offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return int3 (-1,-1,-1);
|
return int3 (-1,-1,-1);
|
||||||
@ -107,26 +107,16 @@ IBoatGenerator::EGeneratorState IBoatGenerator::shipyardStatus() const
|
|||||||
const TerrainTile *t = IObjectInterface::cb->getTile(tile);
|
const TerrainTile *t = IObjectInterface::cb->getTile(tile);
|
||||||
if(!t)
|
if(!t)
|
||||||
return TILE_BLOCKED; //no available water
|
return TILE_BLOCKED; //no available water
|
||||||
else if(t->blockingObjects.empty())
|
|
||||||
|
if(t->blockingObjects.empty())
|
||||||
return GOOD; //OK
|
return GOOD; //OK
|
||||||
else if(t->blockingObjects.front()->ID == Obj::BOAT)
|
|
||||||
|
if(t->blockingObjects.front()->ID == Obj::BOAT)
|
||||||
return BOAT_ALREADY_BUILT; //blocked with boat
|
return BOAT_ALREADY_BUILT; //blocked with boat
|
||||||
else
|
|
||||||
return TILE_BLOCKED; //blocked
|
return TILE_BLOCKED; //blocked
|
||||||
}
|
}
|
||||||
|
|
||||||
BoatId IBoatGenerator::getBoatType() const
|
|
||||||
{
|
|
||||||
//We make good ships by default
|
|
||||||
return EBoatId::BOAT_GOOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
IBoatGenerator::IBoatGenerator(const CGObjectInstance *O)
|
|
||||||
: o(O)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visitor) const
|
void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visitor) const
|
||||||
{
|
{
|
||||||
switch(shipyardStatus())
|
switch(shipyardStatus())
|
||||||
@ -144,7 +134,7 @@ void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visit
|
|||||||
out.addTxt(MetaString::ADVOB_TXT, 189);
|
out.addTxt(MetaString::ADVOB_TXT, 189);
|
||||||
break;
|
break;
|
||||||
case NO_WATER:
|
case NO_WATER:
|
||||||
logGlobal->error("Shipyard without water! %s \t %d", o->pos.toString(), o->id.getNum());
|
logGlobal->error("Shipyard without water at tile %s! ", getObject()->getPosition().toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,34 +145,9 @@ void IShipyard::getBoatCost(TResources & cost) const
|
|||||||
cost[EGameResID::GOLD] = 1000;
|
cost[EGameResID::GOLD] = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
IShipyard::IShipyard(const CGObjectInstance *O)
|
|
||||||
: IBoatGenerator(O)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
IShipyard * IShipyard::castFrom( CGObjectInstance *obj )
|
|
||||||
{
|
|
||||||
if(!obj)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if(obj->ID == Obj::TOWN)
|
|
||||||
{
|
|
||||||
return dynamic_cast<CGTownInstance *>(obj);
|
|
||||||
}
|
|
||||||
else if(obj->ID == Obj::SHIPYARD)
|
|
||||||
{
|
|
||||||
return dynamic_cast<CGShipyard *>(obj);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const IShipyard * IShipyard::castFrom( const CGObjectInstance *obj )
|
const IShipyard * IShipyard::castFrom( const CGObjectInstance *obj )
|
||||||
{
|
{
|
||||||
return castFrom(const_cast<CGObjectInstance*>(obj));
|
return dynamic_cast<const IShipyard *>(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
struct BattleResult;
|
struct BattleResult;
|
||||||
|
struct UpgradeInfo;
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
class CRandomGenerator;
|
class CRandomGenerator;
|
||||||
class IGameCallback;
|
class IGameCallback;
|
||||||
@ -66,42 +67,36 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE ICreatureUpgrader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const = 0;
|
||||||
|
|
||||||
|
virtual ~ICreatureUpgrader() = default;
|
||||||
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE IBoatGenerator
|
class DLL_LINKAGE IBoatGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const CGObjectInstance *o;
|
|
||||||
|
|
||||||
IBoatGenerator(const CGObjectInstance *O);
|
|
||||||
virtual ~IBoatGenerator() = default;
|
virtual ~IBoatGenerator() = default;
|
||||||
|
|
||||||
virtual BoatId getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
virtual const IObjectInterface * getObject() const = 0;
|
||||||
|
|
||||||
|
virtual BoatId getBoatType() const = 0; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||||
virtual void getOutOffsets(std::vector<int3> & offsets) const = 0; //offsets to obj pos when we boat can be placed
|
virtual void getOutOffsets(std::vector<int3> & offsets) const = 0; //offsets to obj pos when we boat can be placed
|
||||||
int3 bestLocation() const; //returns location when the boat should be placed
|
int3 bestLocation() const; //returns location when the boat should be placed
|
||||||
|
|
||||||
enum EGeneratorState {GOOD, BOAT_ALREADY_BUILT, TILE_BLOCKED, NO_WATER};
|
enum EGeneratorState {GOOD, BOAT_ALREADY_BUILT, TILE_BLOCKED, NO_WATER, UNKNOWN};
|
||||||
EGeneratorState shipyardStatus() const; //0 - can buid, 1 - there is already a boat at dest tile, 2 - dest tile is blocked, 3 - no water
|
virtual EGeneratorState shipyardStatus() const;
|
||||||
void getProblemText(MetaString &out, const CGHeroInstance *visitor = nullptr) const;
|
void getProblemText(MetaString &out, const CGHeroInstance *visitor = nullptr) const;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & o;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE IShipyard : public IBoatGenerator
|
class DLL_LINKAGE IShipyard : public IBoatGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IShipyard(const CGObjectInstance *O);
|
|
||||||
|
|
||||||
virtual void getBoatCost(ResourceSet & cost) const;
|
virtual void getBoatCost(ResourceSet & cost) const;
|
||||||
|
|
||||||
static const IShipyard *castFrom(const CGObjectInstance *obj);
|
static const IShipyard *castFrom(const CGObjectInstance *obj);
|
||||||
static IShipyard *castFrom(CGObjectInstance *obj);
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
|
||||||
{
|
|
||||||
h & static_cast<IBoatGenerator&>(*this);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#include "../CPlayerState.h"
|
#include "../CPlayerState.h"
|
||||||
#include "../GameSettings.h"
|
#include "../GameSettings.h"
|
||||||
#include "../serializer/JsonSerializeFormat.h"
|
#include "../serializer/JsonSerializeFormat.h"
|
||||||
|
#include "../mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
|
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -1530,7 +1532,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.type = EInfoWindowMode::AUTO;
|
iw.type = EInfoWindowMode::AUTO;
|
||||||
iw.player = h->getOwner();
|
iw.player = h->getOwner();
|
||||||
iw.text.addTxt(MetaString::ADVOB_TXT,127 + ID - 88);
|
iw.text = visitText;
|
||||||
iw.text.addTxt(MetaString::SPELL_NAME,spell);
|
iw.text.addTxt(MetaString::SPELL_NAME,spell);
|
||||||
iw.text << ".";
|
iw.text << ".";
|
||||||
|
|
||||||
@ -1542,7 +1544,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
{
|
{
|
||||||
iw.text.addTxt(MetaString::ADVOB_TXT,174);
|
iw.text.addTxt(MetaString::ADVOB_TXT,174);
|
||||||
}
|
}
|
||||||
else if(ID == Obj::SHRINE_OF_MAGIC_THOUGHT && h->maxSpellLevel() < 3) //it's third level spell and hero doesn't have wisdom
|
else if(spell.toSpell()->getLevel() > h->maxSpellLevel()) //it's third level spell and hero doesn't have wisdom
|
||||||
{
|
{
|
||||||
iw.text.addTxt(MetaString::ADVOB_TXT,130);
|
iw.text.addTxt(MetaString::ADVOB_TXT,130);
|
||||||
}
|
}
|
||||||
@ -1560,20 +1562,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
|
|
||||||
void CGShrine::initObj(CRandomGenerator & rand)
|
void CGShrine::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
if(spell == SpellID::NONE) //spell not set
|
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand);
|
||||||
{
|
|
||||||
int level = ID-87;
|
|
||||||
std::vector<SpellID> possibilities;
|
|
||||||
cb->getAllowedSpells (possibilities, level);
|
|
||||||
|
|
||||||
if(possibilities.empty())
|
|
||||||
{
|
|
||||||
logGlobal->error("Error: cannot init shrine, no allowed spells!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spell = *RandomGeneratorUtil::nextItem(possibilities, rand);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CGShrine::getHoverText(PlayerColor player) const
|
std::string CGShrine::getHoverText(PlayerColor player) const
|
||||||
@ -1693,8 +1682,7 @@ void CGScholar::initObj(CRandomGenerator & rand)
|
|||||||
break;
|
break;
|
||||||
case SPELL:
|
case SPELL:
|
||||||
std::vector<SpellID> possibilities;
|
std::vector<SpellID> possibilities;
|
||||||
for (int i = 1; i < 6; ++i)
|
cb->getAllowedSpells (possibilities);
|
||||||
cb->getAllowedSpells (possibilities, i);
|
|
||||||
bonusID = *RandomGeneratorUtil::nextItem(possibilities, rand);
|
bonusID = *RandomGeneratorUtil::nextItem(possibilities, rand);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1851,8 +1839,15 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
|
|||||||
{
|
{
|
||||||
h->showInfoDialog(48);
|
h->showInfoDialog(48);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGBoat::CGBoat()
|
||||||
|
{
|
||||||
|
hero = nullptr;
|
||||||
|
direction = 4;
|
||||||
|
layer = EPathfindingLayer::EEPathfindingLayer::SAIL;
|
||||||
|
}
|
||||||
|
|
||||||
void CGBoat::initObj(CRandomGenerator & rand)
|
void CGBoat::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
hero = nullptr;
|
hero = nullptr;
|
||||||
@ -1927,12 +1922,6 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CGShipyard::CGShipyard()
|
|
||||||
:IShipyard(this)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGShipyard::getOutOffsets( std::vector<int3> &offsets ) const
|
void CGShipyard::getOutOffsets( std::vector<int3> &offsets ) const
|
||||||
@ -1947,6 +1936,11 @@ void CGShipyard::getOutOffsets( std::vector<int3> &offsets ) const
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IObjectInterface * CGShipyard::getObject() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
|
void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
|
||||||
{
|
{
|
||||||
if(!cb->gameState()->getPlayerRelations(tempOwner, h->tempOwner))
|
if(!cb->gameState()->getPlayerRelations(tempOwner, h->tempOwner))
|
||||||
@ -1972,6 +1966,12 @@ void CGShipyard::serializeJsonOptions(JsonSerializeFormat& handler)
|
|||||||
serializeJsonOwner(handler);
|
serializeJsonOwner(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoatId CGShipyard::getBoatType() const
|
||||||
|
{
|
||||||
|
// In H3, external shipyard will always create same boat as castle
|
||||||
|
return EBoatId::CASTLE;
|
||||||
|
}
|
||||||
|
|
||||||
void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
|
void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
|
||||||
{
|
{
|
||||||
//if player has not bought map of this subtype yet and underground exist for stalagmite cartographer
|
//if player has not bought map of this subtype yet and underground exist for stalagmite cartographer
|
||||||
@ -2176,4 +2176,26 @@ void CGLighthouse::serializeJsonOptions(JsonSerializeFormat& handler)
|
|||||||
serializeJsonOwner(handler);
|
serializeJsonOwner(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HillFort::onHeroVisit(const CGHeroInstance * h) const
|
||||||
|
{
|
||||||
|
openWindow(EOpenWindowMode::HILL_FORT_WINDOW,id.getNum(),h->id.getNum());
|
||||||
|
}
|
||||||
|
|
||||||
|
void HillFort::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const
|
||||||
|
{
|
||||||
|
int32_t level = stack.type->getLevel();
|
||||||
|
int32_t index = std::clamp<int32_t>(level - 1, 0, upgradeCostPercentage.size() - 1);
|
||||||
|
|
||||||
|
int costModifier = upgradeCostPercentage[index];
|
||||||
|
|
||||||
|
if (costModifier < 0)
|
||||||
|
return; // upgrade not allowed
|
||||||
|
|
||||||
|
for(const auto & nid : stack.type->upgrades)
|
||||||
|
{
|
||||||
|
info.newID.push_back(nid);
|
||||||
|
info.cost.push_back((nid.toCreature()->getFullRecruitCost() - stack.type->getFullRecruitCost()) * costModifier / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -246,7 +246,9 @@ protected:
|
|||||||
class DLL_LINKAGE CGShrine : public CTeamVisited
|
class DLL_LINKAGE CGShrine : public CTeamVisited
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
MetaString visitText;
|
||||||
SpellID spell; //id of spell or NONE if random
|
SpellID spell; //id of spell or NONE if random
|
||||||
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
std::string getHoverText(PlayerColor player) const override;
|
std::string getHoverText(PlayerColor player) const override;
|
||||||
@ -256,6 +258,7 @@ public:
|
|||||||
{
|
{
|
||||||
h & static_cast<CTeamVisited&>(*this);;
|
h & static_cast<CTeamVisited&>(*this);;
|
||||||
h & spell;
|
h & spell;
|
||||||
|
h & visitText;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||||
@ -429,15 +432,10 @@ public:
|
|||||||
std::string overlayAnimation; //waves animations
|
std::string overlayAnimation; //waves animations
|
||||||
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
|
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
|
||||||
|
|
||||||
|
CGBoat();
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
static int3 translatePos(const int3 &pos, bool reverse = false);
|
static int3 translatePos(const int3 &pos, bool reverse = false);
|
||||||
|
|
||||||
CGBoat()
|
|
||||||
{
|
|
||||||
hero = nullptr;
|
|
||||||
direction = 4;
|
|
||||||
layer = EPathfindingLayer::EEPathfindingLayer::SAIL;
|
|
||||||
}
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<CGObjectInstance&>(*this);
|
h & static_cast<CGObjectInstance&>(*this);
|
||||||
@ -455,16 +453,23 @@ public:
|
|||||||
|
|
||||||
class DLL_LINKAGE CGShipyard : public CGObjectInstance, public IShipyard
|
class DLL_LINKAGE CGShipyard : public CGObjectInstance, public IShipyard
|
||||||
{
|
{
|
||||||
public:
|
friend class ShipyardInstanceConstructor;
|
||||||
void getOutOffsets(std::vector<int3> &offsets) const override; //offsets to obj pos when we boat can be placed
|
|
||||||
CGShipyard();
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
|
||||||
|
|
||||||
|
BoatId createdBoat;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void getOutOffsets(std::vector<int3> & offsets) const override;
|
||||||
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
|
const IObjectInterface * getObject() const override;
|
||||||
|
BoatId getBoatType() const override;
|
||||||
|
|
||||||
|
public:
|
||||||
template<typename Handler> void serialize(Handler & h, const int version)
|
template<typename Handler> void serialize(Handler & h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<CGObjectInstance&>(*this);
|
h & static_cast<CGObjectInstance&>(*this);
|
||||||
h & static_cast<IShipyard&>(*this);
|
h & createdBoat;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||||
};
|
};
|
||||||
@ -550,4 +555,22 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE HillFort : public CGObjectInstance, public ICreatureUpgrader
|
||||||
|
{
|
||||||
|
friend class HillFortInstanceConstructor;
|
||||||
|
|
||||||
|
std::vector<int> upgradeCostPercentage;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
|
void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & static_cast<CGObjectInstance&>(*this);
|
||||||
|
h & upgradeCostPercentage;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -164,7 +164,7 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//assuming that object can be placed on other land terrains
|
//assuming that object can be placed on other land terrains
|
||||||
anyTerrain = allowedTerrains.size() >= 8 && !allowedTerrains.count(ETerrainId::WATER);
|
anyLandTerrain = allowedTerrains.size() >= 8 && !allowedTerrains.count(ETerrainId::WATER);
|
||||||
|
|
||||||
id = Obj(boost::lexical_cast<int>(strings[5]));
|
id = Obj(boost::lexical_cast<int>(strings[5]));
|
||||||
subid = boost::lexical_cast<int>(strings[6]);
|
subid = boost::lexical_cast<int>(strings[6]);
|
||||||
@ -230,7 +230,7 @@ void ObjectTemplate::readMap(CBinaryReader & reader)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//assuming that object can be placed on other land terrains
|
//assuming that object can be placed on other land terrains
|
||||||
anyTerrain = allowedTerrains.size() >= 8 && !allowedTerrains.count(ETerrainId::WATER);
|
anyLandTerrain = allowedTerrains.size() >= 8 && !allowedTerrains.count(ETerrainId::WATER);
|
||||||
|
|
||||||
id = Obj(reader.readUInt32());
|
id = Obj(reader.readUInt32());
|
||||||
subid = reader.readUInt32();
|
subid = reader.readUInt32();
|
||||||
@ -277,11 +277,11 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain)
|
|||||||
allowedTerrains.insert(TerrainId(identifier));
|
allowedTerrains.insert(TerrainId(identifier));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
anyTerrain = false;
|
anyLandTerrain = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
anyTerrain = true;
|
anyLandTerrain = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto charToTile = [&](const char & ch) -> ui8
|
auto charToTile = [&](const char & ch) -> ui8
|
||||||
@ -557,7 +557,7 @@ void ObjectTemplate::calculateVisitableOffset()
|
|||||||
|
|
||||||
bool ObjectTemplate::canBePlacedAt(TerrainId terrainID) const
|
bool ObjectTemplate::canBePlacedAt(TerrainId terrainID) const
|
||||||
{
|
{
|
||||||
if (anyTerrain)
|
if (anyLandTerrain)
|
||||||
{
|
{
|
||||||
const auto & terrain = VLC->terrainTypeHandler->getById(terrainID);
|
const auto & terrain = VLC->terrainTypeHandler->getById(terrainID);
|
||||||
return terrain->isLand() && terrain->isPassable();
|
return terrain->isLand() && terrain->isPassable();
|
||||||
|
@ -36,7 +36,7 @@ class DLL_LINKAGE ObjectTemplate
|
|||||||
std::set<TerrainId> allowedTerrains;
|
std::set<TerrainId> allowedTerrains;
|
||||||
|
|
||||||
/// or, allow placing object on any terrain
|
/// or, allow placing object on any terrain
|
||||||
bool anyTerrain;
|
bool anyLandTerrain;
|
||||||
|
|
||||||
void afterLoadFixup();
|
void afterLoadFixup();
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ public:
|
|||||||
|
|
||||||
inline bool canBePlacedAtAnyTerrain() const
|
inline bool canBePlacedAtAnyTerrain() const
|
||||||
{
|
{
|
||||||
return anyTerrain;
|
return anyLandTerrain;
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::set<TerrainId>& getAllowedTerrains() const
|
const std::set<TerrainId>& getAllowedTerrains() const
|
||||||
@ -159,6 +159,7 @@ public:
|
|||||||
{
|
{
|
||||||
h & usedTiles;
|
h & usedTiles;
|
||||||
h & allowedTerrains;
|
h & allowedTerrains;
|
||||||
|
h & anyLandTerrain;
|
||||||
h & animationFile;
|
h & animationFile;
|
||||||
h & stringID;
|
h & stringID;
|
||||||
h & id;
|
h & id;
|
||||||
|
@ -129,9 +129,10 @@ bool TerrainTile::isWater() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
CMap::CMap()
|
CMap::CMap()
|
||||||
: checksum(0), grailPos(-1, -1, -1), grailRadius(0), terrain(nullptr),
|
: checksum(0)
|
||||||
guardingCreaturePositions(nullptr),
|
, grailPos(-1, -1, -1)
|
||||||
uidCounter(0)
|
, grailRadius(0)
|
||||||
|
, uidCounter(0)
|
||||||
{
|
{
|
||||||
allHeroes.resize(allowedHeroes.size());
|
allHeroes.resize(allowedHeroes.size());
|
||||||
allowedAbilities = VLC->skillh->getDefaultAllowed();
|
allowedAbilities = VLC->skillh->getDefaultAllowed();
|
||||||
@ -143,22 +144,6 @@ CMap::~CMap()
|
|||||||
{
|
{
|
||||||
getEditManager()->getUndoManager().clearAll();
|
getEditManager()->getUndoManager().clearAll();
|
||||||
|
|
||||||
if(terrain)
|
|
||||||
{
|
|
||||||
for(int z = 0; z < levels(); z++)
|
|
||||||
{
|
|
||||||
for(int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
delete[] terrain[z][x];
|
|
||||||
delete[] guardingCreaturePositions[z][x];
|
|
||||||
}
|
|
||||||
delete[] terrain[z];
|
|
||||||
delete[] guardingCreaturePositions[z];
|
|
||||||
}
|
|
||||||
delete [] terrain;
|
|
||||||
delete [] guardingCreaturePositions;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto obj : objects)
|
for(auto obj : objects)
|
||||||
obj.dellNull();
|
obj.dellNull();
|
||||||
|
|
||||||
@ -572,19 +557,8 @@ void CMap::removeObject(CGObjectInstance * obj)
|
|||||||
|
|
||||||
void CMap::initTerrain()
|
void CMap::initTerrain()
|
||||||
{
|
{
|
||||||
int level = levels();
|
terrain.resize(boost::extents[levels()][width][height]);
|
||||||
terrain = new TerrainTile**[level];
|
guardingCreaturePositions.resize(boost::extents[levels()][width][height]);
|
||||||
guardingCreaturePositions = new int3**[level];
|
|
||||||
for(int z = 0; z < level; ++z)
|
|
||||||
{
|
|
||||||
terrain[z] = new TerrainTile*[width];
|
|
||||||
guardingCreaturePositions[z] = new int3*[width];
|
|
||||||
for(int x = 0; x < width; ++x)
|
|
||||||
{
|
|
||||||
terrain[z][x] = new TerrainTile[height];
|
|
||||||
guardingCreaturePositions[z][x] = new int3[height];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CMapEditManager * CMap::getEditManager()
|
CMapEditManager * CMap::getEditManager()
|
||||||
|
@ -142,14 +142,14 @@ public:
|
|||||||
std::map<si32, ObjectInstanceID> questIdentifierToId;
|
std::map<si32, ObjectInstanceID> questIdentifierToId;
|
||||||
|
|
||||||
std::unique_ptr<CMapEditManager> editManager;
|
std::unique_ptr<CMapEditManager> editManager;
|
||||||
|
boost::multi_array<int3, 3> guardingCreaturePositions;
|
||||||
int3 ***guardingCreaturePositions;
|
|
||||||
|
|
||||||
std::map<std::string, ConstTransitivePtr<CGObjectInstance> > instanceNames;
|
std::map<std::string, ConstTransitivePtr<CGObjectInstance> > instanceNames;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground
|
/// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground
|
||||||
TerrainTile*** terrain;
|
boost::multi_array<TerrainTile, 3> terrain;
|
||||||
|
|
||||||
si32 uidCounter; //TODO: initialize when loading an old map
|
si32 uidCounter; //TODO: initialize when loading an old map
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -170,50 +170,8 @@ public:
|
|||||||
h & questIdentifierToId;
|
h & questIdentifierToId;
|
||||||
|
|
||||||
//TODO: viccondetails
|
//TODO: viccondetails
|
||||||
const int level = levels();
|
h & terrain;
|
||||||
if(h.saving)
|
h & guardingCreaturePositions;
|
||||||
{
|
|
||||||
// Save terrain
|
|
||||||
for(int z = 0; z < level; ++z)
|
|
||||||
{
|
|
||||||
for(int x = 0; x < width; ++x)
|
|
||||||
{
|
|
||||||
for(int y = 0; y < height; ++y)
|
|
||||||
{
|
|
||||||
h & terrain[z][x][y];
|
|
||||||
h & guardingCreaturePositions[z][x][y];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Load terrain
|
|
||||||
terrain = new TerrainTile**[level];
|
|
||||||
guardingCreaturePositions = new int3**[level];
|
|
||||||
for(int z = 0; z < level; ++z)
|
|
||||||
{
|
|
||||||
terrain[z] = new TerrainTile*[width];
|
|
||||||
guardingCreaturePositions[z] = new int3*[width];
|
|
||||||
for(int x = 0; x < width; ++x)
|
|
||||||
{
|
|
||||||
terrain[z][x] = new TerrainTile[height];
|
|
||||||
guardingCreaturePositions[z][x] = new int3[height];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int z = 0; z < level; ++z)
|
|
||||||
{
|
|
||||||
for(int x = 0; x < width; ++x)
|
|
||||||
{
|
|
||||||
for(int y = 0; y < height; ++y)
|
|
||||||
{
|
|
||||||
|
|
||||||
h & terrain[z][x][y];
|
|
||||||
h & guardingCreaturePositions[z][x][y];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h & objects;
|
h & objects;
|
||||||
h & heroesOnMap;
|
h & heroesOnMap;
|
||||||
|
@ -1292,9 +1292,9 @@ CGObjectInstance * CMapLoaderH3M::readQuestGuard(const int3 & mapPosition)
|
|||||||
return guard;
|
return guard;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGObjectInstance * CMapLoaderH3M::readShipyard(const int3 & mapPosition)
|
CGObjectInstance * CMapLoaderH3M::readShipyard(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
|
||||||
{
|
{
|
||||||
auto * object = new CGShipyard();
|
auto * object = readGeneric(mapPosition, objectTemplate);
|
||||||
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
@ -1448,7 +1448,7 @@ CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplat
|
|||||||
return readQuestGuard(mapPosition);
|
return readQuestGuard(mapPosition);
|
||||||
|
|
||||||
case Obj::SHIPYARD:
|
case Obj::SHIPYARD:
|
||||||
return readShipyard(mapPosition);
|
return readShipyard(mapPosition, objectTemplate);
|
||||||
|
|
||||||
case Obj::HERO_PLACEHOLDER:
|
case Obj::HERO_PLACEHOLDER:
|
||||||
return readHeroPlaceholder(mapPosition);
|
return readHeroPlaceholder(mapPosition);
|
||||||
|
@ -180,7 +180,7 @@ private:
|
|||||||
CGObjectInstance * readBorderGuard();
|
CGObjectInstance * readBorderGuard();
|
||||||
CGObjectInstance * readBorderGate(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
CGObjectInstance * readBorderGate(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||||
CGObjectInstance * readQuestGuard(const int3 & position);
|
CGObjectInstance * readQuestGuard(const int3 & position);
|
||||||
CGObjectInstance * readShipyard(const int3 & mapPosition);
|
CGObjectInstance * readShipyard(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
||||||
CGObjectInstance * readLighthouse(const int3 & mapPosition);
|
CGObjectInstance * readLighthouse(const int3 & mapPosition);
|
||||||
CGObjectInstance * readGeneric(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
CGObjectInstance * readGeneric(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
||||||
CGObjectInstance * readBank(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
CGObjectInstance * readBank(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
||||||
|
@ -20,6 +20,11 @@
|
|||||||
#include "../CModHandler.h" //needed?
|
#include "../CModHandler.h" //needed?
|
||||||
#include "../mapObjectConstructors/CRewardableConstructor.h"
|
#include "../mapObjectConstructors/CRewardableConstructor.h"
|
||||||
#include "../mapObjectConstructors/CommonConstructors.h"
|
#include "../mapObjectConstructors/CommonConstructors.h"
|
||||||
|
#include "../mapObjectConstructors/CBankInstanceConstructor.h"
|
||||||
|
#include "../mapObjectConstructors/DwellingInstanceConstructor.h"
|
||||||
|
#include "../mapObjectConstructors/HillFortInstanceConstructor.h"
|
||||||
|
#include "../mapObjectConstructors/ShipyardInstanceConstructor.h"
|
||||||
|
#include "../mapObjectConstructors/ShrineInstanceConstructor.h"
|
||||||
#include "../mapObjects/MapObjects.h"
|
#include "../mapObjects/MapObjects.h"
|
||||||
#include "../mapObjects/CGTownBuilding.h"
|
#include "../mapObjects/CGTownBuilding.h"
|
||||||
#include "../mapObjects/ObjectTemplate.h"
|
#include "../mapObjects/ObjectTemplate.h"
|
||||||
@ -59,10 +64,11 @@ void registerTypesMapObjects1(Serializer &s)
|
|||||||
s.template registerType<CGObjectInstance, CGBoat>();
|
s.template registerType<CGObjectInstance, CGBoat>();
|
||||||
s.template registerType<CGObjectInstance, CGMagi>();
|
s.template registerType<CGObjectInstance, CGMagi>();
|
||||||
s.template registerType<CGObjectInstance, CGSirens>();
|
s.template registerType<CGObjectInstance, CGSirens>();
|
||||||
s.template registerType<CGObjectInstance, CGShipyard>(); s.template registerType<IShipyard, CGShipyard>();
|
s.template registerType<CGObjectInstance, CGShipyard>();
|
||||||
s.template registerType<CGObjectInstance, CGDenOfthieves>();
|
s.template registerType<CGObjectInstance, CGDenOfthieves>();
|
||||||
s.template registerType<CGObjectInstance, CGLighthouse>();
|
s.template registerType<CGObjectInstance, CGLighthouse>();
|
||||||
s.template registerType<CGObjectInstance, CGTerrainPatch>();
|
s.template registerType<CGObjectInstance, CGTerrainPatch>();
|
||||||
|
s.template registerType<CGObjectInstance, HillFort>();
|
||||||
s.template registerType<CGObjectInstance, CGMarket>();
|
s.template registerType<CGObjectInstance, CGMarket>();
|
||||||
s.template registerType<CGMarket, CGBlackMarket>();
|
s.template registerType<CGMarket, CGBlackMarket>();
|
||||||
s.template registerType<CGMarket, CGUniversity>();
|
s.template registerType<CGMarket, CGUniversity>();
|
||||||
@ -71,9 +77,9 @@ void registerTypesMapObjects1(Serializer &s)
|
|||||||
s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>();
|
s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>();
|
||||||
|
|
||||||
// Armed objects
|
// Armed objects
|
||||||
s.template registerType<CArmedInstance, CGHeroInstance>(); s.template registerType<IBoatGenerator, CGHeroInstance>(); s.template registerType<CArtifactSet, CGHeroInstance>();
|
s.template registerType<CArmedInstance, CGHeroInstance>(); s.template registerType<CArtifactSet, CGHeroInstance>();
|
||||||
s.template registerType<CArmedInstance, CGDwelling>();
|
s.template registerType<CArmedInstance, CGDwelling>();
|
||||||
s.template registerType<CGDwelling, CGTownInstance>(); s.template registerType<IShipyard, CGTownInstance>();
|
s.template registerType<CGDwelling, CGTownInstance>();
|
||||||
s.template registerType<CArmedInstance, CGPandoraBox>();
|
s.template registerType<CArmedInstance, CGPandoraBox>();
|
||||||
s.template registerType<CGPandoraBox, CGEvent>();
|
s.template registerType<CGPandoraBox, CGEvent>();
|
||||||
s.template registerType<CArmedInstance, CGCreature>();
|
s.template registerType<CArmedInstance, CGCreature>();
|
||||||
@ -92,11 +98,14 @@ void registerTypesMapObjectTypes(Serializer &s)
|
|||||||
s.template registerType<AObjectTypeHandler, CRewardableConstructor>();
|
s.template registerType<AObjectTypeHandler, CRewardableConstructor>();
|
||||||
s.template registerType<AObjectTypeHandler, CHeroInstanceConstructor>();
|
s.template registerType<AObjectTypeHandler, CHeroInstanceConstructor>();
|
||||||
s.template registerType<AObjectTypeHandler, CTownInstanceConstructor>();
|
s.template registerType<AObjectTypeHandler, CTownInstanceConstructor>();
|
||||||
s.template registerType<AObjectTypeHandler, CDwellingInstanceConstructor>();
|
s.template registerType<AObjectTypeHandler, DwellingInstanceConstructor>();
|
||||||
s.template registerType<AObjectTypeHandler, CBankInstanceConstructor>();
|
s.template registerType<AObjectTypeHandler, CBankInstanceConstructor>();
|
||||||
s.template registerType<AObjectTypeHandler, BoatInstanceConstructor>();
|
s.template registerType<AObjectTypeHandler, BoatInstanceConstructor>();
|
||||||
s.template registerType<AObjectTypeHandler, MarketInstanceConstructor>();
|
s.template registerType<AObjectTypeHandler, MarketInstanceConstructor>();
|
||||||
s.template registerType<AObjectTypeHandler, CObstacleConstructor>();
|
s.template registerType<AObjectTypeHandler, CObstacleConstructor>();
|
||||||
|
s.template registerType<AObjectTypeHandler, ShrineInstanceConstructor>();
|
||||||
|
s.template registerType<AObjectTypeHandler, ShipyardInstanceConstructor>();
|
||||||
|
s.template registerType<AObjectTypeHandler, HillFortInstanceConstructor>();
|
||||||
|
|
||||||
#define REGISTER_GENERIC_HANDLER(TYPENAME) s.template registerType<AObjectTypeHandler, CDefaultObjectTypeHandler<TYPENAME> >()
|
#define REGISTER_GENERIC_HANDLER(TYPENAME) s.template registerType<AObjectTypeHandler, CDefaultObjectTypeHandler<TYPENAME> >()
|
||||||
|
|
||||||
@ -137,6 +146,7 @@ void registerTypesMapObjectTypes(Serializer &s)
|
|||||||
REGISTER_GENERIC_HANDLER(CGTownInstance);
|
REGISTER_GENERIC_HANDLER(CGTownInstance);
|
||||||
REGISTER_GENERIC_HANDLER(CGUniversity);
|
REGISTER_GENERIC_HANDLER(CGUniversity);
|
||||||
REGISTER_GENERIC_HANDLER(CGWitchHut);
|
REGISTER_GENERIC_HANDLER(CGWitchHut);
|
||||||
|
REGISTER_GENERIC_HANDLER(HillFort);
|
||||||
|
|
||||||
#undef REGISTER_GENERIC_HANDLER
|
#undef REGISTER_GENERIC_HANDLER
|
||||||
|
|
||||||
|
@ -74,8 +74,7 @@ Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Conf
|
|||||||
void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const
|
void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const
|
||||||
{
|
{
|
||||||
std::vector<SpellID> spells;
|
std::vector<SpellID> spells;
|
||||||
for (size_t i=0; i<6; i++)
|
IObjectInterface::cb->getAllowedSpells(spells);
|
||||||
IObjectInterface::cb->getAllowedSpells(spells, static_cast<ui16>(i));
|
|
||||||
|
|
||||||
|
|
||||||
limiter.dayOfWeek = JsonRandom::loadValue(source["dayOfWeek"], rng);
|
limiter.dayOfWeek = JsonRandom::loadValue(source["dayOfWeek"], rng);
|
||||||
@ -124,8 +123,7 @@ void Rewardable::Info::configureReward(Rewardable::Configuration & object, CRand
|
|||||||
reward.secondary = JsonRandom::loadSecondary(source["secondary"], rng);
|
reward.secondary = JsonRandom::loadSecondary(source["secondary"], rng);
|
||||||
|
|
||||||
std::vector<SpellID> spells;
|
std::vector<SpellID> spells;
|
||||||
for (size_t i=0; i<6; i++)
|
IObjectInterface::cb->getAllowedSpells(spells);
|
||||||
IObjectInterface::cb->getAllowedSpells(spells, static_cast<ui16>(i));
|
|
||||||
|
|
||||||
reward.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng);
|
reward.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng);
|
||||||
reward.spells = JsonRandom::loadSpells(source["spells"], rng, spells);
|
reward.spells = JsonRandom::loadSpells(source["spells"], rng, spells);
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
#include "../../ArtifactUtils.h"
|
#include "../../ArtifactUtils.h"
|
||||||
#include "../../mapObjectConstructors/AObjectTypeHandler.h"
|
#include "../../mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
#include "../../mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../../mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "../../mapObjectConstructors/CommonConstructors.h"
|
#include "../../mapObjectConstructors/DwellingInstanceConstructor.h"
|
||||||
|
#include "../../mapObjects/CGHeroInstance.h"
|
||||||
#include "../../mapObjects/CGPandoraBox.h"
|
#include "../../mapObjects/CGPandoraBox.h"
|
||||||
#include "../../CCreatureHandler.h"
|
#include "../../CCreatureHandler.h"
|
||||||
#include "../../spells/CSpellHandler.h" //for choosing random spells
|
#include "../../spells/CSpellHandler.h" //for choosing random spells
|
||||||
@ -171,7 +172,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
|
|
||||||
for(auto secondaryID : subObjects)
|
for(auto secondaryID : subObjects)
|
||||||
{
|
{
|
||||||
const auto * dwellingHandler = dynamic_cast<const CDwellingInstanceConstructor *>(VLC->objtypeh->getHandlerFor(dwellingType, secondaryID).get());
|
const auto * dwellingHandler = dynamic_cast<const DwellingInstanceConstructor *>(VLC->objtypeh->getHandlerFor(dwellingType, secondaryID).get());
|
||||||
auto creatures = dwellingHandler->getProducedCreatures();
|
auto creatures = dwellingHandler->getProducedCreatures();
|
||||||
if(creatures.empty())
|
if(creatures.empty())
|
||||||
continue;
|
continue;
|
||||||
|
@ -215,7 +215,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
{
|
{
|
||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::BOAT;
|
no.ID = Obj::BOAT;
|
||||||
no.subID = BoatId(EBoatId::BOAT_EVIL);
|
no.subID = BoatId(EBoatId::NECROPOLIS);
|
||||||
no.pos = CGBoat::translatePos(summonPos);
|
no.pos = CGBoat::translatePos(summonPos);
|
||||||
env->apply(&no);
|
env->apply(&no);
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,11 @@ int64_t CSpell::calculateDamage(const spells::Caster * caster) const
|
|||||||
return caster->getSpellBonus(this, rawDamage, nullptr);
|
return caster->getSpellBonus(this, rawDamage, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSpell::hasSchool(ESpellSchool which) const
|
||||||
|
{
|
||||||
|
return school.count(which) && school.at(which);
|
||||||
|
}
|
||||||
|
|
||||||
bool CSpell::canBeCast(const CBattleInfoCallback * cb, spells::Mode mode, const spells::Caster * caster) const
|
bool CSpell::canBeCast(const CBattleInfoCallback * cb, spells::Mode mode, const spells::Caster * caster) const
|
||||||
{
|
{
|
||||||
//if caller do not interested in description just discard it and do not pollute even debug log
|
//if caller do not interested in description just discard it and do not pollute even debug log
|
||||||
|
@ -209,6 +209,8 @@ public:
|
|||||||
|
|
||||||
int64_t calculateDamage(const spells::Caster * caster) const override;
|
int64_t calculateDamage(const spells::Caster * caster) const override;
|
||||||
|
|
||||||
|
bool hasSchool(ESpellSchool school) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls cb for each school this spell belongs to
|
* Calls cb for each school this spell belongs to
|
||||||
*
|
*
|
||||||
|
@ -4421,7 +4421,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
|
|||||||
//Create a new boat for hero
|
//Create a new boat for hero
|
||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::BOAT;
|
no.ID = Obj::BOAT;
|
||||||
no.subID = BoatId(EBoatId::BOAT_NEUTRAL);
|
no.subID = BoatId(EBoatId::CASTLE);
|
||||||
no.pos = hr.tile + int3(1,0,0);
|
no.pos = hr.tile + int3(1,0,0);
|
||||||
sendAndApply(&no);
|
sendAndApply(&no);
|
||||||
|
|
||||||
@ -5627,12 +5627,6 @@ bool CGameHandler::buildBoat(ObjectInstanceID objid, PlayerColor playerID)
|
|||||||
complain("Cannot build boat in this shipyard!");
|
complain("Cannot build boat in this shipyard!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (obj->o->ID == Obj::TOWN
|
|
||||||
&& !static_cast<const CGTownInstance*>(obj)->hasBuilt(BuildingID::SHIPYARD))
|
|
||||||
{
|
|
||||||
complain("Cannot build boat in the town - no shipyard!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TResources boatCost;
|
TResources boatCost;
|
||||||
obj->getBoatCost(boatCost);
|
obj->getBoatCost(boatCost);
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
MOCK_CONST_METHOD0(isOffensive, bool());
|
MOCK_CONST_METHOD0(isOffensive, bool());
|
||||||
MOCK_CONST_METHOD0(isSpecial, bool());
|
MOCK_CONST_METHOD0(isSpecial, bool());
|
||||||
MOCK_CONST_METHOD0(isMagical, bool());
|
MOCK_CONST_METHOD0(isMagical, bool());
|
||||||
|
MOCK_CONST_METHOD1(hasSchool, bool(ESpellSchool));
|
||||||
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
|
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
|
||||||
MOCK_CONST_METHOD0(getCastSound, const std::string &());
|
MOCK_CONST_METHOD0(getCastSound, const std::string &());
|
||||||
MOCK_CONST_METHOD1(registerIcons, void(const IconRegistar &));
|
MOCK_CONST_METHOD1(registerIcons, void(const IconRegistar &));
|
||||||
|
Reference in New Issue
Block a user