mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Merge pull request #19 from vcmi/feature/mapObjects
Feature/map objects
This commit is contained in:
commit
3ac306f501
@ -3,9 +3,9 @@
|
||||
#include "VCAI.h"
|
||||
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/mapObjects/CBank.h"
|
||||
|
||||
/*
|
||||
* AIUtility.cpp, part of VCMI engine
|
||||
@ -303,11 +303,11 @@ ui64 evaluateDanger(const CGObjectInstance *obj)
|
||||
case Obj::SHIPWRECK: //shipwreck
|
||||
case Obj::DERELICT_SHIP: //derelict ship
|
||||
// case Obj::PYRAMID:
|
||||
return fh->estimateBankDanger (VLC->objh->bankObjToIndex(obj));
|
||||
return fh->estimateBankDanger (dynamic_cast<const CBank *>(obj));
|
||||
case Obj::PYRAMID:
|
||||
{
|
||||
if(obj->subID == 0)
|
||||
return fh->estimateBankDanger (VLC->objh->bankObjToIndex(obj));
|
||||
return fh->estimateBankDanger (dynamic_cast<const CBank *>(obj));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/Connection.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
@ -162,4 +161,4 @@ bool compareMovement(HeroPtr lhs, HeroPtr rhs);
|
||||
bool compareHeroStrength(HeroPtr h1, HeroPtr h2);
|
||||
bool compareArmyStrength(const CArmedInstance *a1, const CArmedInstance *a2);
|
||||
ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance *t);
|
||||
int3 whereToExplore(HeroPtr h);
|
||||
int3 whereToExplore(HeroPtr h);
|
||||
|
@ -2,11 +2,11 @@
|
||||
#include "Fuzzy.h"
|
||||
#include <limits>
|
||||
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../lib/mapObjects/CommonConstructors.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../CCallback.h"
|
||||
//#include "Goals.cpp"
|
||||
#include "VCAI.h"
|
||||
|
||||
/*
|
||||
@ -42,16 +42,6 @@ struct armyStructure
|
||||
ui32 maxSpeed;
|
||||
};
|
||||
|
||||
ui64 evaluateBankConfig (BankConfig * bc)
|
||||
{
|
||||
ui64 danger = 0;
|
||||
for (auto opt : bc->guards)
|
||||
{
|
||||
danger += VLC->creh->creatures[opt.first]->fightValue * opt.second;
|
||||
}
|
||||
return danger;
|
||||
}
|
||||
|
||||
armyStructure evaluateArmyStructure (const CArmedInstance * army)
|
||||
{
|
||||
ui64 totalStrenght = army->getArmyStrength();
|
||||
@ -209,42 +199,26 @@ void FuzzyHelper::initTacticalAdvantage()
|
||||
}
|
||||
}
|
||||
|
||||
ui64 FuzzyHelper::estimateBankDanger (int ID)
|
||||
ui64 FuzzyHelper::estimateBankDanger (const CBank * bank)
|
||||
{
|
||||
std::vector <ConstTransitivePtr<BankConfig>> & configs = VLC->objh->banksInfo[ID];
|
||||
auto info = VLC->objtypeh->getHandlerFor(bank->ID, bank->subID)->getObjectInfo(bank->appearance);
|
||||
|
||||
ui64 val = std::numeric_limits<ui64>::max();
|
||||
try
|
||||
{
|
||||
switch (configs.size())
|
||||
{
|
||||
case 4:
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
int bankVal = evaluateBankConfig (VLC->objh->banksInfo[ID][i]);
|
||||
bankDanger->term("Bank" + boost::lexical_cast<std::string>(i))->setMinimum(bankVal * 0.5f);
|
||||
bankDanger->term("Bank" + boost::lexical_cast<std::string>(i))->setMaximum(bankVal * 1.5f);
|
||||
}
|
||||
//comparison purposes
|
||||
//int averageValue = (evaluateBankConfig (VLC->objh->banksInfo[ID][0]) + evaluateBankConfig (VLC->objh->banksInfo[ID][3])) * 0.5;
|
||||
//dynamic_cast<fl::SingletonTerm*>(bankInput->term("SET"))->setValue(0.5);
|
||||
bankInput->setInput (0.5);
|
||||
engine.process (BANK_DANGER);
|
||||
//engine.process();
|
||||
val = bankDanger->output().defuzzify(); //some expected value of this bank
|
||||
}
|
||||
catch (fl::FuzzyException & fe)
|
||||
{
|
||||
logAi->errorStream() << fe.name() << ": " << fe.message();
|
||||
}
|
||||
break;
|
||||
case 1: //rare case - Pyramid
|
||||
val = evaluateBankConfig (VLC->objh->banksInfo[ID][0]);
|
||||
break;
|
||||
default:
|
||||
logAi->warnStream() << ("Uhnandled bank config!");
|
||||
}
|
||||
bankDanger->term("Bank0")->setMinimum(info->minGuards().totalStrength * 0.5f);
|
||||
bankDanger->term("Bank0")->setMaximum(info->minGuards().totalStrength * 1.5f);
|
||||
|
||||
bankDanger->term("Bank1")->setMinimum(info->maxGuards().totalStrength * 0.5f);
|
||||
bankDanger->term("Bank1")->setMaximum(info->maxGuards().totalStrength * 1.5f);
|
||||
|
||||
//comparison purposes
|
||||
//int averageValue = (evaluateBankConfig (VLC->objh->banksInfo[ID][0]) + evaluateBankConfig (VLC->objh->banksInfo[ID][3])) * 0.5;
|
||||
//dynamic_cast<fl::SingletonTerm*>(bankInput->term("SET"))->setValue(0.5);
|
||||
bankInput->setInput (0.5);
|
||||
engine.process (BANK_DANGER);
|
||||
//engine.process();
|
||||
val = bankDanger->output().defuzzify(); //some expected value of this bank
|
||||
}
|
||||
catch (fl::FuzzyException & fe)
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
class VCAI;
|
||||
class CArmedInstance;
|
||||
class CBank;
|
||||
|
||||
class FuzzyHelper
|
||||
{
|
||||
@ -72,7 +73,7 @@ public:
|
||||
float evaluate (Goals::AbstractGoal & g);
|
||||
void setPriority (Goals::TSubgoal & g);
|
||||
|
||||
ui64 estimateBankDanger (int ID);
|
||||
ui64 estimateBankDanger (const CBank * bank);
|
||||
float getTacticalAdvantage (const CArmedInstance *we, const CArmedInstance *enemy); //returns factor how many times enemy is stronger than us
|
||||
|
||||
Goals::TSubgoal chooseSolution (Goals::TGoalVec vec);
|
||||
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/CBuildingHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "VCAI.h"
|
||||
#include "Goals.h"
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "Goals.h"
|
||||
#include "../../lib/AI_Base.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CDefObjInfoHandler.h"
|
||||
|
||||
#include "../../lib/CThreadHelper.h"
|
||||
|
||||
@ -14,7 +13,6 @@
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/Connection.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
|
@ -9,10 +9,9 @@
|
||||
#include "client/Client.h"
|
||||
#include "lib/mapping/CMap.h"
|
||||
#include "lib/CBuildingHandler.h"
|
||||
#include "lib/CDefObjInfoHandler.h"
|
||||
#include "lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "lib/CGeneralTextHandler.h"
|
||||
#include "lib/CHeroHandler.h"
|
||||
#include "lib/CObjectHandler.h"
|
||||
#include "lib/Connection.h"
|
||||
#include "lib/NetPacks.h"
|
||||
#include "client/mapHandler.h"
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
@ -25,7 +25,7 @@
|
||||
#include "CPreGame.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "CSoundBase.h"
|
||||
#include "../lib/CSoundBase.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "CMusicHandler.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "CAdvmapInterface.h"
|
||||
|
@ -31,5 +31,5 @@ void CGameInfo::setFromLib()
|
||||
heroh = VLC->heroh;
|
||||
objh = VLC->objh;
|
||||
spellh = VLC->spellh;
|
||||
dobjinfo = VLC->dobjinfo;
|
||||
objtypeh = VLC->objtypeh;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class CBuildingHandler;
|
||||
class CObjectHandler;
|
||||
class CSoundHandler;
|
||||
class CMusicHandler;
|
||||
class CDefObjInfoHandler;
|
||||
class CObjectClassesHandler;
|
||||
class CTownHandler;
|
||||
class CGeneralTextHandler;
|
||||
class CConsoleHandler;
|
||||
@ -57,11 +57,10 @@ public:
|
||||
ConstTransitivePtr<CCreatureHandler> creh;
|
||||
ConstTransitivePtr<CSpellHandler> spellh;
|
||||
ConstTransitivePtr<CObjectHandler> objh;
|
||||
ConstTransitivePtr<CDefObjInfoHandler> dobjinfo;
|
||||
ConstTransitivePtr<CObjectClassesHandler> objtypeh;
|
||||
CGeneralTextHandler * generaltexth;
|
||||
CMapHandler * mh;
|
||||
CTownHandler * townh;
|
||||
//CTownHandler * townh;
|
||||
|
||||
void setFromLib();
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
|
||||
#include "gui/CGuiHandler.h"
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include "gui/CIntObjectClasses.h"
|
||||
#include "GUIClasses.h"
|
||||
|
||||
//#include "CPlayerInterface.h"
|
||||
|
||||
/*
|
||||
* CHeroWindow.h, part of VCMI engine
|
||||
*
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "../lib/CCreatureHandler.h" //creatures name for objects list
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CModHandler.h" //for buildings per turn
|
||||
#include "../lib/CObjectHandler.h" //Hero/Town objects
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/CHeroHandler.h" // only for calculating required xp? worth it?
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "CAnimation.h" //CAnimImage
|
||||
@ -500,7 +500,7 @@ void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInst
|
||||
OwnedObjectInfo &info = visibleObjects[object->subID];
|
||||
if (info.count++ == 0)
|
||||
{
|
||||
info.hoverText = CGI->creh->creatures[CGI->objh->cregens.find(object->subID)->second]->namePl;
|
||||
info.hoverText = object->getHoverText();
|
||||
info.imageID = object->subID;
|
||||
}
|
||||
}
|
||||
@ -953,4 +953,4 @@ void CHeroItem::onArtChange(int tabIndex)
|
||||
//redraw item after background change
|
||||
if (active)
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "CMessage.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CScriptingModule.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
@ -44,7 +43,6 @@
|
||||
#ifdef _WIN32
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
#include "../lib/CDefObjInfoHandler.h"
|
||||
#include "../lib/UnlockGuard.h"
|
||||
#include "CMT.h"
|
||||
|
||||
|
@ -48,8 +48,6 @@ set(client_SRCS
|
||||
)
|
||||
|
||||
set(client_HEADERS
|
||||
CSoundBase.h
|
||||
|
||||
gui/SDL_Pixels.h
|
||||
)
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
#include <SDL_mixer.h>
|
||||
|
||||
#include "CMusicHandler.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../client/CGameInfo.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/filesystem/Filesystem.h"
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "CSoundBase.h"
|
||||
#include "../lib/CSoundBase.h"
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "StdInc.h"
|
||||
#include "../lib/CDefObjInfoHandler.h"
|
||||
#include "CAdvmapInterface.h"
|
||||
#include "battle/CBattleInterface.h"
|
||||
#include "battle/CBattleInterfaceClasses.h"
|
||||
@ -13,7 +12,6 @@
|
||||
#include "CQuestLog.h"
|
||||
#include "CMessage.h"
|
||||
#include "CPlayerInterface.h"
|
||||
//#include "gui/SDL_Extensions.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
#include "battle/CCreatureAnimation.h"
|
||||
@ -21,7 +19,6 @@
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/Connection.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
|
@ -11,11 +11,9 @@
|
||||
#include "gui/CCursorHandler.h"
|
||||
#include "CAnimation.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CDefObjInfoHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/mapping/CCampaignHandler.h"
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/CIntObjectClasses.h"
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include "Graphics.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "CVideoHandler.h"
|
||||
|
@ -11,11 +11,9 @@
|
||||
#include "../lib/BattleState.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CDefObjInfoHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/CBuildingHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/Connection.h"
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CondSh.h"
|
||||
|
@ -12,19 +12,17 @@
|
||||
#include "../CCallback.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "CBitmapHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CDefObjInfoHandler.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
#include "../lib/vcmi_endian.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "CAnimation.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
using namespace CSDL_Ext;
|
||||
@ -148,13 +146,11 @@ void Graphics::loadHeroAnims()
|
||||
|
||||
for(auto & elem : CGI->heroh->classes.heroClasses)
|
||||
{
|
||||
const CHeroClass * hc = elem;
|
||||
|
||||
if (!vstd::contains(heroAnims, hc->imageMapFemale))
|
||||
heroAnims[hc->imageMapFemale] = loadHeroAnim(hc->imageMapFemale, rotations);
|
||||
|
||||
if (!vstd::contains(heroAnims, hc->imageMapMale))
|
||||
heroAnims[hc->imageMapMale] = loadHeroAnim(hc->imageMapMale, rotations);
|
||||
for (auto & templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->id)->getTemplates())
|
||||
{
|
||||
if (!heroAnims.count(templ.animationFile))
|
||||
heroAnims[templ.animationFile] = loadHeroAnim(templ.animationFile, rotations);
|
||||
}
|
||||
}
|
||||
|
||||
boatAnims.push_back(loadHeroAnim("AB01_.DEF", rotations));
|
||||
|
@ -9,14 +9,12 @@
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/Connection.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CDefObjInfoHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "CSoundBase.h"
|
||||
#include "../lib/CSoundBase.h"
|
||||
#include "mapHandler.h"
|
||||
#include "GUIClasses.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "../CAdvmapInterface.h"
|
||||
#include "../CAnimation.h"
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
# include "../CDefHandler.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CVideoHandler.h"
|
||||
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/FunctionList.h"
|
||||
//#include "../CDefHandler.h"
|
||||
#include "../CAnimation.h"
|
||||
|
||||
/*
|
||||
|
@ -14,12 +14,12 @@
|
||||
#include "CBitmapHandler.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/CDefObjInfoHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "Graphics.h"
|
||||
#include "../lib/CObjectHandler.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
@ -541,10 +541,8 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
|
||||
//pick graphics of hero (or boat if hero is sailing)
|
||||
if (themp->boat)
|
||||
iv = &graphics->boatAnims[themp->boat->subID]->ourImages;
|
||||
else if (themp->sex)
|
||||
iv = &graphics->heroAnims[themp->type->heroClass->imageMapFemale]->ourImages;
|
||||
else
|
||||
iv = &graphics->heroAnims[themp->type->heroClass->imageMapMale]->ourImages;
|
||||
iv = &graphics->heroAnims[themp->appearance.animationFile]->ourImages;
|
||||
|
||||
//pick appropriate flag set
|
||||
if(themp->boat)
|
||||
@ -1073,7 +1071,7 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
|
||||
}
|
||||
|
||||
if(t.hasFavourableWinds())
|
||||
out = CGI->generaltexth->names[Obj::FAVORABLE_WINDS];
|
||||
out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
|
||||
else if(terName)
|
||||
out = CGI->generaltexth->terrainNames[t.terType];
|
||||
}
|
||||
|
@ -1,675 +1,9 @@
|
||||
//Resources: Wood, Mercury, Ore, Sulfur, Crystal, Gems, Gold
|
||||
//Artifacts: Treasure, Minor, Major, Relic
|
||||
//NOTE: all H3M banks were moved to objects/creatureBanks.json
|
||||
//Remaining part should be moved to WoG mod
|
||||
{
|
||||
"banks": [
|
||||
{
|
||||
"name" : "Cyclops Stockpile",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 94 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 506,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 4,
|
||||
"mercury" : 4,
|
||||
"ore" : 4,
|
||||
"sulfur" : 4,
|
||||
"crystal" : 4,
|
||||
"gems" : 4,
|
||||
"gold" : 0
|
||||
},
|
||||
"value": 10000,
|
||||
"profitability": 20,
|
||||
"easiest": 100
|
||||
},
|
||||
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 94 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 760,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 6,
|
||||
"mercury" : 6,
|
||||
"ore" : 6,
|
||||
"sulfur" : 6,
|
||||
"crystal" : 6,
|
||||
"gems" : 6
|
||||
},
|
||||
"value": 15000,
|
||||
"profitability": 20,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 40, "id": 94 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1013,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 8,
|
||||
"mercury" : 8,
|
||||
"ore" : 8,
|
||||
"sulfur" : 8,
|
||||
"crystal" : 8,
|
||||
"gems" : 8
|
||||
},
|
||||
"value": 20000,
|
||||
"profitability": 20,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 50, "id": 94 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1266,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 10,
|
||||
"mercury" : 10,
|
||||
"ore" : 10,
|
||||
"sulfur" : 10,
|
||||
"crystal" : 10,
|
||||
"gems" : 10
|
||||
},
|
||||
"value": 25000,
|
||||
"profitability": 20,
|
||||
"easiest": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Dwarven Treasury",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 50, "id": 16 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 194,
|
||||
"reward_resources":
|
||||
{
|
||||
"crystal" : 2,
|
||||
"gold" : 2500
|
||||
},
|
||||
"value": 3500,
|
||||
"profitability": 18,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 75, "id": 16 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 291,
|
||||
"reward_resources":
|
||||
{
|
||||
"crystal" : 3,
|
||||
"gold" : 4000
|
||||
},
|
||||
"value": 5500,
|
||||
"profitability": 19,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 100, "id": 16 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 388,
|
||||
"reward_resources":
|
||||
{
|
||||
"crystal" : 5,
|
||||
"gold" : 5000
|
||||
},
|
||||
"value": 7500,
|
||||
"profitability": 19,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 150, "id": 16 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 582,
|
||||
"reward_resources":
|
||||
{
|
||||
"crystal" : 10,
|
||||
"gold" : 7500
|
||||
},
|
||||
"value": 12500,
|
||||
"profitability": 21,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Griffin Conservatory",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 50, "id": 4 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 351,
|
||||
"reward_creatures": [ { "number": 1, "id": 12 } ],
|
||||
"value": 3000,
|
||||
"profitability": 9,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 100, "id": 4 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 702,
|
||||
"reward_creatures": [ { "number": 2, "id": 12 } ],
|
||||
"value": 6000,
|
||||
"profitability": 9,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 150, "id": 4 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1053,
|
||||
"reward_creatures": [ { "number": 3, "id": 12 } ],
|
||||
"value": 9000,
|
||||
"profitability": 9,
|
||||
"easiest": 300
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 200, "id": 4 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1404,
|
||||
"reward_creatures": [ { "number": 4, "id": 12 } ],
|
||||
"value": 12000,
|
||||
"profitability": 9,
|
||||
"easiest": 400
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Imp Cache",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 100, "id": 42 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 100,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 0,
|
||||
"mercury" : 2,
|
||||
"ore" : 0,
|
||||
"sulfur" : 0,
|
||||
"crystal" : 0,
|
||||
"gems" : 0,
|
||||
"gold" : 1000
|
||||
},
|
||||
"value": 2000,
|
||||
"profitability": 20,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 150, "id": 42 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 150,
|
||||
"reward_resources":
|
||||
{
|
||||
"mercury" : 3,
|
||||
"gold" : 1500
|
||||
},
|
||||
"value": 3000,
|
||||
"profitability": 20,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 200, "id": 42 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 200,
|
||||
"reward_resources":
|
||||
{
|
||||
"mercury" : 4,
|
||||
"gold" : 2000
|
||||
},
|
||||
"value": 4000,
|
||||
"profitability": 20,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 300, "id": 42 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 300,
|
||||
"reward_resources":
|
||||
{
|
||||
"mercury" : 6,
|
||||
"gold" : 3000
|
||||
},
|
||||
"value": 6000,
|
||||
"profitability": 20,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Medusa Stores",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 76 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 207,
|
||||
"reward_resources":
|
||||
{
|
||||
"sulfur" : 5,
|
||||
"gold" : 2000
|
||||
},
|
||||
"value": 4500,
|
||||
"profitability": 22,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 76 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 310,
|
||||
"reward_resources":
|
||||
{
|
||||
"sulfur" : 6,
|
||||
"gold" : 3000
|
||||
},
|
||||
"value": 6000,
|
||||
"profitability": 19,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 40, "id": 76 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 414,
|
||||
"reward_resources":
|
||||
{
|
||||
"sulfur" : 8,
|
||||
"gold" : 4000
|
||||
},
|
||||
"value": 8000,
|
||||
"profitability": 19,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 50, "id": 76 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 517,
|
||||
"reward_resources":
|
||||
{
|
||||
"sulfur" : 10,
|
||||
"gold" : 5000
|
||||
},
|
||||
"value": 10000,
|
||||
"profitability": 19,
|
||||
"easiest": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Naga Bank",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 10, "id": 38 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 403,
|
||||
"reward_resources":
|
||||
{
|
||||
"gems" : 8,
|
||||
"gold" : 4000
|
||||
},
|
||||
"value": 8000,
|
||||
"profitability": 20,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 15, "id": 38 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 605,
|
||||
"reward_resources":
|
||||
{
|
||||
"gems" : 12,
|
||||
"gold" : 6000
|
||||
},
|
||||
"value": 12000,
|
||||
"profitability": 20,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 38 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 806,
|
||||
"reward_resources":
|
||||
{
|
||||
"gems" : 16,
|
||||
"gold" : 8000
|
||||
},
|
||||
"value": 16000,
|
||||
"profitability": 20,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 30, "id": 38 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1210,
|
||||
"reward_resources":
|
||||
{
|
||||
"gems" : 24,
|
||||
"gold" : 12000
|
||||
},
|
||||
"value": 24000,
|
||||
"profitability": 20,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Dragon Fly Hive",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 105} ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 154,
|
||||
"reward_creatures": [ { "number": 4, "id": 108 } ],
|
||||
"value": 3200,
|
||||
"profitability": 21,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 45, "id": 105 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 230,
|
||||
"reward_creatures": [ { "number": 6, "id": 108 } ],
|
||||
"value": 4800,
|
||||
"profitability": 21,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 60, "id": 105 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 307,
|
||||
"reward_creatures": [ { "number": 8, "id": 108 } ],
|
||||
"value": 6400,
|
||||
"profitability": 21,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 90, "id": 105 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 461,
|
||||
"reward_creatures": [ { "number": 12, "id": 108 } ],
|
||||
"value": 9600,
|
||||
"profitability": 21,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Shipwreck",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 10, "id": 60 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 31,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 2000
|
||||
},
|
||||
"value": 2000,
|
||||
"profitability": 65,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 15, "id": 60 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 46,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
},
|
||||
"value": 3000,
|
||||
"profitability": 65,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 25, "id": 60 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 77,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 4000
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 5000,
|
||||
"profitability": 65,
|
||||
"easiest": 250
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 50, "id": 60 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 154,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 5000
|
||||
},
|
||||
"reward_artifacts": [ 0, 1, 0, 0 ],
|
||||
"value": 7000,
|
||||
"profitability": 45,
|
||||
"easiest": 500
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Derelict Ship",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 115 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 138,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
},
|
||||
"value": 3000,
|
||||
"profitability": 22,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 115 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 207,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 4000,
|
||||
"profitability": 19,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 40, "id": 115 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 276,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 4000
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 5000,
|
||||
"profitability": 18,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 60, "id": 115 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 414,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 6000
|
||||
},
|
||||
"reward_artifacts": [ 0, 1, 0, 0 ],
|
||||
"value": 8000,
|
||||
"profitability": 19,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Crypt",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 56 }, { "number": 20, "id": 58 }, { "number": 0, "id": 60 } , { "number": 0, "id": 62 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 75,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 1500
|
||||
},
|
||||
"value": 1500,
|
||||
"profitability": 20,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 25, "id": 56 }, { "number": 20, "id": 58 }, { "number": 5, "id": 60 }, { "number": 0, "id": 62 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 94,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 2000
|
||||
},
|
||||
"value": 2000,
|
||||
"profitability": 21,
|
||||
"easiest": 126
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 56 }, { "number": 20, "id": 58 }, { "number": 10, "id": 60 }, { "number": 5, "id": 62 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 169,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 2500
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 3500,
|
||||
"profitability": 21,
|
||||
"easiest": 225
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 20, "id": 56 }, { "number": 20, "id": 58 }, { "number": 10, "id": 60 }, { "number": 10, "id": 62 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 225,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 5000
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 6000,
|
||||
"profitability": 27,
|
||||
"easiest": 299
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Dragon Utopia",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 8, "id": 26 }, { "number": 5, "id": 82 }, { "number": 2, "id": 27 }, { "number": 1, "id": 83 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 769,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 20000
|
||||
},
|
||||
"reward_artifacts": [ 1, 1, 1, 1 ],
|
||||
"value": 38000,
|
||||
"profitability": 21,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 8, "id": 26 }, { "number": 6, "id": 82 }, { "number": 3, "id": 27 }, { "number": 2, "id": 83 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 209,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 30000
|
||||
},
|
||||
"reward_artifacts": [ 0, 1, 1, 2 ],
|
||||
"value": 57000,
|
||||
"profitability": 26,
|
||||
"easiest": 125
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 8, "id": 26 }, { "number": 6, "id": 82 }, { "number": 4, "id": 27 }, { "number": 3, "id": 83 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 556,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 40000
|
||||
},
|
||||
"reward_artifacts": [ 0, 0, 1, 3 ],
|
||||
"value": 75000,
|
||||
"profitability": 29,
|
||||
"easiest": 145
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 8, "id": 26 }, { "number": 7, "id": 82 }, { "number": 6, "id": 27 }, { "number": 5, "id": 83 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 343,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 50000
|
||||
},
|
||||
"reward_artifacts": [ 0, 0, 0, 4 ],
|
||||
"value": 90000,
|
||||
"profitability": 27,
|
||||
"easiest": 189
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Hunting Lodge",
|
||||
"levels": [
|
||||
@ -1252,21 +586,6 @@
|
||||
"easiest": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Pyramid",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 100,
|
||||
"guards": [ { "number": 20, "id": 116 }, { "number": 10, "id": 117 }, { "number": 20, "id": 116 }, { "number": 10, "id": 117 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 786,
|
||||
"value": 15000,
|
||||
"profitability": 19,
|
||||
"easiest": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -8,7 +8,8 @@
|
||||
"creature" : 150,
|
||||
"faction" : 9,
|
||||
"hero" : 156,
|
||||
"spell" : 81,
|
||||
"spell" : 81,
|
||||
"object" : 256,
|
||||
"mapVersion" : 28 // max supported version, SoD
|
||||
},
|
||||
|
||||
|
@ -1,108 +0,0 @@
|
||||
{
|
||||
// Indicate which dwelling produces which creature
|
||||
// Note that it is 1<->n connection since
|
||||
// a creature can be produced by more than one dwelling.
|
||||
"dwellings": [
|
||||
{ "dwelling": 0, "creature": 106 },
|
||||
{ "dwelling": 1, "creature": 96 },
|
||||
{ "dwelling": 2, "creature": 74 },
|
||||
{ "dwelling": 3, "creature": 66 },
|
||||
{ "dwelling": 4, "creature": 68 },
|
||||
{ "dwelling": 5, "creature": 10 },
|
||||
{ "dwelling": 6, "creature": 14 },
|
||||
{ "dwelling": 7, "creature": 112 },
|
||||
{ "dwelling": 8, "creature": 12 },
|
||||
{ "dwelling": 9, "creature": 94 },
|
||||
{ "dwelling": 10, "creature": 54 },
|
||||
{ "dwelling": 11, "creature": 104 },
|
||||
{ "dwelling": 12, "creature": 16 },
|
||||
{ "dwelling": 13, "creature": 113 },
|
||||
{ "dwelling": 14, "creature": 52 },
|
||||
{ "dwelling": 15, "creature": 18 },
|
||||
{ "dwelling": 16, "creature": 114 },
|
||||
{ "dwelling": 17, "creature": 30 },
|
||||
{ "dwelling": 18, "creature": 36 },
|
||||
{ "dwelling": 19, "creature": 86 },
|
||||
{ "dwelling": 20, "creature": 98 },
|
||||
{ "dwelling": 21, "creature": 84 },
|
||||
{ "dwelling": 22, "creature": 44 },
|
||||
{ "dwelling": 23, "creature": 102 },
|
||||
{ "dwelling": 24, "creature": 26 },
|
||||
{ "dwelling": 25, "creature": 4 },
|
||||
{ "dwelling": 26, "creature": 72 },
|
||||
{ "dwelling": 27, "creature": 46 },
|
||||
{ "dwelling": 28, "creature": 110 },
|
||||
{ "dwelling": 29, "creature": 42 },
|
||||
{ "dwelling": 30, "creature": 100 },
|
||||
{ "dwelling": 31, "creature": 34 },
|
||||
{ "dwelling": 32, "creature": 80 },
|
||||
{ "dwelling": 33, "creature": 76 },
|
||||
{ "dwelling": 34, "creature": 78 },
|
||||
{ "dwelling": 35, "creature": 8 },
|
||||
{ "dwelling": 36, "creature": 38 },
|
||||
{ "dwelling": 37, "creature": 48 },
|
||||
{ "dwelling": 38, "creature": 90 },
|
||||
{ "dwelling": 39, "creature": 88 },
|
||||
{ "dwelling": 40, "creature": 50 },
|
||||
{ "dwelling": 41, "creature": 82 },
|
||||
{ "dwelling": 42, "creature": 92 },
|
||||
{ "dwelling": 43, "creature": 28 },
|
||||
{ "dwelling": 44, "creature": 40 },
|
||||
{ "dwelling": 45, "creature": 22 },
|
||||
{ "dwelling": 46, "creature": 70 },
|
||||
{ "dwelling": 47, "creature": 115 },
|
||||
{ "dwelling": 48, "creature": 60 },
|
||||
{ "dwelling": 49, "creature": 108 },
|
||||
{ "dwelling": 50, "creature": 20 },
|
||||
{ "dwelling": 51, "creature": 24 },
|
||||
{ "dwelling": 52, "creature": 64 },
|
||||
{ "dwelling": 53, "creature": 62 },
|
||||
{ "dwelling": 54, "creature": 56 },
|
||||
{ "dwelling": 55, "creature": 58 },
|
||||
{ "dwelling": 56, "creature": 0 },
|
||||
{ "dwelling": 57, "creature": 2 },
|
||||
{ "dwelling": 58, "creature": 6 },
|
||||
{ "dwelling": 59, "creature": 118 },
|
||||
{ "dwelling": 60, "creature": 120 },
|
||||
{ "dwelling": 61, "creature": 130 },
|
||||
{ "dwelling": 62, "creature": 132 },
|
||||
{ "dwelling": 63, "creature": 133 },
|
||||
{ "dwelling": 64, "creature": 134 },
|
||||
{ "dwelling": 65, "creature": 135 },
|
||||
{ "dwelling": 66, "creature": 136 },
|
||||
{ "dwelling": 67, "creature": 137 },
|
||||
{ "dwelling": 68, "creature": 24 },
|
||||
{ "dwelling": 69, "creature": 112 },
|
||||
{ "dwelling": 70, "creature": 113 },
|
||||
{ "dwelling": 71, "creature": 114 },
|
||||
{ "dwelling": 72, "creature": 115 },
|
||||
{ "dwelling": 73, "creature": 138 },
|
||||
{ "dwelling": 74, "creature": 139 },
|
||||
{ "dwelling": 75, "creature": 140 },
|
||||
{ "dwelling": 76, "creature": 141 },
|
||||
{ "dwelling": 77, "creature": 142 },
|
||||
{ "dwelling": 78, "creature": 143 },
|
||||
{ "dwelling": 79, "creature": 144 },
|
||||
{ "dwelling": 80, "creature": 150 },
|
||||
{ "dwelling": 81, "creature": 151 },
|
||||
{ "dwelling": 82, "creature": 152 },
|
||||
{ "dwelling": 83, "creature": 153 },
|
||||
{ "dwelling": 84, "creature": 154 },
|
||||
{ "dwelling": 85, "creature": 155 },
|
||||
{ "dwelling": 86, "creature": 156 },
|
||||
{ "dwelling": 87, "creature": 157 },
|
||||
{ "dwelling": 88, "creature": 158 },
|
||||
{ "dwelling": 89, "creature": 171 },
|
||||
{ "dwelling": 90, "creature": 170 },
|
||||
{ "dwelling": 91, "creature": 168 },
|
||||
{ "dwelling": 92, "creature": 172 },
|
||||
{ "dwelling": 93, "creature": 164 },
|
||||
{ "dwelling": 94, "creature": 169 },
|
||||
{ "dwelling": 95, "creature": 173 },
|
||||
{ "dwelling": 96, "creature": 192 },
|
||||
{ "dwelling": 97, "creature": 193 },
|
||||
{ "dwelling": 98, "creature": 194 },
|
||||
{ "dwelling": 99, "creature": 195 },
|
||||
{ "dwelling": 100, "creature": 196 }
|
||||
]
|
||||
}
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "AVCcasx0.def",
|
||||
"village" : "AVCCAST0.DEF",
|
||||
"capitol" : "AVCCASZ0.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "AVCcasx0.def" },
|
||||
"village" : { "animation" : "AVCCAST0.DEF" },
|
||||
"capitol" : { "animation" : "AVCCASZ0.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "avchforx.def",
|
||||
"village" : "AVCHFOR0.DEF",
|
||||
"capitol" : "AVCHFORZ.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "avchforx.def" },
|
||||
"village" : { "animation" : "AVCHFOR0.DEF" },
|
||||
"capitol" : { "animation" : "AVCHFORZ.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "AVCdunx0.def",
|
||||
"village" : "AVCDUNG0.DEF",
|
||||
"capitol" : "AVCDUNZ0.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "AVCdunx0.def" },
|
||||
"village" : { "animation" : "AVCDUNG0.DEF" },
|
||||
"capitol" : { "animation" : "AVCDUNZ0.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "AVCftrx0.def",
|
||||
"village" : "AVCFTRT0.DEF",
|
||||
"capitol" : "AVCFORZ0.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "AVCftrx0.def" },
|
||||
"village" : { "animation" : "AVCFTRT0.DEF" },
|
||||
"capitol" : { "animation" : "AVCFORZ0.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "AVCinfx0.def",
|
||||
"village" : "AVCINFT0.DEF",
|
||||
"capitol" : "AVCINFZ0.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "AVCinfx0.def" },
|
||||
"village" : { "animation" : "AVCINFT0.DEF" },
|
||||
"capitol" : { "animation" : "AVCINFZ0.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "AVCnecx0.def",
|
||||
"village" : "AVCNECR0.DEF",
|
||||
"capitol" : "AVCNECZ0.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "AVCnecx0.def" },
|
||||
"village" : { "animation" : "AVCNECR0.DEF" },
|
||||
"capitol" : { "animation" : "AVCNECZ0.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "AVCramx0.def",
|
||||
"village" : "AVCRAMP0.DEF",
|
||||
"capitol" : "AVCRAMZ0.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "AVCramx0.def" },
|
||||
"village" : { "animation" : "AVCRAMP0.DEF" },
|
||||
"capitol" : { "animation" : "AVCRAMZ0.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "AVCstrx0.def",
|
||||
"village" : "AVCSTRO0.DEF",
|
||||
"capitol" : "AVCSTRZ0.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "AVCstrx0.def" },
|
||||
"village" : { "animation" : "AVCSTRO0.DEF" },
|
||||
"capitol" : { "animation" : "AVCSTRZ0.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -66,11 +66,13 @@
|
||||
},
|
||||
"town" :
|
||||
{
|
||||
"adventureMap" :
|
||||
"mapObject" :
|
||||
{
|
||||
"castle" : "AVCtowx0.def",
|
||||
"village" : "AVCTOWR0.DEF",
|
||||
"capitol" : "AVCTOWZ0.DEF"
|
||||
"templates" : {
|
||||
"castle" : { "animation" : "AVCtowx0.def" },
|
||||
"village" : { "animation" : "AVCTOWR0.DEF" },
|
||||
"capitol" : { "animation" : "AVCTOWZ0.DEF" }
|
||||
}
|
||||
},
|
||||
"structures" :
|
||||
{
|
||||
|
@ -45,6 +45,15 @@
|
||||
"config/heroes/special.json"
|
||||
],
|
||||
|
||||
"objects" :
|
||||
[
|
||||
"config/objects/generic.json",
|
||||
"config/objects/moddables.json",
|
||||
"config/objects/creatureBanks.json",
|
||||
"config/objects/dwellings.json",
|
||||
"config/objects/rewardable.json"
|
||||
],
|
||||
|
||||
"artifacts" :
|
||||
[
|
||||
"config/artifacts.json"
|
||||
|
@ -6,11 +6,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "zealot",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" },
|
||||
"map": { "male" : "AH00_.def", "female" : "AH00_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH00_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" } }
|
||||
},
|
||||
"cleric" :
|
||||
{
|
||||
@ -19,11 +16,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "zealot",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" },
|
||||
"map": { "male" : "AH01_.def", "female" : "AH01_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH01_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH00.DEF", "female" : "CH01.DEF" } }
|
||||
},
|
||||
"ranger" :
|
||||
{
|
||||
@ -32,11 +26,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "grandElf",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" },
|
||||
"map": { "male" : "AH02_.def", "female" : "AH02_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH02_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" } }
|
||||
},
|
||||
"druid" :
|
||||
{
|
||||
@ -45,11 +36,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "grandElf",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" },
|
||||
"map": { "male" : "AH03_.def", "female" : "AH03_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH03_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH02.DEF", "female" : "CH03.DEF" } }
|
||||
},
|
||||
"alchemist" :
|
||||
{
|
||||
@ -58,11 +46,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "archMage",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" },
|
||||
"map": { "male" : "AH04_.def", "female" : "AH04_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH04_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" } }
|
||||
},
|
||||
"wizard" :
|
||||
{
|
||||
@ -71,11 +56,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "archMage",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" },
|
||||
"map": { "male" : "AH05_.def", "female" : "AH05_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH05_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH05.DEF", "female" : "CH04.DEF" } }
|
||||
},
|
||||
"demoniac" :
|
||||
{
|
||||
@ -84,11 +66,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "magog",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" },
|
||||
"map": { "male" : "AH06_.def", "female" : "AH06_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH06_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" } }
|
||||
},
|
||||
"heretic" :
|
||||
{
|
||||
@ -97,11 +76,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "magog",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" },
|
||||
"map": { "male" : "AH07_.def", "female" : "AH07_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH07_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH06.DEF", "female" : "CH07.DEF" } }
|
||||
},
|
||||
"deathknight" :
|
||||
{
|
||||
@ -110,11 +86,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "powerLich",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" },
|
||||
"map": { "male" : "AH08_.def", "female" : "AH08_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH08_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" } }
|
||||
},
|
||||
"necromancer" :
|
||||
{
|
||||
@ -123,11 +96,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "powerLich",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" },
|
||||
"map": { "male" : "AH09_.def", "female" : "AH09_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH09_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH08.DEF", "female" : "CH09.DEF" } }
|
||||
},
|
||||
"warlock" :
|
||||
{
|
||||
@ -136,11 +106,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "medusaQueen",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
|
||||
"map": { "male" : "AH10_.def", "female" : "AH10_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH10_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" } }
|
||||
},
|
||||
"overlord" :
|
||||
{
|
||||
@ -149,11 +116,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "medusaQueen",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
|
||||
"map": { "male" : "AH11_.def", "female" : "AH11_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH11_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" } }
|
||||
},
|
||||
"barbarian" :
|
||||
{
|
||||
@ -162,11 +126,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "orcChieftain",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
|
||||
"map": { "male" : "AH12_.def", "female" : "AH12_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH12_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" } }
|
||||
},
|
||||
"battlemage" :
|
||||
{
|
||||
@ -175,11 +136,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "orcChieftain",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
|
||||
"map": { "male" : "AH13_.def", "female" : "AH13_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH13_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" } }
|
||||
},
|
||||
"beastmaster" :
|
||||
{
|
||||
@ -188,11 +146,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "lizardWarrior",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
|
||||
"map": { "male" : "AH14_.def", "female" : "AH14_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH14_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" } }
|
||||
},
|
||||
"witch" :
|
||||
{
|
||||
@ -201,11 +156,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "lizardWarrior",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
|
||||
"map": { "male" : "AH15_.def", "female" : "AH15_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH15_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" } }
|
||||
},
|
||||
"planeswalker" :
|
||||
{
|
||||
@ -214,11 +166,8 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "might",
|
||||
"commander" : "iceElemental",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH16.DEF", "female" : "CH16.DEF" },
|
||||
"map": { "male" : "AH16_.def", "female" : "AH16_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH16_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH16.DEF", "female" : "CH16.DEF" } }
|
||||
},
|
||||
"elementalist" :
|
||||
{
|
||||
@ -227,10 +176,7 @@
|
||||
"defaultTavern" : 5,
|
||||
"affinity" : "magic",
|
||||
"commander" : "iceElemental",
|
||||
"animation":
|
||||
{
|
||||
"battle" : { "male" : "CH17.DEF", "female" : "CH17.DEF" },
|
||||
"map": { "male" : "AH17_.def", "female" : "AH17_.def" }
|
||||
}
|
||||
"mapObject" : { "templates" : { "default" : { "animation" : "AH17_.def" } } },
|
||||
"animation": { "battle" : { "male" : "CH17.DEF", "female" : "CH17.DEF" } }
|
||||
}
|
||||
}
|
||||
|
975
config/objects/creatureBanks.json
Normal file
975
config/objects/creatureBanks.json
Normal file
@ -0,0 +1,975 @@
|
||||
{
|
||||
"creatureBank" : {
|
||||
"index" :16,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"cyclopsStockpile" :
|
||||
{
|
||||
"index" : 0,
|
||||
"name" : "Cyclops Stockpile",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 4, "type": "cyclop" },
|
||||
{ "amount": 4, "type": "cyclop" },
|
||||
{ "amount": 4, "type": "cyclop", "upgradeChance": 50 },
|
||||
{ "amount": 4, "type": "cyclop" },
|
||||
{ "amount": 4, "type": "cyclop" }
|
||||
],
|
||||
|
||||
"combat_value": 506,
|
||||
"reward" : {
|
||||
"value": 10000,
|
||||
"resources":
|
||||
{
|
||||
"wood" : 4,
|
||||
"mercury" : 4,
|
||||
"ore" : 4,
|
||||
"sulfur" : 4,
|
||||
"crystal" : 4,
|
||||
"gems" : 4,
|
||||
"gold" : 0
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "cyclop" },
|
||||
{ "amount": 6, "type": "cyclop" },
|
||||
{ "amount": 6, "type": "cyclop", "upgradeChance": 50 },
|
||||
{ "amount": 6, "type": "cyclop" },
|
||||
{ "amount": 6, "type": "cyclop" }
|
||||
],
|
||||
"combat_value": 760,
|
||||
"reward" : {
|
||||
"value": 15000,
|
||||
"resources":
|
||||
{
|
||||
"wood" : 6,
|
||||
"mercury" : 6,
|
||||
"ore" : 6,
|
||||
"sulfur" : 6,
|
||||
"crystal" : 6,
|
||||
"gems" : 6
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "cyclop" },
|
||||
{ "amount": 8, "type": "cyclop" },
|
||||
{ "amount": 8, "type": "cyclop", "upgradeChance": 50 },
|
||||
{ "amount": 8, "type": "cyclop" },
|
||||
{ "amount": 8, "type": "cyclop" }
|
||||
],
|
||||
"combat_value": 1013,
|
||||
"reward" : {
|
||||
"value": 20000
|
||||
"resources":
|
||||
{
|
||||
"wood" : 8,
|
||||
"mercury" : 8,
|
||||
"ore" : 8,
|
||||
"sulfur" : 8,
|
||||
"crystal" : 8,
|
||||
"gems" : 8
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "cyclop" },
|
||||
{ "amount": 10, "type": "cyclop" },
|
||||
{ "amount": 10, "type": "cyclop", "upgradeChance": 50 },
|
||||
{ "amount": 10, "type": "cyclop" },
|
||||
{ "amount": 10, "type": "cyclop" }
|
||||
],
|
||||
"combat_value": 1266,
|
||||
"reward" : {
|
||||
"value": 25000,
|
||||
"resources":
|
||||
{
|
||||
"wood" : 10,
|
||||
"mercury" : 10,
|
||||
"ore" : 10,
|
||||
"sulfur" : 10,
|
||||
"crystal" : 10,
|
||||
"gems" : 10
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dwarvenTreasury" : {
|
||||
"index" : 1,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Dwarven Treasury",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "dwarf" },
|
||||
{ "amount": 10, "type": "dwarf" },
|
||||
{ "amount": 10, "type": "dwarf", "upgradeChance": 50 },
|
||||
{ "amount": 10, "type": "dwarf" },
|
||||
{ "amount": 10, "type": "dwarf" }
|
||||
],
|
||||
"combat_value": 194,
|
||||
"reward" : {
|
||||
"value": 3500,
|
||||
"resources":
|
||||
{
|
||||
"crystal" : 2,
|
||||
"gold" : 2500
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 15, "type": "dwarf" },
|
||||
{ "amount": 15, "type": "dwarf" },
|
||||
{ "amount": 15, "type": "dwarf", "upgradeChance": 50 },
|
||||
{ "amount": 15, "type": "dwarf" },
|
||||
{ "amount": 15, "type": "dwarf" }
|
||||
],
|
||||
"combat_value": 291,
|
||||
"reward" : {
|
||||
"value": 5500,
|
||||
"resources":
|
||||
{
|
||||
"crystal" : 3,
|
||||
"gold" : 4000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "dwarf" },
|
||||
{ "amount": 20, "type": "dwarf" },
|
||||
{ "amount": 20, "type": "dwarf", "upgradeChance": 50 },
|
||||
{ "amount": 20, "type": "dwarf" },
|
||||
{ "amount": 20, "type": "dwarf" }
|
||||
],
|
||||
"combat_value": 388,
|
||||
"reward" : {
|
||||
"value": 7500,
|
||||
"resources":
|
||||
{
|
||||
"crystal" : 5,
|
||||
"gold" : 5000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 30, "type": "dwarf" },
|
||||
{ "amount": 30, "type": "dwarf" },
|
||||
{ "amount": 30, "type": "dwarf", "upgradeChance": 50 },
|
||||
{ "amount": 30, "type": "dwarf" },
|
||||
{ "amount": 30, "type": "dwarf" }
|
||||
],
|
||||
"combat_value": 582,
|
||||
"reward" : {
|
||||
"value": 12500,
|
||||
"resources":
|
||||
{
|
||||
"crystal" : 10,
|
||||
"gold" : 7500
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"griffinConservatory" : {
|
||||
"index" : 2,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Griffin Conservatory",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "griffin" },
|
||||
{ "amount": 10, "type": "griffin" },
|
||||
{ "amount": 10, "type": "griffin", "upgradeChance": 50 },
|
||||
{ "amount": 10, "type": "griffin" },
|
||||
{ "amount": 10, "type": "griffin" }
|
||||
],
|
||||
"combat_value": 351,
|
||||
"reward" : {
|
||||
"value": 3000,
|
||||
"creatures": [ { "amount": 1, "type": "angel" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "griffin" },
|
||||
{ "amount": 20, "type": "griffin" },
|
||||
{ "amount": 20, "type": "griffin", "upgradeChance": 50 },
|
||||
{ "amount": 20, "type": "griffin" },
|
||||
{ "amount": 20, "type": "griffin" }
|
||||
],
|
||||
"combat_value": 702,
|
||||
"reward" : {
|
||||
"value": 6000,
|
||||
"creatures": [ { "amount": 2, "type": "angel" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 30, "type": "griffin" },
|
||||
{ "amount": 30, "type": "griffin" },
|
||||
{ "amount": 30, "type": "griffin", "upgradeChance": 50 },
|
||||
{ "amount": 30, "type": "griffin" },
|
||||
{ "amount": 30, "type": "griffin" }
|
||||
],
|
||||
"combat_value": 1053,
|
||||
"reward" : {
|
||||
"value": 9000,
|
||||
"creatures": [ { "amount": 3, "type": "angel" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 40, "type": "griffin" },
|
||||
{ "amount": 40, "type": "griffin" },
|
||||
{ "amount": 40, "type": "griffin", "upgradeChance": 50 },
|
||||
{ "amount": 40, "type": "griffin" },
|
||||
{ "amount": 40, "type": "griffin" }
|
||||
],
|
||||
"combat_value": 1404,
|
||||
"reward" : {
|
||||
"value": 12000,
|
||||
"creatures": [ { "amount": 4, "type": "angel" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"inpCache" : {
|
||||
"index" : 3,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Imp Cache",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "imp" },
|
||||
{ "amount": 20, "type": "imp" },
|
||||
{ "amount": 20, "type": "imp", "upgradeChance": 50 },
|
||||
{ "amount": 20, "type": "imp" },
|
||||
{ "amount": 20, "type": "imp" }
|
||||
],
|
||||
"combat_value": 100,
|
||||
"reward" : {
|
||||
"value": 2000,
|
||||
"resources":
|
||||
{
|
||||
"wood" : 0,
|
||||
"mercury" : 2,
|
||||
"ore" : 0,
|
||||
"sulfur" : 0,
|
||||
"crystal" : 0,
|
||||
"gems" : 0,
|
||||
"gold" : 1000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 30, "type": "imp" },
|
||||
{ "amount": 30, "type": "imp" },
|
||||
{ "amount": 30, "type": "imp", "upgradeChance": 50 },
|
||||
{ "amount": 30, "type": "imp" },
|
||||
{ "amount": 30, "type": "imp" }
|
||||
],
|
||||
"combat_value": 150,
|
||||
"reward" : {
|
||||
"value": 3000,
|
||||
"resources":
|
||||
{
|
||||
"mercury" : 3,
|
||||
"gold" : 1500
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 40, "type": "imp" },
|
||||
{ "amount": 40, "type": "imp" },
|
||||
{ "amount": 40, "type": "imp", "upgradeChance": 50 },
|
||||
{ "amount": 40, "type": "imp" },
|
||||
{ "amount": 40, "type": "imp" }
|
||||
],
|
||||
"combat_value": 200,
|
||||
"reward" : {
|
||||
"value": 4000,
|
||||
"resources":
|
||||
{
|
||||
"mercury" : 4,
|
||||
"gold" : 2000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 60, "type": "imp" },
|
||||
{ "amount": 60, "type": "imp" },
|
||||
{ "amount": 60, "type": "imp", "upgradeChance": 50 },
|
||||
{ "amount": 60, "type": "imp" },
|
||||
{ "amount": 60, "type": "imp" }
|
||||
],
|
||||
"combat_value": 300,
|
||||
"reward" : {
|
||||
"value": 6000,
|
||||
"resources":
|
||||
{
|
||||
"mercury" : 6,
|
||||
"gold" : 3000
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"medusaStore" : {
|
||||
"index" : 4,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Medusa Stores",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 4, "type": "medusa" },
|
||||
{ "amount": 4, "type": "medusa" },
|
||||
{ "amount": 4, "type": "medusa", "upgradeChance": 50 },
|
||||
{ "amount": 4, "type": "medusa" },
|
||||
{ "amount": 4, "type": "medusa" }
|
||||
],
|
||||
"combat_value": 207,
|
||||
"reward" : {
|
||||
"value": 4500,
|
||||
"resources":
|
||||
{
|
||||
"sulfur" : 5,
|
||||
"gold" : 2000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "medusa" },
|
||||
{ "amount": 6, "type": "medusa" },
|
||||
{ "amount": 6, "type": "medusa", "upgradeChance": 50 },
|
||||
{ "amount": 6, "type": "medusa" },
|
||||
{ "amount": 6, "type": "medusa" }
|
||||
],
|
||||
"combat_value": 310,
|
||||
"reward" : {
|
||||
"value": 6000,
|
||||
"resources":
|
||||
{
|
||||
"sulfur" : 6,
|
||||
"gold" : 3000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "medusa" },
|
||||
{ "amount": 8, "type": "medusa" },
|
||||
{ "amount": 8, "type": "medusa", "upgradeChance": 50 },
|
||||
{ "amount": 8, "type": "medusa" },
|
||||
{ "amount": 8, "type": "medusa" }
|
||||
],
|
||||
"combat_value": 414,
|
||||
"reward" : {
|
||||
"value": 8000,
|
||||
"resources":
|
||||
{
|
||||
"sulfur" : 8,
|
||||
"gold" : 4000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "medusa" },
|
||||
{ "amount": 10, "type": "medusa" },
|
||||
{ "amount": 10, "type": "medusa", "upgradeChance": 50 },
|
||||
{ "amount": 10, "type": "medusa" },
|
||||
{ "amount": 10, "type": "medusa" }
|
||||
],
|
||||
"combat_value": 517,
|
||||
"reward" : {
|
||||
"value": 10000,
|
||||
"resources":
|
||||
{
|
||||
"sulfur" : 10,
|
||||
"gold" : 5000
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"nagaBank" : {
|
||||
"index" : 5,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Naga Bank",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 2, "type": "naga" },
|
||||
{ "amount": 2, "type": "naga" },
|
||||
{ "amount": 2, "type": "naga", "upgradeChance": 50 },
|
||||
{ "amount": 2, "type": "naga" },
|
||||
{ "amount": 2, "type": "naga" }
|
||||
],
|
||||
"combat_value": 403,
|
||||
"reward" : {
|
||||
"value": 8000,
|
||||
"resources":
|
||||
{
|
||||
"gems" : 8,
|
||||
"gold" : 4000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 3, "type": "naga" },
|
||||
{ "amount": 3, "type": "naga" },
|
||||
{ "amount": 3, "type": "naga", "upgradeChance": 50 },
|
||||
{ "amount": 3, "type": "naga" },
|
||||
{ "amount": 3, "type": "naga" }
|
||||
],
|
||||
"combat_value": 605,
|
||||
"reward" : {
|
||||
"value": 12000,
|
||||
"resources":
|
||||
{
|
||||
"gems" : 12,
|
||||
"gold" : 6000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 4, "type": "naga" },
|
||||
{ "amount": 4, "type": "naga" },
|
||||
{ "amount": 4, "type": "naga", "upgradeChance": 50 },
|
||||
{ "amount": 4, "type": "naga" },
|
||||
{ "amount": 4, "type": "naga" }
|
||||
],
|
||||
"combat_value": 806,
|
||||
"reward" : {
|
||||
"value": 16000,
|
||||
"resources":
|
||||
{
|
||||
"gems" : 16,
|
||||
"gold" : 8000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "naga" },
|
||||
{ "amount": 6, "type": "naga" },
|
||||
{ "amount": 6, "type": "naga", "upgradeChance": 50 },
|
||||
{ "amount": 6, "type": "naga" },
|
||||
{ "amount": 6, "type": "naga" }
|
||||
],
|
||||
"combat_value": 1210,
|
||||
"reward" : {
|
||||
"value": 24000,
|
||||
"resources":
|
||||
{
|
||||
"gems" : 24,
|
||||
"gold" : 12000
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dragonflyHive" : {
|
||||
"index" : 6,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Dragon Fly Hive",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "dragonFly" },
|
||||
{ "amount": 6, "type": "dragonFly" },
|
||||
{ "amount": 6, "type": "dragonFly" },
|
||||
{ "amount": 6, "type": "dragonFly" },
|
||||
{ "amount": 6, "type": "dragonFly" }
|
||||
],
|
||||
"combat_value": 154,
|
||||
"reward" : {
|
||||
"value": 3200,
|
||||
"creatures": [ { "amount": 4, "type": "vyvern" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 9, "type": "dragonFly" },
|
||||
{ "amount": 9, "type": "dragonFly" },
|
||||
{ "amount": 9, "type": "dragonFly" },
|
||||
{ "amount": 9, "type": "dragonFly" },
|
||||
{ "amount": 9, "type": "dragonFly" }
|
||||
],
|
||||
"combat_value": 230,
|
||||
"reward" : {
|
||||
"value": 4800,
|
||||
"creatures": [ { "amount": 6, "type": "vyvern" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 12, "type": "dragonFly" },
|
||||
{ "amount": 12, "type": "dragonFly" },
|
||||
{ "amount": 12, "type": "dragonFly" },
|
||||
{ "amount": 12, "type": "dragonFly" },
|
||||
{ "amount": 12, "type": "dragonFly" }
|
||||
],
|
||||
"combat_value": 307,
|
||||
"reward" : {
|
||||
"value": 6400,
|
||||
"creatures": [ { "amount": 8, "type": "vyvern" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 18, "type": "dragonFly" },
|
||||
{ "amount": 18, "type": "dragonFly" },
|
||||
{ "amount": 18, "type": "dragonFly" },
|
||||
{ "amount": 18, "type": "dragonFly" },
|
||||
{ "amount": 18, "type": "dragonFly" }
|
||||
],
|
||||
"combat_value": 461,
|
||||
"reward" : {
|
||||
"value": 9600,
|
||||
"creatures": [ { "amount": 12, "type": "vyvern" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"shipwreck" : {
|
||||
"index" :85,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"shipwreck" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Shipwreck",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 2, "type": "wight" },
|
||||
{ "amount": 2, "type": "wight" },
|
||||
{ "amount": 2, "type": "wight" },
|
||||
{ "amount": 2, "type": "wight" },
|
||||
{ "amount": 2, "type": "wight" }
|
||||
],
|
||||
"combat_value": 31,
|
||||
"reward" : {
|
||||
"value": 2000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 2000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 3, "type": "wight" },
|
||||
{ "amount": 3, "type": "wight" },
|
||||
{ "amount": 3, "type": "wight" },
|
||||
{ "amount": 3, "type": "wight" },
|
||||
{ "amount": 3, "type": "wight" }
|
||||
],
|
||||
"combat_value": 46,
|
||||
"reward" : {
|
||||
"value": 3000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 5, "type": "wight" }
|
||||
],
|
||||
"combat_value": 77,
|
||||
"reward" : {
|
||||
"value": 5000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 4000
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "wight" }
|
||||
],
|
||||
"combat_value": 154,
|
||||
"reward" : {
|
||||
"value": 7000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 5000
|
||||
},
|
||||
"artifacts": [ { "class" : "MINOR" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
"derelictShip" : {
|
||||
"index" :24,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"derelictShip" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Derelict Ship",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 4, "type": "waterElemental" },
|
||||
{ "amount": 4, "type": "waterElemental" },
|
||||
{ "amount": 4, "type": "waterElemental" },
|
||||
{ "amount": 4, "type": "waterElemental" },
|
||||
{ "amount": 4, "type": "waterElemental" }
|
||||
],
|
||||
"combat_value": 138,
|
||||
"reward" : {
|
||||
"value": 3000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "waterElemental" },
|
||||
{ "amount": 6, "type": "waterElemental" },
|
||||
{ "amount": 6, "type": "waterElemental" },
|
||||
{ "amount": 6, "type": "waterElemental" },
|
||||
{ "amount": 6, "type": "waterElemental" }
|
||||
],
|
||||
"combat_value": 207,
|
||||
"reward" : {
|
||||
"value": 4000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "waterElemental" },
|
||||
{ "amount": 8, "type": "waterElemental" },
|
||||
{ "amount": 8, "type": "waterElemental" },
|
||||
{ "amount": 8, "type": "waterElemental" },
|
||||
{ "amount": 8, "type": "waterElemental" }
|
||||
],
|
||||
"combat_value": 276,
|
||||
"reward" : {
|
||||
"value": 5000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 4000
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 12, "type": "waterElemental" },
|
||||
{ "amount": 12, "type": "waterElemental" },
|
||||
{ "amount": 12, "type": "waterElemental" },
|
||||
{ "amount": 12, "type": "waterElemental" },
|
||||
{ "amount": 12, "type": "waterElemental" }
|
||||
],
|
||||
"combat_value": 414,
|
||||
"reward" : {
|
||||
"value": 8000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 6000
|
||||
},
|
||||
"artifacts": [ { "class" : "MINOR" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"crypt" : {
|
||||
"index" :84,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"crypt" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Crypt",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "skeleton" },
|
||||
{ "amount": 10, "type": "walkingDead" },
|
||||
{ "amount": 10, "type": "walkingDead" },
|
||||
{ "amount": 10, "type": "skeleton" },
|
||||
{ "amount": 10, "type": "skeleton" }
|
||||
],
|
||||
"combat_value": 75,
|
||||
"reward" : {
|
||||
"value": 1500,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 1500
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 13, "type": "skeleton" },
|
||||
{ "amount": 10, "type": "walkingDead" },
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 10, "type": "walkingDead" },
|
||||
{ "amount": 12, "type": "skeleton" }
|
||||
],
|
||||
"combat_value": 94,
|
||||
"reward" : {
|
||||
"value": 2000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 2000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "skeleton" },
|
||||
{ "amount": 20, "type": "walkingDead" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 5, "type": "vampire" }
|
||||
],
|
||||
"combat_value": 169,
|
||||
"reward" : {
|
||||
"value": 3500,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 2500
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "skeleton" },
|
||||
{ "amount": 20, "type": "walkingDead" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "vampire" }
|
||||
],
|
||||
"combat_value": 225,
|
||||
"reward" : {
|
||||
"value": 6000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 5000
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dragonUtopia" : {
|
||||
"index" :25,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"dragonUtopia" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Dragon Utopia",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "greenDragon" },
|
||||
{ "amount": 5, "type": "redDragon" },
|
||||
{ "amount": 2, "type": "goldDragon" },
|
||||
{ "amount": 1, "type": "blackDragon" }
|
||||
],
|
||||
"combat_value": 769,
|
||||
"reward" : {
|
||||
"value": 38000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 20000
|
||||
},
|
||||
"artifacts": [
|
||||
{ "class" : "TREASURE" }
|
||||
{ "class" : "MINOR" }
|
||||
{ "class" : "MAJOR" }
|
||||
{ "class" : "RELIC" }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "greenDragon" },
|
||||
{ "amount": 6, "type": "redDragon" },
|
||||
{ "amount": 3, "type": "goldDragon" },
|
||||
{ "amount": 2, "type": "blackDragon" }
|
||||
],
|
||||
"combat_value": 209,
|
||||
"reward" : {
|
||||
"value": 57000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 30000
|
||||
},
|
||||
"artifacts": [
|
||||
{ "class" : "MINOR" }
|
||||
{ "class" : "MAJOR" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "greenDragon" },
|
||||
{ "amount": 6, "type": "redDragon" },
|
||||
{ "amount": 4, "type": "goldDragon" },
|
||||
{ "amount": 3, "type": "blackDragon" }
|
||||
],
|
||||
"combat_value": 556,
|
||||
"reward" : {
|
||||
"value": 75000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 40000
|
||||
},
|
||||
"artifacts": [ 0, 0, 1, 3 ]
|
||||
"artifacts": [
|
||||
{ "class" : "MAJOR" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "greenDragon" },
|
||||
{ "amount": 7, "type": "redDragon" },
|
||||
{ "amount": 6, "type": "goldDragon" },
|
||||
{ "amount": 5, "type": "blackDragon" }
|
||||
],
|
||||
"combat_value": 343,
|
||||
"reward" : {
|
||||
"value": 90000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 50000
|
||||
},
|
||||
"artifacts": [ 0, 0, 0, 4 ]
|
||||
"artifacts": [
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"pyramid" : {
|
||||
"index" :63,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"pyramid" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Pyramid",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 100,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "goldGolem" },
|
||||
{ "amount": 10, "type": "diamondGolem" },
|
||||
{ "amount": 20, "type": "goldGolem" },
|
||||
{ "amount": 10, "type": "diamondGolem" }
|
||||
],
|
||||
"combat_value": 786,
|
||||
"reward" : {
|
||||
"value": 15000,
|
||||
"spells" : [ { "level" : 5 } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
126
config/objects/dwellings.json
Normal file
126
config/objects/dwellings.json
Normal file
@ -0,0 +1,126 @@
|
||||
{
|
||||
"creatureGeneratorCommon" : {
|
||||
"index" :17,
|
||||
"handler": "dwelling",
|
||||
"base" : {
|
||||
"base" : {
|
||||
"visitableFrom" : [ "---", "+++", "+++" ],
|
||||
"mask" : [ "VVV", "VBB", "VAA" ]
|
||||
}
|
||||
},
|
||||
"types" : {
|
||||
"basiliskPit" : { "index" : 0, "creatures" : [ [ "basilisk" ] ] },
|
||||
"behemothCrag" : { "index" : 1, "creatures" : [ [ "behemoth" ] ], "guards" : true },
|
||||
"pillarOfEyes" : { "index" : 2, "creatures" : [ [ "beholder" ] ] },
|
||||
"hallOfDarkness" : { "index" : 3, "creatures" : [ [ "blackKnight" ] ], "guards" : true },
|
||||
"dragonVault" : { "index" : 4, "creatures" : [ [ "boneDragon" ] ], "guards" : true },
|
||||
"trainingGrounds" : { "index" : 5, "creatures" : [ [ "cavalier" ] ], "guards" : true },
|
||||
"centaurStables" : { "index" : 6, "creatures" : [ [ "centaur" ] ] },
|
||||
"airConflux" : { "index" : 7, "creatures" : [ [ "airElemental" ] ] },
|
||||
"portalOfGlory" : { "index" : 8, "creatures" : [ [ "angel" ] ], "guards" : true },
|
||||
"cyclopsCave" : { "index" : 9, "creatures" : [ [ "cyclop" ] ], "guards" : true },
|
||||
"forsakenPalace" : { "index" : 10, "creatures" : [ [ "devil" ] ], "guards" : true },
|
||||
"serpentFlyHive" : { "index" : 11, "creatures" : [ [ "serpentFly" ] ] },
|
||||
"dwarfCottage" : { "index" : 12, "creatures" : [ [ "dwarf" ] ] },
|
||||
"earthConflux" : { "index" : 13, "creatures" : [ [ "earthElemental" ] ], "guards" : true },
|
||||
"fireLake" : { "index" : 14, "creatures" : [ [ "efreet" ] ], "guards" : true },
|
||||
"homestead" : { "index" : 15, "creatures" : [ [ "woodElf" ] ] },
|
||||
"fireConflux" : { "index" : 16, "creatures" : [ [ "fireElemental" ] ] },
|
||||
"parapet" : { "index" : 17, "creatures" : [ [ "stoneGargoyle" ] ] },
|
||||
"altarOfWishes" : { "index" : 18, "creatures" : [ [ "genie" ] ], "guards" : true },
|
||||
"wolfPen" : { "index" : 19, "creatures" : [ [ "goblinWolfRider" ] ] },
|
||||
"gnollHut" : { "index" : 20, "creatures" : [ [ "gnoll" ] ] },
|
||||
"goblinBarracks" : { "index" : 21, "creatures" : [ [ "goblin" ] ] },
|
||||
"hallOfSins" : { "index" : 22, "creatures" : [ [ "gog" ] ] },
|
||||
"gorgonLair" : { "index" : 23, "creatures" : [ [ "gorgon" ] ], "guards" : true },
|
||||
"dragonCliffs" : { "index" : 24, "creatures" : [ [ "greenDragon" ] ], "guards" : true },
|
||||
"griffinTower" : { "index" : 25, "creatures" : [ [ "griffin" ] ] },
|
||||
"harpyLoft" : { "index" : 26, "creatures" : [ [ "harpy" ] ] },
|
||||
"kennels" : { "index" : 27, "creatures" : [ [ "hellHound" ] ] },
|
||||
"hydraPond" : { "index" : 28, "creatures" : [ [ "hydra" ] ], "guards" : true },
|
||||
"impCrucible" : { "index" : 29, "creatures" : [ [ "imp" ] ] },
|
||||
"lizardDen" : { "index" : 30, "creatures" : [ [ "lizardman" ] ] },
|
||||
"mageTower" : { "index" : 31, "creatures" : [ [ "mage" ] ] },
|
||||
"manticoreLair" : { "index" : 32, "creatures" : [ [ "manticore" ] ], "guards" : true },
|
||||
"medusaChapel" : { "index" : 33, "creatures" : [ [ "medusa" ] ] },
|
||||
"labyrinth" : { "index" : 34, "creatures" : [ [ "minotaur" ] ], "guards" : true },
|
||||
"monastery" : { "index" : 35, "creatures" : [ [ "monk" ] ], "guards" : true },
|
||||
"goldenPavilion" : { "index" : 36, "creatures" : [ [ "naga" ] ], "guards" : true },
|
||||
"demonGate" : { "index" : 37, "creatures" : [ [ "demon" ] ] },
|
||||
"ogreFort" : { "index" : 38, "creatures" : [ [ "ogre" ] ] },
|
||||
"orcTower" : { "index" : 39, "creatures" : [ [ "orc" ] ] },
|
||||
"hellHole" : { "index" : 40, "creatures" : [ [ "pitFiend" ] ], "guards" : true },
|
||||
"dragonCave" : { "index" : 41, "creatures" : [ [ "redDragon" ] ], "guards" : true },
|
||||
"cliffNest" : { "index" : 42, "creatures" : [ [ "roc" ] ], "guards" : true },
|
||||
"workshop" : { "index" : 43, "creatures" : [ [ "gremlin" ] ] },
|
||||
"cloudTemple" : { "index" : 44, "creatures" : [ [ "giant" ] ], "guards" : true },
|
||||
"dendroidArches" : { "index" : 45, "creatures" : [ [ "dendroidGuard" ] ], "guards" : true },
|
||||
"warren" : { "index" : 46, "creatures" : [ [ "troglodyte" ] ] },
|
||||
"waterConflux" : { "index" : 47, "creatures" : [ [ "waterElemental" ] ] },
|
||||
"tombOfSouls" : { "index" : 48, "creatures" : [ [ "wight" ] ] },
|
||||
"wyvernNest" : { "index" : 49, "creatures" : [ [ "wyvern" ] ], "guards" : true },
|
||||
"enchantedSpring" : { "index" : 50, "creatures" : [ [ "pegasus" ] ] },
|
||||
"unicornGladeBig" : { "index" : 51, "creatures" : [ [ "unicorn" ] ], "guards" : true },
|
||||
"mausoleum" : { "index" : 52, "creatures" : [ [ "lich" ] ], "guards" : true },
|
||||
"estate" : { "index" : 53, "creatures" : [ [ "vampire" ] ] },
|
||||
"cursedTemple" : { "index" : 54, "creatures" : [ [ "skeleton" ] ] },
|
||||
"graveyard" : { "index" : 55, "creatures" : [ [ "walkingDead" ] ] },
|
||||
"guardhouse" : { "index" : 56, "creatures" : [ [ "pikeman" ] ] },
|
||||
"archersTower" : { "index" : 57, "creatures" : [ [ "archer" ] ] },
|
||||
"barracks" : { "index" : 58, "creatures" : [ [ "swordsman" ] ] },
|
||||
"magicLantern" : { "index" : 59, "creatures" : [ [ "pixie" ] ] },
|
||||
"altarOfThought" : { "index" : 60, "creatures" : [ [ "psychicElemental" ] ], "guards" : true },
|
||||
"pyre" : { "index" : 61, "creatures" : [ [ "firebird" ] ], "guards" : true },
|
||||
"frozenCliffs" : { "index" : 62, "creatures" : [ [ "azureDragon" ] ], "guards" : true },
|
||||
"crystalCavern" : { "index" : 63, "creatures" : [ [ "crystalDragon" ] ], "guards" : true },
|
||||
"magicForest" : { "index" : 64, "creatures" : [ [ "fairieDragon" ] ], "guards" : true },
|
||||
"sulfurousLair" : { "index" : 65, "creatures" : [ [ "rustDragon" ] ], "guards" : true },
|
||||
"enchantersHollow" : { "index" : 66, "creatures" : [ [ "enchanter" ] ], "guards" : true },
|
||||
"treetopTower" : { "index" : 67, "creatures" : [ [ "sharpshooter" ] ], "guards" : true },
|
||||
"unicornGlade" : { "index" : 68, "creatures" : [ [ "unicorn" ] ], "guards" : true },
|
||||
"altarOfAir" : { "index" : 69, "creatures" : [ [ "airElemental" ] ] },
|
||||
"altarOfEarth" : { "index" : 70, "creatures" : [ [ "earthElemental" ] ], "guards" : true },
|
||||
"altarOfFire" : { "index" : 71, "creatures" : [ [ "fireElemental" ] ] },
|
||||
"altarOfWater" : { "index" : 72, "creatures" : [ [ "waterElemental" ] ] },
|
||||
"thatchedHut" : { "index" : 73, "creatures" : [ [ "halfling" ] ] },
|
||||
"hovel" : { "index" : 74, "creatures" : [ [ "peasant" ] ] },
|
||||
"boarGlen" : { "index" : 75, "creatures" : [ [ "boar" ] ] },
|
||||
"tombOfCurses" : { "index" : 76, "creatures" : [ [ "mummy" ] ] },
|
||||
"nomadTent" : { "index" : 77, "creatures" : [ [ "nomad" ] ] },
|
||||
"rogueCavern" : { "index" : 78, "creatures" : [ [ "rogue" ] ] },
|
||||
"trollBridge" : { "index" : 79, "creatures" : [ [ "troll" ] ], "guards" : true }
|
||||
}
|
||||
},
|
||||
// subtype: unique special dwellings - golem factory and elemental conflux
|
||||
"creatureGeneratorSpecial" : {
|
||||
"index" :20,
|
||||
"handler": "dwelling",
|
||||
"types" : {
|
||||
"elementalConflux" : {
|
||||
"index" : 0,
|
||||
"creatures" : [ // 4 separate "levels" to give them separate growth
|
||||
[ "airElemental" ],
|
||||
[ "waterElemental" ],
|
||||
[ "fireElemental" ],
|
||||
[ "earthElemental" ]
|
||||
],
|
||||
"guards" : [
|
||||
{ "amount" : 12, "type" : "earthElemental" }
|
||||
]
|
||||
},
|
||||
"golemFactory" : {
|
||||
"index" : 1,
|
||||
"creatures" : [ // 4 separate "levels" to give them separate growth
|
||||
[ "ironGolem" ],
|
||||
[ "stoneGolem" ],
|
||||
[ "goldGolem" ],
|
||||
[ "diamondGolem" ]
|
||||
],
|
||||
"guards" : [
|
||||
{ "amount" : 9, "type" : "goldGolem" },
|
||||
{ "amount" : 6, "type" : "diamondGolem" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
133
config/objects/generic.json
Normal file
133
config/objects/generic.json
Normal file
@ -0,0 +1,133 @@
|
||||
{
|
||||
/// These are objects that can not be configured, either due to
|
||||
/// their hardcoded status or because they don't have any configurable functionality
|
||||
"prison" : {
|
||||
"index" :62,
|
||||
"handler": "prison",
|
||||
"types" : {
|
||||
"prison" : { "index" : 0 }
|
||||
}
|
||||
},
|
||||
|
||||
"altarOfSacrifice" : { "index" :2, "handler": "market" },
|
||||
"tradingPost" : { "index" :221, "handler": "market" },
|
||||
"tradingPostDUPLICATE" : { "index" :99, "handler": "market" },
|
||||
"freelancersGuild" : { "index" :213, "handler": "market" },
|
||||
|
||||
"blackMarket" : { "index" :7, "handler": "blackMarket" },
|
||||
|
||||
"pandoraBox" : { "index" :6, "handler": "pandora" },
|
||||
"event" : { "index" :26, "handler": "event" },
|
||||
|
||||
"redwoodObservatory" : { "index" :58, "handler": "observatory" },
|
||||
"pillarOfFire" : { "index" :60, "handler": "observatory" },
|
||||
"coverOfDarkness" : { "index" :15, "handler": "observatory" },
|
||||
|
||||
"subterraneanGate" : { "index" :103, "handler": "teleport" },
|
||||
"whirlpool" : { "index" :111, "handler": "teleport" },
|
||||
|
||||
"refugeeCamp" : { "index" :78, "handler": "dwelling" },
|
||||
"warMachineFactory" : { "index" :106, "handler": "dwelling" },
|
||||
|
||||
"shrineOfMagicLevel1" : { "index" :88, "handler": "shrine" },
|
||||
"shrineOfMagicLevel2" : { "index" :89, "handler": "shrine" },
|
||||
"shrineOfMagicLevel3" : { "index" :90, "handler": "shrine" },
|
||||
|
||||
"eyeOfTheMagi" : { "index" :27, "handler": "magi" },
|
||||
"hutOfTheMagi" : { "index" :37, "handler": "magi" },
|
||||
|
||||
"lighthouse" : { "index" :42, "handler": "lighthouse" },
|
||||
"magicWell" : { "index" :49, "handler": "magicWell" },
|
||||
"obelisk" : { "index" :57, "handler": "obelisk" },
|
||||
"oceanBottle" : { "index" :59, "handler": "sign" },
|
||||
"scholar" : { "index" :81, "handler": "scholar" },
|
||||
"shipyard" : { "index" :87, "handler": "shipyard" },
|
||||
"sign" : { "index" :91, "handler": "sign" },
|
||||
"sirens" : { "index" :92, "handler": "siren" },
|
||||
"denOfThieves" : { "index" :97, "handler": "denOfThieves" },
|
||||
"university" : { "index" :104, "handler": "university" },
|
||||
"witchHut" : { "index" :113, "handler": "witch" },
|
||||
"questGuard" : { "index" :215, "handler": "questGuard" },
|
||||
|
||||
/// Random objects
|
||||
"randomResource" : { "index" :76, "handler": "resource" },
|
||||
"randomTown" : { "index" :77, "handler": "town" },
|
||||
"randomHero" : { "index" :70, "handler": "hero" },
|
||||
|
||||
"randomDwelling" : { "index" :216, "handler": "dwelling" },
|
||||
|
||||
"randomArtifact" : { "index" :65, "handler": "artifact" },
|
||||
"randomArtifactTreasure" : { "index" :66, "handler": "artifact" },
|
||||
"randomArtifactMinor" : { "index" :67, "handler": "artifact" },
|
||||
"randomArtifactMajor" : { "index" :68, "handler": "artifact" },
|
||||
"randomArtifactRelic" : { "index" :69, "handler": "artifact" },
|
||||
|
||||
"randomMonster" : { "index" :71, "handler": "monster" },
|
||||
"randomMonsterLevel1" : { "index" :72, "handler": "monster" },
|
||||
"randomMonsterLevel2" : { "index" :73, "handler": "monster" },
|
||||
"randomMonsterLevel3" : { "index" :74, "handler": "monster" },
|
||||
"randomMonsterLevel4" : { "index" :75, "handler": "monster" },
|
||||
"randomMonsterLevel5" : { "index" :162, "handler": "monster" },
|
||||
"randomMonsterLevel6" : { "index" :163, "handler": "monster" },
|
||||
"randomMonsterLevel7" : { "index" :164, "handler": "monster" },
|
||||
|
||||
/// Classes without dedicated object
|
||||
"hillFort" : { "index" :35, "handler": "generic" },
|
||||
"grail" : { "index" :36, "handler": "generic" },
|
||||
"tavern" : { "index" :95, "handler": "generic" },
|
||||
"sanctuary" : { "index" :80, "handler": "generic" },
|
||||
|
||||
/// Passive objects, terrain overlays
|
||||
"cursedGround" : { "index" :21, "handler": "generic" },
|
||||
"magicPlains" : { "index" :46, "handler": "generic" },
|
||||
"swampFoliage" : { "index" :211, "handler": "generic" },
|
||||
"cloverField" : { "index" :222, "handler": "generic" },
|
||||
"cursedGroundDUPLICATE" : { "index" :223, "handler": "generic" },
|
||||
"evilFog" : { "index" :224, "handler": "generic" },
|
||||
"favorableWinds" : { "index" :225, "handler": "generic" },
|
||||
"fieryFields" : { "index" :226, "handler": "generic" },
|
||||
"holyGround" : { "index" :227, "handler": "generic" },
|
||||
"lucidPools" : { "index" :228, "handler": "generic" },
|
||||
"magicClouds" : { "index" :229, "handler": "generic" },
|
||||
"magicPlainsDUPLICATE" : { "index" :230, "handler": "generic" },
|
||||
"rocklands" : { "index" :231, "handler": "generic" },
|
||||
|
||||
/// Decorations
|
||||
"cactus" : { "index" :116, "handler": "static" },
|
||||
"canyon" : { "index" :117, "handler": "static" },
|
||||
"crater" : { "index" :118, "handler": "static" },
|
||||
"deadVegetation" : { "index" :119, "handler": "static" },
|
||||
"flowers" : { "index" :120, "handler": "static" },
|
||||
"frozenLake" : { "index" :121, "handler": "static" },
|
||||
"hole" : { "index" :124, "handler": "static" },
|
||||
"kelp" : { "index" :125, "handler": "static" },
|
||||
"lake" : { "index" :126, "handler": "static" },
|
||||
"lavaFlow" : { "index" :127, "handler": "static" },
|
||||
"lavaLake" : { "index" :128, "handler": "static" },
|
||||
"mushrooms" : { "index" :129, "handler": "static" },
|
||||
"log" : { "index" :130, "handler": "static" },
|
||||
"mandrake" : { "index" :131, "handler": "static" },
|
||||
"moss" : { "index" :132, "handler": "static" },
|
||||
"mound" : { "index" :133, "handler": "static" },
|
||||
"mountain" : { "index" :134, "handler": "static" },
|
||||
"oakTrees" : { "index" :135, "handler": "static" },
|
||||
"outcropping" : { "index" :136, "handler": "static" },
|
||||
"pineTrees" : { "index" :137, "handler": "static" },
|
||||
"riverDelta" : { "index" :143, "handler": "static" },
|
||||
"rock" : { "index" :147, "handler": "static" },
|
||||
"sandDune" : { "index" :148, "handler": "static" },
|
||||
"sandPit" : { "index" :149, "handler": "static" },
|
||||
"shrub" : { "index" :150, "handler": "static" },
|
||||
"skull" : { "index" :151, "handler": "static" },
|
||||
"stump" : { "index" :153, "handler": "static" },
|
||||
"trees" : { "index" :155, "handler": "static" },
|
||||
"volcano" : { "index" :158, "handler": "static" },
|
||||
"reef" : { "index" :161, "handler": "static" },
|
||||
"lakeDUPLICATE" : { "index" :177, "handler": "static" },
|
||||
"treesDUPLICATE" : { "index" :199, "handler": "static" },
|
||||
"desertHills" : { "index" :206, "handler": "static" },
|
||||
"dirtHills" : { "index" :207, "handler": "static" },
|
||||
"grassHills" : { "index" :208, "handler": "static" },
|
||||
"roughHills" : { "index" :209, "handler": "static" },
|
||||
"subterraneanRocks" : { "index" :210, "handler": "static" }
|
||||
}
|
208
config/objects/moddables.json
Normal file
208
config/objects/moddables.json
Normal file
@ -0,0 +1,208 @@
|
||||
{
|
||||
/// These are objects that have subtypes that change various aspects of their mechanics
|
||||
/// Should be made configurable (either directly or via other parts of modding system ASAP)
|
||||
/// Editing these objects either directly or via mod may have negative effect on game since they are handled by engine
|
||||
|
||||
// subtype: artifact ID
|
||||
"artifact" : {
|
||||
"index" :5,
|
||||
"handler": "artifact",
|
||||
"base" : {
|
||||
"base" : {
|
||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||
"mask" : [ "VV", "VA"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: hero CLASS (not hero).
|
||||
"hero" : {
|
||||
"index" :34,
|
||||
"handler": "hero",
|
||||
"base" : {
|
||||
"base" : {
|
||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||
"mask" : [ "VV", "AV"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: creatures
|
||||
"monster" : {
|
||||
"index" :54,
|
||||
"handler": "monster",
|
||||
"base" : {
|
||||
"base" : {
|
||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||
"mask" : [ "VV", "VA"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: resource ID
|
||||
"resource" : {
|
||||
"index" :79,
|
||||
"handler": "resource",
|
||||
"base" : {
|
||||
"base" : {
|
||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||
"mask" : [ "VA" ]
|
||||
}
|
||||
},
|
||||
"types" : {
|
||||
"wood" : { "index" : 0, "templates" : { "res" : { "animation" : "AVTwood0.def" } } },
|
||||
"mercury" : { "index" : 1, "templates" : { "res" : { "animation" : "AVTmerc0.def" } } },
|
||||
"ore" : { "index" : 2, "templates" : { "res" : { "animation" : "AVTore0.def" } } },
|
||||
"sulfur" : { "index" : 3, "templates" : { "res" : { "animation" : "AVTsulf0.def" } } },
|
||||
"crystal" : { "index" : 4, "templates" : { "res" : { "animation" : "AVTcrys0.def" } } },
|
||||
"gems" : { "index" : 5, "templates" : { "res" : { "animation" : "AVTgems0.def" } } },
|
||||
"gold" : { "index" : 6, "templates" : { "res" : { "animation" : "AVTgold0.def" } } },
|
||||
"mithril" : { "index" : 7 } // TODO: move to WoG?
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: faction
|
||||
"town" : {
|
||||
"index" :98,
|
||||
"handler": "town",
|
||||
"base" : {
|
||||
"filters" : {
|
||||
// village image - fort not present
|
||||
"village" : [ "noneOf", [ "fort" ] ],
|
||||
// fort image - fort is here but not capitol
|
||||
"fort" : [ "allOf", [ "fort" ], [ "noneOf", ["capitol" ] ] ],
|
||||
// capitol image only when capitol is built
|
||||
"capitol" : [ "capitol" ]
|
||||
},
|
||||
|
||||
// "faction" : "stringID", // should be set by engine
|
||||
"base" : {
|
||||
"visitableFrom" : [ "---", "+++", "+++" ],
|
||||
"mask" : [
|
||||
"VVVVVV", // a LOT of just visible rows due to towns like Tower
|
||||
"VVVVVV",
|
||||
"VVVVVV",
|
||||
"VVBBBV",
|
||||
"VBBBBB",
|
||||
"VBBABB"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: one of 3 possible boats
|
||||
"boat" : {
|
||||
"index" :8,
|
||||
"handler": "boat",
|
||||
"base" : {
|
||||
"base" : {
|
||||
"visitableFrom" : [ "+++", "+-+", "+++" ],
|
||||
"mask" : [ "VVV", "VAV" ]
|
||||
}
|
||||
},
|
||||
"types" : {
|
||||
"evil" : { "index" : 0 },
|
||||
"good" : { "index" : 1 },
|
||||
"neutral" : { "index" : 2 },
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: color of guard
|
||||
"borderGuard" : {
|
||||
"index" :9,
|
||||
"handler": "borderGuard",
|
||||
"types" : {
|
||||
"lblue" : { "index" : 0 },
|
||||
"green" : { "index" : 1 },
|
||||
"red" : { "index" : 2 },
|
||||
"dblue" : { "index" : 3 },
|
||||
"brown" : { "index" : 4 },
|
||||
"purple" : { "index" : 5 },
|
||||
"white" : { "index" : 6 },
|
||||
"black" : { "index" : 7 }
|
||||
}
|
||||
},
|
||||
"borderGate" : {
|
||||
"index" :212,
|
||||
"handler": "borderGate",
|
||||
"types" : {
|
||||
"lblue" : { "index" : 0 },
|
||||
"green" : { "index" : 1 },
|
||||
"red" : { "index" : 2 },
|
||||
"dblue" : { "index" : 3 },
|
||||
"brown" : { "index" : 4 },
|
||||
"purple" : { "index" : 5 },
|
||||
"white" : { "index" : 6 },
|
||||
"black" : { "index" : 7 }
|
||||
}
|
||||
},
|
||||
"keymasterTent" : {
|
||||
"index" :10,
|
||||
"handler": "keymaster",
|
||||
"types" : {
|
||||
"lblue" : { "index" : 0 },
|
||||
"green" : { "index" : 1 },
|
||||
"red" : { "index" : 2 },
|
||||
"dblue" : { "index" : 3 },
|
||||
"brown" : { "index" : 4 },
|
||||
"purple" : { "index" : 5 },
|
||||
"white" : { "index" : 6 },
|
||||
"black" : { "index" : 7 }
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: different revealed areas
|
||||
"cartographer" : {
|
||||
"index" :13,
|
||||
"handler": "cartographer",
|
||||
"types" : {
|
||||
"water" : { "index" : 0 },
|
||||
"land" : { "index" : 1 },
|
||||
"subterra" : { "index" : 2 }
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: resource ID
|
||||
"mine" : {
|
||||
"index" :53,
|
||||
"handler": "mine",
|
||||
"types" : {
|
||||
"sawmill" : { "index" : 0 },
|
||||
"alchemistLab" : { "index" : 1 },
|
||||
"orePit" : { "index" : 2 },
|
||||
"sulfurDune" : { "index" : 3 },
|
||||
"crystalCavern" : { "index" : 4 },
|
||||
"gemPond" : { "index" : 5 },
|
||||
"goldMine" : { "index" : 6 },
|
||||
}
|
||||
},
|
||||
"abandonedMine" : {
|
||||
"index" :220,
|
||||
"handler": "mine",
|
||||
"types" : {
|
||||
"mine" : { "index" : 7 }
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: 0 = normal, 1 = anti-magic
|
||||
"garrisonHorizontal" : { "index" :33, "handler": "garrison" },
|
||||
"garrisonVertical" : { "index" :219, "handler": "garrison" },
|
||||
|
||||
// Subtype: paired monoliths
|
||||
"monolithOneWayEntrance" : { "index" :43, "handler": "teleport" },
|
||||
"monolithOneWayExit" : { "index" :44, "handler": "teleport" },
|
||||
"monolithTwoWay" : { "index" :45, "handler": "teleport" },
|
||||
|
||||
// subtype: different appearance. That's all?
|
||||
"seerHut" : { "index" :83, "handler": "seerHut" },
|
||||
|
||||
// subtype: level
|
||||
"randomDwellingLvl" : { "index" :217, "handler": "dwelling" },
|
||||
|
||||
// subtype: faction ID
|
||||
"randomDwellingFaction" : { "index" :218, "handler": "dwelling" },
|
||||
|
||||
// don't have subtypes (at least now), but closely connected to this objects
|
||||
"spellScroll" : { "index" :93, "handler": "artifact" },
|
||||
"heroPlaceholder" : { "index" :214, "handler": "heroPlaceholder" }
|
||||
}
|
44
config/objects/rewardable.json
Normal file
44
config/objects/rewardable.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
/// These are objects that covered by concept of "configurable object"
|
||||
/// Most or even all of their configuration located in this file
|
||||
"magicSpring" : { "index" :48, "handler": "magicSpring" },
|
||||
|
||||
"mysticalGarden" : { "index" :55, "handler": "oncePerWeek" },
|
||||
"windmill" : { "index" :112, "handler": "oncePerWeek" },
|
||||
"waterWheel" : { "index" :109, "handler": "oncePerWeek" },
|
||||
|
||||
"leanTo" : { "index" :39, "handler": "onceVisitable" },
|
||||
"corpse" : { "index" :22, "handler": "onceVisitable" },
|
||||
"wagon" : { "index" :105, "handler": "onceVisitable" },
|
||||
"warriorTomb" : { "index" :108, "handler": "onceVisitable" },
|
||||
|
||||
"campfire" : { "index" :12, "handler": "pickable" },
|
||||
"flotsam" : { "index" :29, "handler": "pickable" },
|
||||
"seaChest" : { "index" :82, "handler": "pickable" },
|
||||
"shipwreckSurvivor" : { "index" :86, "handler": "pickable" },
|
||||
"treasureChest" : { "index" :101, "handler": "pickable" },
|
||||
|
||||
"arena" : { "index" :4, "handler": "oncePerHero" },
|
||||
"marlettoTower" : { "index" :23, "handler": "oncePerHero" },
|
||||
"gardenOfRevelation" : { "index" :32, "handler": "oncePerHero" },
|
||||
"libraryOfEnlightenment" : { "index" :41, "handler": "oncePerHero" },
|
||||
"mercenaryCamp" : { "index" :51, "handler": "oncePerHero" },
|
||||
"starAxis" : { "index" :61, "handler": "oncePerHero" },
|
||||
"learningStone" : { "index" :100, "handler": "oncePerHero" },
|
||||
"treeOfKnowledge" : { "index" :102, "handler": "oncePerHero" },
|
||||
"schoolOfMagic" : { "index" :47, "handler": "oncePerHero" },
|
||||
"schoolOfWar" : { "index" :107, "handler": "oncePerHero" },
|
||||
|
||||
"buoy" : { "index" :11, "handler": "bonusingObject" },
|
||||
"swanPond" : { "index" :14, "handler": "bonusingObject" },
|
||||
"faerieRing" : { "index" :28, "handler": "bonusingObject" },
|
||||
"fountainOfFortune" : { "index" :30, "handler": "bonusingObject" },
|
||||
"fountainOfYouth" : { "index" :31, "handler": "bonusingObject" },
|
||||
"idolOfFortune" : { "index" :38, "handler": "bonusingObject" },
|
||||
"mermaids" : { "index" :52, "handler": "bonusingObject" },
|
||||
"oasis" : { "index" :56, "handler": "bonusingObject" },
|
||||
"stables" : { "index" :94, "handler": "bonusingObject" },
|
||||
"temple" : { "index" :96, "handler": "bonusingObject" },
|
||||
"rallyFlag" : { "index" :64, "handler": "bonusingObject" },
|
||||
"wateringHole" : { "index" :110, "handler": "bonusingObject" },
|
||||
}
|
@ -104,46 +104,16 @@
|
||||
"type":"object",
|
||||
"additionalProperties" : false,
|
||||
"required" : [
|
||||
"adventureMap", "buildingsIcons", "buildings", "creatures", "guildWindow", "names",
|
||||
"mapObject", "buildingsIcons", "buildings", "creatures", "guildWindow", "names",
|
||||
"hallBackground", "hallSlots", "horde", "mageGuild", "moatDamage", "defaultTavern", "tavernVideo", "guildBackground", "musicTheme", "siege", "structures", "townBackground", "warMachine"
|
||||
],
|
||||
"description": "town",
|
||||
"properties":{
|
||||
"adventureMap": {
|
||||
"type":"object",
|
||||
"additionalProperties" : false,
|
||||
"description": "Paths to images of object on adventure map",
|
||||
"required" : [ "capitol", "castle", "village" ],
|
||||
"properties":{
|
||||
"capitol": {
|
||||
"type":"string",
|
||||
"description": "Town with capitol",
|
||||
"format" : "defFile"
|
||||
},
|
||||
"castle": {
|
||||
"type":"string",
|
||||
"description": "Town with built fort",
|
||||
"format" : "defFile"
|
||||
},
|
||||
"village": {
|
||||
"type":"string",
|
||||
"description": "Village without built fort",
|
||||
"format" : "defFile"
|
||||
},
|
||||
"dwellings" : {
|
||||
"type" : "array",
|
||||
"minItems" : 7,
|
||||
"maxItems" : 7,
|
||||
"description" : "Dwellings on adventure map",
|
||||
"items" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"required" : [ "name", "graphics" ],
|
||||
"properties" : {
|
||||
"name": { "type":"string" },
|
||||
"graphics": { "type":"string", "format" : "defFile" }
|
||||
}
|
||||
}
|
||||
"mapObject" : {
|
||||
"properties" : {
|
||||
"filters" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : { "type" : "array" }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -6,7 +6,7 @@
|
||||
"required" : [
|
||||
"animation", "faction", "highLevelChance", "lowLevelChance",
|
||||
"name", "primarySkills", "secondarySkills", "tavern", "defaultTavern",
|
||||
"affinity", "commander"
|
||||
"affinity", "commander", "mapObject"
|
||||
],
|
||||
|
||||
"additionalProperties" : false,
|
||||
@ -15,7 +15,7 @@
|
||||
"type":"object",
|
||||
"additionalProperties" : false,
|
||||
"description": "Files related to hero animation",
|
||||
"required": [ "battle", "map" ],
|
||||
"required": [ "battle" ],
|
||||
"properties":{
|
||||
"battle": {
|
||||
"type":"object",
|
||||
@ -34,24 +34,14 @@
|
||||
"format" : "defFile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"map": {
|
||||
"type":"object",
|
||||
"additionalProperties" : false,
|
||||
"description": "Hero animations for adventure map",
|
||||
"required": [ "female", "male" ],
|
||||
"properties":{
|
||||
"female": {
|
||||
"type":"string",
|
||||
"description": "Female version. Warning: not implemented!",
|
||||
"format" : "defFile"
|
||||
},
|
||||
"male": {
|
||||
"type":"string",
|
||||
"description": "Male version",
|
||||
"format" : "defFile"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mapObject" : {
|
||||
"properties" : {
|
||||
"filters" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : { "type" : "array" }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
31
config/schemas/object.json
Normal file
31
config/schemas/object.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"type":"object",
|
||||
"$schema": "http://json-schema.org/draft-04/schema",
|
||||
"title" : "VCMI map object format",
|
||||
"description" : "Description of map object class",
|
||||
"required": [ "handler", "name" ],
|
||||
"additionalProperties" : false,
|
||||
|
||||
"properties":{
|
||||
"index": {
|
||||
"type":"number",
|
||||
},
|
||||
"name": {
|
||||
"type":"string",
|
||||
},
|
||||
|
||||
"handler": {
|
||||
"type":"string",
|
||||
},
|
||||
|
||||
"base": {
|
||||
"type" : "object"
|
||||
},
|
||||
"types": {
|
||||
"type":"object",
|
||||
"additionalProperties": {
|
||||
"$ref" : "vcmi:objectType"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,18 +3,10 @@
|
||||
"$schema": "http://json-schema.org/draft-04/schema",
|
||||
"title" : "VCMI map object template format",
|
||||
"description" : "Description of map object tempate that describes appearence of object instance",
|
||||
"required": ["basebase", "base", "animation", "mask" ],
|
||||
"required": [ "animation", "mask" ],
|
||||
|
||||
"additionalProperties" : false,
|
||||
"properties":{
|
||||
"basebase": {
|
||||
"type" : "number",
|
||||
"description": "Base object type, e.g. town or hero"
|
||||
},
|
||||
"base": {
|
||||
"type" : "number",
|
||||
"description": "Object subtype, e.g. Castle, Rampart, Cleric, Demon"
|
||||
},
|
||||
"animation": {
|
||||
"type" : "string",
|
||||
"description": "Path to def file with animation of this object",
|
||||
|
27
config/schemas/objectType.json
Normal file
27
config/schemas/objectType.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"type":"object",
|
||||
"$schema": "http://json-schema.org/draft-04/schema",
|
||||
"title" : "VCMI map object type format",
|
||||
"description" : "Description of map object type, used only as sub-schema of object",
|
||||
"required": [ ],
|
||||
"additionalProperties" : true, // may have type-dependant properties
|
||||
|
||||
"properties":{
|
||||
"index": {
|
||||
"type":"number",
|
||||
},
|
||||
"name": {
|
||||
"type":"string",
|
||||
},
|
||||
|
||||
"base": {
|
||||
"type" : "object"
|
||||
},
|
||||
"templates": {
|
||||
"type":"object",
|
||||
"additionalProperties": {
|
||||
"$ref" : "vcmi:objectTemplate"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <numeric>
|
||||
#include "VCMI_Lib.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
#include "CHeroHandler.h"
|
||||
#include "CCreatureHandler.h"
|
||||
#include "CSpellHandler.h"
|
||||
|
@ -4,12 +4,14 @@
|
||||
#include "BattleHex.h"
|
||||
#include "HeroBonus.h"
|
||||
#include "CCreatureSet.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "mapObjects/CGTownInstance.h"
|
||||
#include "mapObjects/CGHeroInstance.h"
|
||||
#include "CCreatureHandler.h"
|
||||
#include "CObstacleInstance.h"
|
||||
#include "ConstTransitivePtr.h"
|
||||
#include "GameConstants.h"
|
||||
#include "CBattleCallback.h"
|
||||
#include "int3.h"
|
||||
|
||||
/*
|
||||
* BattleState.h, part of VCMI engine
|
||||
|
@ -16,11 +16,13 @@
|
||||
#include "VCMI_Lib.h"
|
||||
#include "CModHandler.h"
|
||||
#include "CSpellHandler.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "mapObjects/MapObjects.h"
|
||||
#include "NetPacksBase.h"
|
||||
#include "GameConstants.h"
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
// Note: list must match entries in ArtTraits.txt
|
||||
@ -260,12 +262,21 @@ CArtifact * CArtHandler::loadFromJson(const JsonNode & node)
|
||||
return art;
|
||||
}
|
||||
|
||||
void CArtHandler::addSlot(CArtifact * art, const std::string & slotID)
|
||||
ArtifactPosition CArtHandler::stringToSlot(std::string slotName)
|
||||
{
|
||||
#define ART_POS(x) ( #x, ArtifactPosition::x )
|
||||
static const std::map<std::string, ArtifactPosition> artifactPositionMap = boost::assign::map_list_of ART_POS_LIST;
|
||||
#undef ART_POS
|
||||
auto it = artifactPositionMap.find (slotName);
|
||||
if (it != artifactPositionMap.end())
|
||||
return it->second;
|
||||
|
||||
logGlobal->warnStream() << "Warning! Artifact slot " << slotName << " not recognized!";
|
||||
return ArtifactPosition::PRE_FIRST;
|
||||
}
|
||||
|
||||
void CArtHandler::addSlot(CArtifact * art, const std::string & slotID)
|
||||
{
|
||||
if (slotID == "MISC")
|
||||
{
|
||||
art->possibleSlots[ArtBearer::HERO] += ArtifactPosition::MISC1, ArtifactPosition::MISC2, ArtifactPosition::MISC3, ArtifactPosition::MISC4, ArtifactPosition::MISC5;
|
||||
@ -276,14 +287,9 @@ void CArtHandler::addSlot(CArtifact * art, const std::string & slotID)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = artifactPositionMap.find (slotID);
|
||||
if (it != artifactPositionMap.end())
|
||||
{
|
||||
auto slot = it->second;
|
||||
auto slot = stringToSlot(slotID);
|
||||
if (slot != ArtifactPosition::PRE_FIRST)
|
||||
art->possibleSlots[ArtBearer::HERO].push_back (slot);
|
||||
}
|
||||
else
|
||||
logGlobal->warnStream() << "Warning! Artifact slot " << slotID << " not recognized!";
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,7 +307,7 @@ void CArtHandler::loadSlots(CArtifact * art, const JsonNode & node)
|
||||
}
|
||||
}
|
||||
|
||||
void CArtHandler::loadClass(CArtifact * art, const JsonNode & node)
|
||||
CArtifact::EartClass CArtHandler::stringToClass(std::string className)
|
||||
{
|
||||
static const std::map<std::string, CArtifact::EartClass> artifactClassMap = boost::assign::map_list_of
|
||||
("TREASURE", CArtifact::ART_TREASURE)
|
||||
@ -310,16 +316,17 @@ void CArtHandler::loadClass(CArtifact * art, const JsonNode & node)
|
||||
("RELIC", CArtifact::ART_RELIC)
|
||||
("SPECIAL", CArtifact::ART_SPECIAL);
|
||||
|
||||
auto it = artifactClassMap.find (node["class"].String());
|
||||
auto it = artifactClassMap.find (className);
|
||||
if (it != artifactClassMap.end())
|
||||
{
|
||||
art->aClass = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->warnStream() << "Warning! Artifact rarity " << node["class"].String() << " not recognized!";
|
||||
art->aClass = CArtifact::ART_SPECIAL;
|
||||
}
|
||||
return it->second;
|
||||
|
||||
logGlobal->warnStream() << "Warning! Artifact rarity " << className << " not recognized!";
|
||||
return CArtifact::ART_SPECIAL;
|
||||
}
|
||||
|
||||
void CArtHandler::loadClass(CArtifact * art, const JsonNode & node)
|
||||
{
|
||||
art->aClass = stringToClass(node["class"].String());
|
||||
}
|
||||
|
||||
void CArtHandler::loadType(CArtifact * art, const JsonNode & node)
|
||||
@ -422,7 +429,7 @@ CreatureID CArtHandler::machineIDToCreature(ArtifactID id)
|
||||
return CreatureID::NONE; //this artifact is not a creature
|
||||
}
|
||||
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts)
|
||||
{
|
||||
auto getAllowedArts = [&](std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, CArtifact::EartClass flag)
|
||||
{
|
||||
@ -431,8 +438,11 @@ ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
|
||||
for (auto & arts_i : *arts)
|
||||
{
|
||||
CArtifact *art = arts_i;
|
||||
out.push_back(art);
|
||||
if (accepts(arts_i->id))
|
||||
{
|
||||
CArtifact *art = arts_i;
|
||||
out.push_back(art);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -467,6 +477,16 @@ ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
return artID;
|
||||
}
|
||||
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts)
|
||||
{
|
||||
return pickRandomArtifact(rand, 0xff, accepts);
|
||||
}
|
||||
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
{
|
||||
return pickRandomArtifact(rand, flags, [](ArtifactID){ return true;});
|
||||
}
|
||||
|
||||
Bonus *createBonus(Bonus::BonusType type, int val, int subtype, Bonus::ValueType valType, shared_ptr<ILimiter> limiter = shared_ptr<ILimiter>(), int additionalInfo = 0)
|
||||
{
|
||||
auto added = new Bonus(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,-1,subtype);
|
||||
@ -647,20 +667,22 @@ void CArtHandler::afterLoadFinalization()
|
||||
}
|
||||
}
|
||||
|
||||
//Note: "10" is used here because H3 text files don't define any template for art with ID 0
|
||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::ARTIFACT, 10).front();
|
||||
for (CArtifact * art : artifacts)
|
||||
{
|
||||
VLC->objtypeh->loadSubObject(art->Name(), JsonNode(), Obj::ARTIFACT, art->id.num);
|
||||
|
||||
if (!art->advMapDef.empty())
|
||||
{
|
||||
base.animationFile = art->advMapDef;
|
||||
base.subid = art->id;
|
||||
JsonNode templ;
|
||||
templ["animation"].String() = art->advMapDef;
|
||||
|
||||
// replace existing (if any) and add new template.
|
||||
// add new template.
|
||||
// Necessary for objects added via mods that don't have any templates in H3
|
||||
VLC->dobjinfo->eraseAll(Obj::ARTIFACT, art->id);
|
||||
VLC->dobjinfo->registerTemplate(base);
|
||||
VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, art->id)->addTemplate(templ);
|
||||
}
|
||||
// object does not have any templates - this is not usable object (e.g. pseudo-art like lock)
|
||||
if (VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, art->id)->getTemplates().empty())
|
||||
VLC->objtypeh->removeSubObject(Obj::ARTIFACT, art->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,11 +203,17 @@ public:
|
||||
|
||||
boost::optional<std::vector<CArtifact*>&> listFromClass(CArtifact::EartClass artifactClass);
|
||||
|
||||
ArtifactPosition stringToSlot(std::string slotName);
|
||||
CArtifact::EartClass stringToClass(std::string className);
|
||||
|
||||
/// Gets a artifact ID randomly and removes the selected artifact from this handler.
|
||||
ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags);
|
||||
ArtifactID pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts);
|
||||
ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts);
|
||||
|
||||
bool legalArtifact(ArtifactID id);
|
||||
void getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag);
|
||||
void getAllowed(std::vector<ConstTransitivePtr<CArtifact> > &out, int flags);
|
||||
//void getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag);
|
||||
//void getAllowed(std::vector<ConstTransitivePtr<CArtifact> > &out, int flags);
|
||||
bool isBigArtifact (ArtifactID artID) const {return bigArtifacts.find(artID) != bigArtifacts.end();}
|
||||
void initAllowedArtifactsList(const std::vector<bool> &allowed); //allowed[art_id] -> 0 if not allowed, 1 if allowed
|
||||
static ArtifactID creatureToMachineID(CreatureID id);
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "CModHandler.h"
|
||||
#include "StringConstants.h"
|
||||
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
/*
|
||||
@ -1114,19 +1116,19 @@ void CCreatureHandler::buildBonusTreeForTiers()
|
||||
|
||||
void CCreatureHandler::afterLoadFinalization()
|
||||
{
|
||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::MONSTER, 0).front();
|
||||
for (CCreature * crea : creatures)
|
||||
{
|
||||
VLC->objtypeh->loadSubObject(crea->nameSing, JsonNode(), Obj::MONSTER, crea->idNumber.num);
|
||||
if (!crea->advMapDef.empty())
|
||||
{
|
||||
base.animationFile = crea->advMapDef;
|
||||
base.subid = crea->idNumber;
|
||||
|
||||
// replace existing (if any) and add new template.
|
||||
// Necessary for objects added via mods that don't have any templates in H3
|
||||
VLC->dobjinfo->eraseAll(Obj::MONSTER, crea->idNumber);
|
||||
VLC->dobjinfo->registerTemplate(base);
|
||||
JsonNode templ;
|
||||
templ["animation"].String() = crea->advMapDef;
|
||||
VLC->objtypeh->getHandlerFor(Obj::MONSTER, crea->idNumber)->addTemplate(templ);
|
||||
}
|
||||
|
||||
// object does not have any templates - this is not usable object (e.g. pseudo-creature like Arrow Tower)
|
||||
if (VLC->objtypeh->getHandlerFor(Obj::MONSTER, crea->idNumber.num)->getTemplates().empty())
|
||||
VLC->objtypeh->removeSubObject(Obj::MONSTER, crea->idNumber.num);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "CCreatureHandler.h"
|
||||
#include "VCMI_Lib.h"
|
||||
#include "CModHandler.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "mapObjects/CGHeroInstance.h"
|
||||
#include "IGameCallback.h"
|
||||
#include "CGameState.h"
|
||||
#include "CGeneralTextHandler.h"
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "CGameInfoCallback.h"
|
||||
|
||||
#include "CGameState.h" // PlayerState
|
||||
#include "CObjectHandler.h" // for CGObjectInstance
|
||||
#include "mapObjects/CObjectHandler.h" // for CGObjectInstance
|
||||
#include "StartInfo.h" // for StartInfo
|
||||
#include "BattleState.h" // for BattleInfo
|
||||
#include "NetPacks.h" // for InfoWindow
|
||||
|
7163
lib/CGameState.cpp
7163
lib/CGameState.cpp
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,6 @@
|
||||
#include "IGameCallback.h"
|
||||
#include "ResourceSet.h"
|
||||
#include "int3.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
@ -167,6 +166,7 @@ public:
|
||||
ObjectInstanceID currentSelection; //id of hero/town, 0xffffffff if none
|
||||
TeamID team;
|
||||
TResources resources;
|
||||
std::set<ObjectInstanceID> visitedObjects; // as a std::set, since most accesses here will be from visited status checks
|
||||
std::vector<ConstTransitivePtr<CGHeroInstance> > heroes;
|
||||
std::vector<ConstTransitivePtr<CGTownInstance> > towns;
|
||||
std::vector<ConstTransitivePtr<CGHeroInstance> > availableHeroes; //heroes available in taverns
|
||||
@ -183,7 +183,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & color & human & currentSelection & team & resources & status;
|
||||
h & heroes & towns & availableHeroes & dwellings;
|
||||
h & heroes & towns & availableHeroes & dwellings & visitedObjects;
|
||||
h & getBonusList(); //FIXME FIXME FIXME
|
||||
h & status & daysWithoutCastle;
|
||||
h & enteredLosingCheatCode & enteredWinningCheatCode;
|
||||
|
@ -287,7 +287,6 @@ CGeneralTextHandler::CGeneralTextHandler()
|
||||
readToVector("DATA/HEROSCRN.TXT", heroscrn);
|
||||
readToVector("DATA/TENTCOLR.TXT", tentColors);
|
||||
readToVector("DATA/SKILLLEV.TXT", levels);
|
||||
readToVector("DATA/OBJNAMES.TXT", names);
|
||||
|
||||
localizedTexts = JsonNode(ResourceID("config/translate.json", EResType::TEXT));
|
||||
|
||||
|
@ -112,7 +112,6 @@ public:
|
||||
std::vector<std::string> victoryConditions;
|
||||
|
||||
//objects
|
||||
std::vector<std::string> names; //vector of objects; i-th object in vector has subnumber i
|
||||
std::vector<std::string> creGens; //names of creatures' generators
|
||||
std::vector<std::string> creGens4; //names of multiple creatures' generators
|
||||
std::vector<std::string> advobtxt;
|
||||
|
@ -10,9 +10,11 @@
|
||||
#include "CCreatureHandler.h"
|
||||
#include "CModHandler.h"
|
||||
#include "CTownHandler.h"
|
||||
#include "CObjectHandler.h" //for hero specialty
|
||||
#include "mapObjects/CObjectHandler.h" //for hero specialty
|
||||
#include <math.h>
|
||||
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
/*
|
||||
* CHeroHandler.cpp, part of VCMI engine
|
||||
*
|
||||
@ -102,6 +104,7 @@ CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node)
|
||||
|
||||
heroClass->imageBattleFemale = node["animation"]["battle"]["female"].String();
|
||||
heroClass->imageBattleMale = node["animation"]["battle"]["male"].String();
|
||||
//MODS COMPATIBILITY FOR 0.96
|
||||
heroClass->imageMapFemale = node["animation"]["map"]["female"].String();
|
||||
heroClass->imageMapMale = node["animation"]["map"]["male"].String();
|
||||
|
||||
@ -200,6 +203,14 @@ void CHeroClassHandler::loadObject(std::string scope, std::string name, const Js
|
||||
|
||||
heroClasses.push_back(object);
|
||||
|
||||
VLC->modh->identifiers.requestIdentifier(scope, "object", "hero", [=](si32 index)
|
||||
{
|
||||
JsonNode classConf;
|
||||
classConf["heroClass"].String() = name;
|
||||
classConf.setMeta(scope);
|
||||
VLC->objtypeh->loadSubObject(name, classConf, index, object->id);
|
||||
});
|
||||
|
||||
VLC->modh->identifiers.registerObject(scope, "heroClass", name, object->id);
|
||||
}
|
||||
|
||||
@ -211,6 +222,14 @@ void CHeroClassHandler::loadObject(std::string scope, std::string name, const Js
|
||||
assert(heroClasses[index] == nullptr); // ensure that this id was not loaded before
|
||||
heroClasses[index] = object;
|
||||
|
||||
VLC->modh->identifiers.requestIdentifier(scope, "object", "hero", [=](si32 index)
|
||||
{
|
||||
JsonNode classConf = data["mapObject"];
|
||||
classConf["heroClass"].String() = name;
|
||||
classConf.setMeta(scope);
|
||||
VLC->objtypeh->loadSubObject(name, classConf, index, object->id);
|
||||
});
|
||||
|
||||
VLC->modh->identifiers.registerObject(scope, "heroClass", name, object->id);
|
||||
}
|
||||
|
||||
@ -231,16 +250,14 @@ void CHeroClassHandler::afterLoadFinalization()
|
||||
}
|
||||
}
|
||||
|
||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::HERO, 0).front();
|
||||
for (CHeroClass * hc : heroClasses)
|
||||
{
|
||||
base.animationFile = hc->imageMapMale;
|
||||
base.subid = hc->id;
|
||||
|
||||
// replace existing (if any) and add new template.
|
||||
// Necessary for objects added via mods that don't have any templates in H3
|
||||
VLC->dobjinfo->eraseAll(Obj::HERO, hc->id);
|
||||
VLC->dobjinfo->registerTemplate(base);
|
||||
if (!hc->imageMapMale.empty())
|
||||
{
|
||||
JsonNode templ;
|
||||
templ["animation"].String() = hc->imageMapMale;
|
||||
VLC->objtypeh->getHandlerFor(Obj::HERO, hc->id)->addTemplate(templ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,20 +6,6 @@ include_directories(${Boost_INCLUDE_DIRS} ${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}
|
||||
|
||||
set(lib_SRCS
|
||||
StdInc.cpp
|
||||
IGameCallback.cpp
|
||||
CGameInfoCallback.cpp
|
||||
CGameState.cpp
|
||||
CObjectHandler.cpp
|
||||
Connection.cpp
|
||||
NetPacksLib.cpp
|
||||
|
||||
registerTypes/RegisterTypes.cpp
|
||||
registerTypes/TypesClientPacks1.cpp
|
||||
registerTypes/TypesClientPacks2.cpp
|
||||
registerTypes/TypesMapObjects1.cpp
|
||||
registerTypes/TypesMapObjects2.cpp
|
||||
registerTypes/TypesPregamePacks.cpp
|
||||
registerTypes/TypesServerPacks.cpp
|
||||
|
||||
filesystem/AdapterLoaders.cpp
|
||||
filesystem/CCompressedStream.cpp
|
||||
@ -33,6 +19,22 @@ set(lib_SRCS
|
||||
filesystem/Filesystem.cpp
|
||||
filesystem/ResourceID.cpp
|
||||
|
||||
mapObjects/CArmedInstance.cpp
|
||||
mapObjects/CBank.cpp
|
||||
mapObjects/CGHeroInstance.cpp
|
||||
mapObjects/CGMarket.cpp
|
||||
mapObjects/CGPandoraBox.cpp
|
||||
mapObjects/CGTownInstance.cpp
|
||||
mapObjects/CObjectClassesHandler.cpp
|
||||
mapObjects/CObjectHandler.cpp
|
||||
mapObjects/CommonConstructors.cpp
|
||||
mapObjects/CQuest.cpp
|
||||
mapObjects/CRewardableConstructor.cpp
|
||||
mapObjects/CRewardableObject.cpp
|
||||
mapObjects/JsonRandom.cpp
|
||||
mapObjects/MiscObjects.cpp
|
||||
mapObjects/ObjectTemplate.cpp
|
||||
|
||||
logging/CBasicLogConfigurator.cpp
|
||||
logging/CLogger.cpp
|
||||
|
||||
@ -63,7 +65,6 @@ set(lib_SRCS
|
||||
CConsoleHandler.cpp
|
||||
CCreatureHandler.cpp
|
||||
CCreatureSet.cpp
|
||||
CDefObjInfoHandler.cpp
|
||||
CGameInterface.cpp
|
||||
CGeneralTextHandler.cpp
|
||||
CHeroHandler.cpp
|
||||
@ -81,6 +82,20 @@ set(lib_SRCS
|
||||
ResourceSet.cpp
|
||||
VCMI_Lib.cpp
|
||||
VCMIDirs.cpp
|
||||
|
||||
IGameCallback.cpp
|
||||
CGameInfoCallback.cpp
|
||||
CGameState.cpp
|
||||
Connection.cpp
|
||||
NetPacksLib.cpp
|
||||
|
||||
registerTypes/RegisterTypes.cpp
|
||||
registerTypes/TypesClientPacks1.cpp
|
||||
registerTypes/TypesClientPacks2.cpp
|
||||
registerTypes/TypesMapObjects1.cpp
|
||||
registerTypes/TypesMapObjects2.cpp
|
||||
registerTypes/TypesPregamePacks.cpp
|
||||
registerTypes/TypesServerPacks.cpp
|
||||
)
|
||||
|
||||
set(lib_HEADERS
|
||||
@ -89,6 +104,9 @@ set(lib_HEADERS
|
||||
filesystem/CInputStream.h
|
||||
filesystem/ISimpleResourceLoader.h
|
||||
|
||||
mapObjects/MapObjects.h
|
||||
|
||||
CSoundBase.h
|
||||
AI_Base.h
|
||||
CondSh.h
|
||||
ConstTransitivePtr.h
|
||||
@ -118,5 +136,5 @@ set_target_properties(vcmi PROPERTIES ${PCH_PROPERTIES})
|
||||
cotire(vcmi)
|
||||
|
||||
if (NOT APPLE) # Already inside vcmiclient bundle
|
||||
install(TARGETS vcmi DESTINATION ${LIB_DIR})
|
||||
install(TARGETS vcmi DESTINATION ${LIB_DIR})
|
||||
endif()
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "StdInc.h"
|
||||
#include "CModHandler.h"
|
||||
#include "CDefObjInfoHandler.h"
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
#include "JsonNode.h"
|
||||
#include "filesystem/Filesystem.h"
|
||||
#include "filesystem/AdapterLoaders.h"
|
||||
@ -10,7 +10,7 @@
|
||||
#include "CArtHandler.h"
|
||||
#include "CTownHandler.h"
|
||||
#include "CHeroHandler.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
#include "StringConstants.h"
|
||||
#include "CStopWatch.h"
|
||||
#include "IHandlerBase.h"
|
||||
@ -26,6 +26,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
CIdentifierStorage::CIdentifierStorage():
|
||||
state(LOADING)
|
||||
{
|
||||
}
|
||||
|
||||
void CIdentifierStorage::checkIdentifier(std::string & ID)
|
||||
{
|
||||
if (boost::algorithm::ends_with(ID, "."))
|
||||
@ -81,7 +86,10 @@ void CIdentifierStorage::requestIdentifier(ObjectCallback callback)
|
||||
|
||||
assert(!callback.localScope.empty());
|
||||
|
||||
scheduledRequests.push_back(callback);
|
||||
if (state != FINISHED) // enqueue request if loading is still in progress
|
||||
scheduledRequests.push_back(callback);
|
||||
else // execute immediately for "late" requests
|
||||
resolveIdentifier(callback);
|
||||
}
|
||||
|
||||
void CIdentifierStorage::requestIdentifier(std::string scope, std::string type, std::string name, const std::function<void(si32)> & callback)
|
||||
@ -120,6 +128,19 @@ void CIdentifierStorage::tryRequestIdentifier(std::string type, const JsonNode &
|
||||
requestIdentifier(ObjectCallback(name.meta, pair.first, type, pair.second, callback, true));
|
||||
}
|
||||
|
||||
boost::optional<si32> CIdentifierStorage::getIdentifier(std::string scope, std::string type, std::string name, bool silent)
|
||||
{
|
||||
auto pair = splitString(name, ':'); // remoteScope:name
|
||||
auto idList = getPossibleIdentifiers(ObjectCallback(scope, pair.first, type, pair.second, std::function<void(si32)>(), silent));
|
||||
|
||||
if (idList.size() == 1)
|
||||
return idList.front().id;
|
||||
if (!silent)
|
||||
logGlobal->errorStream() << "Failed to resolve identifier " << name << " of type " << type << " from mod " << scope;
|
||||
|
||||
return boost::optional<si32>();
|
||||
}
|
||||
|
||||
boost::optional<si32> CIdentifierStorage::getIdentifier(std::string type, const JsonNode & name, bool silent)
|
||||
{
|
||||
auto pair = splitString(name.String(), ':'); // remoteScope:name
|
||||
@ -128,7 +149,7 @@ boost::optional<si32> CIdentifierStorage::getIdentifier(std::string type, const
|
||||
if (idList.size() == 1)
|
||||
return idList.front().id;
|
||||
if (!silent)
|
||||
logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " from mod " << type;
|
||||
logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " of type " << type << " from mod " << name.meta;
|
||||
|
||||
return boost::optional<si32>();
|
||||
}
|
||||
@ -142,7 +163,7 @@ boost::optional<si32> CIdentifierStorage::getIdentifier(const JsonNode & name, b
|
||||
if (idList.size() == 1)
|
||||
return idList.front().id;
|
||||
if (!silent)
|
||||
logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " from mod " << name.meta;
|
||||
logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " of type " << pair2.first << " from mod " << name.meta;
|
||||
|
||||
return boost::optional<si32>();
|
||||
}
|
||||
@ -210,7 +231,9 @@ bool CIdentifierStorage::resolveIdentifier(const ObjectCallback & request)
|
||||
}
|
||||
|
||||
if (request.optional && identifiers.empty()) // failed to resolve optinal ID
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// error found. Try to generate some debug info
|
||||
if (identifiers.size() == 0)
|
||||
@ -229,22 +252,25 @@ bool CIdentifierStorage::resolveIdentifier(const ObjectCallback & request)
|
||||
|
||||
void CIdentifierStorage::finalize()
|
||||
{
|
||||
state = FINALIZING;
|
||||
bool errorsFound = false;
|
||||
|
||||
for(const ObjectCallback & request : scheduledRequests)
|
||||
//Note: we may receive new requests during resolution phase -> end may change -> range for can't be used
|
||||
for(auto it = scheduledRequests.begin(); it != scheduledRequests.end(); it++)
|
||||
{
|
||||
errorsFound |= !resolveIdentifier(request);
|
||||
errorsFound |= !resolveIdentifier(*it);
|
||||
}
|
||||
|
||||
if (errorsFound)
|
||||
{
|
||||
for(auto object : registeredObjects)
|
||||
{
|
||||
logGlobal->traceStream() << object.first << " -> " << object.second.id;
|
||||
logGlobal->traceStream() << object.second.scope << " : " << object.first << " -> " << object.second.id;
|
||||
}
|
||||
logGlobal->errorStream() << "All known identifiers were dumped into log file";
|
||||
}
|
||||
assert(errorsFound == false);
|
||||
state = FINISHED;
|
||||
}
|
||||
|
||||
CContentHandler::ContentTypeHandler::ContentTypeHandler(IHandlerBase * handler, std::string objectName):
|
||||
@ -347,10 +373,11 @@ CContentHandler::CContentHandler()
|
||||
handlers.insert(std::make_pair("artifacts", ContentTypeHandler(VLC->arth, "artifact")));
|
||||
handlers.insert(std::make_pair("creatures", ContentTypeHandler(VLC->creh, "creature")));
|
||||
handlers.insert(std::make_pair("factions", ContentTypeHandler(VLC->townh, "faction")));
|
||||
handlers.insert(std::make_pair("objects", ContentTypeHandler(VLC->objtypeh, "object")));
|
||||
handlers.insert(std::make_pair("heroes", ContentTypeHandler(VLC->heroh, "hero")));
|
||||
handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh, "spell")));
|
||||
handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh, "spell")));
|
||||
|
||||
//TODO: bonuses, something else?
|
||||
//TODO: any other types of moddables?
|
||||
}
|
||||
|
||||
bool CContentHandler::preloadModData(std::string modName, JsonNode modConfig, bool validate)
|
||||
|
@ -25,6 +25,13 @@ class IHandlerBase;
|
||||
/// if possible, objects ID's should be in format <type>.<name>, camelCase e.g. "creature.grandElf"
|
||||
class CIdentifierStorage
|
||||
{
|
||||
enum ELoadingState
|
||||
{
|
||||
LOADING,
|
||||
FINALIZING,
|
||||
FINISHED
|
||||
};
|
||||
|
||||
struct ObjectCallback // entry created on ID request
|
||||
{
|
||||
std::string localScope; /// scope from which this ID was requested
|
||||
@ -52,6 +59,8 @@ class CIdentifierStorage
|
||||
std::multimap<std::string, ObjectData > registeredObjects;
|
||||
std::vector<ObjectCallback> scheduledRequests;
|
||||
|
||||
ELoadingState state;
|
||||
|
||||
/// Check if identifier can be valid (camelCase, point as separator)
|
||||
void checkIdentifier(std::string & ID);
|
||||
|
||||
@ -59,6 +68,7 @@ class CIdentifierStorage
|
||||
bool resolveIdentifier(const ObjectCallback & callback);
|
||||
std::vector<ObjectData> getPossibleIdentifiers(const ObjectCallback & callback);
|
||||
public:
|
||||
CIdentifierStorage();
|
||||
/// request identifier for specific object name.
|
||||
/// Function callback will be called during ID resolution phase of loading
|
||||
void requestIdentifier(std::string scope, std::string type, std::string name, const std::function<void(si32)> & callback);
|
||||
@ -70,6 +80,7 @@ public:
|
||||
void tryRequestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback);
|
||||
|
||||
/// get identifier immediately. If identifier is not know and not silent call will result in error message
|
||||
boost::optional<si32> getIdentifier(std::string scope, std::string type, std::string name, bool silent = false);
|
||||
boost::optional<si32> getIdentifier(std::string type, const JsonNode & name, bool silent = false);
|
||||
boost::optional<si32> getIdentifier(const JsonNode & name, bool silent = false);
|
||||
|
||||
@ -81,7 +92,7 @@ public:
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & registeredObjects;
|
||||
h & registeredObjects & state;
|
||||
}
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
1533
lib/CObjectHandler.h
1533
lib/CObjectHandler.h
File diff suppressed because it is too large
Load Diff
@ -11,8 +11,8 @@
|
||||
#include "CArtHandler.h"
|
||||
#include "CSpellHandler.h"
|
||||
#include "filesystem/Filesystem.h"
|
||||
#include "CDefObjInfoHandler.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
|
||||
/*
|
||||
* CTownHandler.cpp, part of VCMI engine
|
||||
@ -554,10 +554,6 @@ void CTownHandler::loadClientData(CTown &town, const JsonNode & source)
|
||||
info.tavernVideo = "TAVERN.BIK";
|
||||
//end of legacy assignment
|
||||
|
||||
info.advMapVillage = source["adventureMap"]["village"].String();
|
||||
info.advMapCastle = source["adventureMap"]["castle"].String();
|
||||
info.advMapCapitol = source["adventureMap"]["capitol"].String();
|
||||
|
||||
loadTownHall(town, source["hallSlots"]);
|
||||
loadStructures(town, source["structures"]);
|
||||
loadSiegeScreen(town, source["siege"]);
|
||||
@ -723,6 +719,8 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
|
||||
auto object = loadFromJson(data, name);
|
||||
|
||||
object->index = factions.size();
|
||||
factions.push_back(object);
|
||||
|
||||
if (object->town)
|
||||
{
|
||||
auto & info = object->town->clientInfo;
|
||||
@ -730,9 +728,16 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
|
||||
info.icons[0][1] = 8 + object->index * 4 + 1;
|
||||
info.icons[1][0] = 8 + object->index * 4 + 2;
|
||||
info.icons[1][1] = 8 + object->index * 4 + 3;
|
||||
}
|
||||
|
||||
factions.push_back(object);
|
||||
VLC->modh->identifiers.requestIdentifier(scope, "object", "town", [=](si32 index)
|
||||
{
|
||||
// register town once objects are loaded
|
||||
JsonNode config = data["town"]["mapObject"];
|
||||
config["faction"].String() = object->identifier;
|
||||
config["faction"].meta = scope;
|
||||
VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
|
||||
});
|
||||
}
|
||||
|
||||
VLC->modh->identifiers.registerObject(scope, "faction", name, object->index);
|
||||
}
|
||||
@ -741,6 +746,9 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
|
||||
{
|
||||
auto object = loadFromJson(data, name);
|
||||
object->index = index;
|
||||
assert(factions[index] == nullptr); // ensure that this id was not loaded before
|
||||
factions[index] = object;
|
||||
|
||||
if (object->town)
|
||||
{
|
||||
auto & info = object->town->clientInfo;
|
||||
@ -748,10 +756,25 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
|
||||
info.icons[0][1] = (GameConstants::F_NUMBER + object->index) * 2 + 1;
|
||||
info.icons[1][0] = object->index * 2 + 0;
|
||||
info.icons[1][1] = object->index * 2 + 1;
|
||||
}
|
||||
|
||||
assert(factions[index] == nullptr); // ensure that this id was not loaded before
|
||||
factions[index] = object;
|
||||
VLC->modh->identifiers.requestIdentifier(scope, "object", "town", [=](si32 index)
|
||||
{
|
||||
// register town once objects are loaded
|
||||
JsonNode config = data["town"]["mapObject"];
|
||||
config["faction"].String() = object->identifier;
|
||||
config["faction"].meta = scope;
|
||||
VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
|
||||
|
||||
// MODS COMPATIBILITY FOR 0.96
|
||||
auto & advMap = data["town"]["adventureMap"];
|
||||
if (!advMap["fort"].isNull())
|
||||
{
|
||||
JsonNode config;
|
||||
config["appearance"] = advMap["fort"];
|
||||
VLC->objtypeh->getHandlerFor(index, object->index)->addTemplate(config);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
VLC->modh->identifiers.registerObject(scope, "faction", name, object->index);
|
||||
}
|
||||
@ -759,38 +782,6 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
|
||||
void CTownHandler::afterLoadFinalization()
|
||||
{
|
||||
initializeRequirements();
|
||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::TOWN, 0).front();
|
||||
for (CFaction * fact : factions)
|
||||
{
|
||||
if (fact->town)
|
||||
{
|
||||
base.animationFile = fact->town->clientInfo.advMapCastle;
|
||||
base.subid = fact->index;
|
||||
|
||||
// replace existing (if any) and add new template.
|
||||
// Necessary for objects added via mods that don't have any templates in H3
|
||||
VLC->dobjinfo->eraseAll(Obj::TOWN, fact->index);
|
||||
VLC->dobjinfo->registerTemplate(base);
|
||||
|
||||
assert(fact->town->dwellings.size() == fact->town->dwellingNames.size());
|
||||
for (size_t i=0; i<fact->town->dwellings.size(); i++)
|
||||
{
|
||||
ObjectTemplate base = VLC->dobjinfo->pickCandidates(Obj::CREATURE_GENERATOR1, 0).front();
|
||||
|
||||
//both unupgraded and upgraded get same dwelling
|
||||
for (auto cre : fact->town->creatures[i])
|
||||
{
|
||||
base.subid = 80 + cre;
|
||||
base.animationFile = fact->town->dwellings[i];
|
||||
if (VLC->objh->cregens.count(cre) == 0)
|
||||
{
|
||||
VLC->dobjinfo->registerTemplate(base);
|
||||
VLC->objh->cregens[80 + cre] = cre; //map of dwelling -> creature id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTownHandler::initializeRequirements()
|
||||
@ -824,4 +815,4 @@ std::set<TFaction> CTownHandler::getAllowedFactions() const
|
||||
allowedFactions.insert(i);
|
||||
|
||||
return allowedFactions;
|
||||
}
|
||||
}
|
||||
|
@ -190,10 +190,6 @@ public:
|
||||
/// NOTE: index in vector is meaningless. Vector used instead of list for a bit faster access
|
||||
std::vector<ConstTransitivePtr<CStructure> > structures;
|
||||
|
||||
std::string advMapVillage;
|
||||
std::string advMapCastle;
|
||||
std::string advMapCapitol;
|
||||
|
||||
std::string siegePrefix;
|
||||
std::vector<Point> siegePositions;
|
||||
CreatureID siegeShooter; // shooter creature ID
|
||||
@ -201,7 +197,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & icons & iconSmall & iconLarge & tavernVideo & musicTheme & townBackground & guildBackground & guildWindow & buildingsIcons & hallBackground;
|
||||
h & advMapVillage & advMapCastle & advMapCapitol & hallSlots & structures;
|
||||
h & hallSlots & structures;
|
||||
h & siegePrefix & siegePositions & siegeShooter;
|
||||
}
|
||||
} clientInfo;
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <typeinfo> //XXX this is in namespace std if you want w/o use typeinfo.h?
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/equal_to.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
@ -24,7 +23,7 @@
|
||||
|
||||
#include "ConstTransitivePtr.h"
|
||||
#include "CCreatureSet.h" //for CStackInstance
|
||||
#include "CObjectHandler.h" //for CArmedInstance
|
||||
#include "mapObjects/CGHeroInstance.h"
|
||||
#include "mapping/CCampaignHandler.h" //for CCampaignState
|
||||
#include "rmg/CMapGenerator.h" // for CMapGenOptions
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "VCMI_Lib.h"
|
||||
#include "CDefObjInfoHandler.h"
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
#include "CArtHandler.h"
|
||||
#include "CCreatureHandler.h"
|
||||
#include "CSpellHandler.h"
|
||||
|
@ -14,9 +14,10 @@
|
||||
#include "CHeroHandler.h" // for CHeroHandler
|
||||
#include "CSpellHandler.h" // for CSpell
|
||||
#include "NetPacks.h"
|
||||
#include "CBonusTypeHandler.h" // for CBonusTypeHandler
|
||||
#include "CBonusTypeHandler.h"
|
||||
|
||||
#include "Connection.h" // for SAVEGAME_MAGIC
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
void CPrivilagedInfoCallback::getFreeTiles (std::vector<int3> &tiles) const
|
||||
{
|
||||
|
@ -737,7 +737,7 @@ void JsonUtils::mergeCopy(JsonNode & dest, JsonNode source)
|
||||
|
||||
void JsonUtils::inherit(JsonNode & descendant, const JsonNode & base)
|
||||
{
|
||||
JsonNode inheritedNode(base);
|
||||
JsonNode inheritedNode(base);
|
||||
merge(inheritedNode,descendant);
|
||||
descendant.swap(inheritedNode);
|
||||
}
|
||||
|
@ -108,19 +108,14 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & meta;
|
||||
// simple saving - save json in its string interpretation
|
||||
if (h.saving)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << *this;
|
||||
std::string str = stream.str();
|
||||
h & str;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string str;
|
||||
h & str;
|
||||
JsonNode(str.c_str(), str.size()).swap(*this);
|
||||
h & type;
|
||||
switch (type) {
|
||||
break; case DATA_NULL:
|
||||
break; case DATA_BOOL: h & data.Bool;
|
||||
break; case DATA_FLOAT: h & data.Float;
|
||||
break; case DATA_STRING: h & data.String;
|
||||
break; case DATA_VECTOR: h & data.Vector;
|
||||
break; case DATA_STRUCT: h & data.Struct;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include "NetPacksBase.h"
|
||||
|
||||
#include "BattleAction.h"
|
||||
#include "HeroBonus.h"
|
||||
#include "mapObjects/CGHeroInstance.h"
|
||||
#include "CCreatureSet.h"
|
||||
#include "mapping/CMapInfo.h"
|
||||
#include "StartInfo.h"
|
||||
@ -1022,11 +1021,10 @@ namespace ObjProperty
|
||||
BONUS_VALUE_FIRST, BONUS_VALUE_SECOND, //used in Rampart for special building that generates resources (storing resource type and quantity)
|
||||
|
||||
//creature-bank specific
|
||||
BANK_DAYCOUNTER, BANK_CLEAR_ARTIFACTS, BANK_ADD_ARTIFACT, BANK_MULTIPLIER, BANK_CONFIG_PRESET,
|
||||
BANK_CLEAR_CONFIG, BANK_INIT_ARMY, BANK_RESET,
|
||||
BANK_DAYCOUNTER, BANK_RESET, BANK_CLEAR,
|
||||
|
||||
//magic spring
|
||||
LEFT_VISITED, RIGHT_VISITED, LEFTRIGHT_CLEAR
|
||||
//object with reward
|
||||
REWARD_RESET, REWARD_SELECT
|
||||
};
|
||||
}
|
||||
|
||||
@ -1036,7 +1034,7 @@ struct SetObjectProperty : public CPackForClient//1001
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
ObjectInstanceID id;
|
||||
ui8 what; //1 - owner; 2 - blockvis; 3 - first stack count; 4 - visitors; 5 - visited; 6 - ID (if 34 then also def is replaced)
|
||||
ui8 what; // see ObjProperty enum
|
||||
ui32 val;
|
||||
SetObjectProperty(){type = 1001;};
|
||||
SetObjectProperty(ObjectInstanceID ID, ui8 What, ui32 Val):id(ID),what(What),val(Val){type = 1001;};
|
||||
@ -1053,14 +1051,44 @@ struct SetHoverName : public CPackForClient//1002
|
||||
|
||||
ObjectInstanceID id;
|
||||
MetaString name;
|
||||
SetHoverName(){type = 1002;};
|
||||
SetHoverName(ObjectInstanceID ID, MetaString& Name):id(ID),name(Name){type = 1002;};
|
||||
SetHoverName(){type = 1002;}
|
||||
SetHoverName(ObjectInstanceID ID, MetaString& Name):id(ID),name(Name){type = 1002;}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & id & name;
|
||||
}
|
||||
};
|
||||
|
||||
struct ChangeObjectVisitors : public CPackForClient // 1003
|
||||
{
|
||||
enum VisitMode
|
||||
{
|
||||
VISITOR_ADD, // mark hero as one that have visited this object
|
||||
VISITOR_REMOVE, // unmark visitor, reversed to ADD
|
||||
VISITOR_CLEAR // clear all visitors from this object (object reset)
|
||||
};
|
||||
ui32 mode; // uses VisitMode enum
|
||||
ObjectInstanceID object;
|
||||
ObjectInstanceID hero; // note: hero owner will be also marked as "visited" this object
|
||||
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
|
||||
ChangeObjectVisitors()
|
||||
{ type = 1003; }
|
||||
|
||||
ChangeObjectVisitors(ui32 mode, ObjectInstanceID object, ObjectInstanceID heroID = ObjectInstanceID(-1)):
|
||||
mode(mode),
|
||||
object(object),
|
||||
hero(heroID)
|
||||
{ type = 1003; }
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & object & hero & mode;
|
||||
}
|
||||
};
|
||||
|
||||
struct HeroLevelUp : public Query//2000
|
||||
{
|
||||
void applyCl(CClient *cl);
|
||||
|
@ -2,10 +2,10 @@
|
||||
#include "NetPacks.h"
|
||||
|
||||
#include "CGeneralTextHandler.h"
|
||||
#include "CDefObjInfoHandler.h"
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
#include "CArtHandler.h"
|
||||
#include "CHeroHandler.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
#include "CModHandler.h"
|
||||
#include "VCMI_Lib.h"
|
||||
#include "mapping/CMap.h"
|
||||
@ -229,15 +229,14 @@ DLL_LINKAGE void GiveBonus::applyGs( CGameState *gs )
|
||||
&& gs->map->objects[bonus.sid]->ID == Obj::EVENT) //it's morale/luck bonus from an event without description
|
||||
{
|
||||
descr = VLC->generaltexth->arraytxt[bonus.val > 0 ? 110 : 109]; //+/-%d Temporary until next battle"
|
||||
|
||||
// Some of(?) versions of H3 use %s here instead of %d. Try to replace both of them
|
||||
boost::replace_first(descr,"%d",boost::lexical_cast<std::string>(std::abs(bonus.val)));
|
||||
boost::replace_first(descr,"%s",boost::lexical_cast<std::string>(std::abs(bonus.val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
bdescr.toString(descr);
|
||||
}
|
||||
// Some of(?) versions of H3 use %s here instead of %d. Try to replace both of them
|
||||
boost::replace_first(descr,"%d",boost::lexical_cast<std::string>(std::abs(bonus.val)));
|
||||
boost::replace_first(descr,"%s",boost::lexical_cast<std::string>(std::abs(bonus.val)));
|
||||
}
|
||||
|
||||
DLL_LINKAGE void ChangeObjPos::applyGs( CGameState *gs )
|
||||
@ -253,6 +252,23 @@ DLL_LINKAGE void ChangeObjPos::applyGs( CGameState *gs )
|
||||
gs->map->addBlockVisTiles(obj);
|
||||
}
|
||||
|
||||
DLL_LINKAGE void ChangeObjectVisitors::applyGs( CGameState *gs )
|
||||
{
|
||||
switch (mode) {
|
||||
case VISITOR_ADD:
|
||||
gs->getHero(hero)->visitedObjects.insert(object);
|
||||
gs->getPlayer(gs->getHero(hero)->tempOwner)->visitedObjects.insert(object);
|
||||
break;
|
||||
case VISITOR_CLEAR:
|
||||
for (CGHeroInstance * hero : gs->map->allHeroes)
|
||||
hero->visitedObjects.erase(object); // remove visit info from all heroes, including those that are not present on map
|
||||
break;
|
||||
case VISITOR_REMOVE:
|
||||
gs->getHero(hero)->visitedObjects.erase(object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DLL_LINKAGE void PlayerEndsGame::applyGs( CGameState *gs )
|
||||
{
|
||||
PlayerState *p = gs->getPlayer(player);
|
||||
@ -549,7 +565,7 @@ DLL_LINKAGE void GiveHero::applyGs( CGameState *gs )
|
||||
//bonus system
|
||||
h->detachFrom(&gs->globalEffects);
|
||||
h->attachTo(gs->getPlayer(player));
|
||||
h->appearance = VLC->dobjinfo->pickCandidates(Obj::HERO, h->type->heroClass->id).front();
|
||||
h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->type->heroClass->id)->getTemplates().front();
|
||||
|
||||
gs->map->removeBlockVisTiles(h,true);
|
||||
h->setOwner(player);
|
||||
@ -590,9 +606,9 @@ DLL_LINKAGE void NewObject::applyGs( CGameState *gs )
|
||||
o->subID = subID;
|
||||
o->pos = pos;
|
||||
const TerrainTile &t = gs->map->getTile(pos);
|
||||
o->appearance = VLC->dobjinfo->pickCandidates(o->ID, o->subID, t.terType).front();
|
||||
o->appearance = VLC->objtypeh->getHandlerFor(o->ID, o->subID)->getTemplates(t.terType).front();
|
||||
id = o->id = ObjectInstanceID(gs->map->objects.size());
|
||||
o->hoverName = VLC->generaltexth->names[ID];
|
||||
o->hoverName = VLC->objtypeh->getObjectName(ID);
|
||||
|
||||
gs->map->objects.push_back(o);
|
||||
gs->map->addBlockVisTiles(o);
|
||||
|
@ -14,9 +14,9 @@
|
||||
#include "CArtHandler.h"
|
||||
#include "CBonusTypeHandler.h"
|
||||
#include "CCreatureHandler.h"
|
||||
#include "CDefObjInfoHandler.h"
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
#include "CHeroHandler.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
#include "CTownHandler.h"
|
||||
#include "CBuildingHandler.h"
|
||||
#include "CSpellHandler.h"
|
||||
@ -45,11 +45,11 @@ DLL_LINKAGE void preinitDLL(CConsoleHandler *Console)
|
||||
|
||||
DLL_LINKAGE void loadDLLClasses()
|
||||
{
|
||||
try
|
||||
//try
|
||||
{
|
||||
VLC->init();
|
||||
}
|
||||
HANDLE_EXCEPTION;
|
||||
//HANDLE_EXCEPTION;
|
||||
}
|
||||
|
||||
const IBonusTypeHandler * LibClasses::getBth() const
|
||||
@ -109,7 +109,7 @@ void LibClasses::init()
|
||||
|
||||
createHandler(objh, "Object", pomtime);
|
||||
|
||||
createHandler(dobjinfo, "Def information", pomtime);
|
||||
createHandler(objtypeh, "Object types information", pomtime);
|
||||
|
||||
createHandler(spellh, "Spell", pomtime);
|
||||
|
||||
@ -135,7 +135,7 @@ void LibClasses::clear()
|
||||
delete creh;
|
||||
delete townh;
|
||||
delete objh;
|
||||
delete dobjinfo;
|
||||
delete objtypeh;
|
||||
delete spellh;
|
||||
delete modh;
|
||||
delete bth;
|
||||
@ -152,7 +152,7 @@ void LibClasses::makeNull()
|
||||
creh = nullptr;
|
||||
townh = nullptr;
|
||||
objh = nullptr;
|
||||
dobjinfo = nullptr;
|
||||
objtypeh = nullptr;
|
||||
spellh = nullptr;
|
||||
modh = nullptr;
|
||||
bth = nullptr;
|
||||
|
@ -16,7 +16,7 @@ class CCreatureHandler;
|
||||
class CSpellHandler;
|
||||
class CBuildingHandler;
|
||||
class CObjectHandler;
|
||||
class CDefObjInfoHandler;
|
||||
class CObjectClassesHandler;
|
||||
class CTownHandler;
|
||||
class CGeneralTextHandler;
|
||||
class CModHandler;
|
||||
@ -42,7 +42,7 @@ public:
|
||||
CCreatureHandler * creh;
|
||||
CSpellHandler * spellh;
|
||||
CObjectHandler * objh;
|
||||
CDefObjInfoHandler * dobjinfo;
|
||||
CObjectClassesHandler * objtypeh;
|
||||
CTownHandler * townh;
|
||||
CGeneralTextHandler * generaltexth;
|
||||
CModHandler * modh;
|
||||
@ -60,7 +60,7 @@ public:
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & heroh & arth & creh & townh & objh & dobjinfo & spellh & modh & IS_AI_ENABLED;
|
||||
h & heroh & arth & creh & townh & objh & objtypeh & spellh & modh & IS_AI_ENABLED;
|
||||
h & bth;
|
||||
if(!h.saving)
|
||||
{
|
||||
|
128
lib/mapObjects/CArmedInstance.cpp
Normal file
128
lib/mapObjects/CArmedInstance.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* CArmedInstance.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 "CArmedInstance.h"
|
||||
|
||||
#include "../CTownHandler.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CGameState.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
void CArmedInstance::randomizeArmy(int type)
|
||||
{
|
||||
for (auto & elem : stacks)
|
||||
{
|
||||
int & randID = elem.second->idRand;
|
||||
if(randID >= 0)
|
||||
{
|
||||
int level = randID / 2;
|
||||
bool upgrade = randID % 2;
|
||||
elem.second->setType(VLC->townh->factions[type]->town->creatures[level][upgrade]);
|
||||
|
||||
randID = -1;
|
||||
}
|
||||
assert(elem.second->valid(false));
|
||||
assert(elem.second->armyObj == this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
CArmedInstance::CArmedInstance()
|
||||
{
|
||||
battle = nullptr;
|
||||
}
|
||||
|
||||
void CArmedInstance::updateMoraleBonusFromArmy()
|
||||
{
|
||||
if(!validTypes(false)) //object not randomized, don't bother
|
||||
return;
|
||||
|
||||
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
|
||||
if(!b)
|
||||
{
|
||||
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
|
||||
addNewBonus(b);
|
||||
}
|
||||
|
||||
//number of alignments and presence of undead
|
||||
std::set<TFaction> factions;
|
||||
bool hasUndead = false;
|
||||
|
||||
for(auto slot : Slots())
|
||||
{
|
||||
const CStackInstance * inst = slot.second;
|
||||
const CCreature * creature = VLC->creh->creatures[inst->getCreatureID()];
|
||||
|
||||
factions.insert(creature->faction);
|
||||
// Check for undead flag instead of faction (undead mummies are neutral)
|
||||
hasUndead |= inst->hasBonusOfType(Bonus::UNDEAD);
|
||||
}
|
||||
|
||||
size_t factionsInArmy = factions.size(); //town garrison seems to take both sets into account
|
||||
|
||||
// Take Angelic Alliance troop-mixing freedom of non-evil units into account.
|
||||
if (hasBonusOfType(Bonus::NONEVIL_ALIGNMENT_MIX))
|
||||
{
|
||||
size_t mixableFactions = 0;
|
||||
|
||||
for(TFaction f : factions)
|
||||
{
|
||||
if (VLC->townh->factions[f]->alignment != EAlignment::EVIL)
|
||||
mixableFactions++;
|
||||
}
|
||||
if (mixableFactions > 0)
|
||||
factionsInArmy -= mixableFactions - 1;
|
||||
}
|
||||
|
||||
if(factionsInArmy == 1)
|
||||
{
|
||||
b->val = +1;
|
||||
b->description = VLC->generaltexth->arraytxt[115]; //All troops of one alignment +1
|
||||
}
|
||||
else if (!factions.empty()) // no bonus from empty garrison
|
||||
{
|
||||
b->val = 2 - factionsInArmy;
|
||||
b->description = boost::str(boost::format(VLC->generaltexth->arraytxt[114]) % factionsInArmy % b->val); //Troops of %d alignments %d
|
||||
}
|
||||
boost::algorithm::trim(b->description);
|
||||
|
||||
//-1 modifier for any Undead unit in army
|
||||
const ui8 UNDEAD_MODIFIER_ID = -2;
|
||||
Bonus *undeadModifier = getBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
|
||||
if(hasUndead)
|
||||
{
|
||||
if(!undeadModifier)
|
||||
addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]));
|
||||
}
|
||||
else if(undeadModifier)
|
||||
removeBonus(undeadModifier);
|
||||
|
||||
}
|
||||
|
||||
void CArmedInstance::armyChanged()
|
||||
{
|
||||
updateMoraleBonusFromArmy();
|
||||
}
|
||||
|
||||
CBonusSystemNode * CArmedInstance::whereShouldBeAttached(CGameState *gs)
|
||||
{
|
||||
if(tempOwner < PlayerColor::PLAYER_LIMIT)
|
||||
return gs->getPlayer(tempOwner);
|
||||
else
|
||||
return &gs->globalEffects;
|
||||
}
|
||||
|
||||
CBonusSystemNode * CArmedInstance::whatShouldBeAttached()
|
||||
{
|
||||
return this;
|
||||
}
|
40
lib/mapObjects/CArmedInstance.h
Normal file
40
lib/mapObjects/CArmedInstance.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "../CCreatureSet.h"
|
||||
|
||||
/*
|
||||
* CArmedInstance.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class DLL_LINKAGE CArmedInstance: public CGObjectInstance, public CBonusSystemNode, public CCreatureSet
|
||||
{
|
||||
public:
|
||||
BattleInfo *battle; //set to the current battle, if engaged
|
||||
|
||||
void randomizeArmy(int type);
|
||||
virtual void updateMoraleBonusFromArmy();
|
||||
|
||||
void armyChanged() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// int valOfGlobalBonuses(CSelector selector) const; //used only for castle interface ???
|
||||
virtual CBonusSystemNode *whereShouldBeAttached(CGameState *gs);
|
||||
virtual CBonusSystemNode *whatShouldBeAttached();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CArmedInstance();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & static_cast<CCreatureSet&>(*this);
|
||||
}
|
||||
};
|
329
lib/mapObjects/CBank.cpp
Normal file
329
lib/mapObjects/CBank.cpp
Normal file
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* CBank.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 "CBank.h"
|
||||
|
||||
#include "../NetPacks.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CSoundBase.h"
|
||||
#include "CommonConstructors.h"
|
||||
#include "../CSpellHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
///helpers
|
||||
static std::string & visitedTxt(const bool visited)
|
||||
{
|
||||
int id = visited ? 352 : 353;
|
||||
return VLC->generaltexth->allTexts[id];
|
||||
}
|
||||
|
||||
CBank::CBank()
|
||||
{
|
||||
}
|
||||
|
||||
CBank::~CBank()
|
||||
{
|
||||
}
|
||||
|
||||
void CBank::initObj()
|
||||
{
|
||||
daycounter = 0;
|
||||
resetDuration = 0;
|
||||
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, cb->gameState()->getRandomGenerator());
|
||||
}
|
||||
|
||||
const std::string & CBank::getHoverText() const
|
||||
{
|
||||
bool visited = (bc == nullptr);
|
||||
hoverName = visitedTxt(visited); // FIXME: USE BANK_SPECIFIC NAMES
|
||||
return hoverName;
|
||||
}
|
||||
|
||||
void CBank::setConfig(const BankConfig & config)
|
||||
{
|
||||
bc.reset(new BankConfig(config));
|
||||
clear(); // remove all stacks, if any
|
||||
|
||||
for (auto & stack : config.guards)
|
||||
setCreature (SlotID(stacksCount()), stack.type->idNumber, stack.count);
|
||||
}
|
||||
|
||||
void CBank::setPropertyDer (ui8 what, ui32 val)
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case ObjProperty::BANK_DAYCOUNTER: //daycounter
|
||||
daycounter+=val;
|
||||
break;
|
||||
case ObjProperty::BANK_RESET:
|
||||
initObj();
|
||||
daycounter = 1; //yes, 1 since "today" daycounter won't be incremented
|
||||
break;
|
||||
case ObjProperty::BANK_CLEAR:
|
||||
bc.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::newTurn() const
|
||||
{
|
||||
if (bc == nullptr)
|
||||
{
|
||||
if (resetDuration != 0)
|
||||
{
|
||||
if (daycounter >= resetDuration)
|
||||
cb->setObjProperty (id, ObjProperty::BANK_RESET, 0); //daycounter 0
|
||||
else
|
||||
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 1); //daycounter++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CBank::wasVisited (PlayerColor player) const
|
||||
{
|
||||
return !bc; //FIXME: player A should not know about visit done by player B
|
||||
}
|
||||
|
||||
void CBank::onHeroVisit (const CGHeroInstance * h) const
|
||||
{
|
||||
if (bc)
|
||||
{
|
||||
int banktext = 0;
|
||||
ui16 soundID = soundBase::ROGUE;
|
||||
switch (ID)
|
||||
{
|
||||
case Obj::CREATURE_BANK:
|
||||
banktext = 32;
|
||||
break;
|
||||
case Obj::DERELICT_SHIP:
|
||||
banktext = 41;
|
||||
break;
|
||||
case Obj::DRAGON_UTOPIA:
|
||||
banktext = 47;
|
||||
break;
|
||||
case Obj::CRYPT:
|
||||
banktext = 119;
|
||||
break;
|
||||
case Obj::SHIPWRECK:
|
||||
banktext = 122;
|
||||
break;
|
||||
case Obj::PYRAMID:
|
||||
soundID = soundBase::MYSTERY;
|
||||
banktext = 105;
|
||||
break;
|
||||
}
|
||||
BlockingDialog bd (true, false);
|
||||
bd.player = h->getOwner();
|
||||
bd.soundID = soundID;
|
||||
bd.text.addTxt(MetaString::ADVOB_TXT, banktext);
|
||||
//if (ID == Obj::CREATURE_BANK)
|
||||
// bd.text.addReplacement(VLC->objh->creBanksNames[index]); // FIXME: USE BANK SPECIFIC NAMES
|
||||
cb->showBlockingDialog (&bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::GRAVEYARD;
|
||||
iw.player = h->getOwner();
|
||||
if (ID == Obj::PYRAMID) // You come upon the pyramid ... pyramid is completely empty.
|
||||
{
|
||||
iw.text << VLC->generaltexth->advobtxt[107];
|
||||
iw.components.push_back (Component (Component::LUCK, 0 , -2, 0));
|
||||
GiveBonus gb;
|
||||
gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,-2,id.getNum(),VLC->generaltexth->arraytxt[70]);
|
||||
gb.id = h->id.getNum();
|
||||
cb->giveHeroBonus(&gb);
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text << VLC->generaltexth->advobtxt[33];// This was X, now is completely empty
|
||||
//iw.text.addReplacement(VLC->objh->creBanksNames[index]); // FIXME: USE BANK SPECIFIC NAMES
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
{
|
||||
int textID = -1;
|
||||
InfoWindow iw;
|
||||
iw.player = hero->getOwner();
|
||||
MetaString loot;
|
||||
|
||||
switch (ID)
|
||||
{
|
||||
case Obj::CREATURE_BANK:
|
||||
case Obj::DRAGON_UTOPIA:
|
||||
textID = 34;
|
||||
break;
|
||||
case Obj::DERELICT_SHIP:
|
||||
if (!bc)
|
||||
textID = 43;
|
||||
else
|
||||
{
|
||||
GiveBonus gbonus;
|
||||
gbonus.id = hero->id.getNum();
|
||||
gbonus.bonus.duration = Bonus::ONE_BATTLE;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
gbonus.bdescr << "\n" << VLC->generaltexth->arraytxt[101];
|
||||
gbonus.bonus.type = Bonus::MORALE;
|
||||
gbonus.bonus.val = -1;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
textID = 42;
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
}
|
||||
break;
|
||||
case Obj::CRYPT:
|
||||
if (bc)
|
||||
textID = 121;
|
||||
else
|
||||
{
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
GiveBonus gbonus;
|
||||
gbonus.id = hero->id.getNum();
|
||||
gbonus.bonus.duration = Bonus::ONE_BATTLE;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
gbonus.bdescr << "\n" << VLC->generaltexth->arraytxt[ID];
|
||||
gbonus.bonus.type = Bonus::MORALE;
|
||||
gbonus.bonus.val = -1;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
textID = 120;
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
}
|
||||
break;
|
||||
case Obj::SHIPWRECK:
|
||||
if (bc)
|
||||
textID = 124;
|
||||
else
|
||||
textID = 123;
|
||||
break;
|
||||
case Obj::PYRAMID:
|
||||
textID = 106;
|
||||
}
|
||||
|
||||
//grant resources
|
||||
if (bc)
|
||||
{
|
||||
for (int it = 0; it < bc->resources.size(); it++)
|
||||
{
|
||||
if (bc->resources[it] != 0)
|
||||
{
|
||||
iw.components.push_back (Component (Component::RESOURCE, it, bc->resources[it], 0));
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(iw.components.back().val);
|
||||
loot.addReplacement(MetaString::RES_NAMES, iw.components.back().subtype);
|
||||
cb->giveResource (hero->getOwner(), static_cast<Res::ERes>(it), bc->resources[it]);
|
||||
}
|
||||
}
|
||||
//grant artifacts
|
||||
for (auto & elem : bc->artifacts)
|
||||
{
|
||||
iw.components.push_back (Component (Component::ARTIFACT, elem, 0, 0));
|
||||
loot << "%s";
|
||||
loot.addReplacement(MetaString::ART_NAMES, elem);
|
||||
cb->giveHeroNewArtifact (hero, VLC->arth->artifacts[elem], ArtifactPosition::FIRST_AVAILABLE);
|
||||
}
|
||||
//display loot
|
||||
if (!iw.components.empty())
|
||||
{
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, textID);
|
||||
if (textID == 34)
|
||||
{
|
||||
const CCreature * strongest = boost::range::max_element(bc->guards, [](const CStackBasicDescriptor & a, const CStackBasicDescriptor & b)
|
||||
{
|
||||
return a.type->fightValue < b.type->fightValue;
|
||||
})->type;
|
||||
|
||||
iw.text.addReplacement(MetaString::CRE_PL_NAMES, strongest->idNumber);
|
||||
iw.text.addReplacement(loot.buildList());
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
|
||||
if (!bc->spells.empty())
|
||||
{
|
||||
std::set<SpellID> spells;
|
||||
|
||||
bool noWisdom = false;
|
||||
for (SpellID spell : bc->spells)
|
||||
{
|
||||
iw.text.addTxt (MetaString::SPELL_NAME, spell);
|
||||
if (VLC->spellh->objects[spell]->level <= hero->getSecSkillLevel(SecondarySkill::WISDOM) + 2)
|
||||
{
|
||||
spells.insert(spell);
|
||||
iw.components.push_back(Component (Component::SPELL, spell, 0, 0));
|
||||
}
|
||||
else
|
||||
noWisdom = true;
|
||||
}
|
||||
|
||||
if (!hero->getArt(ArtifactPosition::SPELLBOOK))
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 109); //no spellbook
|
||||
else if (noWisdom)
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 108); //no expert Wisdom
|
||||
if (spells.empty())
|
||||
cb->changeSpells (hero, true, spells);
|
||||
}
|
||||
loot.clear();
|
||||
iw.components.clear();
|
||||
iw.text.clear();
|
||||
|
||||
//grant creatures
|
||||
CCreatureSet ourArmy;
|
||||
for (auto slot : bc->creatures)
|
||||
{
|
||||
ourArmy.addToSlot(ourArmy.getSlotFor(slot.type->idNumber), slot.type->idNumber, slot.count);
|
||||
}
|
||||
|
||||
for (auto & elem : ourArmy.Slots())
|
||||
{
|
||||
iw.components.push_back(Component(*elem.second));
|
||||
loot << "%s";
|
||||
loot.addReplacement(*elem.second);
|
||||
}
|
||||
|
||||
if (ourArmy.Slots().size())
|
||||
{
|
||||
if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second->count == 1)
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 185);
|
||||
else
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 186);
|
||||
|
||||
iw.text.addReplacement(loot.buildList());
|
||||
iw.text.addReplacement(hero->name);
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->giveCreatures(this, hero, ourArmy, false);
|
||||
}
|
||||
cb->setObjProperty (id, ObjProperty::BANK_CLEAR, 0); //bc = nullptr
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
||||
{
|
||||
if (result.winner == 0)
|
||||
{
|
||||
doVisit(hero);
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
||||
{
|
||||
if (answer)
|
||||
{
|
||||
if (bc) // not looted bank
|
||||
cb->startBattleI(hero, this, true);
|
||||
else
|
||||
doVisit(hero);
|
||||
}
|
||||
}
|
49
lib/mapObjects/CBank.h
Normal file
49
lib/mapObjects/CBank.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CArmedInstance.h"
|
||||
|
||||
/*
|
||||
* CBank.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class BankConfig;
|
||||
class CBankInstanceConstructor;
|
||||
|
||||
class DLL_LINKAGE CBank : public CArmedInstance
|
||||
{
|
||||
std::unique_ptr<BankConfig> bc;
|
||||
ui32 daycounter;
|
||||
ui32 resetDuration;
|
||||
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
void doVisit(const CGHeroInstance * hero) const;
|
||||
|
||||
public:
|
||||
CBank();
|
||||
~CBank();
|
||||
|
||||
void setConfig(const BankConfig & bc);
|
||||
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
void newTurn() const override;
|
||||
bool wasVisited (PlayerColor player) const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & daycounter & bc & resetDuration;
|
||||
}
|
||||
|
||||
friend class CBankInstanceConstructor;
|
||||
};
|
1372
lib/mapObjects/CGHeroInstance.cpp
Normal file
1372
lib/mapObjects/CGHeroInstance.cpp
Normal file
File diff suppressed because it is too large
Load Diff
227
lib/mapObjects/CGHeroInstance.h
Normal file
227
lib/mapObjects/CGHeroInstance.h
Normal file
@ -0,0 +1,227 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CArmedInstance.h"
|
||||
|
||||
#include "../CArtHandler.h" // For CArtifactSet
|
||||
#include "../CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
* CGHeroInstance.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class CHero;
|
||||
class CGBoat;
|
||||
|
||||
class CGHeroPlaceholder : public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
//subID stores id of hero type. If it's 0xff then following field is used
|
||||
ui8 power;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & power;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet
|
||||
{
|
||||
public:
|
||||
enum ECanDig
|
||||
{
|
||||
CAN_DIG, LACK_OF_MOVEMENT, WRONG_TERRAIN, TILE_OCCUPIED
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ui8 moveDir; //format: 123
|
||||
// 8 4
|
||||
// 765
|
||||
mutable ui8 isStanding, tacticFormationEnabled;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ConstTransitivePtr<CHero> type;
|
||||
TExpType exp; //experience points
|
||||
ui32 level; //current level of hero
|
||||
std::string name; //may be custom
|
||||
std::string biography; //if custom
|
||||
si32 portrait; //may be custom
|
||||
si32 mana; // remaining spell points
|
||||
std::vector<std::pair<SecondarySkill,ui8> > secSkills; //first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert); if hero has ability (-1, -1) it meansthat it should have default secondary abilities
|
||||
ui32 movement; //remaining movement points
|
||||
ui8 sex;
|
||||
bool inTownGarrison; // if hero is in town garrison
|
||||
ConstTransitivePtr<CGTownInstance> visitedTown; //set if hero is visiting town or in the town garrison
|
||||
ConstTransitivePtr<CCommanderInstance> commander;
|
||||
const CGBoat *boat; //set to CGBoat when sailing
|
||||
|
||||
|
||||
//std::vector<const CArtifact*> artifacts; //hero's artifacts from bag
|
||||
//std::map<ui16, const CArtifact*> artifWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
|
||||
std::set<SpellID> spells; //known spells (spell IDs)
|
||||
std::set<ObjectInstanceID> visitedObjects;
|
||||
|
||||
struct DLL_LINKAGE Patrol
|
||||
{
|
||||
Patrol(){patrolling=false;patrolRadious=-1;};
|
||||
bool patrolling;
|
||||
ui32 patrolRadious;
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & patrolling & patrolRadious;
|
||||
}
|
||||
} patrol;
|
||||
|
||||
struct DLL_LINKAGE HeroSpecial : CBonusSystemNode
|
||||
{
|
||||
bool growsWithLevel;
|
||||
|
||||
HeroSpecial(){growsWithLevel = false;};
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & growsWithLevel;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<HeroSpecial*> specialty;
|
||||
|
||||
struct DLL_LINKAGE SecondarySkillsInfo
|
||||
{
|
||||
//skills are determined, initialized at map start
|
||||
//FIXME remove mutable
|
||||
mutable CRandomGenerator rand;
|
||||
ui8 magicSchoolCounter;
|
||||
ui8 wisdomCounter;
|
||||
|
||||
void resetMagicSchoolCounter();
|
||||
void resetWisdomCounter();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & magicSchoolCounter & wisdomCounter & rand;
|
||||
}
|
||||
} skillsInfo;
|
||||
|
||||
int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
|
||||
int getSightRadious() const; //sight distance (should be used if player-owned structure)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||
void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool hasSpellbook() const;
|
||||
EAlignment::EAlignment getAlignment() const;
|
||||
const std::string &getBiography() const;
|
||||
bool needsLastStack()const;
|
||||
ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||
ui32 getLowestCreatureSpeed() const;
|
||||
int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
|
||||
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
||||
bool canWalkOnSea() const;
|
||||
int getCurrentLuck(int stack=-1, bool town=false) const;
|
||||
int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored
|
||||
|
||||
// ----- primary and secondary skill, experience, level handling -----
|
||||
|
||||
/// Returns true if hero has lower level than should upon his experience.
|
||||
bool gainsLevel() const;
|
||||
|
||||
/// Returns the next primary skill on level up. Can only be called if hero can gain a level up.
|
||||
PrimarySkill::PrimarySkill nextPrimarySkill() const;
|
||||
|
||||
/// Returns the next secondary skill randomly on level up. Can only be called if hero can gain a level up.
|
||||
boost::optional<SecondarySkill> nextSecondarySkill() const;
|
||||
|
||||
/// Gets 0, 1 or 2 secondary skills which are proposed on hero level up.
|
||||
std::vector<SecondarySkill> getLevelUpProposedSecondarySkills() const;
|
||||
|
||||
ui8 getSecSkillLevel(SecondarySkill skill) const; //0 - no skill
|
||||
|
||||
/// Returns true if hero has free secondary skill slot.
|
||||
bool canLearnSkill() const;
|
||||
|
||||
void setPrimarySkill(PrimarySkill::PrimarySkill primarySkill, si64 value, ui8 abs);
|
||||
void setSecSkillLevel(SecondarySkill which, int val, bool abs);// abs == 0 - changes by value; 1 - sets to value
|
||||
void levelUp(std::vector<SecondarySkill> skills);
|
||||
|
||||
int maxMovePoints(bool onLand) const;
|
||||
int movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark = false) const;
|
||||
|
||||
//int getSpellSecLevel(int spell) const; //returns level of secondary ability (fire, water, earth, air magic) known to this hero and applicable to given spell; -1 if error
|
||||
static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest
|
||||
double getFightingStrength() const; // takes attack / defense skill into account
|
||||
double getMagicStrength() const; // takes knowledge / spell power skill into account
|
||||
double getHeroStrength() const; // includes fighting and magic strength
|
||||
ui64 getTotalStrength() const; // includes fighting strength and army strength
|
||||
TExpType calculateXp(TExpType exp) const; //apply learning skill
|
||||
ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = nullptr) const; //returns level on which given spell would be cast by this hero (0 - none, 1 - basic etc); optionally returns number of selected school by arg - 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic,
|
||||
bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
|
||||
CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
|
||||
void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
|
||||
ECanDig diggingStatus() const; //0 - can dig; 1 - lack of movement; 2 -
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setType(si32 ID, si32 subID);
|
||||
|
||||
void initHero();
|
||||
void initHero(HeroTypeID SUBID);
|
||||
|
||||
void putArtifact(ArtifactPosition pos, CArtifactInstance *art);
|
||||
void putInBackpack(CArtifactInstance *art);
|
||||
void initExp();
|
||||
void initArmy(IArmyDescriptor *dst = nullptr);
|
||||
//void giveArtifact (ui32 aid);
|
||||
void pushPrimSkill(PrimarySkill::PrimarySkill which, int val);
|
||||
ui8 maxlevelsToMagicSchool() const;
|
||||
ui8 maxlevelsToWisdom() const;
|
||||
void Updatespecialty();
|
||||
void recreateSecondarySkillsBonuses();
|
||||
void updateSkill(SecondarySkill which, int val);
|
||||
|
||||
CGHeroInstance();
|
||||
virtual ~CGHeroInstance();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
ArtBearer::ArtBearer bearerType() const override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBonusSystemNode *whereShouldBeAttached(CGameState *gs) override;
|
||||
std::string nodeName() const override;
|
||||
void deserializationFix();
|
||||
|
||||
void initObj() override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
const std::string & getHoverText() const override;
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;//synchr
|
||||
|
||||
private:
|
||||
void levelUpAutomatically();
|
||||
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & static_cast<CArtifactSet&>(*this);
|
||||
h & exp & level & name & biography & portrait & mana & secSkills & movement
|
||||
& sex & inTownGarrison & spells & patrol & moveDir & skillsInfo;
|
||||
h & visitedTown & boat;
|
||||
h & type & specialty & commander;
|
||||
BONUS_TREE_DESERIALIZATION_FIX
|
||||
//visitied town pointer will be restored by map serialization method
|
||||
}
|
||||
};
|
335
lib/mapObjects/CGMarket.cpp
Normal file
335
lib/mapObjects/CGMarket.cpp
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
*
|
||||
* CGMarket.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 "CGMarket.h"
|
||||
|
||||
#include "../NetPacks.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
///helpers
|
||||
static void openWindow(const OpenWindow::EWindow type, const int id1, const int id2 = -1)
|
||||
{
|
||||
OpenWindow ow;
|
||||
ow.window = type;
|
||||
ow.id1 = id1;
|
||||
ow.id2 = id2;
|
||||
IObjectInterface::cb->sendAndApply(&ow);
|
||||
}
|
||||
|
||||
bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case EMarketMode::RESOURCE_RESOURCE:
|
||||
{
|
||||
double effectiveness = std::min((getMarketEfficiency() + 1.0) / 20.0, 0.5);
|
||||
|
||||
double r = VLC->objh->resVals[id1], //value of given resource
|
||||
g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
|
||||
|
||||
if(r>g) //if given resource is more expensive than wanted
|
||||
{
|
||||
val2 = ceil(r / g);
|
||||
val1 = 1;
|
||||
}
|
||||
else //if wanted resource is more expensive
|
||||
{
|
||||
val1 = (g / r) + 0.5;
|
||||
val2 = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EMarketMode::CREATURE_RESOURCE:
|
||||
{
|
||||
const double effectivenessArray[] = {0.0, 0.3, 0.45, 0.50, 0.65, 0.7, 0.85, 0.9, 1.0};
|
||||
double effectiveness = effectivenessArray[std::min(getMarketEfficiency(), 8)];
|
||||
|
||||
double r = VLC->creh->creatures[id1]->cost[6], //value of given creature in gold
|
||||
g = VLC->objh->resVals[id2] / effectiveness; //value of wanted resource
|
||||
|
||||
if(r>g) //if given resource is more expensive than wanted
|
||||
{
|
||||
val2 = ceil(r / g);
|
||||
val1 = 1;
|
||||
}
|
||||
else //if wanted resource is more expensive
|
||||
{
|
||||
val1 = (g / r) + 0.5;
|
||||
val2 = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EMarketMode::RESOURCE_PLAYER:
|
||||
val1 = 1;
|
||||
val2 = 1;
|
||||
break;
|
||||
case EMarketMode::RESOURCE_ARTIFACT:
|
||||
{
|
||||
double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
|
||||
double r = VLC->objh->resVals[id1], //value of offered resource
|
||||
g = VLC->arth->artifacts[id2]->price / effectiveness; //value of bought artifact in gold
|
||||
|
||||
if(id1 != 6) //non-gold prices are doubled
|
||||
r /= 2;
|
||||
|
||||
val1 = std::max(1, (int)((g / r) + 0.5)); //don't sell arts for less than 1 resource
|
||||
val2 = 1;
|
||||
}
|
||||
break;
|
||||
case EMarketMode::ARTIFACT_RESOURCE:
|
||||
{
|
||||
double effectiveness = std::min((getMarketEfficiency() + 3.0) / 20.0, 0.6);
|
||||
double r = VLC->arth->artifacts[id1]->price * effectiveness,
|
||||
g = VLC->objh->resVals[id2];
|
||||
|
||||
// if(id2 != 6) //non-gold prices are doubled
|
||||
// r /= 2;
|
||||
|
||||
val1 = 1;
|
||||
val2 = std::max(1, (int)((r / g) + 0.5)); //at least one resource is given in return
|
||||
}
|
||||
break;
|
||||
case EMarketMode::CREATURE_EXP:
|
||||
{
|
||||
val1 = 1;
|
||||
val2 = (VLC->creh->creatures[id1]->AIValue / 40) * 5;
|
||||
}
|
||||
break;
|
||||
case EMarketMode::ARTIFACT_EXP:
|
||||
{
|
||||
val1 = 1;
|
||||
|
||||
int givenClass = VLC->arth->artifacts[id1]->getArtClassSerial();
|
||||
if(givenClass < 0 || givenClass > 3)
|
||||
{
|
||||
val2 = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static const int expPerClass[] = {1000, 1500, 3000, 6000};
|
||||
val2 = expPerClass[givenClass];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IMarket::allowsTrade(EMarketMode::EMarketMode mode) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int IMarket::availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case EMarketMode::RESOURCE_RESOURCE:
|
||||
case EMarketMode::ARTIFACT_RESOURCE:
|
||||
case EMarketMode::CREATURE_RESOURCE:
|
||||
return -1;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> IMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
|
||||
{
|
||||
std::vector<int> ret;
|
||||
switch(mode)
|
||||
{
|
||||
case EMarketMode::RESOURCE_RESOURCE:
|
||||
case EMarketMode::ARTIFACT_RESOURCE:
|
||||
case EMarketMode::CREATURE_RESOURCE:
|
||||
for (int i = 0; i < 7; i++)
|
||||
ret.push_back(i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const IMarket * IMarket::castFrom(const CGObjectInstance *obj, bool verbose /*= true*/)
|
||||
{
|
||||
switch(obj->ID)
|
||||
{
|
||||
case Obj::TOWN:
|
||||
return static_cast<const CGTownInstance*>(obj);
|
||||
case Obj::ALTAR_OF_SACRIFICE:
|
||||
case Obj::BLACK_MARKET:
|
||||
case Obj::TRADING_POST:
|
||||
case Obj::TRADING_POST_SNOW:
|
||||
case Obj::FREELANCERS_GUILD:
|
||||
return static_cast<const CGMarket*>(obj);
|
||||
case Obj::UNIVERSITY:
|
||||
return static_cast<const CGUniversity*>(obj);
|
||||
default:
|
||||
if(verbose)
|
||||
logGlobal->errorStream() << "Cannot cast to IMarket object with ID " << obj->ID;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IMarket::IMarket(const CGObjectInstance *O)
|
||||
:o(O)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::vector<EMarketMode::EMarketMode> IMarket::availableModes() const
|
||||
{
|
||||
std::vector<EMarketMode::EMarketMode> ret;
|
||||
for (int i = 0; i < EMarketMode::MARTKET_AFTER_LAST_PLACEHOLDER; i++)
|
||||
if(allowsTrade((EMarketMode::EMarketMode)i))
|
||||
ret.push_back((EMarketMode::EMarketMode)i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CGMarket::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
openWindow(OpenWindow::MARKET_WINDOW,id.getNum(),h->id.getNum());
|
||||
}
|
||||
|
||||
int CGMarket::getMarketEfficiency() const
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
bool CGMarket::allowsTrade(EMarketMode::EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case EMarketMode::RESOURCE_RESOURCE:
|
||||
case EMarketMode::RESOURCE_PLAYER:
|
||||
switch(ID)
|
||||
{
|
||||
case Obj::TRADING_POST:
|
||||
case Obj::TRADING_POST_SNOW:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case EMarketMode::CREATURE_RESOURCE:
|
||||
return ID == Obj::FREELANCERS_GUILD;
|
||||
//case ARTIFACT_RESOURCE:
|
||||
case EMarketMode::RESOURCE_ARTIFACT:
|
||||
return ID == Obj::BLACK_MARKET;
|
||||
case EMarketMode::ARTIFACT_EXP:
|
||||
case EMarketMode::CREATURE_EXP:
|
||||
return ID == Obj::ALTAR_OF_SACRIFICE; //TODO? check here for alignment of visiting hero? - would not be coherent with other checks here
|
||||
case EMarketMode::RESOURCE_SKILL:
|
||||
return ID == Obj::UNIVERSITY;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int CGMarket::availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<int> CGMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case EMarketMode::RESOURCE_RESOURCE:
|
||||
case EMarketMode::RESOURCE_PLAYER:
|
||||
return IMarket::availableItemsIds(mode);
|
||||
default:
|
||||
return std::vector<int>();
|
||||
}
|
||||
}
|
||||
|
||||
CGMarket::CGMarket()
|
||||
:IMarket(this)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<int> CGBlackMarket::availableItemsIds(EMarketMode::EMarketMode mode) const
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case EMarketMode::ARTIFACT_RESOURCE:
|
||||
return IMarket::availableItemsIds(mode);
|
||||
case EMarketMode::RESOURCE_ARTIFACT:
|
||||
{
|
||||
std::vector<int> ret;
|
||||
for(const CArtifact *a : artifacts)
|
||||
if(a)
|
||||
ret.push_back(a->id);
|
||||
else
|
||||
ret.push_back(-1);
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
return std::vector<int>();
|
||||
}
|
||||
}
|
||||
|
||||
void CGBlackMarket::newTurn() const
|
||||
{
|
||||
if(cb->getDate(Date::DAY_OF_MONTH) != 1) //new month
|
||||
return;
|
||||
|
||||
SetAvailableArtifacts saa;
|
||||
saa.id = id.getNum();
|
||||
cb->pickAllowedArtsSet(saa.arts);
|
||||
cb->sendAndApply(&saa);
|
||||
}
|
||||
|
||||
void CGUniversity::initObj()
|
||||
{
|
||||
std::vector<int> toChoose;
|
||||
for(int i = 0; i < GameConstants::SKILL_QUANTITY; ++i)
|
||||
{
|
||||
if(cb->isAllowed(2, i))
|
||||
{
|
||||
toChoose.push_back(i);
|
||||
}
|
||||
}
|
||||
if(toChoose.size() < 4)
|
||||
{
|
||||
logGlobal->warnStream()<<"Warning: less then 4 available skills was found by University initializer!";
|
||||
return;
|
||||
}
|
||||
|
||||
// get 4 skills
|
||||
for(int i = 0; i < 4; ++i)
|
||||
{
|
||||
// move randomly one skill to selected and remove from list
|
||||
auto it = RandomGeneratorUtil::nextItem(toChoose, cb->gameState()->getRandomGenerator());
|
||||
skills.push_back(*it);
|
||||
toChoose.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> CGUniversity::availableItemsIds(EMarketMode::EMarketMode mode) const
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case EMarketMode::RESOURCE_SKILL:
|
||||
return skills;
|
||||
|
||||
default:
|
||||
return std::vector <int> ();
|
||||
}
|
||||
}
|
||||
|
||||
void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
openWindow(OpenWindow::UNIVERSITY_WINDOW,id.getNum(),h->id.getNum());
|
||||
}
|
88
lib/mapObjects/CGMarket.h
Normal file
88
lib/mapObjects/CGMarket.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
|
||||
/*
|
||||
* CGMarket.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class DLL_LINKAGE IMarket
|
||||
{
|
||||
public:
|
||||
const CGObjectInstance *o;
|
||||
|
||||
IMarket(const CGObjectInstance *O);
|
||||
virtual ~IMarket() {}
|
||||
|
||||
virtual int getMarketEfficiency() const =0;
|
||||
virtual bool allowsTrade(EMarketMode::EMarketMode mode) const;
|
||||
virtual int availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const; //-1 if unlimited
|
||||
virtual std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
|
||||
|
||||
bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode::EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units
|
||||
std::vector<EMarketMode::EMarketMode> availableModes() const;
|
||||
|
||||
static const IMarket *castFrom(const CGObjectInstance *obj, bool verbose = true);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & o;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGMarket : public CGObjectInstance, public IMarket
|
||||
{
|
||||
public:
|
||||
CGMarket();
|
||||
///IObjectIntercae
|
||||
void onHeroVisit(const CGHeroInstance * h) const override; //open trading window
|
||||
|
||||
///IMarket
|
||||
int getMarketEfficiency() const override;
|
||||
bool allowsTrade(EMarketMode::EMarketMode mode) const override;
|
||||
int availableUnits(EMarketMode::EMarketMode mode, int marketItemSerial) const override; //-1 if unlimited
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & static_cast<IMarket&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGBlackMarket : public CGMarket
|
||||
{
|
||||
public:
|
||||
std::vector<const CArtifact *> artifacts; //available artifacts
|
||||
|
||||
void newTurn() const override; //reset artifacts for black market every month
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGMarket&>(*this);
|
||||
h & artifacts;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGUniversity : public CGMarket
|
||||
{
|
||||
public:
|
||||
std::vector<int> skills; //available skills
|
||||
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
|
||||
void initObj() override;//set skills for trade
|
||||
void onHeroVisit(const CGHeroInstance * h) const override; //open window
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGMarket&>(*this);
|
||||
h & skills;
|
||||
}
|
||||
};
|
364
lib/mapObjects/CGPandoraBox.cpp
Normal file
364
lib/mapObjects/CGPandoraBox.cpp
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* CGPandoraBox.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 "CGPandoraBox.h"
|
||||
|
||||
#include "../NetPacks.h"
|
||||
#include "../CSoundBase.h"
|
||||
|
||||
#include "../CSpellHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
///helpers
|
||||
static void showInfoDialog(const PlayerColor playerID, const ui32 txtID, const ui16 soundID)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundID;
|
||||
iw.player = playerID;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
|
||||
IObjectInterface::cb->sendAndApply(&iw);
|
||||
}
|
||||
|
||||
static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 soundID)
|
||||
{
|
||||
const PlayerColor playerID = h->getOwner();
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}
|
||||
|
||||
void CGPandoraBox::initObj()
|
||||
{
|
||||
blockVisit = (ID==Obj::PANDORAS_BOX); //block only if it's really pandora's box (events also derive from that class)
|
||||
hasGuardians = stacks.size();
|
||||
}
|
||||
|
||||
void CGPandoraBox::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
BlockingDialog bd (true, false);
|
||||
bd.player = h->getOwner();
|
||||
bd.soundID = soundBase::QUEST;
|
||||
bd.text.addTxt (MetaString::ADVOB_TXT, 14);
|
||||
cb->showBlockingDialog (&bd);
|
||||
}
|
||||
|
||||
void CGPandoraBox::giveContentsUpToExp(const CGHeroInstance *h) const
|
||||
{
|
||||
cb->removeAfterVisit(this);
|
||||
|
||||
InfoWindow iw;
|
||||
iw.player = h->getOwner();
|
||||
|
||||
bool changesPrimSkill = false;
|
||||
for (auto & elem : primskills)
|
||||
{
|
||||
if(elem)
|
||||
{
|
||||
changesPrimSkill = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(gainedExp || changesPrimSkill || abilities.size())
|
||||
{
|
||||
TExpType expVal = h->calculateXp(gainedExp);
|
||||
//getText(iw,afterBattle,175,h); //wtf?
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 175); //%s learns something
|
||||
iw.text.addReplacement(h->name);
|
||||
|
||||
if(expVal)
|
||||
iw.components.push_back(Component(Component::EXPERIENCE,0,expVal,0));
|
||||
for(int i=0; i<primskills.size(); i++)
|
||||
if(primskills[i])
|
||||
iw.components.push_back(Component(Component::PRIM_SKILL,i,primskills[i],0));
|
||||
|
||||
for(int i=0; i<abilities.size(); i++)
|
||||
iw.components.push_back(Component(Component::SEC_SKILL,abilities[i],abilityLevels[i],0));
|
||||
|
||||
cb->showInfoDialog(&iw);
|
||||
|
||||
//give sec skills
|
||||
for(int i=0; i<abilities.size(); i++)
|
||||
{
|
||||
int curLev = h->getSecSkillLevel(abilities[i]);
|
||||
|
||||
if( (curLev && curLev < abilityLevels[i]) || (h->canLearnSkill() ))
|
||||
{
|
||||
cb->changeSecSkill(h,abilities[i],abilityLevels[i],true);
|
||||
}
|
||||
}
|
||||
|
||||
//give prim skills
|
||||
for(int i=0; i<primskills.size(); i++)
|
||||
if(primskills[i])
|
||||
cb->changePrimSkill(h,static_cast<PrimarySkill::PrimarySkill>(i),primskills[i],false);
|
||||
|
||||
assert(!cb->isVisitCoveredByAnotherQuery(this, h));
|
||||
|
||||
//give exp
|
||||
if(expVal)
|
||||
cb->changePrimSkill(h, PrimarySkill::EXPERIENCE, expVal, false);
|
||||
}
|
||||
|
||||
if(!cb->isVisitCoveredByAnotherQuery(this, h))
|
||||
giveContentsAfterExp(h);
|
||||
//Otherwise continuation occurs via post-level-up callback.
|
||||
}
|
||||
|
||||
void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
{
|
||||
bool hadGuardians = hasGuardians; //copy, because flag will be emptied after issuing first post-battle message
|
||||
|
||||
std::string msg = message; //in case box is removed in the meantime
|
||||
InfoWindow iw;
|
||||
iw.player = h->getOwner();
|
||||
|
||||
if(spells.size())
|
||||
{
|
||||
std::set<SpellID> spellsToGive;
|
||||
iw.components.clear();
|
||||
if (spells.size() > 1)
|
||||
{
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 188); //%s learns spells
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 184); //%s learns a spell
|
||||
}
|
||||
iw.text.addReplacement(h->name);
|
||||
std::vector<ConstTransitivePtr<CSpell> > * sp = &VLC->spellh->objects;
|
||||
for(auto i=spells.cbegin(); i != spells.cend(); i++)
|
||||
{
|
||||
if ((*sp)[*i]->level <= h->getSecSkillLevel(SecondarySkill::WISDOM) + 2) //enough wisdom
|
||||
{
|
||||
iw.components.push_back(Component(Component::SPELL,*i,0,0));
|
||||
spellsToGive.insert(*i);
|
||||
}
|
||||
}
|
||||
if(!spellsToGive.empty())
|
||||
{
|
||||
cb->changeSpells(h,true,spellsToGive);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
}
|
||||
|
||||
if(manaDiff)
|
||||
{
|
||||
getText(iw,hadGuardians,manaDiff,176,177,h);
|
||||
iw.components.push_back(Component(Component::PRIM_SKILL,5,manaDiff,0));
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->setManaPoints(h->id, h->mana + manaDiff);
|
||||
}
|
||||
|
||||
if(moraleDiff)
|
||||
{
|
||||
getText(iw,hadGuardians,moraleDiff,178,179,h);
|
||||
iw.components.push_back(Component(Component::MORALE,0,moraleDiff,0));
|
||||
cb->showInfoDialog(&iw);
|
||||
GiveBonus gb;
|
||||
gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::MORALE,Bonus::OBJECT,moraleDiff,id.getNum(),"");
|
||||
gb.id = h->id.getNum();
|
||||
cb->giveHeroBonus(&gb);
|
||||
}
|
||||
|
||||
if(luckDiff)
|
||||
{
|
||||
getText(iw,hadGuardians,luckDiff,180,181,h);
|
||||
iw.components.push_back(Component(Component::LUCK,0,luckDiff,0));
|
||||
cb->showInfoDialog(&iw);
|
||||
GiveBonus gb;
|
||||
gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,luckDiff,id.getNum(),"");
|
||||
gb.id = h->id.getNum();
|
||||
cb->giveHeroBonus(&gb);
|
||||
}
|
||||
|
||||
iw.components.clear();
|
||||
iw.text.clear();
|
||||
for(int i=0; i<resources.size(); i++)
|
||||
{
|
||||
if(resources[i] < 0)
|
||||
iw.components.push_back(Component(Component::RESOURCE,i,resources[i],0));
|
||||
}
|
||||
if(iw.components.size())
|
||||
{
|
||||
getText(iw,hadGuardians,182,h);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
|
||||
iw.components.clear();
|
||||
iw.text.clear();
|
||||
for(int i=0; i<resources.size(); i++)
|
||||
{
|
||||
if(resources[i] > 0)
|
||||
iw.components.push_back(Component(Component::RESOURCE,i,resources[i],0));
|
||||
}
|
||||
if(iw.components.size())
|
||||
{
|
||||
getText(iw,hadGuardians,183,h);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
|
||||
iw.components.clear();
|
||||
// getText(iw,afterBattle,183,h);
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 183); //% has found treasure
|
||||
iw.text.addReplacement(h->name);
|
||||
for(auto & elem : artifacts)
|
||||
{
|
||||
iw.components.push_back(Component(Component::ARTIFACT,elem,0,0));
|
||||
if(iw.components.size() >= 14)
|
||||
{
|
||||
cb->showInfoDialog(&iw);
|
||||
iw.components.clear();
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 183); //% has found treasure - once more?
|
||||
iw.text.addReplacement(h->name);
|
||||
}
|
||||
}
|
||||
if(iw.components.size())
|
||||
{
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
|
||||
for(int i=0; i<resources.size(); i++)
|
||||
if(resources[i])
|
||||
cb->giveResource(h->getOwner(),static_cast<Res::ERes>(i),resources[i]);
|
||||
|
||||
for(auto & elem : artifacts)
|
||||
cb->giveHeroNewArtifact(h, VLC->arth->artifacts[elem],ArtifactPosition::FIRST_AVAILABLE);
|
||||
|
||||
iw.components.clear();
|
||||
iw.text.clear();
|
||||
|
||||
if (creatures.Slots().size())
|
||||
{ //this part is taken straight from creature bank
|
||||
MetaString loot;
|
||||
for(auto & elem : creatures.Slots())
|
||||
{ //build list of joined creatures
|
||||
iw.components.push_back(Component(*elem.second));
|
||||
loot << "%s";
|
||||
loot.addReplacement(*elem.second);
|
||||
}
|
||||
|
||||
if (creatures.Slots().size() == 1 && creatures.Slots().begin()->second->count == 1)
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 185);
|
||||
else
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 186);
|
||||
|
||||
iw.text.addReplacement(loot.buildList());
|
||||
iw.text.addReplacement(h->name);
|
||||
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->giveCreatures(this, h, creatures, true);
|
||||
}
|
||||
if(!hasGuardians && msg.size())
|
||||
{
|
||||
iw.text << msg;
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
}
|
||||
|
||||
void CGPandoraBox::getText( InfoWindow &iw, bool &afterBattle, int text, const CGHeroInstance * h ) const
|
||||
{
|
||||
if(afterBattle || !message.size())
|
||||
{
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,text);//%s has lost treasure.
|
||||
iw.text.addReplacement(h->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text << message;
|
||||
afterBattle = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CGPandoraBox::getText( InfoWindow &iw, bool &afterBattle, int val, int negative, int positive, const CGHeroInstance * h ) const
|
||||
{
|
||||
iw.components.clear();
|
||||
iw.text.clear();
|
||||
if(afterBattle || !message.size())
|
||||
{
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,val < 0 ? negative : positive); //%s's luck takes a turn for the worse / %s's luck increases
|
||||
iw.text.addReplacement(h->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text << message;
|
||||
afterBattle = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CGPandoraBox::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
||||
{
|
||||
if(result.winner)
|
||||
return;
|
||||
|
||||
giveContentsUpToExp(hero);
|
||||
}
|
||||
|
||||
void CGPandoraBox::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
||||
{
|
||||
if (answer)
|
||||
{
|
||||
if (stacksCount() > 0) //if pandora's box is protected by army
|
||||
{
|
||||
showInfoDialog(hero,16,0);
|
||||
cb->startBattleI(hero, this); //grants things after battle
|
||||
}
|
||||
else if (message.size() == 0 && resources.size() == 0
|
||||
&& primskills.size() == 0 && abilities.size() == 0
|
||||
&& abilityLevels.size() == 0 && artifacts.size() == 0
|
||||
&& spells.size() == 0 && creatures.Slots().size() > 0
|
||||
&& gainedExp == 0 && manaDiff == 0 && moraleDiff == 0 && luckDiff == 0) //if it gives nothing without battle
|
||||
{
|
||||
showInfoDialog(hero,15,0);
|
||||
cb->removeObject(this);
|
||||
}
|
||||
else //if it gives something without battle
|
||||
{
|
||||
giveContentsUpToExp(hero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CGPandoraBox::heroLevelUpDone(const CGHeroInstance *hero) const
|
||||
{
|
||||
giveContentsAfterExp(hero);
|
||||
}
|
||||
|
||||
void CGEvent::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
if(!(availableFor & (1 << h->tempOwner.getNum())))
|
||||
return;
|
||||
if(cb->getPlayerSettings(h->tempOwner)->playerID)
|
||||
{
|
||||
if(humanActivate)
|
||||
activated(h);
|
||||
}
|
||||
else if(computerActivate)
|
||||
activated(h);
|
||||
}
|
||||
|
||||
void CGEvent::activated( const CGHeroInstance * h ) const
|
||||
{
|
||||
if(stacksCount() > 0)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = h->tempOwner;
|
||||
if(message.size())
|
||||
iw.text << message;
|
||||
else
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 16);
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->startBattleI(h, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
giveContentsUpToExp(h);
|
||||
}
|
||||
}
|
72
lib/mapObjects/CGPandoraBox.h
Normal file
72
lib/mapObjects/CGPandoraBox.h
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CArmedInstance.h"
|
||||
|
||||
/*
|
||||
* CGPandoraBox.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class DLL_LINKAGE CGPandoraBox : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
std::string message;
|
||||
bool hasGuardians; //helper - after battle even though we have no stacks, allows us to know that there was battle
|
||||
|
||||
//gained things:
|
||||
ui32 gainedExp;
|
||||
si32 manaDiff; //amount of gained / lost mana
|
||||
si32 moraleDiff; //morale modifier
|
||||
si32 luckDiff; //luck modifier
|
||||
TResources resources;//gained / lost resources
|
||||
std::vector<si32> primskills;//gained / lost prim skills
|
||||
std::vector<SecondarySkill> abilities; //gained abilities
|
||||
std::vector<si32> abilityLevels; //levels of gained abilities
|
||||
std::vector<ArtifactID> artifacts; //gained artifacts
|
||||
std::vector<SpellID> spells; //gained spells
|
||||
CCreatureSet creatures; //gained creatures
|
||||
|
||||
void initObj() override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
void heroLevelUpDone(const CGHeroInstance *hero) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & message & hasGuardians & gainedExp & manaDiff & moraleDiff & luckDiff & resources & primskills
|
||||
& abilities & abilityLevels & artifacts & spells & creatures;
|
||||
}
|
||||
protected:
|
||||
void giveContentsUpToExp(const CGHeroInstance *h) const;
|
||||
void giveContentsAfterExp(const CGHeroInstance *h) const;
|
||||
private:
|
||||
void getText( InfoWindow &iw, bool &afterBattle, int val, int negative, int positive, const CGHeroInstance * h ) const;
|
||||
void getText( InfoWindow &iw, bool &afterBattle, int text, const CGHeroInstance * h ) const;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGEvent : public CGPandoraBox //event objects
|
||||
{
|
||||
public:
|
||||
bool removeAfterVisit; //true if event is removed after occurring
|
||||
ui8 availableFor; //players whom this event is available for
|
||||
bool computerActivate; //true if computer player can activate this event
|
||||
bool humanActivate; //true if human player can activate this event
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGPandoraBox &>(*this);
|
||||
h & removeAfterVisit & availableFor & computerActivate & humanActivate;
|
||||
}
|
||||
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
private:
|
||||
void activated(const CGHeroInstance * h) const;
|
||||
};
|
1165
lib/mapObjects/CGTownInstance.cpp
Normal file
1165
lib/mapObjects/CGTownInstance.cpp
Normal file
File diff suppressed because it is too large
Load Diff
248
lib/mapObjects/CGTownInstance.h
Normal file
248
lib/mapObjects/CGTownInstance.h
Normal file
@ -0,0 +1,248 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CGMarket.h" // For IMarket interface
|
||||
#include "CArmedInstance.h"
|
||||
|
||||
#include "../CTownHandler.h" // For CTown
|
||||
|
||||
/*
|
||||
* CGTownInstance.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class CCastleEvent;
|
||||
|
||||
class DLL_LINKAGE CSpecObjInfo
|
||||
{
|
||||
public:
|
||||
virtual ~CSpecObjInfo(){};
|
||||
PlayerColor player; //owner
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CCreGenAsCastleInfo : public virtual CSpecObjInfo
|
||||
{
|
||||
public:
|
||||
bool asCastle;
|
||||
ui32 identifier;
|
||||
ui8 castles[2]; //allowed castles
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CCreGenLeveledInfo : public virtual CSpecObjInfo
|
||||
{
|
||||
public:
|
||||
ui8 minLevel, maxLevel; //minimal and maximal level of creature in dwelling: <0, 6>
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CCreGenLeveledCastleInfo : public CCreGenAsCastleInfo, public CCreGenLeveledInfo
|
||||
{
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGDwelling : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::pair<ui32, std::vector<CreatureID> > > TCreaturesSet;
|
||||
|
||||
CSpecObjInfo * info; //h3m info about dewlling
|
||||
TCreaturesSet creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount>
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this) & creatures;
|
||||
}
|
||||
|
||||
void initObj() override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void newTurn() const override;
|
||||
void setProperty(ui8 what, ui32 val) override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
private:
|
||||
void heroAcceptsCreatures(const CGHeroInstance *h) const;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGTownBuilding : public IObjectInterface
|
||||
{
|
||||
///basic class for town structures handled as map objects
|
||||
public:
|
||||
BuildingID ID; //from buildig list
|
||||
si32 id; //identifies its index on towns vector
|
||||
CGTownInstance *town;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & ID & id;
|
||||
}
|
||||
};
|
||||
class DLL_LINKAGE COPWBonus : public CGTownBuilding
|
||||
{///used for OPW bonusing structures
|
||||
public:
|
||||
std::set<si32> visitors;
|
||||
void setProperty(ui8 what, ui32 val) override;
|
||||
void onHeroVisit (const CGHeroInstance * h) const override;
|
||||
|
||||
COPWBonus (BuildingID index, CGTownInstance *TOWN);
|
||||
COPWBonus (){ID = BuildingID::NONE; town = nullptr;};
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGTownBuilding&>(*this);
|
||||
h & visitors;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CTownBonus : public CGTownBuilding
|
||||
{
|
||||
///used for one-time bonusing structures
|
||||
///feel free to merge inheritance tree
|
||||
public:
|
||||
std::set<ObjectInstanceID> visitors;
|
||||
void setProperty(ui8 what, ui32 val) override;
|
||||
void onHeroVisit (const CGHeroInstance * h) const override;
|
||||
|
||||
CTownBonus (BuildingID index, CGTownInstance *TOWN);
|
||||
CTownBonus (){ID = BuildingID::NONE; town = nullptr;};
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGTownBuilding&>(*this);
|
||||
h & visitors;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CTownAndVisitingHero : public CBonusSystemNode
|
||||
{
|
||||
public:
|
||||
CTownAndVisitingHero();
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE GrowthInfo
|
||||
{
|
||||
struct Entry
|
||||
{
|
||||
int count;
|
||||
std::string description;
|
||||
Entry(const std::string &format, int _count);
|
||||
Entry(int subID, BuildingID building, int _count);
|
||||
};
|
||||
|
||||
std::vector<Entry> entries;
|
||||
int totalGrowth() const;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket
|
||||
{
|
||||
public:
|
||||
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
|
||||
|
||||
CTownAndVisitingHero townAndVis;
|
||||
const CTown * town;
|
||||
std::string name; // name of town
|
||||
si32 builded; //how many buildings has been built this turn
|
||||
si32 destroyed; //how many buildings has been destroyed this turn
|
||||
ConstTransitivePtr<CGHeroInstance> garrisonHero, visitingHero;
|
||||
ui32 identifier; //special identifier from h3m (only > RoE maps)
|
||||
si32 alignment;
|
||||
std::set<BuildingID> forbiddenBuildings, builtBuildings;
|
||||
std::vector<CGTownBuilding*> bonusingBuildings;
|
||||
std::vector<SpellID> possibleSpells, obligatorySpells;
|
||||
std::vector<std::vector<SpellID> > spells; //spells[level] -> vector of spells, first will be available in guild
|
||||
std::list<CCastleEvent> events;
|
||||
std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static std::vector<const CArtifact *> merchantArtifacts; //vector of artifacts available at Artifact merchant, NULLs possible (for making empty space when artifact is bought)
|
||||
static std::vector<int> universitySkills;//skills for university of magic
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGDwelling&>(*this);
|
||||
h & static_cast<IShipyard&>(*this);
|
||||
h & static_cast<IMarket&>(*this);
|
||||
h & name & builded & destroyed & identifier;
|
||||
h & garrisonHero & visitingHero;
|
||||
h & alignment & forbiddenBuildings & builtBuildings & bonusValue
|
||||
& possibleSpells & obligatorySpells & spells & /*strInfo & */events & bonusingBuildings;
|
||||
|
||||
for (std::vector<CGTownBuilding*>::iterator i = bonusingBuildings.begin(); i!=bonusingBuildings.end(); i++)
|
||||
(*i)->town = this;
|
||||
|
||||
h & town & townAndVis;
|
||||
BONUS_TREE_DESERIALIZATION_FIX
|
||||
|
||||
vstd::erase_if(builtBuildings, [this](BuildingID building) -> bool
|
||||
{
|
||||
if(!town->buildings.count(building) || !town->buildings.at(building))
|
||||
{
|
||||
logGlobal->errorStream() << boost::format("#1444-like issue in CGTownInstance::serialize. From town %s at %s removing the bogus builtBuildings item %s")
|
||||
% name % pos % building;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBonusSystemNode *whatShouldBeAttached() override;
|
||||
std::string nodeName() const override;
|
||||
void updateMoraleBonusFromArmy() override;
|
||||
void deserializationFix();
|
||||
void recreateBuildingsBonuses();
|
||||
bool addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, TPropagatorPtr &prop, int subtype = -1); //returns true if building is built and bonus has been added
|
||||
bool addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, int subtype = -1); //convienence version of above
|
||||
void setVisitingHero(CGHeroInstance *h);
|
||||
void setGarrisonedHero(CGHeroInstance *h);
|
||||
const CArmedInstance *getUpperArmy() const; //garrisoned hero if present or the town itself
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ui8 getPassableness() const; //bitmap - if the bit is set the corresponding player can pass through the visitable tiles of object, even if it's blockvis; if not set - default properties from definfo are used
|
||||
int3 getSightCenter() const override; //"center" tile from which the sight distance is calculated
|
||||
int getSightRadious() const override; //returns sight distance
|
||||
int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||
void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed
|
||||
int getMarketEfficiency() const override; //=market count
|
||||
bool allowsTrade(EMarketMode::EMarketMode mode) const;
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
|
||||
|
||||
void setType(si32 ID, si32 subID);
|
||||
void updateAppearance();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool needsLastStack() const;
|
||||
CGTownInstance::EFortLevel fortLevel() const;
|
||||
int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
|
||||
int mageGuildLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
|
||||
int getHordeLevel(const int & HID) const; //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
|
||||
int creatureGrowth(const int & level) const;
|
||||
GrowthInfo getGrowthInfo(int level) const;
|
||||
bool hasFort() const;
|
||||
bool hasCapitol() const;
|
||||
//checks if building is constructed and town has same subID
|
||||
bool hasBuilt(BuildingID buildingID) const;
|
||||
bool hasBuilt(BuildingID buildingID, int townID) const;
|
||||
TResources dailyIncome() const; //calculates daily income of this town
|
||||
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
|
||||
bool armedGarrison() const; //true if town has creatures in garrison or garrisoned hero
|
||||
int getTownLevel() const;
|
||||
|
||||
void removeCapitols (PlayerColor owner) const;
|
||||
void addHeroToStructureVisitors(const CGHeroInstance *h, si32 structureInstanceID) const; //hero must be visiting or garrisoned in town
|
||||
|
||||
CGTownInstance();
|
||||
virtual ~CGTownInstance();
|
||||
|
||||
///IObjectInterface overrides
|
||||
void newTurn() const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void onHeroLeave(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
};
|
397
lib/mapObjects/CObjectClassesHandler.cpp
Normal file
397
lib/mapObjects/CObjectClassesHandler.cpp
Normal file
@ -0,0 +1,397 @@
|
||||
#include "StdInc.h"
|
||||
#include "CObjectClassesHandler.h"
|
||||
|
||||
#include "../filesystem/Filesystem.h"
|
||||
#include "../filesystem/CBinaryReader.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../GameConstants.h"
|
||||
#include "../StringConstants.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CModHandler.h"
|
||||
#include "../JsonNode.h"
|
||||
|
||||
#include "CRewardableConstructor.h"
|
||||
#include "CommonConstructors.h"
|
||||
#include "MapObjects.h"
|
||||
|
||||
/*
|
||||
* CObjectClassesHandler.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
|
||||
*
|
||||
*/
|
||||
|
||||
CObjectClassesHandler::CObjectClassesHandler()
|
||||
{
|
||||
#define SET_HANDLER_CLASS(STRING, CLASSNAME) handlerConstructors[STRING] = std::make_shared<CLASSNAME>;
|
||||
#define SET_HANDLER(STRING, TYPENAME) handlerConstructors[STRING] = std::make_shared<CDefaultObjectTypeHandler<TYPENAME> >
|
||||
|
||||
// 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
|
||||
SET_HANDLER_CLASS("configurable", CRewardableConstructor);
|
||||
SET_HANDLER_CLASS("dwelling", CDwellingInstanceConstructor);
|
||||
SET_HANDLER_CLASS("hero", CHeroInstanceConstructor);
|
||||
SET_HANDLER_CLASS("town", CTownInstanceConstructor);
|
||||
SET_HANDLER_CLASS("bank", CBankInstanceConstructor);
|
||||
|
||||
SET_HANDLER_CLASS("static", CObstacleConstructor);
|
||||
SET_HANDLER_CLASS("", CObstacleConstructor);
|
||||
|
||||
SET_HANDLER("generic", CGObjectInstance);
|
||||
SET_HANDLER("market", CGMarket);
|
||||
SET_HANDLER("cartographer", CCartographer);
|
||||
SET_HANDLER("artifact", CGArtifact);
|
||||
SET_HANDLER("blackMarket", CGBlackMarket);
|
||||
SET_HANDLER("boat", CGBoat);
|
||||
SET_HANDLER("bonusingObject", CGBonusingObject);
|
||||
SET_HANDLER("borderGate", CGBorderGate);
|
||||
SET_HANDLER("borderGuard", CGBorderGuard);
|
||||
SET_HANDLER("monster", CGCreature);
|
||||
SET_HANDLER("denOfThieves", CGDenOfthieves);
|
||||
SET_HANDLER("event", CGEvent);
|
||||
SET_HANDLER("garrison", CGGarrison);
|
||||
SET_HANDLER("heroPlaceholder", CGHeroPlaceholder);
|
||||
SET_HANDLER("keymaster", CGKeymasterTent);
|
||||
SET_HANDLER("lighthouse", CGLighthouse);
|
||||
SET_HANDLER("magi", CGMagi);
|
||||
SET_HANDLER("magicSpring", CGMagicSpring);
|
||||
SET_HANDLER("magicWell", CGMagicWell);
|
||||
SET_HANDLER("market", CGMarket);
|
||||
SET_HANDLER("mine", CGMine);
|
||||
SET_HANDLER("obelisk", CGObelisk);
|
||||
SET_HANDLER("observatory", CGObservatory);
|
||||
SET_HANDLER("onceVisitable", CGOnceVisitable);
|
||||
SET_HANDLER("pandora", CGPandoraBox);
|
||||
SET_HANDLER("pickable", CGPickable);
|
||||
SET_HANDLER("prison", CGHeroInstance);
|
||||
SET_HANDLER("questGuard", CGQuestGuard);
|
||||
SET_HANDLER("resource", CGResource);
|
||||
SET_HANDLER("scholar", CGScholar);
|
||||
SET_HANDLER("seerHut", CGSeerHut);
|
||||
SET_HANDLER("shipyard", CGShipyard);
|
||||
SET_HANDLER("shrine", CGShrine);
|
||||
SET_HANDLER("sign", CGSignBottle);
|
||||
SET_HANDLER("siren", CGSirens);
|
||||
SET_HANDLER("teleport", CGTeleport);
|
||||
SET_HANDLER("university", CGUniversity);
|
||||
SET_HANDLER("oncePerHero", CGVisitableOPH);
|
||||
SET_HANDLER("oncePerWeek", CGVisitableOPW);
|
||||
SET_HANDLER("witch", CGWitchHut);
|
||||
|
||||
#undef SET_HANDLER_CLASS
|
||||
#undef SET_HANDLER
|
||||
}
|
||||
|
||||
std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
|
||||
{
|
||||
CLegacyConfigParser parser("Data/Objects.txt");
|
||||
size_t totalNumber = parser.readNumber(); // first line contains number of objects to read and nothing else
|
||||
parser.endLine();
|
||||
|
||||
for (size_t i=0; i<totalNumber; i++)
|
||||
{
|
||||
ObjectTemplate templ;
|
||||
templ.readTxt(parser);
|
||||
parser.endLine();
|
||||
std::pair<si32, si32> key(templ.id.num, templ.subid);
|
||||
legacyTemplates.insert(std::make_pair(key, templ));
|
||||
}
|
||||
|
||||
std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
|
||||
assert(dataSize == 256);
|
||||
|
||||
CLegacyConfigParser namesParser("Data/ObjNames.txt");
|
||||
for (size_t i=0; i<256; i++)
|
||||
{
|
||||
ret[i]["name"].String() = namesParser.readString();
|
||||
namesParser.endLine();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// selects preferred ID (or subID) for new object
|
||||
template<typename Map>
|
||||
si32 selectNextID(const JsonNode & fixedID, const Map & map, si32 defaultID)
|
||||
{
|
||||
if (!fixedID.isNull() && fixedID.Float() < defaultID)
|
||||
return fixedID.Float(); // H3M object with fixed ID
|
||||
|
||||
if (map.empty())
|
||||
return defaultID; // no objects loaded, keep gap for H3M objects
|
||||
if (map.rbegin()->first > defaultID)
|
||||
return map.rbegin()->first + 1; // some modded objects loaded, return next available
|
||||
|
||||
return defaultID; // some H3M objects loaded, first modded found
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContainter * obj)
|
||||
{
|
||||
if (!handlerConstructors.count(obj->handlerName))
|
||||
{
|
||||
logGlobal->errorStream() << "Handler with name " << obj->handlerName << " was not found!";
|
||||
return;
|
||||
}
|
||||
auto handler = handlerConstructors.at(obj->handlerName)();
|
||||
handler->init(entry);
|
||||
|
||||
si32 id = selectNextID(entry["index"], obj->objects, 1000);
|
||||
handler->setType(obj->id, id);
|
||||
|
||||
if (handler->getTemplates().empty())
|
||||
{
|
||||
auto range = legacyTemplates.equal_range(std::make_pair(obj->id, id));
|
||||
for (auto & templ : boost::make_iterator_range(range.first, range.second))
|
||||
{
|
||||
handler->addTemplate(templ.second);
|
||||
}
|
||||
legacyTemplates.erase(range.first, range.second);
|
||||
}
|
||||
|
||||
obj->objects[id] = handler;
|
||||
logGlobal->debugStream() << "Loaded object " << obj->id << ":" << id;
|
||||
}
|
||||
|
||||
CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(const JsonNode & json)
|
||||
{
|
||||
auto obj = new ObjectContainter();
|
||||
obj->name = json["name"].String();
|
||||
obj->handlerName = json["handler"].String();
|
||||
obj->base = json["base"];
|
||||
obj->id = selectNextID(json["index"], objects, 256);
|
||||
for (auto entry : json["types"].Struct())
|
||||
{
|
||||
loadObjectEntry(entry.second, obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
|
||||
{
|
||||
auto object = loadFromJson(data);
|
||||
objects[object->id] = object;
|
||||
|
||||
VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
|
||||
{
|
||||
auto object = loadFromJson(data);
|
||||
|
||||
assert(objects[index] == nullptr); // ensure that this id was not loaded before
|
||||
objects[index] = object;
|
||||
|
||||
VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::loadSubObject(std::string name, JsonNode config, si32 ID, boost::optional<si32> subID)
|
||||
{
|
||||
config.setType(JsonNode::DATA_STRUCT); // ensure that input is not NULL
|
||||
assert(objects.count(ID));
|
||||
if (subID)
|
||||
{
|
||||
assert(objects.at(ID)->objects.count(subID.get()) == 0);
|
||||
assert(config["index"].isNull());
|
||||
config["index"].Float() = subID.get();
|
||||
}
|
||||
|
||||
std::string oldMeta = config.meta; // FIXME: move into inheritNode?
|
||||
JsonUtils::inherit(config, objects.at(ID)->base);
|
||||
config.setMeta(oldMeta);
|
||||
loadObjectEntry(config, objects[ID]);
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::removeSubObject(si32 ID, si32 subID)
|
||||
{
|
||||
assert(objects.count(ID));
|
||||
assert(objects.at(ID)->objects.count(subID));
|
||||
objects.at(ID)->objects.erase(subID);
|
||||
}
|
||||
|
||||
std::vector<bool> CObjectClassesHandler::getDefaultAllowed() const
|
||||
{
|
||||
return std::vector<bool>(); //TODO?
|
||||
}
|
||||
|
||||
TObjectTypeHandler CObjectClassesHandler::getHandlerFor(si32 type, si32 subtype) const
|
||||
{
|
||||
if (objects.count(type))
|
||||
{
|
||||
if (objects.at(type)->objects.count(subtype))
|
||||
return objects.at(type)->objects.at(subtype);
|
||||
}
|
||||
logGlobal->errorStream() << "Failed to find object of type " << type << ":" << subtype;
|
||||
assert(0); // FIXME: throw error?
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::set<si32> CObjectClassesHandler::knownObjects() const
|
||||
{
|
||||
std::set<si32> ret;
|
||||
|
||||
for (auto entry : objects)
|
||||
ret.insert(entry.first);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::set<si32> CObjectClassesHandler::knownSubObjects(si32 primaryID) const
|
||||
{
|
||||
std::set<si32> ret;
|
||||
|
||||
if (objects.count(primaryID))
|
||||
{
|
||||
for (auto entry : objects.at(primaryID)->objects)
|
||||
ret.insert(entry.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::beforeValidate(JsonNode & object)
|
||||
{
|
||||
for (auto & entry : object["types"].Struct())
|
||||
{
|
||||
JsonUtils::inherit(entry.second, object["base"]);
|
||||
for (auto & templ : entry.second["templates"].Struct())
|
||||
{
|
||||
JsonUtils::inherit(templ.second, entry.second["base"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CObjectClassesHandler::afterLoadFinalization()
|
||||
{
|
||||
for (auto entry : objects)
|
||||
{
|
||||
for (auto obj : entry.second->objects)
|
||||
{
|
||||
obj.second->afterLoadFinalization();
|
||||
if (obj.second->getTemplates().empty())
|
||||
logGlobal->warnStream() << "No templates found for " << entry.first << ":" << obj.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string CObjectClassesHandler::getObjectName(si32 type) const
|
||||
{
|
||||
assert(objects.count(type));
|
||||
return objects.at(type)->name;
|
||||
}
|
||||
|
||||
void AObjectTypeHandler::setType(si32 type, si32 subtype)
|
||||
{
|
||||
this->type = type;
|
||||
this->subtype = subtype;
|
||||
}
|
||||
|
||||
static ui32 loadJsonOrMax(const JsonNode & input)
|
||||
{
|
||||
if (input.isNull())
|
||||
return std::numeric_limits<ui32>::max();
|
||||
else
|
||||
return input.Float();
|
||||
}
|
||||
|
||||
void AObjectTypeHandler::init(const JsonNode & input)
|
||||
{
|
||||
base = input["base"];
|
||||
|
||||
if (!input["rmg"].isNull())
|
||||
{
|
||||
rmgInfo.value = input["rmg"]["value"].Float();
|
||||
rmgInfo.mapLimit = loadJsonOrMax(input["rmg"]["mapLimit"]);
|
||||
rmgInfo.zoneLimit = loadJsonOrMax(input["rmg"]["zoneLimit"]);
|
||||
rmgInfo.rarity = input["rmg"]["rarity"].Float();
|
||||
} // else block is not needed - set in constructor
|
||||
|
||||
for (auto entry : input["templates"].Struct())
|
||||
{
|
||||
entry.second.setType(JsonNode::DATA_STRUCT);
|
||||
JsonUtils::inherit(entry.second, base);
|
||||
|
||||
ObjectTemplate tmpl;
|
||||
tmpl.id = Obj(type);
|
||||
tmpl.subid = subtype;
|
||||
tmpl.stringID = entry.first; // FIXME: create "fullID" - type.object.template?
|
||||
tmpl.readJson(entry.second);
|
||||
templates.push_back(tmpl);
|
||||
}
|
||||
initTypeData(input);
|
||||
}
|
||||
|
||||
bool AObjectTypeHandler::objectFilter(const CGObjectInstance *, const ObjectTemplate &) const
|
||||
{
|
||||
return false; // by default there are no overrides
|
||||
}
|
||||
|
||||
void AObjectTypeHandler::initTypeData(const JsonNode & input)
|
||||
{
|
||||
}
|
||||
|
||||
void AObjectTypeHandler::addTemplate(ObjectTemplate templ)
|
||||
{
|
||||
templ.id = Obj(type);
|
||||
templ.subid = subtype;
|
||||
templates.push_back(templ);
|
||||
}
|
||||
|
||||
void AObjectTypeHandler::addTemplate(JsonNode config)
|
||||
{
|
||||
config.setType(JsonNode::DATA_STRUCT); // ensure that input is not null
|
||||
JsonUtils::inherit(config, base);
|
||||
ObjectTemplate tmpl;
|
||||
tmpl.id = Obj(type);
|
||||
tmpl.subid = subtype;
|
||||
tmpl.stringID = ""; // TODO?
|
||||
tmpl.readJson(config);
|
||||
addTemplate(tmpl);
|
||||
}
|
||||
|
||||
std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates() const
|
||||
{
|
||||
return templates;
|
||||
}
|
||||
|
||||
std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates(si32 terrainType) const// FIXME: replace with ETerrainType
|
||||
{
|
||||
std::vector<ObjectTemplate> templates = getTemplates();
|
||||
std::vector<ObjectTemplate> filtered;
|
||||
|
||||
std::copy_if(templates.begin(), templates.end(), std::back_inserter(filtered), [&](const ObjectTemplate & obj)
|
||||
{
|
||||
return obj.canBePlacedAt(ETerrainType(terrainType));
|
||||
});
|
||||
// H3 defines allowed terrains in a weird way - artifacts, monsters and resources have faulty masks here
|
||||
// Perhaps we should re-define faulty templates and remove this workaround (already done for resources)
|
||||
if (type == Obj::ARTIFACT || type == Obj::MONSTER)
|
||||
return templates;
|
||||
else
|
||||
return filtered;
|
||||
}
|
||||
|
||||
boost::optional<ObjectTemplate> AObjectTypeHandler::getOverride(si32 terrainType, const CGObjectInstance * object) const
|
||||
{
|
||||
std::vector<ObjectTemplate> ret = getTemplates(terrainType);
|
||||
for (auto & tmpl : ret)
|
||||
{
|
||||
if (objectFilter(object, tmpl))
|
||||
return tmpl;
|
||||
}
|
||||
return boost::optional<ObjectTemplate>();
|
||||
}
|
||||
|
||||
const RandomMapInfo & AObjectTypeHandler::getRMGInfo()
|
||||
{
|
||||
return rmgInfo;
|
||||
}
|
||||
|
||||
bool AObjectTypeHandler::isStaticObject()
|
||||
{
|
||||
return false; // most of classes are not static
|
||||
}
|
||||
|
||||
void AObjectTypeHandler::afterLoadFinalization()
|
||||
{
|
||||
}
|
218
lib/mapObjects/CObjectClassesHandler.h
Normal file
218
lib/mapObjects/CObjectClassesHandler.h
Normal file
@ -0,0 +1,218 @@
|
||||
#pragma once
|
||||
|
||||
#include "ObjectTemplate.h"
|
||||
|
||||
#include "../GameConstants.h"
|
||||
#include "../ConstTransitivePtr.h"
|
||||
#include "../IHandlerBase.h"
|
||||
|
||||
/*
|
||||
* CObjectClassesHandler.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class JsonNode;
|
||||
class CRandomGenerator;
|
||||
|
||||
/// Structure that describes placement rules for this object in random map
|
||||
struct RandomMapInfo
|
||||
{
|
||||
/// How valuable this object is, 1k = worthless, 10k = Utopia-level
|
||||
ui32 value;
|
||||
|
||||
/// How many of such objects can be placed on map, 0 = object can not be placed by RMG
|
||||
ui32 mapLimit;
|
||||
|
||||
/// How many of such objects can be placed in one zone, 0 = unplaceable
|
||||
ui32 zoneLimit;
|
||||
|
||||
/// Rarity of object, 5 = extremely rare, 100 = common
|
||||
ui32 rarity;
|
||||
|
||||
RandomMapInfo():
|
||||
value(0),
|
||||
mapLimit(0),
|
||||
zoneLimit(0),
|
||||
rarity(0)
|
||||
{}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & value & mapLimit & zoneLimit & rarity;
|
||||
}
|
||||
};
|
||||
|
||||
class IObjectInfo
|
||||
{
|
||||
public:
|
||||
struct CArmyStructure
|
||||
{
|
||||
ui32 totalStrength;
|
||||
ui32 shootersStrength;
|
||||
ui32 flyersStrength;
|
||||
ui32 walkersStrength;
|
||||
|
||||
CArmyStructure() :
|
||||
totalStrength(0),
|
||||
shootersStrength(0),
|
||||
flyersStrength(0),
|
||||
walkersStrength(0)
|
||||
{}
|
||||
|
||||
bool operator <(const CArmyStructure & other)
|
||||
{
|
||||
return this->totalStrength < other.totalStrength;
|
||||
}
|
||||
};
|
||||
|
||||
/// Returns possible composition of guards. Actual guards would be
|
||||
/// somewhere between these two values
|
||||
virtual CArmyStructure minGuards() const { return CArmyStructure(); }
|
||||
virtual CArmyStructure maxGuards() const { return CArmyStructure(); }
|
||||
|
||||
virtual bool givesResources() const { return false; }
|
||||
|
||||
virtual bool givesExperience() const { return false; }
|
||||
virtual bool givesMana() const { return false; }
|
||||
virtual bool givesMovement() const { return false; }
|
||||
|
||||
virtual bool givesPrimarySkills() const { return false; }
|
||||
virtual bool givesSecondarySkills() const { return false; }
|
||||
|
||||
virtual bool givesArtifacts() const { return false; }
|
||||
virtual bool givesCreatures() const { return false; }
|
||||
virtual bool givesSpells() const { return false; }
|
||||
|
||||
virtual bool givesBonuses() const { return false; }
|
||||
};
|
||||
|
||||
class CGObjectInstance;
|
||||
|
||||
class AObjectTypeHandler : public boost::noncopyable
|
||||
{
|
||||
RandomMapInfo rmgInfo;
|
||||
|
||||
si32 type;
|
||||
si32 subtype;
|
||||
|
||||
JsonNode base; /// describes base template
|
||||
|
||||
std::vector<ObjectTemplate> templates;
|
||||
protected:
|
||||
|
||||
virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||
|
||||
/// initialization for classes that inherit this one
|
||||
virtual void initTypeData(const JsonNode & input);
|
||||
public:
|
||||
virtual ~AObjectTypeHandler(){}
|
||||
|
||||
void setType(si32 type, si32 subtype);
|
||||
|
||||
/// loads generic data from Json structure and passes it towards type-specific constructors
|
||||
void init(const JsonNode & input);
|
||||
|
||||
void addTemplate(ObjectTemplate templ);
|
||||
void addTemplate(JsonNode config);
|
||||
|
||||
/// returns all templates matching parameters
|
||||
std::vector<ObjectTemplate> getTemplates() const;
|
||||
std::vector<ObjectTemplate> getTemplates(si32 terrainType) const;
|
||||
|
||||
/// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle)
|
||||
/// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)
|
||||
boost::optional<ObjectTemplate> getOverride(si32 terrainType, const CGObjectInstance * object) const;
|
||||
|
||||
const RandomMapInfo & getRMGInfo();
|
||||
|
||||
virtual bool isStaticObject();
|
||||
|
||||
virtual void afterLoadFinalization();
|
||||
|
||||
/// Creates object and set up core properties (like ID/subID). Object is NOT initialized
|
||||
/// to allow creating objects before game start (e.g. map loading)
|
||||
virtual CGObjectInstance * create(ObjectTemplate tmpl) const = 0;
|
||||
|
||||
/// Configures object properties. Should be re-entrable, resetting state of the object if necessarily
|
||||
/// This should set remaining properties, including randomized or depending on map
|
||||
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const = 0;
|
||||
|
||||
/// Returns object configuration, if available. Othervice returns NULL
|
||||
virtual std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const = 0;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & type & subtype & templates & rmgInfo;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<AObjectTypeHandler> TObjectTypeHandler;
|
||||
|
||||
class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
|
||||
{
|
||||
/// Small internal structure that contains information on specific group of objects
|
||||
/// (creating separate entity is overcomplicating at least at this point)
|
||||
struct ObjectContainter
|
||||
{
|
||||
si32 id;
|
||||
|
||||
std::string name; // human-readable name
|
||||
std::string handlerName; // ID of handler that controls this object, shoul be determined using hadlerConstructor map
|
||||
|
||||
JsonNode base;
|
||||
std::map<si32, TObjectTypeHandler> objects;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & name & handlerName & base & objects;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::multimap<std::pair<si32, si32>, ObjectTemplate> TTemplatesContainer;
|
||||
|
||||
/// list of object handlers, each of them handles only one type
|
||||
std::map<si32, ObjectContainter * > objects;
|
||||
|
||||
/// map that is filled during contruction with all known handlers. Not serializeable due to usage of std::function
|
||||
std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;
|
||||
|
||||
/// container with H3 templates, used only during loading, no need to serialize it
|
||||
TTemplatesContainer legacyTemplates;
|
||||
|
||||
void loadObjectEntry(const JsonNode & entry, ObjectContainter * obj);
|
||||
ObjectContainter * loadFromJson(const JsonNode & json);
|
||||
public:
|
||||
CObjectClassesHandler();
|
||||
|
||||
std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
|
||||
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||
|
||||
void loadSubObject(std::string name, JsonNode config, si32 ID, boost::optional<si32> subID = boost::optional<si32>());
|
||||
void removeSubObject(si32 ID, si32 subID);
|
||||
|
||||
void beforeValidate(JsonNode & object) override;
|
||||
void afterLoadFinalization() override;
|
||||
|
||||
std::vector<bool> getDefaultAllowed() const override;
|
||||
|
||||
/// Queries to detect loaded objects
|
||||
std::set<si32> knownObjects() const;
|
||||
std::set<si32> knownSubObjects(si32 primaryID) const;
|
||||
|
||||
/// returns handler for specified object (ID-based). ObjectHandler keeps ownership
|
||||
TObjectTypeHandler getHandlerFor(si32 type, si32 subtype) const;
|
||||
|
||||
std::string getObjectName(si32 type) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & objects;
|
||||
}
|
||||
};
|
497
lib/mapObjects/CObjectHandler.cpp
Normal file
497
lib/mapObjects/CObjectHandler.cpp
Normal file
@ -0,0 +1,497 @@
|
||||
/*
|
||||
* CObjectHandler.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 "CObjectHandler.h"
|
||||
|
||||
#include "../NetPacks.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CHeroHandler.h"
|
||||
#include "../CSoundBase.h"
|
||||
|
||||
#include "CObjectClassesHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
IGameCallback * IObjectInterface::cb = nullptr;
|
||||
|
||||
///helpers
|
||||
static void openWindow(const OpenWindow::EWindow type, const int id1, const int id2 = -1)
|
||||
{
|
||||
OpenWindow ow;
|
||||
ow.window = type;
|
||||
ow.id1 = id1;
|
||||
ow.id2 = id2;
|
||||
IObjectInterface::cb->sendAndApply(&ow);
|
||||
}
|
||||
|
||||
static void showInfoDialog(const PlayerColor playerID, const ui32 txtID, const ui16 soundID)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundID;
|
||||
iw.player = playerID;
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,txtID);
|
||||
IObjectInterface::cb->sendAndApply(&iw);
|
||||
}
|
||||
|
||||
/*static void showInfoDialog(const ObjectInstanceID heroID, const ui32 txtID, const ui16 soundID)
|
||||
{
|
||||
const PlayerColor playerID = IObjectInterface::cb->getOwner(heroID);
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}*/
|
||||
|
||||
static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 soundID)
|
||||
{
|
||||
const PlayerColor playerID = h->getOwner();
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}
|
||||
|
||||
static std::string & visitedTxt(const bool visited)
|
||||
{
|
||||
int id = visited ? 352 : 353;
|
||||
return VLC->generaltexth->allTexts[id];
|
||||
}
|
||||
|
||||
///IObjectInterface
|
||||
void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
|
||||
{}
|
||||
|
||||
void IObjectInterface::onHeroLeave(const CGHeroInstance * h) const
|
||||
{}
|
||||
|
||||
void IObjectInterface::newTurn () const
|
||||
{}
|
||||
|
||||
IObjectInterface::~IObjectInterface()
|
||||
{}
|
||||
|
||||
IObjectInterface::IObjectInterface()
|
||||
{}
|
||||
|
||||
void IObjectInterface::initObj()
|
||||
{}
|
||||
|
||||
void IObjectInterface::setProperty( ui8 what, ui32 val )
|
||||
{}
|
||||
|
||||
bool IObjectInterface::wasVisited (PlayerColor player) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool IObjectInterface::wasVisited (const CGHeroInstance * h) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void IObjectInterface::postInit()
|
||||
{}
|
||||
|
||||
void IObjectInterface::preInit()
|
||||
{}
|
||||
|
||||
void IObjectInterface::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
||||
{}
|
||||
|
||||
void IObjectInterface::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
||||
{}
|
||||
|
||||
void IObjectInterface::garrisonDialogClosed(const CGHeroInstance *hero) const
|
||||
{}
|
||||
|
||||
void IObjectInterface::heroLevelUpDone(const CGHeroInstance *hero) const
|
||||
{}
|
||||
|
||||
CObjectHandler::CObjectHandler()
|
||||
{
|
||||
logGlobal->traceStream() << "\t\tReading resources prices ";
|
||||
const JsonNode config2(ResourceID("config/resources.json"));
|
||||
for(const JsonNode &price : config2["resources_prices"].Vector())
|
||||
{
|
||||
resVals.push_back(price.Float());
|
||||
}
|
||||
logGlobal->traceStream() << "\t\tDone loading resource prices!";
|
||||
}
|
||||
|
||||
PlayerColor CGObjectInstance::getOwner() const
|
||||
{
|
||||
//if (state)
|
||||
// return state->owner;
|
||||
//else
|
||||
return tempOwner; //won't have owner
|
||||
}
|
||||
|
||||
CGObjectInstance::CGObjectInstance():
|
||||
pos(-1,-1,-1),
|
||||
ID(Obj::NO_OBJ),
|
||||
subID(-1),
|
||||
tempOwner(PlayerColor::UNFLAGGABLE),
|
||||
blockVisit(false)
|
||||
{
|
||||
}
|
||||
CGObjectInstance::~CGObjectInstance()
|
||||
{
|
||||
//if (state)
|
||||
// delete state;
|
||||
//state=nullptr;
|
||||
}
|
||||
|
||||
const std::string & CGObjectInstance::getHoverText() const
|
||||
{
|
||||
return hoverName;
|
||||
}
|
||||
void CGObjectInstance::setOwner(PlayerColor ow)
|
||||
{
|
||||
//if (state)
|
||||
// state->owner = ow;
|
||||
//else
|
||||
tempOwner = ow;
|
||||
}
|
||||
int CGObjectInstance::getWidth() const//returns width of object graphic in tiles
|
||||
{
|
||||
return appearance.getWidth();
|
||||
}
|
||||
int CGObjectInstance::getHeight() const //returns height of object graphic in tiles
|
||||
{
|
||||
return appearance.getHeight();
|
||||
}
|
||||
bool CGObjectInstance::visitableAt(int x, int y) const //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
|
||||
{
|
||||
return appearance.isVisitableAt(pos.x - x, pos.y - y);
|
||||
}
|
||||
bool CGObjectInstance::blockingAt(int x, int y) const
|
||||
{
|
||||
return appearance.isBlockedAt(pos.x - x, pos.y - y);
|
||||
}
|
||||
|
||||
bool CGObjectInstance::coveringAt(int x, int y) const
|
||||
{
|
||||
return appearance.isVisibleAt(pos.x - x, pos.y - y);
|
||||
}
|
||||
|
||||
std::set<int3> CGObjectInstance::getBlockedPos() const
|
||||
{
|
||||
std::set<int3> ret;
|
||||
for(int w=0; w<getWidth(); ++w)
|
||||
{
|
||||
for(int h=0; h<getHeight(); ++h)
|
||||
{
|
||||
if (appearance.isBlockedAt(w, h))
|
||||
ret.insert(int3(pos.x - w, pos.y - h, pos.z));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::set<int3> CGObjectInstance::getBlockedOffsets() const
|
||||
{
|
||||
std::set<int3> ret;
|
||||
for(int w=0; w<getWidth(); ++w)
|
||||
{
|
||||
for(int h=0; h<getHeight(); ++h)
|
||||
{
|
||||
if (appearance.isBlockedAt(w, h))
|
||||
ret.insert(int3(-w, -h, 0));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool CGObjectInstance::operator<(const CGObjectInstance & cmp) const //screen printing priority comparing
|
||||
{
|
||||
if (appearance.printPriority != cmp.appearance.printPriority)
|
||||
return appearance.printPriority > cmp.appearance.printPriority;
|
||||
|
||||
if(pos.y != cmp.pos.y)
|
||||
return pos.y < cmp.pos.y;
|
||||
|
||||
if(cmp.ID==Obj::HERO && ID!=Obj::HERO)
|
||||
return true;
|
||||
if(cmp.ID!=Obj::HERO && ID==Obj::HERO)
|
||||
return false;
|
||||
|
||||
if(!isVisitable() && cmp.isVisitable())
|
||||
return true;
|
||||
if(!cmp.isVisitable() && isVisitable())
|
||||
return false;
|
||||
if(this->pos.x<cmp.pos.x)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGObjectInstance::setType(si32 ID, si32 subID)
|
||||
{
|
||||
const TerrainTile &tile = cb->gameState()->map->getTile(visitablePos());
|
||||
|
||||
this->ID = Obj(ID);
|
||||
this->subID = subID;
|
||||
|
||||
//recalculate blockvis tiles - new appearance might have different blockmap than before
|
||||
cb->gameState()->map->removeBlockVisTiles(this, true);
|
||||
auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
|
||||
appearance = handler->getTemplates(tile.terType).at(0);
|
||||
cb->gameState()->map->addBlockVisTiles(this);
|
||||
}
|
||||
|
||||
void CGObjectInstance::initObj()
|
||||
{
|
||||
switch(ID)
|
||||
{
|
||||
case Obj::TAVERN:
|
||||
blockVisit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CGObjectInstance::setProperty( ui8 what, ui32 val )
|
||||
{
|
||||
switch(what)
|
||||
{
|
||||
case ObjProperty::OWNER:
|
||||
tempOwner = PlayerColor(val);
|
||||
break;
|
||||
case ObjProperty::BLOCKVIS:
|
||||
blockVisit = val;
|
||||
break;
|
||||
case ObjProperty::ID:
|
||||
ID = Obj(val);
|
||||
break;
|
||||
case ObjProperty::SUBID:
|
||||
subID = val;
|
||||
break;
|
||||
}
|
||||
setPropertyDer(what, val);
|
||||
}
|
||||
|
||||
void CGObjectInstance::setPropertyDer( ui8 what, ui32 val )
|
||||
{}
|
||||
|
||||
int3 CGObjectInstance::getSightCenter() const
|
||||
{
|
||||
//return vistiable tile if possible
|
||||
for(int i=0; i < 8; i++)
|
||||
for(int j=0; j < 6; j++)
|
||||
if(visitableAt(i,j))
|
||||
return(pos + int3(i-7, j-5, 0));
|
||||
return pos;
|
||||
}
|
||||
|
||||
int CGObjectInstance::getSightRadious() const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
void CGObjectInstance::getSightTiles(std::unordered_set<int3, ShashInt3> &tiles) const //returns reference to the set
|
||||
{
|
||||
cb->getTilesInRange(tiles, getSightCenter(), getSightRadious(), tempOwner, 1);
|
||||
}
|
||||
void CGObjectInstance::hideTiles(PlayerColor ourplayer, int radius) const
|
||||
{
|
||||
for (auto i = cb->gameState()->teams.begin(); i != cb->gameState()->teams.end(); i++)
|
||||
{
|
||||
if ( !vstd::contains(i->second.players, ourplayer ))//another team
|
||||
{
|
||||
for (auto & elem : i->second.players)
|
||||
if ( cb->getPlayer(elem)->status == EPlayerStatus::INGAME )//seek for living player (if any)
|
||||
{
|
||||
FoWChange fw;
|
||||
fw.mode = 0;
|
||||
fw.player = elem;
|
||||
cb->getTilesInRange (fw.tiles, pos, radius, (elem), -1);
|
||||
cb->sendAndApply (&fw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int3 CGObjectInstance::getVisitableOffset() const
|
||||
{
|
||||
for(int y = 0; y < appearance.getHeight(); y++)
|
||||
for (int x = 0; x < appearance.getWidth(); x++)
|
||||
if (appearance.isVisitableAt(x, y))
|
||||
return int3(x,y,0);
|
||||
|
||||
logGlobal->warnStream() << "Warning: getVisitableOffset called on non-visitable obj!";
|
||||
return int3(0,0,0);
|
||||
}
|
||||
|
||||
void CGObjectInstance::getNameVis( std::string &hname ) const
|
||||
{
|
||||
const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
|
||||
hname = VLC->objtypeh->getObjectName(ID);
|
||||
if(h)
|
||||
{
|
||||
const bool visited = h->hasBonusFrom(Bonus::OBJECT,ID);
|
||||
hname + " " + visitedTxt(visited);
|
||||
}
|
||||
}
|
||||
|
||||
void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) const
|
||||
{
|
||||
GiveBonus gbonus;
|
||||
gbonus.bonus.type = Bonus::NONE;
|
||||
gbonus.id = heroID.getNum();
|
||||
gbonus.bonus.duration = duration;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
}
|
||||
|
||||
void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
switch(ID)
|
||||
{
|
||||
case Obj::HILL_FORT:
|
||||
{
|
||||
openWindow(OpenWindow::HILL_FORT_WINDOW,id.getNum(),h->id.getNum());
|
||||
}
|
||||
break;
|
||||
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.
|
||||
showInfoDialog(h,114,soundBase::GETPROTECTION);
|
||||
}
|
||||
break;
|
||||
case Obj::TAVERN:
|
||||
{
|
||||
openWindow(OpenWindow::TAVERN_WINDOW,h->id.getNum(),id.getNum());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ui8 CGObjectInstance::getPassableness() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int3 CGObjectInstance::visitablePos() const
|
||||
{
|
||||
return pos - getVisitableOffset();
|
||||
}
|
||||
|
||||
bool CGObjectInstance::isVisitable() const
|
||||
{
|
||||
return appearance.isVisitable();
|
||||
}
|
||||
|
||||
bool CGObjectInstance::passableFor(PlayerColor color) const
|
||||
{
|
||||
return getPassableness() & 1<<color.getNum();
|
||||
}
|
||||
|
||||
CGObjectInstanceBySubIdFinder::CGObjectInstanceBySubIdFinder(CGObjectInstance * obj) : obj(obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CGObjectInstanceBySubIdFinder::operator()(CGObjectInstance * obj) const
|
||||
{
|
||||
return this->obj->subID == obj->subID;
|
||||
}
|
||||
|
||||
int3 IBoatGenerator::bestLocation() const
|
||||
{
|
||||
std::vector<int3> offsets;
|
||||
getOutOffsets(offsets);
|
||||
|
||||
for (auto & offset : offsets)
|
||||
{
|
||||
if (const TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offset, false)) //tile is in the map
|
||||
{
|
||||
if (tile->terType == ETerrainType::WATER && (!tile->blocked || tile->blockingObjects.front()->ID == 8)) //and is water and is not blocked or is blocked by boat
|
||||
return o->pos + offset;
|
||||
}
|
||||
}
|
||||
return int3 (-1,-1,-1);
|
||||
}
|
||||
|
||||
IBoatGenerator::EGeneratorState IBoatGenerator::shipyardStatus() const
|
||||
{
|
||||
int3 tile = bestLocation();
|
||||
const TerrainTile *t = IObjectInterface::cb->getTile(tile);
|
||||
if(!t)
|
||||
return TILE_BLOCKED; //no available water
|
||||
else if(!t->blockingObjects.size())
|
||||
return GOOD; //OK
|
||||
else if(t->blockingObjects.front()->ID == Obj::BOAT)
|
||||
return BOAT_ALREADY_BUILT; //blocked with boat
|
||||
else
|
||||
return TILE_BLOCKED; //blocked
|
||||
}
|
||||
|
||||
int IBoatGenerator::getBoatType() const
|
||||
{
|
||||
//We make good ships by default
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
IBoatGenerator::IBoatGenerator(const CGObjectInstance *O)
|
||||
: o(O)
|
||||
{
|
||||
}
|
||||
|
||||
void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visitor) const
|
||||
{
|
||||
switch(shipyardStatus())
|
||||
{
|
||||
case BOAT_ALREADY_BUILT:
|
||||
out.addTxt(MetaString::GENERAL_TXT, 51);
|
||||
break;
|
||||
case TILE_BLOCKED:
|
||||
if(visitor)
|
||||
{
|
||||
out.addTxt(MetaString::GENERAL_TXT, 134);
|
||||
out.addReplacement(visitor->name);
|
||||
}
|
||||
else
|
||||
out.addTxt(MetaString::ADVOB_TXT, 189);
|
||||
break;
|
||||
case NO_WATER:
|
||||
logGlobal->errorStream() << "Shipyard without water!!! " << o->pos << "\t" << o->id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void IShipyard::getBoatCost( std::vector<si32> &cost ) const
|
||||
{
|
||||
cost.resize(GameConstants::RESOURCE_QUANTITY);
|
||||
cost[Res::WOOD] = 10;
|
||||
cost[Res::GOLD] = 1000;
|
||||
}
|
||||
|
||||
IShipyard::IShipyard(const CGObjectInstance *O)
|
||||
: IBoatGenerator(O)
|
||||
{
|
||||
}
|
||||
|
||||
IShipyard * IShipyard::castFrom( CGObjectInstance *obj )
|
||||
{
|
||||
if(!obj)
|
||||
return nullptr;
|
||||
|
||||
if(obj->ID == Obj::TOWN)
|
||||
{
|
||||
return static_cast<CGTownInstance*>(obj);
|
||||
}
|
||||
else if(obj->ID == Obj::SHIPYARD)
|
||||
{
|
||||
return static_cast<CGShipyard*>(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const IShipyard * IShipyard::castFrom( const CGObjectInstance *obj )
|
||||
{
|
||||
return castFrom(const_cast<CGObjectInstance*>(obj));
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user