mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Finally shattered CObjectHandler.cpp into tiny bits
- This file is now split into multiple smaller files in mapObjects directory - CObjectHandler itself now contains only core classes (Handler itself, CGObject and interfaces) - Cleaned up excessive #include's through whole project
This commit is contained in:
parent
0afdfa529c
commit
652ceb2bde
@ -3,7 +3,7 @@
|
||||
#include "VCAI.h"
|
||||
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/Connection.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
@ -200,4 +200,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,7 +2,7 @@
|
||||
#include "Fuzzy.h"
|
||||
#include <limits>
|
||||
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../CCallback.h"
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/CBuildingHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
|
@ -2,8 +2,7 @@
|
||||
#include "VCAI.h"
|
||||
#include "Goals.h"
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/mapObjects/CRewardableObject.h"
|
||||
#include "../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "Goals.h"
|
||||
#include "../../lib/AI_Base.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../../lib/mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
#include "../../lib/CThreadHelper.h"
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/Connection.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "lib/CGeneralTextHandler.h"
|
||||
#include "lib/CHeroHandler.h"
|
||||
#include "lib/mapObjects/CObjectHandler.h"
|
||||
//#include "lib/mapObjects/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/mapObjects/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/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "CAdvmapInterface.h"
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
|
||||
#include "gui/CGuiHandler.h"
|
||||
|
@ -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/mapObjects/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
|
||||
@ -953,4 +953,4 @@ void CHeroItem::onArtChange(int tabIndex)
|
||||
//redraw item after background change
|
||||
if (active)
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "CMessage.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CScriptingModule.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
@ -44,7 +44,7 @@
|
||||
#ifdef _WIN32
|
||||
#include "SDL_syswm.h"
|
||||
#endif
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/UnlockGuard.h"
|
||||
#include "CMT.h"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "StdInc.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "CAdvmapInterface.h"
|
||||
#include "battle/CBattleInterface.h"
|
||||
#include "battle/CBattleInterfaceClasses.h"
|
||||
@ -21,7 +21,7 @@
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/Connection.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
|
@ -11,11 +11,11 @@
|
||||
#include "gui/CCursorHandler.h"
|
||||
#include "CAnimation.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/mapping/CCampaignHandler.h"
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/CIntObjectClasses.h"
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "Graphics.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "CVideoHandler.h"
|
||||
|
@ -11,11 +11,11 @@
|
||||
#include "../lib/BattleState.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/CBuildingHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/Connection.h"
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CondSh.h"
|
||||
|
@ -12,13 +12,13 @@
|
||||
#include "../CCallback.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CCreatureHandler.h"
|
||||
#include "CBitmapHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/JsonNode.h"
|
||||
#include "../lib/vcmi_endian.h"
|
||||
|
@ -9,9 +9,9 @@
|
||||
#include "CGameInfo.h"
|
||||
#include "../lib/Connection.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/VCMI_Lib.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "../CAdvmapInterface.h"
|
||||
#include "../CAnimation.h"
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
# include "../CDefHandler.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CVideoHandler.h"
|
||||
|
@ -14,12 +14,12 @@
|
||||
#include "CBitmapHandler.h"
|
||||
#include "gui/SDL_Extensions.h"
|
||||
#include "CGameInfo.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/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "CDefHandler.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
|
@ -4,12 +4,14 @@
|
||||
#include "BattleHex.h"
|
||||
#include "HeroBonus.h"
|
||||
#include "CCreatureSet.h"
|
||||
#include "mapObjects/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 "mapObjects/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
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "CModHandler.h"
|
||||
#include "StringConstants.h"
|
||||
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
/*
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "CCreatureHandler.h"
|
||||
#include "VCMI_Lib.h"
|
||||
#include "CModHandler.h"
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
#include "mapObjects/CGHeroInstance.h"
|
||||
#include "IGameCallback.h"
|
||||
#include "CGameState.h"
|
||||
#include "CGeneralTextHandler.h"
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include "IGameCallback.h"
|
||||
#include "ResourceSet.h"
|
||||
#include "int3.h"
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
//#include "mapObjects/CObjectHandler.h"
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "mapObjects/CObjectHandler.h" //for hero specialty
|
||||
#include <math.h>
|
||||
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
/*
|
||||
* CHeroHandler.cpp, part of VCMI engine
|
||||
*
|
||||
|
@ -6,19 +6,6 @@ include_directories(${Boost_INCLUDE_DIRS} ${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}
|
||||
|
||||
set(lib_SRCS
|
||||
StdInc.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
|
||||
|
||||
filesystem/AdapterLoaders.cpp
|
||||
filesystem/CCompressedStream.cpp
|
||||
@ -32,10 +19,18 @@ set(lib_SRCS
|
||||
filesystem/Filesystem.cpp
|
||||
filesystem/ResourceID.cpp
|
||||
|
||||
mapObjects/CGArmedInstance.cpp
|
||||
mapObjects/CGBank.cpp
|
||||
mapObjects/CGHeroInstance.cpp
|
||||
mapObjects/CGMarket.cpp
|
||||
mapObjects/CGPandoraBox.cpp
|
||||
mapObjects/CGTownInstance.cpp
|
||||
mapObjects/CObjectClassesHandler.cpp
|
||||
mapObjects/CObjectHandler.cpp
|
||||
mapObjects/CQuest.cpp
|
||||
mapObjects/CRewardableConstructor.cpp
|
||||
mapObjects/CRewardableObject.cpp
|
||||
mapObjects/MiscObjects.cpp
|
||||
mapObjects/ObjectTemplate.cpp
|
||||
|
||||
logging/CBasicLogConfigurator.cpp
|
||||
@ -85,6 +80,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
|
||||
@ -93,6 +102,8 @@ set(lib_HEADERS
|
||||
filesystem/CInputStream.h
|
||||
filesystem/ISimpleResourceLoader.h
|
||||
|
||||
mapObjects/MapObjects.h
|
||||
|
||||
AI_Base.h
|
||||
CondSh.h
|
||||
ConstTransitivePtr.h
|
||||
|
@ -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 "mapObjects/CObjectHandler.h" //for CArmedInstance
|
||||
#include "mapObjects/CGHeroInstance.h"
|
||||
#include "mapping/CCampaignHandler.h" //for CCampaignState
|
||||
#include "rmg/CMapGenerator.h" // for CMapGenOptions
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "CBonusTypeHandler.h"
|
||||
|
||||
#include "Connection.h" // for SAVEGAME_MAGIC
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
void CPrivilagedInfoCallback::getFreeTiles (std::vector<int3> &tiles) const
|
||||
{
|
||||
|
@ -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"
|
||||
|
128
lib/mapObjects/CGArmedInstance.cpp
Normal file
128
lib/mapObjects/CGArmedInstance.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 "CGArmedInstance.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/CGArmedInstance.h
Normal file
40
lib/mapObjects/CGArmedInstance.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "../CCreatureSet.h"
|
||||
|
||||
/*
|
||||
* CObjectHandler.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);
|
||||
}
|
||||
};
|
443
lib/mapObjects/CGBank.cpp
Normal file
443
lib/mapObjects/CGBank.cpp
Normal file
@ -0,0 +1,443 @@
|
||||
/*
|
||||
* 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 "CGBank.h"
|
||||
|
||||
#include "NetPacks.h"
|
||||
#include "CGeneralTextHandler.h"
|
||||
#include "../client/CSoundBase.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
///helpers
|
||||
static std::string & visitedTxt(const bool visited)
|
||||
{
|
||||
int id = visited ? 352 : 353;
|
||||
return VLC->generaltexth->allTexts[id];
|
||||
}
|
||||
|
||||
void CBank::initObj()
|
||||
{
|
||||
index = VLC->objh->bankObjToIndex(this);
|
||||
bc = nullptr;
|
||||
daycounter = 0;
|
||||
multiplier = 1;
|
||||
}
|
||||
const std::string & CBank::getHoverText() const
|
||||
{
|
||||
bool visited = (bc == nullptr);
|
||||
hoverName = VLC->objh->creBanksNames[index] + " " + visitedTxt(visited);
|
||||
return hoverName;
|
||||
}
|
||||
void CBank::reset(ui16 var1) //prevents desync
|
||||
{
|
||||
ui8 chance = 0;
|
||||
for (auto & elem : VLC->objh->banksInfo[index])
|
||||
{
|
||||
if (var1 < (chance += elem->chance))
|
||||
{
|
||||
bc = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
artifacts.clear();
|
||||
}
|
||||
|
||||
void CBank::initialize() const
|
||||
{
|
||||
cb->setObjProperty(id, ObjProperty::BANK_RESET, cb->gameState()->getRandomGenerator().nextInt()); //synchronous reset
|
||||
|
||||
for (ui8 i = 0; i <= 3; i++)
|
||||
{
|
||||
for (ui8 n = 0; n < bc->artifacts[i]; n++)
|
||||
{
|
||||
CArtifact::EartClass artClass;
|
||||
switch(i)
|
||||
{
|
||||
case 0: artClass = CArtifact::ART_TREASURE; break;
|
||||
case 1: artClass = CArtifact::ART_MINOR; break;
|
||||
case 2: artClass = CArtifact::ART_MAJOR; break;
|
||||
case 3: artClass = CArtifact::ART_RELIC; break;
|
||||
default: assert(0); continue;
|
||||
}
|
||||
|
||||
int artID = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), artClass);
|
||||
cb->setObjProperty(id, ObjProperty::BANK_ADD_ARTIFACT, artID);
|
||||
}
|
||||
}
|
||||
|
||||
cb->setObjProperty(id, ObjProperty::BANK_INIT_ARMY, cb->gameState()->getRandomGenerator().nextInt()); //get army
|
||||
}
|
||||
void CBank::setPropertyDer (ui8 what, ui32 val)
|
||||
/// random values are passed as arguments and processed identically on all clients
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case ObjProperty::BANK_DAYCOUNTER: //daycounter
|
||||
if (val == 0)
|
||||
daycounter = 1; //yes, 1
|
||||
else
|
||||
daycounter++;
|
||||
break;
|
||||
case ObjProperty::BANK_MULTIPLIER: //multiplier, in percent
|
||||
multiplier = val / 100.0;
|
||||
break;
|
||||
case 13: //bank preset
|
||||
bc = VLC->objh->banksInfo[index][val];
|
||||
break;
|
||||
case ObjProperty::BANK_RESET:
|
||||
reset (val%100);
|
||||
break;
|
||||
case ObjProperty::BANK_CLEAR_CONFIG:
|
||||
bc = nullptr;
|
||||
break;
|
||||
case ObjProperty::BANK_CLEAR_ARTIFACTS: //remove rewards from Derelict Ship
|
||||
artifacts.clear();
|
||||
break;
|
||||
case ObjProperty::BANK_INIT_ARMY: //set ArmedInstance army
|
||||
{
|
||||
int upgraded = 0;
|
||||
if (val%100 < bc->upgradeChance) //once again anti-desync
|
||||
upgraded = 1;
|
||||
switch (bc->guards.size())
|
||||
{
|
||||
case 1:
|
||||
for (int i = 0; i < 4; ++i)
|
||||
setCreature (SlotID(i), bc->guards[0].first, bc->guards[0].second / 5 );
|
||||
setCreature (SlotID(4), CreatureID(bc->guards[0].first + upgraded), bc->guards[0].second / 5 );
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
if (bc->guards.back().second) //all stacks are present
|
||||
{
|
||||
for (auto & elem : bc->guards)
|
||||
{
|
||||
setCreature (SlotID(stacksCount()), elem.first, elem.second);
|
||||
}
|
||||
}
|
||||
else if (bc->guards[2].second)//Wraiths are present, split two stacks in Crypt
|
||||
{
|
||||
setCreature (SlotID(0), bc->guards[0].first, bc->guards[0].second / 2 );
|
||||
setCreature (SlotID(1), bc->guards[1].first, bc->guards[1].second / 2);
|
||||
setCreature (SlotID(2), CreatureID(bc->guards[2].first + upgraded), bc->guards[2].second);
|
||||
setCreature (SlotID(3), bc->guards[1].first, bc->guards[1].second / 2 );
|
||||
setCreature (SlotID(4), bc->guards[0].first, bc->guards[0].second - (bc->guards[0].second / 2) );
|
||||
|
||||
}
|
||||
else //split both stacks
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) //skellies
|
||||
setCreature (SlotID(2*i), bc->guards[0].first, bc->guards[0].second / 3);
|
||||
for (int i = 0; i < 2; ++i) //zombies
|
||||
setCreature (SlotID(2*i+1), bc->guards[1].first, bc->guards[1].second / 2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logGlobal->warnStream() << "Error: Unexpected army data: " << bc->guards.size() <<" items found";
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ObjProperty::BANK_ADD_ARTIFACT: //add Artifact
|
||||
{
|
||||
artifacts.push_back (val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::newTurn() const
|
||||
{
|
||||
if (bc == nullptr)
|
||||
{
|
||||
if (cb->getDate() == 1)
|
||||
initialize(); //initialize on first day
|
||||
else if (daycounter >= 28 && (subID < 13 || subID > 16)) //no reset for Emissaries
|
||||
{
|
||||
initialize();
|
||||
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 0); //daycounter 0
|
||||
if (ID == Obj::DERELICT_SHIP && cb->getDate() > 1)
|
||||
{
|
||||
cb->setObjProperty (id, ObjProperty::BANK_MULTIPLIER, 0);//ugly hack to make derelict ships usable only once
|
||||
cb->setObjProperty (id, ObjProperty::BANK_CLEAR_ARTIFACTS, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 1); //daycounter++
|
||||
}
|
||||
}
|
||||
bool CBank::wasVisited (PlayerColor player) const
|
||||
{
|
||||
return !bc;
|
||||
}
|
||||
|
||||
void CBank::onHeroVisit (const CGHeroInstance * h) const
|
||||
{
|
||||
if (bc)
|
||||
{
|
||||
int banktext = 0;
|
||||
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;
|
||||
}
|
||||
BlockingDialog bd (true, false);
|
||||
bd.player = h->getOwner();
|
||||
bd.soundID = soundBase::ROGUE;
|
||||
bd.text.addTxt(MetaString::ADVOB_TXT,banktext);
|
||||
if (ID == Obj::CREATURE_BANK)
|
||||
bd.text.addReplacement(VLC->objh->creBanksNames[index]);
|
||||
cb->showBlockingDialog (&bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::GRAVEYARD;
|
||||
iw.player = h->getOwner();
|
||||
if (ID == Obj::CRYPT) //morale penalty for empty Crypt
|
||||
{
|
||||
GiveBonus gbonus;
|
||||
gbonus.id = h->id.getNum();
|
||||
gbonus.bonus.duration = Bonus::ONE_BATTLE;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
gbonus.bdescr << "\n" << VLC->generaltexth->arraytxt[98];
|
||||
gbonus.bonus.type = Bonus::MORALE;
|
||||
gbonus.bonus.val = -1;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
iw.text << VLC->generaltexth->advobtxt[120];
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text << VLC->generaltexth->advobtxt[33];
|
||||
iw.text.addReplacement(VLC->objh->creBanksNames[index]);
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
||||
{
|
||||
if (result.winner == 0)
|
||||
{
|
||||
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 (multiplier)
|
||||
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->resources.size() != 0)
|
||||
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->resources.size())
|
||||
textID = 124;
|
||||
else
|
||||
textID = 123;
|
||||
break;
|
||||
}
|
||||
|
||||
//grant resources
|
||||
if (textID != 42) //empty derelict ship gives no cash
|
||||
{
|
||||
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 : 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)
|
||||
{
|
||||
iw.text.addReplacement(MetaString::CRE_PL_NAMES, result.casualties[1].begin()->first);
|
||||
iw.text.addReplacement(loot.buildList());
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
loot.clear();
|
||||
iw.components.clear();
|
||||
iw.text.clear();
|
||||
|
||||
//grant creatures
|
||||
CCreatureSet ourArmy;
|
||||
for (auto it = bc->creatures.cbegin(); it != bc->creatures.cend(); it++)
|
||||
{
|
||||
SlotID slot = ourArmy.getSlotFor(it->first);
|
||||
ourArmy.addToSlot(slot, it->first, it->second);
|
||||
}
|
||||
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_CONFIG, 0); //bc = nullptr
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
||||
{
|
||||
if (answer)
|
||||
{
|
||||
cb->startBattleI(hero, this, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CGPyramid::initObj()
|
||||
{
|
||||
std::vector<SpellID> available;
|
||||
cb->getAllowedSpells (available, 5);
|
||||
if (available.size())
|
||||
{
|
||||
bc = VLC->objh->banksInfo[21].front(); //TODO: remove hardcoded value?
|
||||
spell = *RandomGeneratorUtil::nextItem(available, cb->gameState()->getRandomGenerator());
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->errorStream() <<"No spells available for Pyramid! Object set to empty.";
|
||||
}
|
||||
setPropertyDer(ObjProperty::BANK_INIT_ARMY, cb->gameState()->getRandomGenerator().nextInt()); //set guards at game start
|
||||
}
|
||||
const std::string & CGPyramid::getHoverText() const
|
||||
{
|
||||
hoverName = VLC->objh->creBanksNames[21]+ " " + visitedTxt((bc==nullptr));
|
||||
return hoverName;
|
||||
}
|
||||
void CGPyramid::onHeroVisit (const CGHeroInstance * h) const
|
||||
{
|
||||
if (bc)
|
||||
{
|
||||
BlockingDialog bd (true, false);
|
||||
bd.player = h->getOwner();
|
||||
bd.soundID = soundBase::MYSTERY;
|
||||
bd.text << VLC->generaltexth->advobtxt[105];
|
||||
cb->showBlockingDialog(&bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = h->getOwner();
|
||||
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);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
}
|
||||
|
||||
void CGPyramid::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
||||
{
|
||||
if (result.winner == 0)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = hero->getOwner();
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 106);
|
||||
iw.text.addTxt (MetaString::SPELL_NAME, spell);
|
||||
if (!hero->getArt(ArtifactPosition::SPELLBOOK))
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 109); //no spellbook
|
||||
else if (hero->getSecSkillLevel(SecondarySkill::WISDOM) < 3)
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 108); //no expert Wisdom
|
||||
else
|
||||
{
|
||||
std::set<SpellID> spells;
|
||||
spells.insert (SpellID(spell));
|
||||
cb->changeSpells (hero, true, spells);
|
||||
iw.components.push_back(Component (Component::SPELL, spell, 0, 0));
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->setObjProperty (id, ObjProperty::BANK_CLEAR_CONFIG, 0);
|
||||
}
|
||||
}
|
59
lib/mapObjects/CGBank.h
Normal file
59
lib/mapObjects/CGBank.h
Normal file
@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CGArmedInstance.h"
|
||||
|
||||
/*
|
||||
* CObjectHandler.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 CBank : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
int index; //banks have unusal numbering - see ZCRBANK.txt and initObj()
|
||||
BankConfig *bc;
|
||||
double multiplier; //for improved banks script
|
||||
std::vector<ui32> artifacts; //fixed and deterministic
|
||||
ui32 daycounter;
|
||||
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
void initialize() const;
|
||||
void reset(ui16 var1);
|
||||
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 & index & multiplier & artifacts & daycounter & bc;
|
||||
}
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
};
|
||||
class DLL_LINKAGE CGPyramid : public CBank
|
||||
{
|
||||
public:
|
||||
ui16 spell;
|
||||
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
void newTurn() const override {}; //empty, no reset
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CBank&>(*this);
|
||||
h & spell;
|
||||
}
|
||||
};
|
1368
lib/mapObjects/CGHeroInstance.cpp
Normal file
1368
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 "CGArmedInstance.h"
|
||||
|
||||
#include "../CArtHandler.h" // For CArtifactSet
|
||||
#include "../CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
* CObjectHandler.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
|
||||
}
|
||||
};
|
334
lib/mapObjects/CGMarket.cpp
Normal file
334
lib/mapObjects/CGMarket.cpp
Normal file
@ -0,0 +1,334 @@
|
||||
/*
|
||||
* 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 "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"
|
||||
|
||||
/*
|
||||
* CObjectHandler.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 @@
|
||||
/*
|
||||
* 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 "CGPandoraBox.h"
|
||||
|
||||
#include "NetPacks.h"
|
||||
#include "../client/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);
|
||||
}
|
||||
}
|
73
lib/mapObjects/CGPandoraBox.h
Normal file
73
lib/mapObjects/CGPandoraBox.h
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CGArmedInstance.h"
|
||||
|
||||
|
||||
/*
|
||||
* CObjectHandler.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;
|
||||
};
|
1201
lib/mapObjects/CGTownInstance.cpp
Normal file
1201
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 "CGArmedInstance.h"
|
||||
|
||||
#include "../CTownHandler.h" // For CTown
|
||||
|
||||
/*
|
||||
* CObjectHandler.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;
|
||||
};
|
@ -7,11 +7,11 @@
|
||||
#include "GameConstants.h"
|
||||
#include "StringConstants.h"
|
||||
#include "CGeneralTextHandler.h"
|
||||
#include "CObjectHandler.h"
|
||||
#include "CModHandler.h"
|
||||
#include "JsonNode.h"
|
||||
|
||||
#include "CRewardableConstructor.h"
|
||||
#include "MapObjects.h"
|
||||
|
||||
/*
|
||||
* CObjectClassesHandler.cpp, part of VCMI engine
|
||||
|
@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "GameConstants.h"
|
||||
#include "../lib/ConstTransitivePtr.h"
|
||||
#include "IHandlerBase.h"
|
||||
#include "ObjectTemplate.h"
|
||||
|
||||
#include "../GameConstants.h"
|
||||
#include "../ConstTransitivePtr.h"
|
||||
#include "../IHandlerBase.h"
|
||||
|
||||
/*
|
||||
* CObjectClassesHandler.h, part of VCMI engine
|
||||
*
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
861
lib/mapObjects/CQuest.cpp
Normal file
861
lib/mapObjects/CQuest.cpp
Normal file
@ -0,0 +1,861 @@
|
||||
/*
|
||||
* 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 "CQuest.h"
|
||||
|
||||
#include "NetPacks.h"
|
||||
#include "../client/CSoundBase.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CHeroHandler.h"
|
||||
#include "CObjectClassesHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
std::map <PlayerColor, std::set <ui8> > CGKeys::playerKeyMap;
|
||||
|
||||
///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);
|
||||
}
|
||||
|
||||
static std::string & visitedTxt(const bool visited)
|
||||
{
|
||||
int id = visited ? 352 : 353;
|
||||
return VLC->generaltexth->allTexts[id];
|
||||
}
|
||||
|
||||
bool CQuest::checkQuest (const CGHeroInstance * h) const
|
||||
{
|
||||
switch (missionType)
|
||||
{
|
||||
case MISSION_NONE:
|
||||
return true;
|
||||
case MISSION_LEVEL:
|
||||
if (m13489val <= h->level)
|
||||
return true;
|
||||
return false;
|
||||
case MISSION_PRIMARY_STAT:
|
||||
for (int i = 0; i < GameConstants::PRIMARY_SKILLS; ++i)
|
||||
{
|
||||
if (h->getPrimSkillLevel(static_cast<PrimarySkill::PrimarySkill>(i)) < m2stats[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case MISSION_KILL_HERO:
|
||||
case MISSION_KILL_CREATURE:
|
||||
if (!h->cb->getObjByQuestIdentifier(m13489val))
|
||||
return true;
|
||||
return false;
|
||||
case MISSION_ART:
|
||||
for (auto & elem : m5arts)
|
||||
{
|
||||
if (h->hasArt(elem))
|
||||
continue;
|
||||
return false; //if the artifact was not found
|
||||
}
|
||||
return true;
|
||||
case MISSION_ARMY:
|
||||
{
|
||||
std::vector<CStackBasicDescriptor>::const_iterator cre;
|
||||
TSlots::const_iterator it;
|
||||
ui32 count;
|
||||
for (cre = m6creatures.begin(); cre != m6creatures.end(); ++cre)
|
||||
{
|
||||
for (count = 0, it = h->Slots().begin(); it != h->Slots().end(); ++it)
|
||||
{
|
||||
if (it->second->type == cre->type)
|
||||
count += it->second->count;
|
||||
}
|
||||
if (count < cre->count) //not enough creatures of this kind
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case MISSION_RESOURCES:
|
||||
for (Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, +1)) //including Mithril ?
|
||||
{ //Quest has no direct access to callback
|
||||
if (h->cb->getResource (h->tempOwner, i) < m7resources[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case MISSION_HERO:
|
||||
if (m13489val == h->type->ID.getNum())
|
||||
return true;
|
||||
return false;
|
||||
case MISSION_PLAYER:
|
||||
if (m13489val == h->getOwner().getNum())
|
||||
return true;
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CQuest::getVisitText (MetaString &iwText, std::vector<Component> &components, bool isCustom, bool firstVisit, const CGHeroInstance * h) const
|
||||
{
|
||||
std::string text;
|
||||
bool failRequirements = (h ? !checkQuest(h) : true);
|
||||
|
||||
if (firstVisit)
|
||||
{
|
||||
isCustom = isCustomFirst;
|
||||
iwText << (text = firstVisitText);
|
||||
}
|
||||
else if (failRequirements)
|
||||
{
|
||||
isCustom = isCustomNext;
|
||||
iwText << (text = nextVisitText);
|
||||
}
|
||||
switch (missionType)
|
||||
{
|
||||
case MISSION_LEVEL:
|
||||
components.push_back(Component (Component::EXPERIENCE, 0, m13489val, 0));
|
||||
if (!isCustom)
|
||||
iwText.addReplacement(m13489val);
|
||||
break;
|
||||
case MISSION_PRIMARY_STAT:
|
||||
{
|
||||
MetaString loot;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (m2stats[i])
|
||||
{
|
||||
components.push_back(Component (Component::PRIM_SKILL, i, m2stats[i], 0));
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m2stats[i]);
|
||||
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
|
||||
}
|
||||
}
|
||||
if (!isCustom)
|
||||
iwText.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
components.push_back(Component(Component::HERO_PORTRAIT, heroPortrait, 0, 0));
|
||||
if (!isCustom)
|
||||
addReplacements(iwText, text);
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
//FIXME: portrait may not match hero, if custom portrait was set in map editor
|
||||
components.push_back(Component (Component::HERO_PORTRAIT, VLC->heroh->heroes[m13489val]->imageIndex, 0, 0));
|
||||
if (!isCustom)
|
||||
iwText.addReplacement(VLC->heroh->heroes[m13489val]->name);
|
||||
break;
|
||||
case MISSION_KILL_CREATURE:
|
||||
{
|
||||
components.push_back(Component(stackToKill));
|
||||
if (!isCustom)
|
||||
{
|
||||
addReplacements(iwText, text);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MISSION_ART:
|
||||
{
|
||||
MetaString loot;
|
||||
for (auto & elem : m5arts)
|
||||
{
|
||||
components.push_back(Component (Component::ARTIFACT, elem, 0, 0));
|
||||
loot << "%s";
|
||||
loot.addReplacement(MetaString::ART_NAMES, elem);
|
||||
}
|
||||
if (!isCustom)
|
||||
iwText.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_ARMY:
|
||||
{
|
||||
MetaString loot;
|
||||
for (auto & elem : m6creatures)
|
||||
{
|
||||
components.push_back(Component(elem));
|
||||
loot << "%s";
|
||||
loot.addReplacement(elem);
|
||||
}
|
||||
if (!isCustom)
|
||||
iwText.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_RESOURCES:
|
||||
{
|
||||
MetaString loot;
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
if (m7resources[i])
|
||||
{
|
||||
components.push_back(Component (Component::RESOURCE, i, m7resources[i], 0));
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m7resources[i]);
|
||||
loot.addReplacement(MetaString::RES_NAMES, i);
|
||||
}
|
||||
}
|
||||
if (!isCustom)
|
||||
iwText.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_PLAYER:
|
||||
components.push_back(Component (Component::FLAG, m13489val, 0, 0));
|
||||
if (!isCustom)
|
||||
iwText.addReplacement(VLC->generaltexth->colors[m13489val]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CQuest::getRolloverText (MetaString &ms, bool onHover) const
|
||||
{
|
||||
if (onHover)
|
||||
ms << "\n\n";
|
||||
|
||||
ms << VLC->generaltexth->quests[missionType-1][onHover ? 3 : 4][textOption];
|
||||
|
||||
switch (missionType)
|
||||
{
|
||||
case MISSION_LEVEL:
|
||||
ms.addReplacement(m13489val);
|
||||
break;
|
||||
case MISSION_PRIMARY_STAT:
|
||||
{
|
||||
MetaString loot;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (m2stats[i])
|
||||
{
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m2stats[i]);
|
||||
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
|
||||
}
|
||||
}
|
||||
ms.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
ms.addReplacement(heroName);
|
||||
break;
|
||||
case MISSION_KILL_CREATURE:
|
||||
ms.addReplacement(stackToKill);
|
||||
break;
|
||||
case MISSION_ART:
|
||||
{
|
||||
MetaString loot;
|
||||
for (auto & elem : m5arts)
|
||||
{
|
||||
loot << "%s";
|
||||
loot.addReplacement(MetaString::ART_NAMES, elem);
|
||||
}
|
||||
ms.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_ARMY:
|
||||
{
|
||||
MetaString loot;
|
||||
for (auto & elem : m6creatures)
|
||||
{
|
||||
loot << "%s";
|
||||
loot.addReplacement(elem);
|
||||
}
|
||||
ms.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_RESOURCES:
|
||||
{
|
||||
MetaString loot;
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
if (m7resources[i])
|
||||
{
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m7resources[i]);
|
||||
loot.addReplacement(MetaString::RES_NAMES, i);
|
||||
}
|
||||
}
|
||||
ms.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
ms.addReplacement(VLC->heroh->heroes[m13489val]->name);
|
||||
break;
|
||||
case MISSION_PLAYER:
|
||||
ms.addReplacement(VLC->generaltexth->colors[m13489val]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CQuest::getCompletionText (MetaString &iwText, std::vector<Component> &components, bool isCustom, const CGHeroInstance * h) const
|
||||
{
|
||||
iwText << completedText;
|
||||
switch (missionType)
|
||||
{
|
||||
case CQuest::MISSION_LEVEL:
|
||||
if (!isCustomComplete)
|
||||
iwText.addReplacement(m13489val);
|
||||
break;
|
||||
case CQuest::MISSION_PRIMARY_STAT:
|
||||
if (vstd::contains (completedText,'%')) //there's one case when there's nothing to replace
|
||||
{
|
||||
MetaString loot;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (m2stats[i])
|
||||
{
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m2stats[i]);
|
||||
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
|
||||
}
|
||||
}
|
||||
if (!isCustomComplete)
|
||||
iwText.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case CQuest::MISSION_ART:
|
||||
{
|
||||
MetaString loot;
|
||||
for (auto & elem : m5arts)
|
||||
{
|
||||
loot << "%s";
|
||||
loot.addReplacement(MetaString::ART_NAMES, elem);
|
||||
}
|
||||
if (!isCustomComplete)
|
||||
iwText.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case CQuest::MISSION_ARMY:
|
||||
{
|
||||
MetaString loot;
|
||||
for (auto & elem : m6creatures)
|
||||
{
|
||||
loot << "%s";
|
||||
loot.addReplacement(elem);
|
||||
}
|
||||
if (!isCustomComplete)
|
||||
iwText.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case CQuest::MISSION_RESOURCES:
|
||||
{
|
||||
MetaString loot;
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
if (m7resources[i])
|
||||
{
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(m7resources[i]);
|
||||
loot.addReplacement(MetaString::RES_NAMES, i);
|
||||
}
|
||||
}
|
||||
if (!isCustomComplete)
|
||||
iwText.addReplacement(loot.buildList());
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
case MISSION_KILL_CREATURE:
|
||||
if (!isCustomComplete)
|
||||
addReplacements(iwText, completedText);
|
||||
break;
|
||||
case MISSION_HERO:
|
||||
if (!isCustomComplete)
|
||||
iwText.addReplacement(VLC->heroh->heroes[m13489val]->name);
|
||||
break;
|
||||
case MISSION_PLAYER:
|
||||
if (!isCustomComplete)
|
||||
iwText.addReplacement(VLC->generaltexth->colors[m13489val]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::setObjToKill()
|
||||
{
|
||||
if (quest->missionType == CQuest::MISSION_KILL_CREATURE)
|
||||
{
|
||||
quest->stackToKill = getCreatureToKill(false)->getStack(SlotID(0)); //FIXME: stacks tend to disappear (desync?) on server :?
|
||||
assert(quest->stackToKill.type);
|
||||
quest->stackToKill.count = 0; //no count in info window
|
||||
quest->stackDirection = checkDirection();
|
||||
}
|
||||
else if (quest->missionType == CQuest::MISSION_KILL_HERO)
|
||||
{
|
||||
quest->heroName = getHeroToKill(false)->name;
|
||||
quest->heroPortrait = getHeroToKill(false)->portrait;
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::init()
|
||||
{
|
||||
seerName = *RandomGeneratorUtil::nextItem(VLC->generaltexth->seerNames, cb->gameState()->getRandomGenerator());
|
||||
quest->textOption = cb->gameState()->getRandomGenerator().nextInt(2);
|
||||
}
|
||||
|
||||
void CGSeerHut::initObj()
|
||||
{
|
||||
init();
|
||||
|
||||
quest->progress = CQuest::NOT_ACTIVE;
|
||||
if (quest->missionType)
|
||||
{
|
||||
if (!quest->isCustomFirst)
|
||||
quest->firstVisitText = VLC->generaltexth->quests[quest->missionType-1][0][quest->textOption];
|
||||
if (!quest->isCustomNext)
|
||||
quest->nextVisitText = VLC->generaltexth->quests[quest->missionType-1][1][quest->textOption];
|
||||
if (!quest->isCustomComplete)
|
||||
quest->completedText = VLC->generaltexth->quests[quest->missionType-1][2][quest->textOption];
|
||||
}
|
||||
else
|
||||
{
|
||||
quest->progress = CQuest::COMPLETE;
|
||||
quest->firstVisitText = VLC->generaltexth->seerEmpty[quest->textOption];
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::getRolloverText (MetaString &text, bool onHover) const
|
||||
{
|
||||
quest->getRolloverText (text, onHover);//TODO: simplify?
|
||||
if (!onHover)
|
||||
text.addReplacement(seerName);
|
||||
}
|
||||
|
||||
const std::string & CGSeerHut::getHoverText() const
|
||||
{
|
||||
switch (ID)
|
||||
{
|
||||
case Obj::SEER_HUT:
|
||||
if (quest->progress != CQuest::NOT_ACTIVE)
|
||||
{
|
||||
hoverName = VLC->generaltexth->allTexts[347];
|
||||
boost::algorithm::replace_first(hoverName,"%s", seerName);
|
||||
}
|
||||
else //just seer hut
|
||||
hoverName = VLC->objtypeh->getObjectName(ID);
|
||||
break;
|
||||
case Obj::QUEST_GUARD:
|
||||
hoverName = VLC->objtypeh->getObjectName(ID);
|
||||
break;
|
||||
default:
|
||||
logGlobal->debugStream() << "unrecognized quest object";
|
||||
}
|
||||
if (quest->progress & quest->missionType) //rollover when the quest is active
|
||||
{
|
||||
MetaString ms;
|
||||
getRolloverText (ms, true);
|
||||
hoverName += ms.toString();
|
||||
}
|
||||
return hoverName;
|
||||
}
|
||||
|
||||
void CQuest::addReplacements(MetaString &out, const std::string &base) const
|
||||
{
|
||||
switch(missionType)
|
||||
{
|
||||
case MISSION_KILL_CREATURE:
|
||||
out.addReplacement(stackToKill);
|
||||
if (std::count(base.begin(), base.end(), '%') == 2) //say where is placed monster
|
||||
{
|
||||
out.addReplacement(VLC->generaltexth->arraytxt[147+stackDirection]);
|
||||
}
|
||||
break;
|
||||
case MISSION_KILL_HERO:
|
||||
out.addReplacement(heroName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool IQuestObject::checkQuest(const CGHeroInstance* h) const
|
||||
{
|
||||
return quest->checkQuest(h);
|
||||
}
|
||||
|
||||
void IQuestObject::getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h) const
|
||||
{
|
||||
quest->getVisitText (text,components, isCustom, FirstVisit, h);
|
||||
}
|
||||
|
||||
void CGSeerHut::getCompletionText(MetaString &text, std::vector<Component> &components, bool isCustom, const CGHeroInstance * h) const
|
||||
{
|
||||
quest->getCompletionText (text, components, isCustom, h);
|
||||
switch (rewardType)
|
||||
{
|
||||
case EXPERIENCE: components.push_back(Component (Component::EXPERIENCE, 0, h->calculateXp(rVal), 0));
|
||||
break;
|
||||
case MANA_POINTS: components.push_back(Component (Component::PRIM_SKILL, 5, rVal, 0));
|
||||
break;
|
||||
case MORALE_BONUS: components.push_back(Component (Component::MORALE, 0, rVal, 0));
|
||||
break;
|
||||
case LUCK_BONUS: components.push_back(Component (Component::LUCK, 0, rVal, 0));
|
||||
break;
|
||||
case RESOURCES: components.push_back(Component (Component::RESOURCE, rID, rVal, 0));
|
||||
break;
|
||||
case PRIMARY_SKILL: components.push_back(Component (Component::PRIM_SKILL, rID, rVal, 0));
|
||||
break;
|
||||
case SECONDARY_SKILL: components.push_back(Component (Component::SEC_SKILL, rID, rVal, 0));
|
||||
break;
|
||||
case ARTIFACT: components.push_back(Component (Component::ARTIFACT, rID, 0, 0));
|
||||
break;
|
||||
case SPELL: components.push_back(Component (Component::SPELL, rID, 0, 0));
|
||||
break;
|
||||
case CREATURE: components.push_back(Component (Component::CREATURE, rID, rVal, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::setPropertyDer (ui8 what, ui32 val)
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case 10:
|
||||
quest->progress = static_cast<CQuest::Eprogress>(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::newTurn() const
|
||||
{
|
||||
if (quest->lastDay >= 0 && quest->lastDay < cb->getDate()-1) //time is up
|
||||
{
|
||||
cb->setObjProperty (id, 10, CQuest::COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = h->getOwner();
|
||||
if (quest->progress < CQuest::COMPLETE)
|
||||
{
|
||||
bool firstVisit = !quest->progress;
|
||||
bool failRequirements = !checkQuest(h);
|
||||
bool isCustom=false;
|
||||
|
||||
if (firstVisit)
|
||||
{
|
||||
isCustom = quest->isCustomFirst;
|
||||
cb->setObjProperty (id, 10, CQuest::IN_PROGRESS);
|
||||
|
||||
AddQuest aq;
|
||||
aq.quest = QuestInfo (quest, this, visitablePos());
|
||||
aq.player = h->tempOwner;
|
||||
cb->sendAndApply (&aq); //TODO: merge with setObjProperty?
|
||||
}
|
||||
else if (failRequirements)
|
||||
{
|
||||
isCustom = quest->isCustomNext;
|
||||
}
|
||||
|
||||
if (firstVisit || failRequirements)
|
||||
{
|
||||
getVisitText (iw.text, iw.components, isCustom, firstVisit, h);
|
||||
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
if (!failRequirements) // propose completion, also on first visit
|
||||
{
|
||||
BlockingDialog bd (true, false);
|
||||
bd.player = h->getOwner();
|
||||
bd.soundID = soundBase::QUEST;
|
||||
|
||||
getCompletionText (bd.text, bd.components, isCustom, h);
|
||||
|
||||
cb->showBlockingDialog (&bd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text << VLC->generaltexth->seerEmpty[quest->textOption];
|
||||
if (ID == Obj::SEER_HUT)
|
||||
iw.text.addReplacement(seerName);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
}
|
||||
|
||||
int CGSeerHut::checkDirection() const
|
||||
{
|
||||
int3 cord = getCreatureToKill()->pos;
|
||||
if ((double)cord.x/(double)cb->getMapSize().x < 0.34) //north
|
||||
{
|
||||
if ((double)cord.y/(double)cb->getMapSize().y < 0.34) //northwest
|
||||
return 8;
|
||||
else if ((double)cord.y/(double)cb->getMapSize().y < 0.67) //north
|
||||
return 1;
|
||||
else //northeast
|
||||
return 2;
|
||||
}
|
||||
else if ((double)cord.x/(double)cb->getMapSize().x < 0.67) //horizontal
|
||||
{
|
||||
if ((double)cord.y/(double)cb->getMapSize().y < 0.34) //west
|
||||
return 7;
|
||||
else if ((double)cord.y/(double)cb->getMapSize().y < 0.67) //central
|
||||
return 9;
|
||||
else //east
|
||||
return 3;
|
||||
}
|
||||
else //south
|
||||
{
|
||||
if ((double)cord.y/(double)cb->getMapSize().y < 0.34) //southwest
|
||||
return 6;
|
||||
else if ((double)cord.y/(double)cb->getMapSize().y < 0.67) //south
|
||||
return 5;
|
||||
else //southeast
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const
|
||||
{
|
||||
if (accept)
|
||||
{
|
||||
switch (quest->missionType)
|
||||
{
|
||||
case CQuest::MISSION_ART:
|
||||
for (auto & elem : quest->m5arts)
|
||||
{
|
||||
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(elem, false)));
|
||||
}
|
||||
break;
|
||||
case CQuest::MISSION_ARMY:
|
||||
cb->takeCreatures(h->id, quest->m6creatures);
|
||||
break;
|
||||
case CQuest::MISSION_RESOURCES:
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
cb->giveResource(h->getOwner(), static_cast<Res::ERes>(i), -quest->m7resources[i]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cb->setObjProperty (id, 10, CQuest::COMPLETE); //mission complete
|
||||
completeQuest(h); //make sure to remove QuestGuard at the very end
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
|
||||
{
|
||||
switch (rewardType)
|
||||
{
|
||||
case EXPERIENCE:
|
||||
{
|
||||
TExpType expVal = h->calculateXp(rVal);
|
||||
cb->changePrimSkill(h, PrimarySkill::EXPERIENCE, expVal, false);
|
||||
break;
|
||||
}
|
||||
case MANA_POINTS:
|
||||
{
|
||||
cb->setManaPoints(h->id, h->mana+rVal);
|
||||
break;
|
||||
}
|
||||
case MORALE_BONUS: case LUCK_BONUS:
|
||||
{
|
||||
Bonus hb(Bonus::ONE_WEEK, (rewardType == 3 ? Bonus::MORALE : Bonus::LUCK),
|
||||
Bonus::OBJECT, rVal, h->id.getNum(), "", -1);
|
||||
GiveBonus gb;
|
||||
gb.id = h->id.getNum();
|
||||
gb.bonus = hb;
|
||||
cb->giveHeroBonus(&gb);
|
||||
}
|
||||
break;
|
||||
case RESOURCES:
|
||||
cb->giveResource(h->getOwner(), static_cast<Res::ERes>(rID), rVal);
|
||||
break;
|
||||
case PRIMARY_SKILL:
|
||||
cb->changePrimSkill(h, static_cast<PrimarySkill::PrimarySkill>(rID), rVal, false);
|
||||
break;
|
||||
case SECONDARY_SKILL:
|
||||
cb->changeSecSkill(h, SecondarySkill(rID), rVal, false);
|
||||
break;
|
||||
case ARTIFACT:
|
||||
cb->giveHeroNewArtifact(h, VLC->arth->artifacts[rID],ArtifactPosition::FIRST_AVAILABLE);
|
||||
break;
|
||||
case SPELL:
|
||||
{
|
||||
std::set<SpellID> spell;
|
||||
spell.insert (SpellID(rID));
|
||||
cb->changeSpells(h, true, spell);
|
||||
}
|
||||
break;
|
||||
case CREATURE:
|
||||
{
|
||||
CCreatureSet creatures;
|
||||
creatures.setCreature(SlotID(0), CreatureID(rID), rVal);
|
||||
cb->giveCreatures(this, h, creatures, false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const CGHeroInstance * CGSeerHut::getHeroToKill(bool allowNull) const
|
||||
{
|
||||
const CGObjectInstance *o = cb->getObjByQuestIdentifier(quest->m13489val);
|
||||
if(allowNull && !o)
|
||||
return nullptr;
|
||||
assert(o && (o->ID == Obj::HERO || o->ID == Obj::PRISON));
|
||||
return static_cast<const CGHeroInstance*>(o);
|
||||
}
|
||||
|
||||
const CGCreature * CGSeerHut::getCreatureToKill(bool allowNull) const
|
||||
{
|
||||
const CGObjectInstance *o = cb->getObjByQuestIdentifier(quest->m13489val);
|
||||
if(allowNull && !o)
|
||||
return nullptr;
|
||||
assert(o && o->ID == Obj::MONSTER);
|
||||
return static_cast<const CGCreature*>(o);
|
||||
}
|
||||
|
||||
void CGSeerHut::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
||||
{
|
||||
finishQuest(hero, answer);
|
||||
}
|
||||
|
||||
void CGQuestGuard::init()
|
||||
{
|
||||
blockVisit = true;
|
||||
quest->textOption = cb->gameState()->getRandomGenerator().nextInt(3, 5);
|
||||
}
|
||||
|
||||
void CGQuestGuard::completeQuest(const CGHeroInstance *h) const
|
||||
{
|
||||
cb->removeObject(this);
|
||||
}
|
||||
|
||||
void CGKeys::setPropertyDer (ui8 what, ui32 val) //101-108 - enable key for player 1-8
|
||||
{
|
||||
if (what >= 101 && what <= (100 + PlayerColor::PLAYER_LIMIT_I))
|
||||
{
|
||||
PlayerColor player(what-101);
|
||||
playerKeyMap[player].insert((ui8)val);
|
||||
}
|
||||
else
|
||||
logGlobal->errorStream() << boost::format("Unexpected properties requested to set: what=%d, val=%d") % (int)what % val;
|
||||
}
|
||||
|
||||
bool CGKeys::wasMyColorVisited (PlayerColor player) const
|
||||
{
|
||||
if (vstd::contains(playerKeyMap[player], subID)) //creates set if it's not there
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string& CGKeys::getHoverText() const
|
||||
{
|
||||
bool visited = wasMyColorVisited (cb->getLocalPlayer());
|
||||
hoverName = getName() + "\n" + visitedTxt(visited);
|
||||
return hoverName;
|
||||
}
|
||||
|
||||
|
||||
const std::string CGKeys::getName() const
|
||||
{
|
||||
std::string name;
|
||||
name = VLC->generaltexth->tentColors[subID] + " " + VLC->objtypeh->getObjectName(ID);
|
||||
return name;
|
||||
}
|
||||
|
||||
bool CGKeymasterTent::wasVisited (PlayerColor player) const
|
||||
{
|
||||
return wasMyColorVisited (player);
|
||||
}
|
||||
|
||||
void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
int txt_id;
|
||||
if (!wasMyColorVisited (h->getOwner()) )
|
||||
{
|
||||
cb->setObjProperty(id, h->tempOwner.getNum()+101, subID);
|
||||
txt_id=19;
|
||||
}
|
||||
else
|
||||
txt_id=20;
|
||||
showInfoDialog(h,txt_id,soundBase::CAVEHEAD);
|
||||
}
|
||||
|
||||
void CGBorderGuard::initObj()
|
||||
{
|
||||
//ui32 m13489val = subID; //store color as quest info
|
||||
blockVisit = true;
|
||||
}
|
||||
|
||||
void CGBorderGuard::getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h) const
|
||||
{
|
||||
text << std::pair<ui8,ui32>(11,18);
|
||||
}
|
||||
|
||||
void CGBorderGuard::getRolloverText (MetaString &text, bool onHover) const
|
||||
{
|
||||
if (!onHover)
|
||||
text << VLC->generaltexth->tentColors[subID] << " " << VLC->objtypeh->getObjectName(Obj::KEYMASTER);
|
||||
}
|
||||
|
||||
bool CGBorderGuard::checkQuest (const CGHeroInstance * h) const
|
||||
{
|
||||
return wasMyColorVisited (h->tempOwner);
|
||||
}
|
||||
|
||||
void CGBorderGuard::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
if (wasMyColorVisited (h->getOwner()) )
|
||||
{
|
||||
BlockingDialog bd (true, false);
|
||||
bd.player = h->getOwner();
|
||||
bd.soundID = soundBase::QUEST;
|
||||
bd.text.addTxt (MetaString::ADVOB_TXT, 17);
|
||||
cb->showBlockingDialog (&bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
showInfoDialog(h,18,soundBase::CAVEHEAD);
|
||||
|
||||
AddQuest aq;
|
||||
aq.quest = QuestInfo (quest, this, visitablePos());
|
||||
aq.player = h->tempOwner;
|
||||
cb->sendAndApply (&aq);
|
||||
//TODO: add this quest only once OR check for multiple instances later
|
||||
}
|
||||
}
|
||||
|
||||
void CGBorderGuard::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
||||
{
|
||||
if (answer)
|
||||
cb->removeObject(this);
|
||||
}
|
||||
|
||||
void CGBorderGate::onHeroVisit( const CGHeroInstance * h ) const //TODO: passability
|
||||
{
|
||||
if (!wasMyColorVisited (h->getOwner()) )
|
||||
{
|
||||
showInfoDialog(h,18,0);
|
||||
|
||||
AddQuest aq;
|
||||
aq.quest = QuestInfo (quest, this, visitablePos());
|
||||
aq.player = h->tempOwner;
|
||||
cb->sendAndApply (&aq);
|
||||
}
|
||||
}
|
||||
|
||||
ui8 CGBorderGate::getPassableness() const
|
||||
{
|
||||
ui8 ret = 0;
|
||||
for (int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
|
||||
ret |= wasMyColorVisited(PlayerColor(i))<<i;
|
||||
return ret;
|
||||
}
|
198
lib/mapObjects/CQuest.h
Normal file
198
lib/mapObjects/CQuest.h
Normal file
@ -0,0 +1,198 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CGArmedInstance.h"
|
||||
|
||||
#include "../CCreatureSet.h"
|
||||
#include "../NetPacksBase.h"
|
||||
|
||||
/*
|
||||
* CObjectHandler.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 CQuest
|
||||
{
|
||||
public:
|
||||
enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4,
|
||||
MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9, MISSION_KEYMASTER = 10};
|
||||
enum Eprogress {NOT_ACTIVE, IN_PROGRESS, COMPLETE};
|
||||
|
||||
si32 qid; //unique quest id for serialization / identification
|
||||
|
||||
Emission missionType;
|
||||
Eprogress progress;
|
||||
si32 lastDay; //after this day (first day is 0) mission cannot be completed; if -1 - no limit
|
||||
|
||||
ui32 m13489val;
|
||||
std::vector<ui32> m2stats;
|
||||
std::vector<ui16> m5arts; //artifacts id
|
||||
std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
|
||||
std::vector<ui32> m7resources; //TODO: use resourceset?
|
||||
|
||||
//following field are used only for kill creature/hero missions, the original objects became inaccessible after their removal, so we need to store info needed for messages / hover text
|
||||
ui8 textOption;
|
||||
CStackBasicDescriptor stackToKill;
|
||||
ui8 stackDirection;
|
||||
std::string heroName; //backup of hero name
|
||||
si32 heroPortrait;
|
||||
|
||||
std::string firstVisitText, nextVisitText, completedText;
|
||||
bool isCustomFirst, isCustomNext, isCustomComplete;
|
||||
|
||||
CQuest(){missionType = MISSION_NONE;}; //default constructor
|
||||
virtual ~CQuest(){};
|
||||
|
||||
virtual bool checkQuest (const CGHeroInstance * h) const; //determines whether the quest is complete or not
|
||||
virtual void getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
|
||||
virtual void getCompletionText (MetaString &text, std::vector<Component> &components, bool isCustom, const CGHeroInstance * h = nullptr) const;
|
||||
virtual void getRolloverText (MetaString &text, bool onHover) const; //hover or quest log entry
|
||||
virtual void completeQuest (const CGHeroInstance * h) const {};
|
||||
virtual void addReplacements(MetaString &out, const std::string &base) const;
|
||||
|
||||
bool operator== (const CQuest & quest) const
|
||||
{
|
||||
return (quest.qid == qid);
|
||||
}
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & qid & missionType & progress & lastDay & m13489val & m2stats & m5arts & m6creatures & m7resources
|
||||
& textOption & stackToKill & stackDirection & heroName & heroPortrait
|
||||
& firstVisitText & nextVisitText & completedText & isCustomFirst & isCustomNext & isCustomComplete;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE IQuestObject
|
||||
{
|
||||
public:
|
||||
CQuest * quest;
|
||||
|
||||
IQuestObject(): quest(new CQuest()){};
|
||||
virtual ~IQuestObject() {};
|
||||
virtual void getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
|
||||
virtual bool checkQuest (const CGHeroInstance * h) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & quest;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGSeerHut : public CArmedInstance, public IQuestObject //army is used when giving reward
|
||||
{
|
||||
public:
|
||||
enum ERewardType {NOTHING, EXPERIENCE, MANA_POINTS, MORALE_BONUS, LUCK_BONUS, RESOURCES, PRIMARY_SKILL, SECONDARY_SKILL, ARTIFACT, SPELL, CREATURE};
|
||||
ERewardType rewardType;
|
||||
si32 rID; //reward ID
|
||||
si32 rVal; //reward value
|
||||
std::string seerName;
|
||||
|
||||
CGSeerHut() : IQuestObject(){};
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
void newTurn() const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
virtual void init();
|
||||
int checkDirection() const; //calculates the region of map where monster is placed
|
||||
void setObjToKill(); //remember creatures / heroes to kill after they are initialized
|
||||
const CGHeroInstance *getHeroToKill(bool allowNull = false) const;
|
||||
const CGCreature *getCreatureToKill(bool allowNull = false) const;
|
||||
void getRolloverText (MetaString &text, bool onHover) const;
|
||||
void getCompletionText(MetaString &text, std::vector<Component> &components, bool isCustom, const CGHeroInstance * h = nullptr) const;
|
||||
void finishQuest (const CGHeroInstance * h, ui32 accept) const; //common for both objects
|
||||
virtual void completeQuest (const CGHeroInstance * h) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this) & static_cast<IQuestObject&>(*this);
|
||||
h & rewardType & rID & rVal & seerName;
|
||||
}
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGQuestGuard : public CGSeerHut
|
||||
{
|
||||
public:
|
||||
CGQuestGuard() : CGSeerHut(){};
|
||||
void init() override;
|
||||
void completeQuest (const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGSeerHut&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGKeys : public CGObjectInstance //Base class for Keymaster and guards
|
||||
{
|
||||
public:
|
||||
static std::map <PlayerColor, std::set <ui8> > playerKeyMap; //[players][keysowned]
|
||||
//SubID 0 - lightblue, 1 - green, 2 - red, 3 - darkblue, 4 - brown, 5 - purple, 6 - white, 7 - black
|
||||
|
||||
const std::string getName() const; //depending on color
|
||||
bool wasMyColorVisited (PlayerColor player) const;
|
||||
|
||||
const std::string & getHoverText() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGKeymasterTent : public CGKeys
|
||||
{
|
||||
public:
|
||||
bool wasVisited (PlayerColor player) const;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGBorderGuard : public CGKeys, public IQuestObject
|
||||
{
|
||||
public:
|
||||
CGBorderGuard() : IQuestObject(){};
|
||||
void initObj() override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
void getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
|
||||
void getRolloverText (MetaString &text, bool onHover) const;
|
||||
bool checkQuest (const CGHeroInstance * h) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<IQuestObject&>(*this);
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & blockVisit;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGBorderGate : public CGBorderGuard
|
||||
{
|
||||
public:
|
||||
CGBorderGate() : CGBorderGuard(){};
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
ui8 getPassableness() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGBorderGuard&>(*this); //need to serialize or object will be empty
|
||||
}
|
||||
};
|
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "mapObjects/CRewardableObject.h"
|
||||
#include "CRewardableObject.h"
|
||||
#include "CObjectClassesHandler.h"
|
||||
#include "JsonNode.h"
|
||||
|
||||
#include "../JsonNode.h"
|
||||
|
||||
/*
|
||||
* CObjectConstructor.h, part of VCMI engine
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "../client/CSoundBase.h"
|
||||
#include "NetPacks.h"
|
||||
|
||||
#include "CObjectClassesHandler.h"
|
||||
|
||||
bool CRewardLimiter::heroAllowed(const CGHeroInstance * hero) const
|
||||
{
|
||||
if (dayOfWeek != 0)
|
||||
|
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "NetPacksBase.h"
|
||||
#include "CGArmedInstance.h"
|
||||
|
||||
#include "../NetPacksBase.h"
|
||||
|
||||
/*
|
||||
* CRewardableObject.h, part of VCMI engine
|
||||
|
25
lib/mapObjects/MapObjects.h
Normal file
25
lib/mapObjects/MapObjects.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* MapObjects.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
|
||||
*
|
||||
*/
|
||||
|
||||
// Helper header that includes all map objects, similar to old CObjectHandler.h
|
||||
// Possible TODO - remove this header after CObjectHandler.cpp will be fully split into smaller files
|
||||
#include "CObjectHandler.h"
|
||||
|
||||
#include "CGArmedInstance.h"
|
||||
#include "CGBank.h"
|
||||
#include "CGHeroInstance.h"
|
||||
#include "CGMarket.h"
|
||||
#include "CGTownInstance.h"
|
||||
#include "CGPandoraBox.h"
|
||||
#include "CRewardableObject.h"
|
||||
#include "MiscObjects.h"
|
||||
#include "CQuest.h"
|
1574
lib/mapObjects/MiscObjects.cpp
Normal file
1574
lib/mapObjects/MiscObjects.cpp
Normal file
File diff suppressed because it is too large
Load Diff
377
lib/mapObjects/MiscObjects.h
Normal file
377
lib/mapObjects/MiscObjects.h
Normal file
@ -0,0 +1,377 @@
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CGArmedInstance.h"
|
||||
|
||||
/*
|
||||
* CObjectHandler.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 CPlayersVisited: public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
std::set<PlayerColor> players; //players that visited this object
|
||||
|
||||
bool wasVisited(PlayerColor player) const;
|
||||
bool wasVisited(TeamID team) const;
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & players;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGCreature : public CArmedInstance //creatures on map
|
||||
{
|
||||
enum Action {
|
||||
FIGHT = -2, FLEE = -1, JOIN_FOR_FREE = 0 //values > 0 mean gold price
|
||||
};
|
||||
|
||||
public:
|
||||
ui32 identifier; //unique code for this monster (used in missions)
|
||||
si8 character; //character of this set of creatures (0 - the most friendly, 4 - the most hostile) => on init changed to -4 (compliant) ... 10 value (savage)
|
||||
std::string message; //message printed for attacking hero
|
||||
TResources resources; // resources given to hero that has won with monsters
|
||||
ArtifactID gainedArtifact; //ID of artifact gained to hero, -1 if none
|
||||
bool neverFlees; //if true, the troops will never flee
|
||||
bool notGrowingTeam; //if true, number of units won't grow
|
||||
ui64 temppower; //used to handle fractional stack growth for tiny stacks
|
||||
|
||||
bool refusedJoining;
|
||||
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
const std::string & getHoverText() const override;
|
||||
void initObj() override;
|
||||
void newTurn() const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
|
||||
struct DLL_LINKAGE formationInfo // info about merging stacks after battle back into one
|
||||
{
|
||||
si32 basicType;
|
||||
ui32 randomFormation; //random seed used to determine number of stacks and is there's upgraded stack
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & basicType & randomFormation;
|
||||
}
|
||||
} formation;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & identifier & character & message & resources & gainedArtifact & neverFlees & notGrowingTeam & temppower;
|
||||
h & refusedJoining & formation;
|
||||
}
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
private:
|
||||
|
||||
void fight(const CGHeroInstance *h) const;
|
||||
void flee( const CGHeroInstance * h ) const;
|
||||
void fleeDecision(const CGHeroInstance *h, ui32 pursue) const;
|
||||
void joinDecision(const CGHeroInstance *h, int cost, ui32 accept) const;
|
||||
|
||||
int takenAction(const CGHeroInstance *h, bool allowJoin=true) const; //action on confrontation: -2 - fight, -1 - flee, >=0 - will join for given value of gold (may be 0)
|
||||
|
||||
};
|
||||
|
||||
|
||||
class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles
|
||||
{
|
||||
public:
|
||||
std::string message;
|
||||
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & message;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGWitchHut : public CPlayersVisited
|
||||
{
|
||||
public:
|
||||
std::vector<si32> allowedAbilities;
|
||||
ui32 ability;
|
||||
|
||||
const std::string & getHoverText() const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CPlayersVisited&>(*this);
|
||||
h & allowedAbilities & ability;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGScholar : public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
enum EBonusType {PRIM_SKILL, SECONDARY_SKILL, SPELL, RANDOM = 255};
|
||||
EBonusType bonusType;
|
||||
ui16 bonusID; //ID of skill/spell
|
||||
|
||||
// void giveAnyBonus(const CGHeroInstance * h) const; //TODO: remove
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & bonusType & bonusID;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGGarrison : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
bool removableUnits;
|
||||
|
||||
ui8 getPassableness() const;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & removableUnits;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGArtifact : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
CArtifactInstance *storedArtifact;
|
||||
std::string message;
|
||||
|
||||
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 pick( const CGHeroInstance * h ) const;
|
||||
void initObj() override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & message & storedArtifact;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGResource : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
ui32 amount; //0 if random
|
||||
std::string message;
|
||||
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
void collectRes(PlayerColor player) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & amount & message;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGShrine : public CPlayersVisited
|
||||
{
|
||||
public:
|
||||
SpellID spell; //id of spell or NONE if random
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CPlayersVisited&>(*this);;
|
||||
h & spell;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGMine : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
Res::ERes producedResource;
|
||||
ui32 producedQuantity;
|
||||
|
||||
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 flagMine(PlayerColor player) const;
|
||||
void newTurn() const override;
|
||||
void initObj() override;
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & producedResource & producedQuantity;
|
||||
}
|
||||
ui32 defaultResProduction();
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGTeleport : public CGObjectInstance //teleports and subterranean gates
|
||||
{
|
||||
public:
|
||||
static std::map<Obj, std::map<int, std::vector<ObjectInstanceID> > > objs; //teleports: map[ID][subID] => vector of ids
|
||||
static std::vector<std::pair<ObjectInstanceID, ObjectInstanceID> > gates; //subterranean gates: pairs of ids
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
static void postInit();
|
||||
static ObjectInstanceID getMatchingGate(ObjectInstanceID id); //receives id of one subterranean gate and returns id of the paired one, -1 if none
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGMagicWell : public CGObjectInstance //objects giving bonuses to luck/morale/movement
|
||||
{
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
const std::string & getHoverText() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGSirens : public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
const std::string & getHoverText() const override;
|
||||
void initObj() override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGObservatory : public CGObjectInstance //Redwood observatory
|
||||
{
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGBoat : public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
ui8 direction;
|
||||
const CGHeroInstance *hero; //hero on board
|
||||
|
||||
void initObj() override;
|
||||
|
||||
CGBoat()
|
||||
{
|
||||
hero = nullptr;
|
||||
direction = 4;
|
||||
}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this) & direction & hero;
|
||||
}
|
||||
};
|
||||
|
||||
class CGShipyard : public CGObjectInstance, public IShipyard
|
||||
{
|
||||
public:
|
||||
void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed
|
||||
CGShipyard();
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
h & static_cast<IShipyard&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGMagi : public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
static std::map <si32, std::vector<ObjectInstanceID> > eyelist; //[subID][id], supports multiple sets as in H5
|
||||
|
||||
void initObj() override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DLL_LINKAGE CCartographer : public CPlayersVisited
|
||||
{
|
||||
///behaviour varies depending on surface and floor
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CPlayersVisited&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGDenOfthieves : public CGObjectInstance
|
||||
{
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGObelisk : public CPlayersVisited
|
||||
{
|
||||
public:
|
||||
static ui8 obeliskCount; //how many obelisks are on map
|
||||
static std::map<TeamID, ui8> visited; //map: team_id => how many obelisks has been visited
|
||||
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CPlayersVisited&>(*this);
|
||||
}
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGLighthouse : public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
}
|
||||
void giveBonusTo( PlayerColor player ) const;
|
||||
};
|
@ -10,7 +10,7 @@
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../StartInfo.h"
|
||||
#include "../CArtHandler.h" //for hero crossover
|
||||
#include "../mapObjects/CObjectHandler.h" //for hero crossover
|
||||
#include "../mapObjects/CGHeroInstance.h"//for hero crossover
|
||||
#include "../CHeroHandler.h"
|
||||
#include "CMapService.h"
|
||||
#include "CMap.h"
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "../CTownHandler.h"
|
||||
#include "../CHeroHandler.h"
|
||||
#include "../mapObjects/CObjectClassesHandler.h"
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CSpellHandler.h"
|
||||
#include "CMapEditManager.h"
|
||||
|
@ -12,7 +12,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ConstTransitivePtr.h"
|
||||
#include "../mapObjects/CObjectHandler.h"
|
||||
#include "../mapObjects/MiscObjects.h" // To serialize static props
|
||||
#include "../mapObjects/CQuest.h" // To serialize static props
|
||||
#include "../mapObjects/CGTownInstance.h" // To serialize static props
|
||||
#include "../ResourceSet.h"
|
||||
#include "../int3.h"
|
||||
#include "../GameConstants.h"
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "../JsonNode.h"
|
||||
#include "../filesystem/Filesystem.h"
|
||||
#include "../mapObjects/CObjectClassesHandler.h"
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
|
||||
MapRect::MapRect() : x(0), y(0), z(0), width(0), height(0)
|
||||
|
@ -20,9 +20,8 @@
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CHeroHandler.h"
|
||||
#include "../mapObjects/CObjectHandler.h"
|
||||
#include "../mapObjects/CRewardableObject.h"
|
||||
#include "../mapObjects/CObjectClassesHandler.h"
|
||||
#include "../mapObjects/MapObjects.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
#include "../NetPacksBase.h"
|
||||
|
||||
|
@ -14,7 +14,8 @@
|
||||
#include "CMapService.h"
|
||||
#include "../GameConstants.h"
|
||||
#include "../ResourceSet.h"
|
||||
#include "../mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../mapObjects/CObjectClassesHandler.h"
|
||||
#include "../mapObjects/ObjectTemplate.h"
|
||||
|
||||
#include "../int3.h"
|
||||
|
||||
|
@ -4,14 +4,13 @@
|
||||
#include "../NetPacks.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
#include "../CArtHandler.h"
|
||||
#include "../mapObjects/CObjectHandler.h"
|
||||
#include "../mapObjects/CRewardableObject.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../CHeroHandler.h"
|
||||
#include "../CTownHandler.h"
|
||||
#include "../CModHandler.h" //needed?
|
||||
#include "../mapObjects/CObjectClassesHandler.h"
|
||||
#include "../mapObjects/CRewardableConstructor.h"
|
||||
#include "../mapObjects/MapObjects.h"
|
||||
|
||||
/*
|
||||
* RegisterTypes.h, part of VCMI engine
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include "../VCMI_Lib.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../mapping/CMapEditManager.h"
|
||||
#include "../mapObjects/CObjectHandler.h"
|
||||
#include "../mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../mapObjects/CObjectHandler.h"
|
||||
//#include "../mapObjects/CObjectClassesHandler.h"
|
||||
#include "../CTownHandler.h"
|
||||
#include "../StringConstants.h"
|
||||
#include "../filesystem/Filesystem.h"
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "CMapGenOptions.h"
|
||||
#include "CRmgTemplateZone.h"
|
||||
#include "../mapObjects/CObjectHandler.h"
|
||||
#include "../int3.h"
|
||||
|
||||
class CMap;
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "../CTownHandler.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
|
||||
#include "../mapObjects/CObjectClassesHandler.h"
|
||||
|
||||
class CMap;
|
||||
class CMapEditManager;
|
||||
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/CBuildingHandler.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/CSpellHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "../lib/Connection.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "../lib/CArtHandler.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
@ -26,7 +26,7 @@
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "CGameHandler.h"
|
||||
#include "../lib/mapping/CMapInfo.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/logging/CBasicLogConfigurator.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "../lib/NetPacks.h"
|
||||
|
||||
#include "CGameHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
//#include "../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../lib/IGameCallback.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/CGameState.h"
|
||||
|
Loading…
Reference in New Issue
Block a user