mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-17 01:32:21 +02:00
Merge pull request #5896 from IvanSavenko/code_reorganize
Split large source files into smaller files per 1 class
This commit is contained in:
@ -19,6 +19,7 @@
|
|||||||
#include "../../lib/mapObjects/MapObjects.h"
|
#include "../../lib/mapObjects/MapObjects.h"
|
||||||
#include "../../lib/mapObjects/ObjectTemplate.h"
|
#include "../../lib/mapObjects/ObjectTemplate.h"
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../lib/CConfigHandler.h"
|
#include "../../lib/CConfigHandler.h"
|
||||||
#include "../../lib/IGameSettings.h"
|
#include "../../lib/IGameSettings.h"
|
||||||
#include "../../lib/gameState/CGameState.h"
|
#include "../../lib/gameState/CGameState.h"
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include "../../lib/entities/artifact/CArtifact.h"
|
#include "../../lib/entities/artifact/CArtifact.h"
|
||||||
#include "../../lib/mapObjects/MapObjects.h"
|
#include "../../lib/mapObjects/MapObjects.h"
|
||||||
#include "../../lib/mapObjects/CQuest.h"
|
#include "../../lib/mapObjects/CQuest.h"
|
||||||
#include "../../lib/mapping/CMapDefines.h"
|
#include "../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../lib/gameState/QuestInfo.h"
|
#include "../../lib/gameState/QuestInfo.h"
|
||||||
#include "../../lib/IGameSettings.h"
|
#include "../../lib/IGameSettings.h"
|
||||||
#include "../../lib/bonuses/Limiters.h"
|
#include "../../lib/bonuses/Limiters.h"
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "ArmyManager.h"
|
#include "ArmyManager.h"
|
||||||
#include "../Engine/Nullkiller.h"
|
#include "../Engine/Nullkiller.h"
|
||||||
#include "../../../lib/mapObjects/MapObjects.h"
|
#include "../../../lib/mapObjects/MapObjects.h"
|
||||||
#include "../../../lib/mapping/CMapDefines.h"
|
#include "../../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../../lib/IGameSettings.h"
|
#include "../../../lib/IGameSettings.h"
|
||||||
#include "../../../lib/GameConstants.h"
|
#include "../../../lib/GameConstants.h"
|
||||||
#include "../../../lib/TerrainHandler.h"
|
#include "../../../lib/TerrainHandler.h"
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
#include "../../../lib/mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../../../lib/mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "../../../lib/mapObjects/CGResource.h"
|
#include "../../../lib/mapObjects/CGResource.h"
|
||||||
#include "../../../lib/mapping/CMapDefines.h"
|
#include "../../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../../lib/RoadHandler.h"
|
#include "../../../lib/RoadHandler.h"
|
||||||
#include "../../../lib/CCreatureHandler.h"
|
#include "../../../lib/CCreatureHandler.h"
|
||||||
#include "../../../lib/GameLibrary.h"
|
#include "../../../lib/GameLibrary.h"
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "../AIGateway.h"
|
#include "../AIGateway.h"
|
||||||
#include "../Engine/Nullkiller.h"
|
#include "../Engine/Nullkiller.h"
|
||||||
#include "../../../lib/mapObjects/MapObjects.h"
|
#include "../../../lib/mapObjects/MapObjects.h"
|
||||||
#include "../../../lib/mapping/CMapDefines.h"
|
#include "../../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../../lib/pathfinder/TurnInfo.h"
|
#include "../../../lib/pathfinder/TurnInfo.h"
|
||||||
#include "Actions/BuyArmyAction.h"
|
#include "Actions/BuyArmyAction.h"
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "../../lib/entities/artifact/CArtifact.h"
|
#include "../../lib/entities/artifact/CArtifact.h"
|
||||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||||
#include "../../lib/mapObjects/CQuest.h"
|
#include "../../lib/mapObjects/CQuest.h"
|
||||||
#include "../../lib/mapping/CMapDefines.h"
|
#include "../../lib/mapping/TerrainTile.h"
|
||||||
|
|
||||||
extern FuzzyHelper * fh;
|
extern FuzzyHelper * fh;
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "AIPathfinder.h"
|
#include "AIPathfinder.h"
|
||||||
#include "AIPathfinderConfig.h"
|
#include "AIPathfinderConfig.h"
|
||||||
#include "../../../lib/mapping/CMapDefines.h"
|
|
||||||
|
#include "../../../lib/mapping/TerrainTile.h"
|
||||||
|
|
||||||
#include <tbb/task_group.h>
|
#include <tbb/task_group.h>
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "../Goals/Goals.h"
|
#include "../Goals/Goals.h"
|
||||||
#include "../Goals/CompleteQuest.h"
|
#include "../Goals/CompleteQuest.h"
|
||||||
#include "../../../lib/gameState/QuestInfo.h"
|
#include "../../../lib/gameState/QuestInfo.h"
|
||||||
#include "../../../lib/mapping/CMapDefines.h"
|
|
||||||
#include "../../../lib/mapObjects/CQuest.h"
|
#include "../../../lib/mapObjects/CQuest.h"
|
||||||
|
|
||||||
PathfindingManager::PathfindingManager(CPlayerSpecificInfoCallback * CB, VCAI * AI)
|
PathfindingManager::PathfindingManager(CPlayerSpecificInfoCallback * CB, VCAI * AI)
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "../../lib/entities/artifact/CArtifact.h"
|
#include "../../lib/entities/artifact/CArtifact.h"
|
||||||
#include "../../lib/entities/building/CBuilding.h"
|
#include "../../lib/entities/building/CBuilding.h"
|
||||||
#include "../../lib/mapObjects/CQuest.h"
|
#include "../../lib/mapObjects/CQuest.h"
|
||||||
|
#include "../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../lib/networkPacks/PacksForClient.h"
|
#include "../../lib/networkPacks/PacksForClient.h"
|
||||||
#include "../../lib/networkPacks/PacksForClientBattle.h"
|
#include "../../lib/networkPacks/PacksForClientBattle.h"
|
||||||
#include "../../lib/networkPacks/PacksForServer.h"
|
#include "../../lib/networkPacks/PacksForServer.h"
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
|
|
||||||
#include "../lib/callback/CDynLibHandler.h"
|
#include "../lib/callback/CDynLibHandler.h"
|
||||||
#include "../lib/CConfigHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
|
#include "../lib/GameLibrary.h"
|
||||||
#include "../lib/texts/CGeneralTextHandler.h"
|
#include "../lib/texts/CGeneralTextHandler.h"
|
||||||
#include "../lib/CPlayerState.h"
|
#include "../lib/CPlayerState.h"
|
||||||
#include "../lib/CRandomGenerator.h"
|
#include "../lib/CRandomGenerator.h"
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "mainmenu/CHighScoreScreen.h"
|
#include "mainmenu/CHighScoreScreen.h"
|
||||||
|
|
||||||
#include "../lib/CConfigHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
|
#include "../lib/GameLibrary.h"
|
||||||
#include "../lib/texts/CGeneralTextHandler.h"
|
#include "../lib/texts/CGeneralTextHandler.h"
|
||||||
#include "../lib/ConditionalWait.h"
|
#include "../lib/ConditionalWait.h"
|
||||||
#include "../lib/CThreadHelper.h"
|
#include "../lib/CThreadHelper.h"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "mapView/mapHandler.h"
|
#include "mapView/mapHandler.h"
|
||||||
|
|
||||||
#include "../lib/CConfigHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
|
#include "../lib/GameLibrary.h"
|
||||||
#include "../lib/battle/BattleInfo.h"
|
#include "../lib/battle/BattleInfo.h"
|
||||||
#include "../lib/battle/CPlayerBattleCallback.h"
|
#include "../lib/battle/CPlayerBattleCallback.h"
|
||||||
#include "../lib/callback/CCallback.h"
|
#include "../lib/callback/CCallback.h"
|
||||||
@ -35,8 +36,8 @@
|
|||||||
#include "../lib/VCMIDirs.h"
|
#include "../lib/VCMIDirs.h"
|
||||||
#include "../lib/UnlockGuard.h"
|
#include "../lib/UnlockGuard.h"
|
||||||
#include "../lib/serializer/Connection.h"
|
#include "../lib/serializer/Connection.h"
|
||||||
|
#include "../lib/mapObjects/army/CArmedInstance.h"
|
||||||
#include "../lib/mapping/CMapService.h"
|
#include "../lib/mapping/CMapService.h"
|
||||||
#include "../lib/mapObjects/CArmedInstance.h"
|
|
||||||
#include "../lib/pathfinder/CGPathNode.h"
|
#include "../lib/pathfinder/CGPathNode.h"
|
||||||
#include "../lib/filesystem/Filesystem.h"
|
#include "../lib/filesystem/Filesystem.h"
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "../lib/callback/CCallback.h"
|
#include "../lib/callback/CCallback.h"
|
||||||
#include "../lib/networkPacks/PacksForLobby.h"
|
#include "../lib/networkPacks/PacksForLobby.h"
|
||||||
#include "../lib/mapObjects/CArmedInstance.h"
|
#include "../lib/mapObjects/army/CArmedInstance.h"
|
||||||
#include "../lib/CConfigHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
#include "../lib/GameLibrary.h"
|
#include "../lib/GameLibrary.h"
|
||||||
#include "../lib/texts/CGeneralTextHandler.h"
|
#include "../lib/texts/CGeneralTextHandler.h"
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "../lib/callback/CCallback.h"
|
#include "../lib/callback/CCallback.h"
|
||||||
#include "../lib/pathfinder/CGPathNode.h"
|
#include "../lib/pathfinder/CGPathNode.h"
|
||||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../lib/mapping/TerrainTile.h"
|
||||||
#include "../lib/networkPacks/PacksForClient.h"
|
#include "../lib/networkPacks/PacksForClient.h"
|
||||||
#include "../lib/RoadHandler.h"
|
#include "../lib/RoadHandler.h"
|
||||||
#include "../lib/TerrainHandler.h"
|
#include "../lib/TerrainHandler.h"
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||||
#include "../lib/networkPacks/ArtifactLocation.h"
|
#include "../lib/networkPacks/ArtifactLocation.h"
|
||||||
#include "../lib/CRandomGenerator.h"
|
#include "../lib/CRandomGenerator.h"
|
||||||
#include "../lib/CCreatureSet.h"
|
|
||||||
|
|
||||||
std::vector<Component> UIHelper::getArtifactsComponents(const CArtifactSet & artSet, const std::vector<MoveArtifactInfo> & movedPack)
|
std::vector<Component> UIHelper::getArtifactsComponents(const CArtifactSet & artSet, const std::vector<MoveArtifactInfo> & movedPack)
|
||||||
{
|
{
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "../PlayerLocalState.h"
|
#include "../PlayerLocalState.h"
|
||||||
#include "../CPlayerInterface.h"
|
#include "../CPlayerInterface.h"
|
||||||
|
|
||||||
|
#include "../../lib/GameLibrary.h"
|
||||||
#include "../../lib/IGameSettings.h"
|
#include "../../lib/IGameSettings.h"
|
||||||
#include "../../lib/StartInfo.h"
|
#include "../../lib/StartInfo.h"
|
||||||
#include "../../lib/callback/CCallback.h"
|
#include "../../lib/callback/CCallback.h"
|
||||||
@ -44,7 +45,6 @@
|
|||||||
#include "../../lib/spells/CSpellHandler.h"
|
#include "../../lib/spells/CSpellHandler.h"
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||||
#include "../../lib/mapping/CMapDefines.h"
|
|
||||||
#include "../../lib/pathfinder/CGPathNode.h"
|
#include "../../lib/pathfinder/CGPathNode.h"
|
||||||
#include "../../lib/pathfinder/TurnInfo.h"
|
#include "../../lib/pathfinder/TurnInfo.h"
|
||||||
#include "../../lib/spells/ISpellMechanics.h"
|
#include "../../lib/spells/ISpellMechanics.h"
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include "../../lib/CConfigHandler.h"
|
#include "../../lib/CConfigHandler.h"
|
||||||
#include "../../lib/CThreadHelper.h"
|
#include "../../lib/CThreadHelper.h"
|
||||||
#include "../../lib/mapObjects/CArmedInstance.h"
|
#include "../../lib/texts/MetaString.h"
|
||||||
#include "../../lib/texts/TextOperations.h"
|
#include "../../lib/texts/TextOperations.h"
|
||||||
|
|
||||||
CInGameConsole::CInGameConsole()
|
CInGameConsole::CInGameConsole()
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "../../lib/TerrainHandler.h"
|
#include "../../lib/TerrainHandler.h"
|
||||||
#include "../../lib/callback/CCallback.h"
|
#include "../../lib/callback/CCallback.h"
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
#include "../../lib/mapping/CMapDefines.h"
|
#include "../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../lib/texts/CGeneralTextHandler.h"
|
#include "../../lib/texts/CGeneralTextHandler.h"
|
||||||
|
|
||||||
ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
|
ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "../../lib/CRandomGenerator.h"
|
#include "../../lib/CRandomGenerator.h"
|
||||||
#include "../../lib/TerrainHandler.h"
|
#include "../../lib/TerrainHandler.h"
|
||||||
#include "../../lib/callback/CCallback.h"
|
#include "../../lib/callback/CCallback.h"
|
||||||
#include "../../lib/mapObjects/CArmedInstance.h"
|
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
#include "../../lib/mapping/CMap.h"
|
#include "../../lib/mapping/CMap.h"
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
#include "../../lib/mapObjects/MiscObjects.h"
|
#include "../../lib/mapObjects/MiscObjects.h"
|
||||||
#include "../../lib/mapObjects/ObjectTemplate.h"
|
#include "../../lib/mapObjects/ObjectTemplate.h"
|
||||||
#include "../../lib/mapping/CMapDefines.h"
|
#include "../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../lib/pathfinder/CGPathNode.h"
|
#include "../../lib/pathfinder/CGPathNode.h"
|
||||||
|
|
||||||
struct NeighborTilesInfo
|
struct NeighborTilesInfo
|
||||||
|
@ -1,356 +0,0 @@
|
|||||||
/*
|
|
||||||
* CCreatureSet.h, part of VCMI engine
|
|
||||||
*
|
|
||||||
* Authors: listed in file AUTHORS in main folder
|
|
||||||
*
|
|
||||||
* License: GNU General Public License v2.0 or later
|
|
||||||
* Full text of license available in license.txt file, in main folder
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CCreatureHandler.h"
|
|
||||||
#include "GameConstants.h"
|
|
||||||
#include "bonuses/Bonus.h"
|
|
||||||
#include "bonuses/BonusCache.h"
|
|
||||||
#include "bonuses/CBonusSystemNode.h"
|
|
||||||
#include "callback/GameCallbackHolder.h"
|
|
||||||
#include "serializer/Serializeable.h"
|
|
||||||
#include "mapObjects/CGObjectInstance.h"
|
|
||||||
#include "entities/artifact/CArtifactSet.h"
|
|
||||||
|
|
||||||
#include <vcmi/Entity.h>
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
class JsonNode;
|
|
||||||
class CCreature;
|
|
||||||
class CGHeroInstance;
|
|
||||||
class CArmedInstance;
|
|
||||||
class CCreatureArtifactSet;
|
|
||||||
class JsonSerializeFormat;
|
|
||||||
|
|
||||||
class DLL_LINKAGE CStackBasicDescriptor
|
|
||||||
{
|
|
||||||
CreatureID typeID;
|
|
||||||
TQuantity count = -1; //exact quantity or quantity ID from CCreature::getQuantityID when getting info about enemy army
|
|
||||||
|
|
||||||
public:
|
|
||||||
CStackBasicDescriptor();
|
|
||||||
CStackBasicDescriptor(const CreatureID & id, TQuantity Count);
|
|
||||||
CStackBasicDescriptor(const CCreature *c, TQuantity Count);
|
|
||||||
virtual ~CStackBasicDescriptor() = default;
|
|
||||||
|
|
||||||
const Creature * getType() const;
|
|
||||||
const CCreature * getCreature() const;
|
|
||||||
CreatureID getId() const;
|
|
||||||
TQuantity getCount() const;
|
|
||||||
|
|
||||||
virtual void setType(const CCreature * c);
|
|
||||||
virtual void setCount(TQuantity amount);
|
|
||||||
|
|
||||||
friend bool operator== (const CStackBasicDescriptor & l, const CStackBasicDescriptor & r);
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h)
|
|
||||||
{
|
|
||||||
if(h.saving)
|
|
||||||
{
|
|
||||||
h & typeID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CreatureID creatureID;
|
|
||||||
h & creatureID;
|
|
||||||
if(creatureID != CreatureID::NONE)
|
|
||||||
setType(creatureID.toCreature());
|
|
||||||
}
|
|
||||||
|
|
||||||
h & count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serializeJson(JsonSerializeFormat & handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CArtifactSet, public ACreature, public GameCallbackHolder
|
|
||||||
{
|
|
||||||
BonusValueCache nativeTerrain;
|
|
||||||
BonusValueCache initiative;
|
|
||||||
|
|
||||||
CArmedInstance * armyInstance = nullptr; //stack must be part of some army, army must be part of some object
|
|
||||||
|
|
||||||
IGameInfoCallback * getCallback() const final { return cb; }
|
|
||||||
|
|
||||||
TExpType totalExperience;//commander needs same amount of exp as hero
|
|
||||||
public:
|
|
||||||
struct RandomStackInfo
|
|
||||||
{
|
|
||||||
uint8_t level;
|
|
||||||
uint8_t upgrade;
|
|
||||||
};
|
|
||||||
// helper variable used during loading map, when object (hero or town) have creatures that must have same alignment.
|
|
||||||
std::optional<RandomStackInfo> randomStack;
|
|
||||||
|
|
||||||
CArmedInstance * getArmy();
|
|
||||||
const CArmedInstance * getArmy() const; //stack must be part of some army, army must be part of some object
|
|
||||||
void setArmy(CArmedInstance *ArmyObj);
|
|
||||||
|
|
||||||
TExpType getTotalExperience() const;
|
|
||||||
TExpType getAverageExperience() const;
|
|
||||||
virtual bool canGainExperience() const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h)
|
|
||||||
{
|
|
||||||
h & static_cast<CBonusSystemNode&>(*this);
|
|
||||||
h & static_cast<CStackBasicDescriptor&>(*this);
|
|
||||||
h & static_cast<CArtifactSet&>(*this);
|
|
||||||
|
|
||||||
if (h.hasFeature(Handler::Version::STACK_INSTANCE_ARMY_FIX))
|
|
||||||
{
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
if (h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
|
||||||
{
|
|
||||||
ObjectInstanceID dummyID;
|
|
||||||
h & dummyID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::shared_ptr<CGObjectInstance> army;
|
|
||||||
h & army;
|
|
||||||
}
|
|
||||||
|
|
||||||
h & totalExperience;
|
|
||||||
if (!h.hasFeature(Handler::Version::STACK_INSTANCE_EXPERIENCE_FIX))
|
|
||||||
{
|
|
||||||
totalExperience *= getCount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void serializeJson(JsonSerializeFormat & handler);
|
|
||||||
|
|
||||||
//overrides CBonusSystemNode
|
|
||||||
std::string bonusToString(const std::shared_ptr<Bonus>& bonus) const override; // how would bonus description look for this particular type of node
|
|
||||||
ImagePath bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const; //file name of graphics from StackSkills , in future possibly others
|
|
||||||
|
|
||||||
//IConstBonusProvider
|
|
||||||
const IBonusBearer* getBonusBearer() const override;
|
|
||||||
//INativeTerrainProvider
|
|
||||||
FactionID getFactionID() const override;
|
|
||||||
|
|
||||||
virtual ui64 getPower() const;
|
|
||||||
/// Returns total market value of resources needed to recruit this unit
|
|
||||||
virtual ui64 getMarketValue() const;
|
|
||||||
CCreature::CreatureQuantityId getQuantityID() const;
|
|
||||||
std::string getQuantityTXT(bool capitalized = true) const;
|
|
||||||
virtual int getExpRank() const;
|
|
||||||
virtual int getLevel() const; //different for regular stack and commander
|
|
||||||
CreatureID getCreatureID() const; //-1 if not available
|
|
||||||
std::string getName() const; //plural or singular
|
|
||||||
CStackInstance(IGameInfoCallback *cb);
|
|
||||||
CStackInstance(IGameInfoCallback *cb, BonusNodeType nodeType, bool isHypothetic = false);
|
|
||||||
CStackInstance(IGameInfoCallback *cb, const CreatureID & id, TQuantity count, bool isHypothetic = false);
|
|
||||||
virtual ~CStackInstance() = default;
|
|
||||||
|
|
||||||
void setType(const CreatureID & creID);
|
|
||||||
void setType(const CCreature * c) final;
|
|
||||||
void setCount(TQuantity amount) final;
|
|
||||||
|
|
||||||
/// Gives specified amount of stack experience that will not be scaled by unit size
|
|
||||||
void giveAverageStackExperience(TExpType exp);
|
|
||||||
void giveTotalStackExperience(TExpType exp);
|
|
||||||
|
|
||||||
bool valid(bool allowUnrandomized) const;
|
|
||||||
ArtPlacementMap putArtifact(const ArtifactPosition & pos, const CArtifactInstance * art) override;//from CArtifactSet
|
|
||||||
void removeArtifact(const ArtifactPosition & pos) override;
|
|
||||||
ArtBearer bearerType() const override; //from CArtifactSet
|
|
||||||
std::string nodeName() const override; //from CBonusSystemnode
|
|
||||||
PlayerColor getOwner() const override;
|
|
||||||
|
|
||||||
int32_t getInitiative(int turn = 0) const final;
|
|
||||||
TerrainId getNativeTerrain() const final;
|
|
||||||
TerrainId getCurrentTerrain() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLL_LINKAGE CCommanderInstance : public CStackInstance
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//TODO: what if Commander is not a part of creature set?
|
|
||||||
|
|
||||||
//commander class is determined by its base creature
|
|
||||||
ui8 alive; //maybe change to bool when breaking save compatibility?
|
|
||||||
ui8 level; //required only to count callbacks
|
|
||||||
std::string name; // each Commander has different name
|
|
||||||
std::vector <ui8> secondarySkills; //ID -> level
|
|
||||||
std::set <ui8> specialSkills;
|
|
||||||
//std::vector <CArtifactInstance *> arts;
|
|
||||||
CCommanderInstance(IGameInfoCallback *cb);
|
|
||||||
CCommanderInstance(IGameInfoCallback *cb, const CreatureID & id);
|
|
||||||
void setAlive (bool alive);
|
|
||||||
void levelUp ();
|
|
||||||
|
|
||||||
bool canGainExperience() const override;
|
|
||||||
bool gainsLevel() const; //true if commander has lower level than should upon his experience
|
|
||||||
ui64 getPower() const override {return 0;};
|
|
||||||
int getExpRank() const override;
|
|
||||||
int getLevel() const override;
|
|
||||||
ArtBearer bearerType() const override; //from CArtifactSet
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h)
|
|
||||||
{
|
|
||||||
h & static_cast<CStackInstance&>(*this);
|
|
||||||
h & alive;
|
|
||||||
h & level;
|
|
||||||
h & name;
|
|
||||||
h & secondarySkills;
|
|
||||||
h & specialSkills;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using TSlots = std::map<SlotID, std::unique_ptr<CStackInstance>>;
|
|
||||||
using TSimpleSlots = std::map<SlotID, std::pair<CreatureID, TQuantity>>;
|
|
||||||
|
|
||||||
using TPairCreatureSlot = std::pair<const CCreature *, SlotID>;
|
|
||||||
using TMapCreatureSlot = std::map<const CCreature *, SlotID>;
|
|
||||||
|
|
||||||
struct DLL_LINKAGE CreatureSlotComparer
|
|
||||||
{
|
|
||||||
bool operator()(const TPairCreatureSlot & lhs, const TPairCreatureSlot & rhs);
|
|
||||||
};
|
|
||||||
|
|
||||||
using TCreatureQueue = std::priority_queue<TPairCreatureSlot, std::vector<TPairCreatureSlot>, CreatureSlotComparer>;
|
|
||||||
|
|
||||||
class IArmyDescriptor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void clearSlots() = 0;
|
|
||||||
virtual bool setCreature(SlotID slot, CreatureID cre, TQuantity count) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//simplified version of CCreatureSet
|
|
||||||
class DLL_LINKAGE CSimpleArmy : public IArmyDescriptor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TSimpleSlots army;
|
|
||||||
void clearSlots() override;
|
|
||||||
bool setCreature(SlotID slot, CreatureID cre, TQuantity count) override;
|
|
||||||
operator bool() const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h)
|
|
||||||
{
|
|
||||||
h & army;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace NArmyFormation
|
|
||||||
{
|
|
||||||
static const std::vector<std::string> names{ "wide", "tight" };
|
|
||||||
}
|
|
||||||
|
|
||||||
class DLL_LINKAGE CCreatureSet : public IArmyDescriptor, public virtual Serializeable //seven combined creatures
|
|
||||||
{
|
|
||||||
CCreatureSet(const CCreatureSet &) = delete;
|
|
||||||
CCreatureSet &operator=(const CCreatureSet&);
|
|
||||||
|
|
||||||
public:
|
|
||||||
TSlots stacks; //slots[slot_id]->> pair(creature_id,creature_quantity)
|
|
||||||
EArmyFormation formation = EArmyFormation::LOOSE; //0 - wide, 1 - tight
|
|
||||||
|
|
||||||
CCreatureSet() = default; //Should be here to avoid compile errors
|
|
||||||
virtual ~CCreatureSet();
|
|
||||||
virtual void armyChanged();
|
|
||||||
|
|
||||||
const CStackInstance & operator[](const SlotID & slot) const;
|
|
||||||
|
|
||||||
const TSlots &Slots() const {return stacks;}
|
|
||||||
|
|
||||||
void addToSlot(const SlotID & slot, const CreatureID & cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
|
|
||||||
void addToSlot(const SlotID & slot, std::unique_ptr<CStackInstance> stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
|
|
||||||
void clearSlots() override;
|
|
||||||
void setFormation(EArmyFormation tight);
|
|
||||||
virtual CArmedInstance * getArmy() { return nullptr; }
|
|
||||||
virtual const CArmedInstance * getArmy() const { return nullptr; }
|
|
||||||
|
|
||||||
//basic operations
|
|
||||||
void putStack(const SlotID & slot, std::unique_ptr<CStackInstance> stack); //adds new stack to the army, slot must be empty
|
|
||||||
void setStackCount(const SlotID & slot, TQuantity count); //stack must exist!
|
|
||||||
std::unique_ptr<CStackInstance> detachStack(const SlotID & slot); //removes stack from army but doesn't destroy it (so it can be moved somewhere else or safely deleted)
|
|
||||||
void setStackType(const SlotID & slot, const CreatureID & type);
|
|
||||||
|
|
||||||
/// Give specified amount of experience to all units in army
|
|
||||||
/// Amount of granted experience is scaled by unit stack size
|
|
||||||
void giveAverageStackExperience(TExpType exp);
|
|
||||||
|
|
||||||
/// Give specified amount of experience to unit in specified slot
|
|
||||||
/// Amount of granted experience is not scaled by unit stack size
|
|
||||||
void giveTotalStackExperience(const SlotID & slot, TExpType exp);
|
|
||||||
|
|
||||||
/// Erased stack from specified slot. Slot must be non-empty
|
|
||||||
void eraseStack(const SlotID & slot);
|
|
||||||
|
|
||||||
/// Joins stack into stack that occupies targeted slot.
|
|
||||||
/// Slot must be non-empty and contain same creature type
|
|
||||||
void joinStack(const SlotID & slot, std::unique_ptr<CStackInstance> stack); //adds new stack to the existing stack of the same type
|
|
||||||
|
|
||||||
/// Splits off some units of specified stack and returns newly created stack
|
|
||||||
/// Slot must be non-empty and contain more units that split quantity
|
|
||||||
std::unique_ptr<CStackInstance> splitStack(const SlotID & slot, TQuantity toSplit);
|
|
||||||
|
|
||||||
void changeStackCount(const SlotID & slot, TQuantity toAdd); //stack must exist!
|
|
||||||
bool setCreature (SlotID slot, CreatureID type, TQuantity quantity) override; //replaces creature in stack; slots 0 to 6, if quantity=0 erases stack
|
|
||||||
void setToArmy(CSimpleArmy &src); //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
|
|
||||||
|
|
||||||
const CStackInstance & getStack(const SlotID & slot) const; //stack must exist
|
|
||||||
CStackInstance * getStackPtr(const SlotID & slot) const; //if stack doesn't exist, returns nullptr
|
|
||||||
const CCreature * getCreature(const SlotID & slot) const; //workaround of map issue;
|
|
||||||
int getStackCount(const SlotID & slot) const;
|
|
||||||
TExpType getStackTotalExperience(const SlotID & slot) const;
|
|
||||||
TExpType getStackAverageExperience(const SlotID & slot) const;
|
|
||||||
SlotID findStack(const CStackInstance *stack) const; //-1 if none
|
|
||||||
SlotID getSlotFor(const CreatureID & creature, ui32 slotsAmount = GameConstants::ARMY_SIZE) const; //returns -1 if no slot available
|
|
||||||
SlotID getSlotFor(const CCreature *c, ui32 slotsAmount = GameConstants::ARMY_SIZE) const; //returns -1 if no slot available
|
|
||||||
bool hasCreatureSlots(const CCreature * c, const SlotID & exclude) const;
|
|
||||||
std::vector<SlotID> getCreatureSlots(const CCreature * c, const SlotID & exclude, TQuantity ignoreAmount = -1) const;
|
|
||||||
bool isCreatureBalanced(const CCreature* c, TQuantity ignoreAmount = 1) const; // Check if the creature is evenly distributed across slots
|
|
||||||
|
|
||||||
SlotID getFreeSlot(ui32 slotsAmount = GameConstants::ARMY_SIZE) const; //returns first free slot
|
|
||||||
std::vector<SlotID> getFreeSlots(ui32 slotsAmount = GameConstants::ARMY_SIZE) const;
|
|
||||||
std::queue<SlotID> getFreeSlotsQueue(ui32 slotsAmount = GameConstants::ARMY_SIZE) const;
|
|
||||||
|
|
||||||
TMapCreatureSlot getCreatureMap() const;
|
|
||||||
TCreatureQueue getCreatureQueue(const SlotID & exclude) const;
|
|
||||||
|
|
||||||
bool mergeableStacks(std::pair<SlotID, SlotID> & out, const SlotID & preferable = SlotID()) const; //looks for two same stacks, returns slot positions;
|
|
||||||
bool validTypes(bool allowUnrandomized = false) const; //checks if all types of creatures are set properly
|
|
||||||
bool slotEmpty(const SlotID & slot) const;
|
|
||||||
int stacksCount() const;
|
|
||||||
virtual bool needsLastStack() const; //true if last stack cannot be taken
|
|
||||||
ui64 getArmyStrength(int fortLevel = 0) const; //sum of AI values of creatures
|
|
||||||
ui64 getArmyCost() const; //sum of cost of creatures
|
|
||||||
ui64 getPower(const SlotID & slot) const; //value of specific stack
|
|
||||||
std::string getRoughAmount(const SlotID & slot, int mode = 0) const; //rough size of specific stack
|
|
||||||
std::string getArmyDescription() const;
|
|
||||||
bool hasStackAtSlot(const SlotID & slot) const;
|
|
||||||
|
|
||||||
bool contains(const CStackInstance *stack) const;
|
|
||||||
bool canBeMergedWith(const CCreatureSet &cs, bool allowMergingStacks = true) const;
|
|
||||||
|
|
||||||
/// Returns true if this creature set contains all listed units
|
|
||||||
/// If requireLastStack is true, then this function will also
|
|
||||||
/// require presence of any unit other than requested (or more units than requested)
|
|
||||||
bool hasUnits(const std::vector<CStackBasicDescriptor> & units, bool requireLastStack = true) const;
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h)
|
|
||||||
{
|
|
||||||
h & stacks;
|
|
||||||
h & formation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serializeJson(JsonSerializeFormat & handler, const std::string & armyFieldName, const std::optional<int> fixedSize = std::nullopt);
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return !stacks.empty();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
|
@ -142,7 +142,6 @@ set(lib_MAIN_SRCS
|
|||||||
mapObjectConstructors/HillFortInstanceConstructor.cpp
|
mapObjectConstructors/HillFortInstanceConstructor.cpp
|
||||||
mapObjectConstructors/ShipyardInstanceConstructor.cpp
|
mapObjectConstructors/ShipyardInstanceConstructor.cpp
|
||||||
|
|
||||||
mapObjects/CArmedInstance.cpp
|
|
||||||
mapObjects/CGCreature.cpp
|
mapObjects/CGCreature.cpp
|
||||||
mapObjects/CGDwelling.cpp
|
mapObjects/CGDwelling.cpp
|
||||||
mapObjects/CGHeroInstance.cpp
|
mapObjects/CGHeroInstance.cpp
|
||||||
@ -162,6 +161,12 @@ set(lib_MAIN_SRCS
|
|||||||
mapObjects/ObjectTemplate.cpp
|
mapObjects/ObjectTemplate.cpp
|
||||||
mapObjects/ObstacleSetHandler.cpp
|
mapObjects/ObstacleSetHandler.cpp
|
||||||
|
|
||||||
|
mapObjects/army/CArmedInstance.cpp
|
||||||
|
mapObjects/army/CCommanderInstance.cpp
|
||||||
|
mapObjects/army/CCreatureSet.cpp
|
||||||
|
mapObjects/army/CStackBasicDescriptor.cpp
|
||||||
|
mapObjects/army/CStackInstance.cpp
|
||||||
|
|
||||||
mapping/CDrawRoadsOperation.cpp
|
mapping/CDrawRoadsOperation.cpp
|
||||||
mapping/CMap.cpp
|
mapping/CMap.cpp
|
||||||
mapping/CMapHeader.cpp
|
mapping/CMapHeader.cpp
|
||||||
@ -251,7 +256,6 @@ set(lib_MAIN_SRCS
|
|||||||
serializer/SerializerReflection.cpp
|
serializer/SerializerReflection.cpp
|
||||||
|
|
||||||
spells/AbilityCaster.cpp
|
spells/AbilityCaster.cpp
|
||||||
spells/AdventureSpellMechanics.cpp
|
|
||||||
spells/BattleSpellMechanics.cpp
|
spells/BattleSpellMechanics.cpp
|
||||||
spells/BonusCaster.cpp
|
spells/BonusCaster.cpp
|
||||||
spells/CSpellHandler.cpp
|
spells/CSpellHandler.cpp
|
||||||
@ -264,6 +268,13 @@ set(lib_MAIN_SRCS
|
|||||||
spells/TargetCondition.cpp
|
spells/TargetCondition.cpp
|
||||||
spells/ViewSpellInt.cpp
|
spells/ViewSpellInt.cpp
|
||||||
|
|
||||||
|
spells/adventure/AdventureSpellMechanics.cpp
|
||||||
|
spells/adventure/DimensionDoorMechanics.cpp
|
||||||
|
spells/adventure/ScuttleBoatMechanics.cpp
|
||||||
|
spells/adventure/SummonBoatMechanics.cpp
|
||||||
|
spells/adventure/TownPortalMechanics.cpp
|
||||||
|
spells/adventure/ViewWorldMechanics.cpp
|
||||||
|
|
||||||
spells/effects/Catapult.cpp
|
spells/effects/Catapult.cpp
|
||||||
spells/effects/Clone.cpp
|
spells/effects/Clone.cpp
|
||||||
spells/effects/Damage.cpp
|
spells/effects/Damage.cpp
|
||||||
@ -293,7 +304,6 @@ set(lib_MAIN_SRCS
|
|||||||
CAndroidVMHelper.cpp
|
CAndroidVMHelper.cpp
|
||||||
CBonusTypeHandler.cpp
|
CBonusTypeHandler.cpp
|
||||||
CCreatureHandler.cpp
|
CCreatureHandler.cpp
|
||||||
CCreatureSet.cpp
|
|
||||||
CPlayerState.cpp
|
CPlayerState.cpp
|
||||||
CRandomGenerator.cpp
|
CRandomGenerator.cpp
|
||||||
CScriptingModule.cpp
|
CScriptingModule.cpp
|
||||||
@ -558,7 +568,6 @@ set(lib_MAIN_HEADERS
|
|||||||
mapObjectConstructors/ShipyardInstanceConstructor.h
|
mapObjectConstructors/ShipyardInstanceConstructor.h
|
||||||
mapObjectConstructors/SObjectSounds.h
|
mapObjectConstructors/SObjectSounds.h
|
||||||
|
|
||||||
mapObjects/CArmedInstance.h
|
|
||||||
mapObjects/CGCreature.h
|
mapObjects/CGCreature.h
|
||||||
mapObjects/CGDwelling.h
|
mapObjects/CGDwelling.h
|
||||||
mapObjects/CGHeroInstance.h
|
mapObjects/CGHeroInstance.h
|
||||||
@ -581,9 +590,17 @@ set(lib_MAIN_HEADERS
|
|||||||
mapObjects/ObjectTemplate.h
|
mapObjects/ObjectTemplate.h
|
||||||
mapObjects/ObstacleSetHandler.h
|
mapObjects/ObstacleSetHandler.h
|
||||||
|
|
||||||
|
mapObjects/army/CArmedInstance.h
|
||||||
|
mapObjects/army/CCommanderInstance.h
|
||||||
|
mapObjects/army/CCreatureSet.h
|
||||||
|
mapObjects/army/CSimpleArmy.h
|
||||||
|
mapObjects/army/CStackBasicDescriptor.h
|
||||||
|
mapObjects/army/CStackInstance.h
|
||||||
|
|
||||||
mapping/CDrawRoadsOperation.h
|
mapping/CDrawRoadsOperation.h
|
||||||
mapping/CMapDefines.h
|
mapping/CCastleEvent.h
|
||||||
mapping/CMapEditManager.h
|
mapping/CMapEditManager.h
|
||||||
|
mapping/CMapEvent.h
|
||||||
mapping/CMapHeader.h
|
mapping/CMapHeader.h
|
||||||
mapping/CMap.h
|
mapping/CMap.h
|
||||||
mapping/CMapInfo.h
|
mapping/CMapInfo.h
|
||||||
@ -598,6 +615,7 @@ set(lib_MAIN_HEADERS
|
|||||||
mapping/MapReaderH3M.h
|
mapping/MapReaderH3M.h
|
||||||
mapping/MapFormatJson.h
|
mapping/MapFormatJson.h
|
||||||
mapping/ObstacleProxy.h
|
mapping/ObstacleProxy.h
|
||||||
|
mapping/TerrainTile.h
|
||||||
|
|
||||||
modding/ActiveModsInSaveList.h
|
modding/ActiveModsInSaveList.h
|
||||||
modding/CModHandler.h
|
modding/CModHandler.h
|
||||||
@ -700,7 +718,6 @@ set(lib_MAIN_HEADERS
|
|||||||
serializer/SerializerReflection.h
|
serializer/SerializerReflection.h
|
||||||
|
|
||||||
spells/AbilityCaster.h
|
spells/AbilityCaster.h
|
||||||
spells/AdventureSpellMechanics.h
|
|
||||||
spells/BattleSpellMechanics.h
|
spells/BattleSpellMechanics.h
|
||||||
spells/BonusCaster.h
|
spells/BonusCaster.h
|
||||||
spells/CSpellHandler.h
|
spells/CSpellHandler.h
|
||||||
@ -713,6 +730,13 @@ set(lib_MAIN_HEADERS
|
|||||||
spells/TargetCondition.h
|
spells/TargetCondition.h
|
||||||
spells/ViewSpellInt.h
|
spells/ViewSpellInt.h
|
||||||
|
|
||||||
|
spells/adventure/AdventureSpellMechanics.h
|
||||||
|
spells/adventure/DimensionDoorMechanics.h
|
||||||
|
spells/adventure/ScuttleBoatMechanics.h
|
||||||
|
spells/adventure/SummonBoatMechanics.h
|
||||||
|
spells/adventure/TownPortalMechanics.h
|
||||||
|
spells/adventure/ViewWorldMechanics.h
|
||||||
|
|
||||||
spells/effects/Catapult.h
|
spells/effects/Catapult.h
|
||||||
spells/effects/Clone.h
|
spells/effects/Clone.h
|
||||||
spells/effects/Damage.h
|
spells/effects/Damage.h
|
||||||
@ -744,7 +768,6 @@ set(lib_MAIN_HEADERS
|
|||||||
CAndroidVMHelper.h
|
CAndroidVMHelper.h
|
||||||
CBonusTypeHandler.h
|
CBonusTypeHandler.h
|
||||||
CCreatureHandler.h
|
CCreatureHandler.h
|
||||||
CCreatureSet.h
|
|
||||||
ConditionalWait.h
|
ConditionalWait.h
|
||||||
Color.h
|
Color.h
|
||||||
CPlayerState.h
|
CPlayerState.h
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
#include "../GameSettings.h"
|
#include "../GameSettings.h"
|
||||||
#include "../GameLibrary.h"
|
#include "../GameLibrary.h"
|
||||||
#include "../callback/IGameInfoCallback.h"
|
#include "../callback/IGameInfoCallback.h"
|
||||||
|
#include "../mapObjects/army/CArmedInstance.h"
|
||||||
#include "../json/JsonNode.h"
|
#include "../json/JsonNode.h"
|
||||||
#include "../mapObjects/CArmedInstance.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "BattleStateInfoForRetreat.h"
|
#include "BattleStateInfoForRetreat.h"
|
||||||
#include "Unit.h"
|
#include "Unit.h"
|
||||||
#include "CBattleInfoCallback.h"
|
#include "CBattleInfoCallback.h"
|
||||||
#include "../CCreatureSet.h"
|
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "Unit.h"
|
#include "Unit.h"
|
||||||
|
|
||||||
#include "../bonuses/Bonus.h"
|
#include "../bonuses/Bonus.h"
|
||||||
|
#include "../CCreatureHandler.h"
|
||||||
#include "../mapObjects/CGTownInstance.h"
|
#include "../mapObjects/CGTownInstance.h"
|
||||||
#include "../spells/CSpellHandler.h"
|
#include "../spells/CSpellHandler.h"
|
||||||
#include "../IGameSettings.h"
|
#include "../IGameSettings.h"
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
#include "../CBonusTypeHandler.h"
|
#include "../CBonusTypeHandler.h"
|
||||||
#include "../CCreatureHandler.h"
|
#include "../CCreatureHandler.h"
|
||||||
#include "../CCreatureSet.h"
|
|
||||||
#include "../CSkillHandler.h"
|
#include "../CSkillHandler.h"
|
||||||
#include "../TerrainHandler.h"
|
#include "../TerrainHandler.h"
|
||||||
#include "../GameLibrary.h"
|
#include "../GameLibrary.h"
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include "../GameLibrary.h"
|
#include "../GameLibrary.h"
|
||||||
#include "../entities/faction/CTownHandler.h"
|
#include "../entities/faction/CTownHandler.h"
|
||||||
#include "../CCreatureHandler.h"
|
#include "../CCreatureHandler.h"
|
||||||
#include "../CCreatureSet.h"
|
|
||||||
#include "../CStack.h"
|
#include "../CStack.h"
|
||||||
#include "../TerrainHandler.h"
|
#include "../TerrainHandler.h"
|
||||||
#include "../constants/StringConstants.h"
|
#include "../constants/StringConstants.h"
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include "../mapObjects/CGTownInstance.h"
|
#include "../mapObjects/CGTownInstance.h"
|
||||||
#include "../mapObjects/CQuest.h"
|
#include "../mapObjects/CQuest.h"
|
||||||
#include "../mapObjects/MiscObjects.h"
|
#include "../mapObjects/MiscObjects.h"
|
||||||
|
#include "../mapping/CCastleEvent.h"
|
||||||
#include "../mapping/CMap.h"
|
#include "../mapping/CMap.h"
|
||||||
#include "../mapping/CMapEditManager.h"
|
#include "../mapping/CMapEditManager.h"
|
||||||
#include "../mapping/CMapService.h"
|
#include "../mapping/CMapService.h"
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../texts/MetaString.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class DLL_LINKAGE EVictoryLossCheckResult
|
class DLL_LINKAGE EVictoryLossCheckResult
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CCreatureSet.h"
|
#include "../mapObjects/army/CStackBasicDescriptor.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
#include "../constants/StringConstants.h"
|
#include "../constants/StringConstants.h"
|
||||||
#include "../GameLibrary.h"
|
#include "../GameLibrary.h"
|
||||||
#include "../CCreatureHandler.h"
|
#include "../CCreatureHandler.h"
|
||||||
#include "../CCreatureSet.h"
|
|
||||||
#include "../spells/CSpellHandler.h"
|
#include "../spells/CSpellHandler.h"
|
||||||
#include "../CSkillHandler.h"
|
#include "../CSkillHandler.h"
|
||||||
#include "../entities/artifact/CArtHandler.h"
|
#include "../entities/artifact/CArtHandler.h"
|
||||||
#include "../entities/hero/CHero.h"
|
#include "../entities/hero/CHero.h"
|
||||||
#include "../entities/hero/CHeroClass.h"
|
#include "../entities/hero/CHeroClass.h"
|
||||||
#include "../gameState/CGameState.h"
|
#include "../gameState/CGameState.h"
|
||||||
|
#include "../mapObjects/army/CStackBasicDescriptor.h"
|
||||||
#include "../mapObjects/IObjectInterface.h"
|
#include "../mapObjects/IObjectInterface.h"
|
||||||
#include "../modding/IdentifierStorage.h"
|
#include "../modding/IdentifierStorage.h"
|
||||||
#include "../modding/ModScope.h"
|
#include "../modding/ModScope.h"
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
#include "../mapObjects/CGTownInstance.h"
|
#include "../mapObjects/CGTownInstance.h"
|
||||||
#include "../mapObjects/MiscObjects.h"
|
#include "../mapObjects/MiscObjects.h"
|
||||||
#include "../mapObjects/ObjectTemplate.h"
|
#include "../mapObjects/ObjectTemplate.h"
|
||||||
|
#include "../mapping/TerrainTile.h"
|
||||||
#include "../modding/IdentifierStorage.h"
|
#include "../modding/IdentifierStorage.h"
|
||||||
#include "../mapping/CMapDefines.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "../texts/CGeneralTextHandler.h"
|
#include "../texts/CGeneralTextHandler.h"
|
||||||
#include "../json/JsonRandom.h"
|
#include "../json/JsonRandom.h"
|
||||||
#include "../GameLibrary.h"
|
#include "../GameLibrary.h"
|
||||||
|
#include "../mapObjects/army/CStackInstance.h"
|
||||||
#include "../mapObjects/CGDwelling.h"
|
#include "../mapObjects/CGDwelling.h"
|
||||||
#include "../mapObjects/ObjectTemplate.h"
|
#include "../mapObjects/ObjectTemplate.h"
|
||||||
#include "../modding/IdentifierStorage.h"
|
#include "../modding/IdentifierStorage.h"
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CArmedInstance.h"
|
#include "army/CArmedInstance.h"
|
||||||
#include "../ResourceSet.h"
|
#include "../ResourceSet.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
@ -10,9 +10,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CArmedInstance.h"
|
|
||||||
#include "IOwnableObject.h"
|
#include "IOwnableObject.h"
|
||||||
|
|
||||||
|
#include "army/CArmedInstance.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class CGDwelling;
|
class CGDwelling;
|
||||||
|
@ -11,9 +11,11 @@
|
|||||||
|
|
||||||
#include <vcmi/spells/Caster.h>
|
#include <vcmi/spells/Caster.h>
|
||||||
|
|
||||||
#include "CArmedInstance.h"
|
|
||||||
#include "IOwnableObject.h"
|
#include "IOwnableObject.h"
|
||||||
|
|
||||||
|
#include "army/CArmedInstance.h"
|
||||||
|
#include "army/CCommanderInstance.h"
|
||||||
|
|
||||||
#include "../bonuses/BonusCache.h"
|
#include "../bonuses/BonusCache.h"
|
||||||
#include "../entities/hero/EHeroGender.h"
|
#include "../entities/hero/EHeroGender.h"
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CArmedInstance.h"
|
#include "army/CArmedInstance.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "../texts/CGeneralTextHandler.h"
|
#include "../texts/CGeneralTextHandler.h"
|
||||||
#include "../gameState/CGameState.h"
|
#include "../gameState/CGameState.h"
|
||||||
#include "../gameState/UpgradeInfo.h"
|
#include "../gameState/UpgradeInfo.h"
|
||||||
|
#include "../mapping/CCastleEvent.h"
|
||||||
#include "../mapping/CMap.h"
|
#include "../mapping/CMap.h"
|
||||||
#include "../CPlayerState.h"
|
#include "../CPlayerState.h"
|
||||||
#include "../StartInfo.h"
|
#include "../StartInfo.h"
|
||||||
|
@ -167,7 +167,7 @@ public:
|
|||||||
void removeAllBuildings();
|
void removeAllBuildings();
|
||||||
std::set<BuildingID> getBuildings() const;
|
std::set<BuildingID> getBuildings() const;
|
||||||
|
|
||||||
TResources getBuildingCost(const BuildingID & buildingID) const;
|
ResourceSet getBuildingCost(const BuildingID & buildingID) const;
|
||||||
ResourceSet dailyIncome() const override;
|
ResourceSet dailyIncome() const override;
|
||||||
std::vector<CreatureID> providedCreatures() const override;
|
std::vector<CreatureID> providedCreatures() const override;
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CArmedInstance.h"
|
#include "army/CArmedInstance.h"
|
||||||
|
|
||||||
#include "../rewardable/Interface.h"
|
#include "../rewardable/Interface.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "../callback/IGameInfoCallback.h"
|
#include "../callback/IGameInfoCallback.h"
|
||||||
#include "../callback/IGameEventCallback.h"
|
#include "../callback/IGameEventCallback.h"
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../mapping/TerrainTile.h"
|
||||||
#include "../networkPacks/PacksForClient.h"
|
#include "../networkPacks/PacksForClient.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
// Possible TODO - remove this header after CObjectHandler.cpp will be fully split into smaller files
|
// Possible TODO - remove this header after CObjectHandler.cpp will be fully split into smaller files
|
||||||
#include "CObjectHandler.h"
|
#include "CObjectHandler.h"
|
||||||
|
|
||||||
#include "CArmedInstance.h"
|
|
||||||
#include "CGDwelling.h"
|
#include "CGDwelling.h"
|
||||||
#include "CGHeroInstance.h"
|
#include "CGHeroInstance.h"
|
||||||
#include "CGMarket.h"
|
#include "CGMarket.h"
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CArmedInstance.h"
|
|
||||||
#include "IOwnableObject.h"
|
#include "IOwnableObject.h"
|
||||||
|
#include "army/CArmedInstance.h"
|
||||||
|
#include "../entities/artifact/CArtifactInstance.h"
|
||||||
#include "../texts/MetaString.h"
|
#include "../texts/MetaString.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
@ -11,16 +11,14 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CArmedInstance.h"
|
#include "CArmedInstance.h"
|
||||||
|
|
||||||
#include "../CCreatureHandler.h"
|
#include "CStackInstance.h"
|
||||||
#include "../CPlayerState.h"
|
|
||||||
#include "../callback/IGameInfoCallback.h"
|
#include "../../CPlayerState.h"
|
||||||
#include "../entities/faction/CFaction.h"
|
#include "../../entities/faction/CTown.h"
|
||||||
#include "../entities/faction/CTown.h"
|
#include "../../entities/faction/CTownHandler.h"
|
||||||
#include "../entities/faction/CTownHandler.h"
|
#include "../../mapping/TerrainTile.h"
|
||||||
#include "../GameLibrary.h"
|
#include "../../GameLibrary.h"
|
||||||
#include "../gameState/CGameState.h"
|
#include "../../gameState/CGameState.h"
|
||||||
#include "../mapping/CMapDefines.h"
|
|
||||||
#include "../texts/CGeneralTextHandler.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -46,11 +44,11 @@ CArmedInstance::CArmedInstance(IGameInfoCallback *cb)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CArmedInstance::CArmedInstance(IGameInfoCallback *cb, BonusNodeType nodeType, bool isHypothetic):
|
CArmedInstance::CArmedInstance(IGameInfoCallback * cb, BonusNodeType nodeType, bool isHypothetic)
|
||||||
CGObjectInstance(cb),
|
: CGObjectInstance(cb)
|
||||||
CBonusSystemNode(nodeType, isHypothetic),
|
, CBonusSystemNode(nodeType, isHypothetic)
|
||||||
nonEvilAlignmentMix(this, Selector::type()(BonusType::NONEVIL_ALIGNMENT_MIX)), // Take Angelic Alliance troop-mixing freedom of non-evil units into account.
|
, nonEvilAlignmentMix(this, Selector::type()(BonusType::NONEVIL_ALIGNMENT_MIX)) // Take Angelic Alliance troop-mixing freedom of non-evil units into account.
|
||||||
battle(nullptr)
|
, battle(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +127,6 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
|||||||
}
|
}
|
||||||
else if(undeadModifier)
|
else if(undeadModifier)
|
||||||
removeBonus(undeadModifier);
|
removeBonus(undeadModifier);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CArmedInstance::armyChanged()
|
void CArmedInstance::armyChanged()
|
@ -9,10 +9,14 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CGObjectInstance.h"
|
#include "CCreatureSet.h"
|
||||||
#include "../CCreatureSet.h"
|
|
||||||
#include "../bonuses/CBonusSystemNode.h"
|
#include "../CGObjectInstance.h"
|
||||||
#include "../bonuses/BonusCache.h"
|
|
||||||
|
#include "../../bonuses/BonusCache.h"
|
||||||
|
#include "../../bonuses/CBonusSystemNode.h"
|
||||||
|
|
||||||
|
#include <vcmi/Entity.h>
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -38,8 +42,14 @@ public:
|
|||||||
virtual void updateMoraleBonusFromArmy();
|
virtual void updateMoraleBonusFromArmy();
|
||||||
|
|
||||||
void armyChanged() override;
|
void armyChanged() override;
|
||||||
CArmedInstance * getArmy() final { return this; }
|
CArmedInstance * getArmy() final
|
||||||
const CArmedInstance * getArmy() const final { return this; }
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
const CArmedInstance * getArmy() const final
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
//IConstBonusProvider
|
//IConstBonusProvider
|
||||||
@ -62,7 +72,8 @@ public:
|
|||||||
|
|
||||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h)
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
{
|
{
|
||||||
h & static_cast<CGObjectInstance &>(*this);
|
h & static_cast<CGObjectInstance &>(*this);
|
||||||
h & static_cast<CBonusSystemNode &>(*this);
|
h & static_cast<CBonusSystemNode &>(*this);
|
80
lib/mapObjects/army/CCommanderInstance.cpp
Normal file
80
lib/mapObjects/army/CCommanderInstance.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* CCommanderInstance.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 "CCommanderInstance.h"
|
||||||
|
|
||||||
|
#include "../../GameLibrary.h"
|
||||||
|
#include "../../entities/hero/CHeroHandler.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
CCommanderInstance::CCommanderInstance(IGameInfoCallback * cb)
|
||||||
|
: CStackInstance(cb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CCommanderInstance::CCommanderInstance(IGameInfoCallback * cb, const CreatureID & id)
|
||||||
|
: CStackInstance(cb, BonusNodeType::COMMANDER, false)
|
||||||
|
, name("Commando")
|
||||||
|
{
|
||||||
|
alive = true;
|
||||||
|
level = 1;
|
||||||
|
setCount(1);
|
||||||
|
setType(nullptr);
|
||||||
|
secondarySkills.resize(ECommander::SPELL_POWER + 1);
|
||||||
|
setType(id);
|
||||||
|
//TODO - parse them
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCommanderInstance::setAlive(bool Alive)
|
||||||
|
{
|
||||||
|
//TODO: helm of immortality
|
||||||
|
alive = Alive;
|
||||||
|
if(!alive)
|
||||||
|
{
|
||||||
|
removeBonusesRecursive(Bonus::UntilCommanderKilled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCommanderInstance::canGainExperience() const
|
||||||
|
{
|
||||||
|
return alive;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CCommanderInstance::getExpRank() const
|
||||||
|
{
|
||||||
|
return LIBRARY->heroh->level(getTotalExperience());
|
||||||
|
}
|
||||||
|
|
||||||
|
int CCommanderInstance::getLevel() const
|
||||||
|
{
|
||||||
|
return std::max(1, getExpRank());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCommanderInstance::levelUp()
|
||||||
|
{
|
||||||
|
level++;
|
||||||
|
for(const auto & bonus : LIBRARY->creh->commanderLevelPremy)
|
||||||
|
{ //grant all regular level-up bonuses
|
||||||
|
accumulateBonus(bonus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArtBearer CCommanderInstance::bearerType() const
|
||||||
|
{
|
||||||
|
return ArtBearer::COMMANDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCommanderInstance::gainsLevel() const
|
||||||
|
{
|
||||||
|
return getTotalExperience() >= LIBRARY->heroh->reqExp(level + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
55
lib/mapObjects/army/CCommanderInstance.h
Normal file
55
lib/mapObjects/army/CCommanderInstance.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* CCommanderInstance.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CStackInstance.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class DLL_LINKAGE CCommanderInstance : public CStackInstance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//TODO: what if Commander is not a part of creature set?
|
||||||
|
|
||||||
|
//commander class is determined by its base creature
|
||||||
|
ui8 alive; //maybe change to bool when breaking save compatibility?
|
||||||
|
ui8 level; //required only to count callbacks
|
||||||
|
std::string name; // each Commander has different name
|
||||||
|
std::vector<ui8> secondarySkills; //ID -> level
|
||||||
|
std::set<ui8> specialSkills;
|
||||||
|
//std::vector <CArtifactInstance *> arts;
|
||||||
|
CCommanderInstance(IGameInfoCallback * cb);
|
||||||
|
CCommanderInstance(IGameInfoCallback * cb, const CreatureID & id);
|
||||||
|
void setAlive(bool alive);
|
||||||
|
void levelUp();
|
||||||
|
|
||||||
|
bool canGainExperience() const override;
|
||||||
|
bool gainsLevel() const; //true if commander has lower level than should upon his experience
|
||||||
|
ui64 getPower() const override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
int getExpRank() const override;
|
||||||
|
int getLevel() const override;
|
||||||
|
ArtBearer bearerType() const override; //from CArtifactSet
|
||||||
|
|
||||||
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
|
{
|
||||||
|
h & static_cast<CStackInstance &>(*this);
|
||||||
|
h & alive;
|
||||||
|
h & level;
|
||||||
|
h & name;
|
||||||
|
h & secondarySkills;
|
||||||
|
h & specialSkills;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -10,26 +10,14 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CCreatureSet.h"
|
#include "CCreatureSet.h"
|
||||||
|
|
||||||
#include "CConfigHandler.h"
|
#include "../CGHeroInstance.h"
|
||||||
#include "CCreatureHandler.h"
|
|
||||||
#include "GameLibrary.h"
|
|
||||||
#include "IGameSettings.h"
|
|
||||||
#include "callback/IGameInfoCallback.h"
|
|
||||||
#include "entities/hero/CHeroHandler.h"
|
|
||||||
#include "mapObjects/CGHeroInstance.h"
|
|
||||||
#include "modding/ModScope.h"
|
|
||||||
#include "texts/CGeneralTextHandler.h"
|
|
||||||
#include "spells/CSpellHandler.h"
|
|
||||||
#include "IBonusTypeHandler.h"
|
|
||||||
#include "serializer/JsonSerializeFormat.h"
|
|
||||||
#include "gameState/CGameState.h"
|
|
||||||
|
|
||||||
#include <vcmi/FactionService.h>
|
#include "../../CConfigHandler.h"
|
||||||
#include <vcmi/Faction.h>
|
#include "../../texts/CGeneralTextHandler.h"
|
||||||
|
#include "../../serializer/JsonSerializeFormat.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
bool CreatureSlotComparer::operator()(const TPairCreatureSlot & lhs, const TPairCreatureSlot & rhs)
|
bool CreatureSlotComparer::operator()(const TPairCreatureSlot & lhs, const TPairCreatureSlot & rhs)
|
||||||
{
|
{
|
||||||
return lhs.first->getAIValue() < rhs.first->getAIValue(); // Descendant order sorting
|
return lhs.first->getAIValue() < rhs.first->getAIValue(); // Descendant order sorting
|
||||||
@ -149,7 +137,6 @@ bool CCreatureSet::isCreatureBalanced(const CCreature * c, TQuantity ignoreAmoun
|
|||||||
if(count == ignoreAmount || count < 1)
|
if(count == ignoreAmount || count < 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
if(count > max)
|
if(count > max)
|
||||||
max = count;
|
max = count;
|
||||||
if(count < min)
|
if(count < min)
|
||||||
@ -461,7 +448,8 @@ CStackInstance * CCreatureSet::getStackPtr(const SlotID & slot) const
|
|||||||
{
|
{
|
||||||
if(hasStackAtSlot(slot))
|
if(hasStackAtSlot(slot))
|
||||||
return stacks.find(slot)->second.get();
|
return stacks.find(slot)->second.get();
|
||||||
else return nullptr;
|
else
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCreatureSet::eraseStack(const SlotID & slot)
|
void CCreatureSet::eraseStack(const SlotID & slot)
|
||||||
@ -649,16 +637,7 @@ bool CCreatureSet::hasStackAtSlot(const SlotID & slot) const
|
|||||||
return vstd::contains(stacks, slot);
|
return vstd::contains(stacks, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCreatureSet & CCreatureSet::operator=(const CCreatureSet&cs)
|
void CCreatureSet::armyChanged() {}
|
||||||
{
|
|
||||||
assert(0);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreatureSet::armyChanged()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreatureSet::serializeJson(JsonSerializeFormat & handler, const std::string & armyFieldName, const std::optional<int> fixedSize)
|
void CCreatureSet::serializeJson(JsonSerializeFormat & handler, const std::string & armyFieldName, const std::optional<int> fixedSize)
|
||||||
{
|
{
|
||||||
@ -668,7 +647,6 @@ void CCreatureSet::serializeJson(JsonSerializeFormat & handler, const std::strin
|
|||||||
handler.serializeEnum("formation", formation, NArmyFormation::names);
|
handler.serializeEnum("formation", formation, NArmyFormation::names);
|
||||||
auto a = handler.enterArray(armyFieldName);
|
auto a = handler.enterArray(armyFieldName);
|
||||||
|
|
||||||
|
|
||||||
if(handler.saving)
|
if(handler.saving)
|
||||||
{
|
{
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
@ -707,483 +685,4 @@ void CCreatureSet::serializeJson(JsonSerializeFormat & handler, const std::strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CStackInstance::CStackInstance(IGameInfoCallback *cb)
|
|
||||||
: CStackInstance(cb, BonusNodeType::STACK_INSTANCE, false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
CStackInstance::CStackInstance(IGameInfoCallback *cb, BonusNodeType nodeType, bool isHypothetic)
|
|
||||||
: CBonusSystemNode(nodeType, isHypothetic)
|
|
||||||
, CStackBasicDescriptor(nullptr, 0)
|
|
||||||
, CArtifactSet(cb)
|
|
||||||
, GameCallbackHolder(cb)
|
|
||||||
, nativeTerrain(this, Selector::type()(BonusType::TERRAIN_NATIVE))
|
|
||||||
, initiative(this, Selector::type()(BonusType::STACKS_SPEED))
|
|
||||||
, totalExperience(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
CStackInstance::CStackInstance(IGameInfoCallback *cb, const CreatureID & id, TQuantity Count, bool isHypothetic)
|
|
||||||
: CStackInstance(cb, BonusNodeType::STACK_INSTANCE, false)
|
|
||||||
{
|
|
||||||
setType(id);
|
|
||||||
setCount(Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
CCreature::CreatureQuantityId CStackInstance::getQuantityID() const
|
|
||||||
{
|
|
||||||
return CCreature::getQuantityID(getCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
int CStackInstance::getExpRank() const
|
|
||||||
{
|
|
||||||
if (!LIBRARY->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
|
|
||||||
return 0;
|
|
||||||
int tier = getType()->getLevel();
|
|
||||||
if (vstd::iswithin(tier, 1, 7))
|
|
||||||
{
|
|
||||||
for(int i = static_cast<int>(LIBRARY->creh->expRanks[tier].size()) - 2; i > -1; --i) //sic!
|
|
||||||
{ //exp values vary from 1st level to max exp at 11th level
|
|
||||||
if (getAverageExperience() >= LIBRARY->creh->expRanks[tier][i])
|
|
||||||
return ++i; //faster, but confusing - 0 index mean 1st level of experience
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else //higher tier
|
|
||||||
{
|
|
||||||
for(int i = static_cast<int>(LIBRARY->creh->expRanks[0].size()) - 2; i > -1; --i)
|
|
||||||
{
|
|
||||||
if (getAverageExperience() >= LIBRARY->creh->expRanks[0][i])
|
|
||||||
return ++i;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int CStackInstance::getLevel() const
|
|
||||||
{
|
|
||||||
return std::max(1, getType()->getLevel());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackInstance::giveAverageStackExperience(TExpType desiredAmountPerUnit)
|
|
||||||
{
|
|
||||||
if (!canGainExperience())
|
|
||||||
return;
|
|
||||||
|
|
||||||
int level = std::clamp(getLevel(), 1, 7);
|
|
||||||
TExpType maxAmountPerUnit = LIBRARY->creh->expRanks[level].back();
|
|
||||||
TExpType actualAmountPerUnit = std::min(desiredAmountPerUnit, maxAmountPerUnit * LIBRARY->creh->maxExpPerBattle[level]/100);
|
|
||||||
TExpType maxExperience = maxAmountPerUnit * getCount();
|
|
||||||
TExpType maxExperienceToGain = maxExperience - totalExperience;
|
|
||||||
TExpType actualGainedExperience = std::min(maxExperienceToGain, actualAmountPerUnit * getCount());
|
|
||||||
|
|
||||||
totalExperience += actualGainedExperience;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackInstance::giveTotalStackExperience(TExpType experienceToGive)
|
|
||||||
{
|
|
||||||
if (!canGainExperience())
|
|
||||||
return;
|
|
||||||
|
|
||||||
totalExperience += experienceToGive;
|
|
||||||
}
|
|
||||||
|
|
||||||
TExpType CStackInstance::getTotalExperience() const
|
|
||||||
{
|
|
||||||
return totalExperience;
|
|
||||||
}
|
|
||||||
|
|
||||||
TExpType CStackInstance::getAverageExperience() const
|
|
||||||
{
|
|
||||||
return totalExperience / getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CStackInstance::canGainExperience() const
|
|
||||||
{
|
|
||||||
return cb->getSettings().getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackInstance::setType(const CreatureID & creID)
|
|
||||||
{
|
|
||||||
if (creID == CreatureID::NONE)
|
|
||||||
setType(nullptr);//FIXME: unused branch?
|
|
||||||
else
|
|
||||||
setType(creID.toCreature());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackInstance::setType(const CCreature *c)
|
|
||||||
{
|
|
||||||
if(getCreature())
|
|
||||||
{
|
|
||||||
detachFromSource(*getCreature());
|
|
||||||
if (LIBRARY->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
|
|
||||||
totalExperience = totalExperience * LIBRARY->creh->expAfterUpgrade / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
CStackBasicDescriptor::setType(c);
|
|
||||||
|
|
||||||
if(getCreature())
|
|
||||||
attachToSource(*getCreature());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackInstance::setCount(TQuantity newCount)
|
|
||||||
{
|
|
||||||
assert(newCount >= 0);
|
|
||||||
|
|
||||||
if (newCount < getCount())
|
|
||||||
{
|
|
||||||
TExpType averageExperience = totalExperience / getCount();
|
|
||||||
totalExperience = averageExperience * newCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
CStackBasicDescriptor::setCount(newCount);
|
|
||||||
nodeHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CStackInstance::bonusToString(const std::shared_ptr<Bonus>& bonus) const
|
|
||||||
{
|
|
||||||
if (!bonus->description.empty())
|
|
||||||
return bonus->description.toString();
|
|
||||||
else
|
|
||||||
return LIBRARY->getBth()->bonusToString(bonus, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImagePath CStackInstance::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const
|
|
||||||
{
|
|
||||||
if (!bonus->customIconPath.empty())
|
|
||||||
return bonus->customIconPath;
|
|
||||||
return LIBRARY->getBth()->bonusToGraphics(bonus);
|
|
||||||
}
|
|
||||||
|
|
||||||
CArmedInstance * CStackInstance::getArmy()
|
|
||||||
{
|
|
||||||
return armyInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CArmedInstance * CStackInstance::getArmy() const
|
|
||||||
{
|
|
||||||
return armyInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackInstance::setArmy(CArmedInstance * ArmyObj)
|
|
||||||
{
|
|
||||||
auto oldArmy = getArmy();
|
|
||||||
|
|
||||||
if(oldArmy)
|
|
||||||
{
|
|
||||||
detachFrom(*oldArmy);
|
|
||||||
armyInstance = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ArmyObj)
|
|
||||||
{
|
|
||||||
attachTo(const_cast<CArmedInstance&>(*ArmyObj));
|
|
||||||
armyInstance = ArmyObj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CStackInstance::getQuantityTXT(bool capitalized) const
|
|
||||||
{
|
|
||||||
CCreature::CreatureQuantityId quantity = getQuantityID();
|
|
||||||
|
|
||||||
if ((int)quantity)
|
|
||||||
{
|
|
||||||
if(settings["gameTweaks"]["numericCreaturesQuantities"].Bool())
|
|
||||||
return CCreature::getQuantityRangeStringForId(quantity);
|
|
||||||
|
|
||||||
return LIBRARY->generaltexth->arraytxt[174 + (int)quantity*3 - 1 - capitalized];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CStackInstance::valid(bool allowUnrandomized) const
|
|
||||||
{
|
|
||||||
if(!randomStack)
|
|
||||||
{
|
|
||||||
return (getType() && getType() == getId().toEntity(LIBRARY));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return allowUnrandomized;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CStackInstance::nodeName() const
|
|
||||||
{
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "Stack of " << getCount() << " of ";
|
|
||||||
if(getType())
|
|
||||||
oss << getType()->getNamePluralTextID();
|
|
||||||
else
|
|
||||||
oss << "[UNDEFINED TYPE]";
|
|
||||||
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerColor CStackInstance::getOwner() const
|
|
||||||
{
|
|
||||||
auto army = getArmy();
|
|
||||||
return army ? army->getOwner() : PlayerColor::NEUTRAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t CStackInstance::getInitiative(int turn) const
|
|
||||||
{
|
|
||||||
if (turn == 0)
|
|
||||||
return initiative.getValue();
|
|
||||||
|
|
||||||
return ACreature::getInitiative(turn);
|
|
||||||
}
|
|
||||||
|
|
||||||
TerrainId CStackInstance::getNativeTerrain() const
|
|
||||||
{
|
|
||||||
if (nativeTerrain.hasBonus())
|
|
||||||
return TerrainId::ANY_TERRAIN;
|
|
||||||
|
|
||||||
return getFactionID().toEntity(LIBRARY)->getNativeTerrain();
|
|
||||||
}
|
|
||||||
|
|
||||||
TerrainId CStackInstance::getCurrentTerrain() const
|
|
||||||
{
|
|
||||||
assert(getArmy() != nullptr);
|
|
||||||
return getArmy()->getCurrentTerrain();
|
|
||||||
}
|
|
||||||
|
|
||||||
CreatureID CStackInstance::getCreatureID() const
|
|
||||||
{
|
|
||||||
if(getType())
|
|
||||||
return getType()->getId();
|
|
||||||
else
|
|
||||||
return CreatureID::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CStackInstance::getName() const
|
|
||||||
{
|
|
||||||
return (getCount() > 1) ? getType()->getNamePluralTranslated() : getType()->getNameSingularTranslated();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui64 CStackInstance::getPower() const
|
|
||||||
{
|
|
||||||
assert(getType());
|
|
||||||
return static_cast<ui64>(getType()->getAIValue()) * getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui64 CStackInstance::getMarketValue() const
|
|
||||||
{
|
|
||||||
assert(getType());
|
|
||||||
return getType()->getFullRecruitCost().marketValue() * getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArtBearer CStackInstance::bearerType() const
|
|
||||||
{
|
|
||||||
return ArtBearer::CREATURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CStackInstance::ArtPlacementMap CStackInstance::putArtifact(const ArtifactPosition & pos, const CArtifactInstance * art)
|
|
||||||
{
|
|
||||||
assert(!getArt(pos));
|
|
||||||
assert(art->canBePutAt(this, pos));
|
|
||||||
|
|
||||||
attachToSource(*art);
|
|
||||||
return CArtifactSet::putArtifact(pos, art);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackInstance::removeArtifact(const ArtifactPosition & pos)
|
|
||||||
{
|
|
||||||
assert(getArt(pos));
|
|
||||||
|
|
||||||
detachFromSource(*getArt(pos));
|
|
||||||
CArtifactSet::removeArtifact(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackInstance::serializeJson(JsonSerializeFormat & handler)
|
|
||||||
{
|
|
||||||
//todo: artifacts
|
|
||||||
CStackBasicDescriptor::serializeJson(handler);//must be first
|
|
||||||
|
|
||||||
if(handler.saving)
|
|
||||||
{
|
|
||||||
if(randomStack)
|
|
||||||
{
|
|
||||||
int level = randomStack->level;
|
|
||||||
int upgrade = randomStack->upgrade;
|
|
||||||
|
|
||||||
handler.serializeInt("level", level, 0);
|
|
||||||
handler.serializeInt("upgraded", upgrade, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//type set by CStackBasicDescriptor::serializeJson
|
|
||||||
if(getType() == nullptr)
|
|
||||||
{
|
|
||||||
uint8_t level = 0;
|
|
||||||
uint8_t upgrade = 0;
|
|
||||||
|
|
||||||
handler.serializeInt("level", level, 0);
|
|
||||||
handler.serializeInt("upgrade", upgrade, 0);
|
|
||||||
|
|
||||||
randomStack = RandomStackInfo{ level, upgrade };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FactionID CStackInstance::getFactionID() const
|
|
||||||
{
|
|
||||||
if(getType())
|
|
||||||
return getType()->getFactionID();
|
|
||||||
|
|
||||||
return FactionID::NEUTRAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const IBonusBearer* CStackInstance::getBonusBearer() const
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CCommanderInstance::CCommanderInstance(IGameInfoCallback *cb)
|
|
||||||
:CStackInstance(cb)
|
|
||||||
{}
|
|
||||||
|
|
||||||
CCommanderInstance::CCommanderInstance(IGameInfoCallback *cb, const CreatureID & id)
|
|
||||||
: CStackInstance(cb, BonusNodeType::COMMANDER, false)
|
|
||||||
, name("Commando")
|
|
||||||
{
|
|
||||||
alive = true;
|
|
||||||
level = 1;
|
|
||||||
setCount(1);
|
|
||||||
setType(nullptr);
|
|
||||||
secondarySkills.resize (ECommander::SPELL_POWER + 1);
|
|
||||||
setType(id);
|
|
||||||
//TODO - parse them
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCommanderInstance::setAlive (bool Alive)
|
|
||||||
{
|
|
||||||
//TODO: helm of immortality
|
|
||||||
alive = Alive;
|
|
||||||
if (!alive)
|
|
||||||
{
|
|
||||||
removeBonusesRecursive(Bonus::UntilCommanderKilled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CCommanderInstance::canGainExperience() const
|
|
||||||
{
|
|
||||||
return alive;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CCommanderInstance::getExpRank() const
|
|
||||||
{
|
|
||||||
return LIBRARY->heroh->level (getTotalExperience());
|
|
||||||
}
|
|
||||||
|
|
||||||
int CCommanderInstance::getLevel() const
|
|
||||||
{
|
|
||||||
return std::max (1, getExpRank());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCommanderInstance::levelUp ()
|
|
||||||
{
|
|
||||||
level++;
|
|
||||||
for(const auto & bonus : LIBRARY->creh->commanderLevelPremy)
|
|
||||||
{ //grant all regular level-up bonuses
|
|
||||||
accumulateBonus(bonus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ArtBearer CCommanderInstance::bearerType() const
|
|
||||||
{
|
|
||||||
return ArtBearer::COMMANDER;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CCommanderInstance::gainsLevel() const
|
|
||||||
{
|
|
||||||
return getTotalExperience() >= LIBRARY->heroh->reqExp(level + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//This constructor should be placed here to avoid side effects
|
|
||||||
CStackBasicDescriptor::CStackBasicDescriptor() = default;
|
|
||||||
|
|
||||||
CStackBasicDescriptor::CStackBasicDescriptor(const CreatureID & id, TQuantity Count):
|
|
||||||
typeID(id),
|
|
||||||
count(Count)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CStackBasicDescriptor::CStackBasicDescriptor(const CCreature *c, TQuantity Count)
|
|
||||||
: typeID(c ? c->getId() : CreatureID()), count(Count)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const CCreature * CStackBasicDescriptor::getCreature() const
|
|
||||||
{
|
|
||||||
return typeID.hasValue() ? typeID.toCreature() : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Creature * CStackBasicDescriptor::getType() const
|
|
||||||
{
|
|
||||||
return typeID.hasValue() ? typeID.toEntity(LIBRARY) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CreatureID CStackBasicDescriptor::getId() const
|
|
||||||
{
|
|
||||||
return typeID;
|
|
||||||
}
|
|
||||||
|
|
||||||
TQuantity CStackBasicDescriptor::getCount() const
|
|
||||||
{
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackBasicDescriptor::setType(const CCreature * c)
|
|
||||||
{
|
|
||||||
typeID = c ? c->getId() : CreatureID();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackBasicDescriptor::setCount(TQuantity newCount)
|
|
||||||
{
|
|
||||||
assert(newCount >= 0);
|
|
||||||
count = newCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== (const CStackBasicDescriptor & l, const CStackBasicDescriptor & r)
|
|
||||||
{
|
|
||||||
return l.typeID == r.typeID && l.count == r.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler)
|
|
||||||
{
|
|
||||||
handler.serializeInt("amount", count);
|
|
||||||
|
|
||||||
if(handler.saving)
|
|
||||||
{
|
|
||||||
if(typeID.hasValue())
|
|
||||||
{
|
|
||||||
std::string typeName = typeID.toEntity(LIBRARY)->getJsonKey();
|
|
||||||
handler.serializeString("type", typeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string typeName;
|
|
||||||
handler.serializeString("type", typeName);
|
|
||||||
if(!typeName.empty())
|
|
||||||
setType(CreatureID(CreatureID::decode(typeName)).toCreature());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSimpleArmy::clearSlots()
|
|
||||||
{
|
|
||||||
army.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSimpleArmy::operator bool() const
|
|
||||||
{
|
|
||||||
return !army.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSimpleArmy::setCreature(SlotID slot, CreatureID cre, TQuantity count)
|
|
||||||
{
|
|
||||||
assert(!vstd::contains(army, slot));
|
|
||||||
army[slot] = std::make_pair(cre, count);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
160
lib/mapObjects/army/CCreatureSet.h
Normal file
160
lib/mapObjects/army/CCreatureSet.h
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* CCreatureSet.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CSimpleArmy.h"
|
||||||
|
#include "CStackInstance.h"
|
||||||
|
|
||||||
|
#include "serializer/Serializeable.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class CStackInstance;
|
||||||
|
class CArmedInstance;
|
||||||
|
class CStackBasicDescriptor;
|
||||||
|
class JsonSerializeFormat;
|
||||||
|
|
||||||
|
using TSlots = std::map<SlotID, std::unique_ptr<CStackInstance>>;
|
||||||
|
|
||||||
|
using TPairCreatureSlot = std::pair<const CCreature *, SlotID>;
|
||||||
|
using TMapCreatureSlot = std::map<const CCreature *, SlotID>;
|
||||||
|
|
||||||
|
struct DLL_LINKAGE CreatureSlotComparer
|
||||||
|
{
|
||||||
|
bool operator()(const TPairCreatureSlot & lhs, const TPairCreatureSlot & rhs);
|
||||||
|
};
|
||||||
|
|
||||||
|
using TCreatureQueue = std::priority_queue<TPairCreatureSlot, std::vector<TPairCreatureSlot>, CreatureSlotComparer>;
|
||||||
|
|
||||||
|
namespace NArmyFormation
|
||||||
|
{
|
||||||
|
static const std::vector<std::string> names{"wide", "tight"};
|
||||||
|
}
|
||||||
|
|
||||||
|
class DLL_LINKAGE CCreatureSet : public IArmyDescriptor, public virtual Serializeable, boost::noncopyable //seven combined creatures
|
||||||
|
{
|
||||||
|
CCreatureSet(const CCreatureSet &) = delete;
|
||||||
|
CCreatureSet & operator=(const CCreatureSet &) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TSlots stacks; //slots[slot_id]->> pair(creature_id,creature_quantity)
|
||||||
|
EArmyFormation formation = EArmyFormation::LOOSE; //0 - wide, 1 - tight
|
||||||
|
|
||||||
|
CCreatureSet() = default; //Should be here to avoid compile errors
|
||||||
|
virtual ~CCreatureSet();
|
||||||
|
virtual void armyChanged();
|
||||||
|
|
||||||
|
const CStackInstance & operator[](const SlotID & slot) const;
|
||||||
|
|
||||||
|
const TSlots &Slots() const {return stacks;}
|
||||||
|
|
||||||
|
//Adds stack to slot. Slot must be empty or with same type creature
|
||||||
|
void addToSlot(const SlotID & slot, const CreatureID & cre, TQuantity count, bool allowMerging = true);
|
||||||
|
//Adds stack to slot. Slot must be empty or with same type creature
|
||||||
|
void addToSlot(const SlotID & slot, std::unique_ptr<CStackInstance> stack, bool allowMerging = true);
|
||||||
|
|
||||||
|
void clearSlots() override;
|
||||||
|
void setFormation(EArmyFormation tight);
|
||||||
|
virtual CArmedInstance * getArmy() { return nullptr; }
|
||||||
|
virtual const CArmedInstance * getArmy() const { return nullptr; }
|
||||||
|
|
||||||
|
//adds new stack to the army, slot must be empty
|
||||||
|
void putStack(const SlotID & slot, std::unique_ptr<CStackInstance> stack);
|
||||||
|
//stack must exist!
|
||||||
|
void setStackCount(const SlotID & slot, TQuantity count);
|
||||||
|
//removes stack from army but doesn't destroy it (so it can be moved somewhere else or safely deleted)
|
||||||
|
std::unique_ptr<CStackInstance> detachStack(const SlotID & slot);
|
||||||
|
|
||||||
|
void setStackType(const SlotID & slot, const CreatureID & type);
|
||||||
|
|
||||||
|
/// Give specified amount of experience to all units in army
|
||||||
|
/// Amount of granted experience is scaled by unit stack size
|
||||||
|
void giveAverageStackExperience(TExpType exp);
|
||||||
|
|
||||||
|
/// Give specified amount of experience to unit in specified slot
|
||||||
|
/// Amount of granted experience is not scaled by unit stack size
|
||||||
|
void giveTotalStackExperience(const SlotID & slot, TExpType exp);
|
||||||
|
|
||||||
|
/// Erased stack from specified slot. Slot must be non-empty
|
||||||
|
void eraseStack(const SlotID & slot);
|
||||||
|
|
||||||
|
/// Joins stack into stack that occupies targeted slot.
|
||||||
|
/// Slot must be non-empty and contain same creature type
|
||||||
|
void joinStack(const SlotID & slot, std::unique_ptr<CStackInstance> stack); //adds new stack to the existing stack of the same type
|
||||||
|
|
||||||
|
/// Splits off some units of specified stack and returns newly created stack
|
||||||
|
/// Slot must be non-empty and contain more units that split quantity
|
||||||
|
std::unique_ptr<CStackInstance> splitStack(const SlotID & slot, TQuantity toSplit);
|
||||||
|
|
||||||
|
//stack must exist!
|
||||||
|
void changeStackCount(const SlotID & slot, TQuantity toAdd);
|
||||||
|
|
||||||
|
//replaces creature in stack; slots 0 to 6, if quantity=0 erases stack
|
||||||
|
bool setCreature(SlotID slot, CreatureID type, TQuantity quantity) override;
|
||||||
|
|
||||||
|
//erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
|
||||||
|
void setToArmy(CSimpleArmy & src);
|
||||||
|
|
||||||
|
const CStackInstance & getStack(const SlotID & slot) const; //stack must exist
|
||||||
|
CStackInstance * getStackPtr(const SlotID & slot) const; //if stack doesn't exist, returns nullptr
|
||||||
|
const CCreature * getCreature(const SlotID & slot) const; //workaround of map issue;
|
||||||
|
int getStackCount(const SlotID & slot) const;
|
||||||
|
TExpType getStackTotalExperience(const SlotID & slot) const;
|
||||||
|
TExpType getStackAverageExperience(const SlotID & slot) const;
|
||||||
|
SlotID findStack(const CStackInstance * stack) const; //-1 if none
|
||||||
|
SlotID getSlotFor(const CreatureID & creature, ui32 slotsAmount = GameConstants::ARMY_SIZE) const; //returns -1 if no slot available
|
||||||
|
SlotID getSlotFor(const CCreature * c, ui32 slotsAmount = GameConstants::ARMY_SIZE) const; //returns -1 if no slot available
|
||||||
|
bool hasCreatureSlots(const CCreature * c, const SlotID & exclude) const;
|
||||||
|
std::vector<SlotID> getCreatureSlots(const CCreature * c, const SlotID & exclude, TQuantity ignoreAmount = -1) const;
|
||||||
|
bool isCreatureBalanced(const CCreature * c, TQuantity ignoreAmount = 1) const; // Check if the creature is evenly distributed across slots
|
||||||
|
|
||||||
|
SlotID getFreeSlot(ui32 slotsAmount = GameConstants::ARMY_SIZE) const; //returns first free slot
|
||||||
|
std::vector<SlotID> getFreeSlots(ui32 slotsAmount = GameConstants::ARMY_SIZE) const;
|
||||||
|
std::queue<SlotID> getFreeSlotsQueue(ui32 slotsAmount = GameConstants::ARMY_SIZE) const;
|
||||||
|
|
||||||
|
TMapCreatureSlot getCreatureMap() const;
|
||||||
|
TCreatureQueue getCreatureQueue(const SlotID & exclude) const;
|
||||||
|
|
||||||
|
bool mergeableStacks(std::pair<SlotID, SlotID> & out, const SlotID & preferable = SlotID()) const; //looks for two same stacks, returns slot positions;
|
||||||
|
bool validTypes(bool allowUnrandomized = false) const; //checks if all types of creatures are set properly
|
||||||
|
bool slotEmpty(const SlotID & slot) const;
|
||||||
|
int stacksCount() const;
|
||||||
|
virtual bool needsLastStack() const; //true if last stack cannot be taken
|
||||||
|
ui64 getArmyStrength(int fortLevel = 0) const; //sum of AI values of creatures
|
||||||
|
ui64 getArmyCost() const; //sum of cost of creatures
|
||||||
|
ui64 getPower(const SlotID & slot) const; //value of specific stack
|
||||||
|
std::string getRoughAmount(const SlotID & slot, int mode = 0) const; //rough size of specific stack
|
||||||
|
std::string getArmyDescription() const;
|
||||||
|
bool hasStackAtSlot(const SlotID & slot) const;
|
||||||
|
|
||||||
|
bool contains(const CStackInstance * stack) const;
|
||||||
|
bool canBeMergedWith(const CCreatureSet & cs, bool allowMergingStacks = true) const;
|
||||||
|
|
||||||
|
/// Returns true if this creature set contains all listed units
|
||||||
|
/// If requireLastStack is true, then this function will also
|
||||||
|
/// require presence of any unit other than requested (or more units than requested)
|
||||||
|
bool hasUnits(const std::vector<CStackBasicDescriptor> & units, bool requireLastStack = true) const;
|
||||||
|
|
||||||
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
|
{
|
||||||
|
h & stacks;
|
||||||
|
h & formation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler, const std::string & armyFieldName, const std::optional<int> fixedSize = std::nullopt);
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return !stacks.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
54
lib/mapObjects/army/CSimpleArmy.h
Normal file
54
lib/mapObjects/army/CSimpleArmy.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* CSimpleArmy.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GameConstants.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class IArmyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void clearSlots() = 0;
|
||||||
|
virtual bool setCreature(SlotID slot, CreatureID cre, TQuantity count) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
using TSimpleSlots = std::map<SlotID, std::pair<CreatureID, TQuantity>>;
|
||||||
|
|
||||||
|
//simplified version of CCreatureSet
|
||||||
|
class DLL_LINKAGE CSimpleArmy : public IArmyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TSimpleSlots army;
|
||||||
|
void clearSlots() override
|
||||||
|
{
|
||||||
|
army.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setCreature(SlotID slot, CreatureID cre, TQuantity count) override
|
||||||
|
{
|
||||||
|
assert(!vstd::contains(army, slot));
|
||||||
|
army[slot] = std::make_pair(cre, count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return !army.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
|
{
|
||||||
|
h & army;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
91
lib/mapObjects/army/CStackBasicDescriptor.cpp
Normal file
91
lib/mapObjects/army/CStackBasicDescriptor.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* CStackBasicDescriptor.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 "CStackBasicDescriptor.h"
|
||||||
|
|
||||||
|
#include "../../CCreatureHandler.h"
|
||||||
|
#include "../../GameLibrary.h"
|
||||||
|
#include "../../serializer/JsonSerializeFormat.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
//This constructor should be placed here to avoid side effects
|
||||||
|
CStackBasicDescriptor::CStackBasicDescriptor() = default;
|
||||||
|
|
||||||
|
CStackBasicDescriptor::CStackBasicDescriptor(const CreatureID & id, TQuantity Count)
|
||||||
|
: typeID(id)
|
||||||
|
, count(Count)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CStackBasicDescriptor::CStackBasicDescriptor(const CCreature * c, TQuantity Count)
|
||||||
|
: typeID(c ? c->getId() : CreatureID())
|
||||||
|
, count(Count)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const CCreature * CStackBasicDescriptor::getCreature() const
|
||||||
|
{
|
||||||
|
return typeID.hasValue() ? typeID.toCreature() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Creature * CStackBasicDescriptor::getType() const
|
||||||
|
{
|
||||||
|
return typeID.hasValue() ? typeID.toEntity(LIBRARY) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatureID CStackBasicDescriptor::getId() const
|
||||||
|
{
|
||||||
|
return typeID;
|
||||||
|
}
|
||||||
|
|
||||||
|
TQuantity CStackBasicDescriptor::getCount() const
|
||||||
|
{
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackBasicDescriptor::setType(const CCreature * c)
|
||||||
|
{
|
||||||
|
typeID = c ? c->getId() : CreatureID();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackBasicDescriptor::setCount(TQuantity newCount)
|
||||||
|
{
|
||||||
|
assert(newCount >= 0);
|
||||||
|
count = newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const CStackBasicDescriptor & l, const CStackBasicDescriptor & r)
|
||||||
|
{
|
||||||
|
return l.typeID == r.typeID && l.count == r.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler)
|
||||||
|
{
|
||||||
|
handler.serializeInt("amount", count);
|
||||||
|
|
||||||
|
if(handler.saving)
|
||||||
|
{
|
||||||
|
if(typeID.hasValue())
|
||||||
|
{
|
||||||
|
std::string typeName = typeID.toEntity(LIBRARY)->getJsonKey();
|
||||||
|
handler.serializeString("type", typeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string typeName;
|
||||||
|
handler.serializeString("type", typeName);
|
||||||
|
if(!typeName.empty())
|
||||||
|
setType(CreatureID(CreatureID::decode(typeName)).toCreature());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
65
lib/mapObjects/army/CStackBasicDescriptor.h
Normal file
65
lib/mapObjects/army/CStackBasicDescriptor.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* CStackBasicDescriptor.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GameConstants.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class JsonNode;
|
||||||
|
class CCreature;
|
||||||
|
class CGHeroInstance;
|
||||||
|
class CArmedInstance;
|
||||||
|
class CCreatureArtifactSet;
|
||||||
|
class JsonSerializeFormat;
|
||||||
|
|
||||||
|
class DLL_LINKAGE CStackBasicDescriptor
|
||||||
|
{
|
||||||
|
CreatureID typeID;
|
||||||
|
TQuantity count = -1; //exact quantity or quantity ID from CCreature::getQuantityID when getting info about enemy army
|
||||||
|
|
||||||
|
public:
|
||||||
|
CStackBasicDescriptor();
|
||||||
|
CStackBasicDescriptor(const CreatureID & id, TQuantity Count);
|
||||||
|
CStackBasicDescriptor(const CCreature * c, TQuantity Count);
|
||||||
|
virtual ~CStackBasicDescriptor() = default;
|
||||||
|
|
||||||
|
const Creature * getType() const;
|
||||||
|
const CCreature * getCreature() const;
|
||||||
|
CreatureID getId() const;
|
||||||
|
TQuantity getCount() const;
|
||||||
|
|
||||||
|
virtual void setType(const CCreature * c);
|
||||||
|
virtual void setCount(TQuantity amount);
|
||||||
|
|
||||||
|
friend bool operator==(const CStackBasicDescriptor & l, const CStackBasicDescriptor & r);
|
||||||
|
|
||||||
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
|
{
|
||||||
|
if(h.saving)
|
||||||
|
{
|
||||||
|
h & typeID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CreatureID creatureID;
|
||||||
|
h & creatureID;
|
||||||
|
if(creatureID != CreatureID::NONE)
|
||||||
|
setType(creatureID.toCreature());
|
||||||
|
}
|
||||||
|
|
||||||
|
h & count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
358
lib/mapObjects/army/CStackInstance.cpp
Normal file
358
lib/mapObjects/army/CStackInstance.cpp
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
/*
|
||||||
|
* CStackInstance.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 "CStackInstance.h"
|
||||||
|
|
||||||
|
#include "CArmedInstance.h"
|
||||||
|
|
||||||
|
#include "../../CConfigHandler.h"
|
||||||
|
#include "../../GameLibrary.h"
|
||||||
|
#include "../../IGameSettings.h"
|
||||||
|
#include "../../callback/IGameInfoCallback.h"
|
||||||
|
#include "../../entities/faction/CFaction.h"
|
||||||
|
#include "../../texts/CGeneralTextHandler.h"
|
||||||
|
#include "../../IBonusTypeHandler.h"
|
||||||
|
#include "../../serializer/JsonSerializeFormat.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
CStackInstance::CStackInstance(IGameInfoCallback * cb)
|
||||||
|
: CStackInstance(cb, BonusNodeType::STACK_INSTANCE, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CStackInstance::CStackInstance(IGameInfoCallback * cb, BonusNodeType nodeType, bool isHypothetic)
|
||||||
|
: CBonusSystemNode(nodeType, isHypothetic)
|
||||||
|
, CStackBasicDescriptor(nullptr, 0)
|
||||||
|
, CArtifactSet(cb)
|
||||||
|
, GameCallbackHolder(cb)
|
||||||
|
, nativeTerrain(this, Selector::type()(BonusType::TERRAIN_NATIVE))
|
||||||
|
, initiative(this, Selector::type()(BonusType::STACKS_SPEED))
|
||||||
|
, totalExperience(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CStackInstance::CStackInstance(IGameInfoCallback * cb, const CreatureID & id, TQuantity Count, bool isHypothetic)
|
||||||
|
: CStackInstance(cb, BonusNodeType::STACK_INSTANCE, false)
|
||||||
|
{
|
||||||
|
setType(id);
|
||||||
|
setCount(Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCreature::CreatureQuantityId CStackInstance::getQuantityID() const
|
||||||
|
{
|
||||||
|
return CCreature::getQuantityID(getCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
int CStackInstance::getExpRank() const
|
||||||
|
{
|
||||||
|
if(!LIBRARY->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
|
||||||
|
return 0;
|
||||||
|
int tier = getType()->getLevel();
|
||||||
|
if(vstd::iswithin(tier, 1, 7))
|
||||||
|
{
|
||||||
|
for(int i = static_cast<int>(LIBRARY->creh->expRanks[tier].size()) - 2; i > -1; --i) //sic!
|
||||||
|
{ //exp values vary from 1st level to max exp at 11th level
|
||||||
|
if(getAverageExperience() >= LIBRARY->creh->expRanks[tier][i])
|
||||||
|
return ++i; //faster, but confusing - 0 index mean 1st level of experience
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else //higher tier
|
||||||
|
{
|
||||||
|
for(int i = static_cast<int>(LIBRARY->creh->expRanks[0].size()) - 2; i > -1; --i)
|
||||||
|
{
|
||||||
|
if(getAverageExperience() >= LIBRARY->creh->expRanks[0][i])
|
||||||
|
return ++i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CStackInstance::getLevel() const
|
||||||
|
{
|
||||||
|
return std::max(1, getType()->getLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackInstance::giveAverageStackExperience(TExpType desiredAmountPerUnit)
|
||||||
|
{
|
||||||
|
if(!canGainExperience())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int level = std::clamp(getLevel(), 1, 7);
|
||||||
|
TExpType maxAmountPerUnit = LIBRARY->creh->expRanks[level].back();
|
||||||
|
TExpType actualAmountPerUnit = std::min(desiredAmountPerUnit, maxAmountPerUnit * LIBRARY->creh->maxExpPerBattle[level] / 100);
|
||||||
|
TExpType maxExperience = maxAmountPerUnit * getCount();
|
||||||
|
TExpType maxExperienceToGain = maxExperience - totalExperience;
|
||||||
|
TExpType actualGainedExperience = std::min(maxExperienceToGain, actualAmountPerUnit * getCount());
|
||||||
|
|
||||||
|
totalExperience += actualGainedExperience;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackInstance::giveTotalStackExperience(TExpType experienceToGive)
|
||||||
|
{
|
||||||
|
if(!canGainExperience())
|
||||||
|
return;
|
||||||
|
|
||||||
|
totalExperience += experienceToGive;
|
||||||
|
}
|
||||||
|
|
||||||
|
TExpType CStackInstance::getTotalExperience() const
|
||||||
|
{
|
||||||
|
return totalExperience;
|
||||||
|
}
|
||||||
|
|
||||||
|
TExpType CStackInstance::getAverageExperience() const
|
||||||
|
{
|
||||||
|
return totalExperience / getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CStackInstance::canGainExperience() const
|
||||||
|
{
|
||||||
|
return cb->getSettings().getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackInstance::setType(const CreatureID & creID)
|
||||||
|
{
|
||||||
|
if(creID == CreatureID::NONE)
|
||||||
|
setType(nullptr); //FIXME: unused branch?
|
||||||
|
else
|
||||||
|
setType(creID.toCreature());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackInstance::setType(const CCreature * c)
|
||||||
|
{
|
||||||
|
if(getCreature())
|
||||||
|
{
|
||||||
|
detachFromSource(*getCreature());
|
||||||
|
if(LIBRARY->engineSettings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
|
||||||
|
totalExperience = totalExperience * LIBRARY->creh->expAfterUpgrade / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
CStackBasicDescriptor::setType(c);
|
||||||
|
|
||||||
|
if(getCreature())
|
||||||
|
attachToSource(*getCreature());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackInstance::setCount(TQuantity newCount)
|
||||||
|
{
|
||||||
|
assert(newCount >= 0);
|
||||||
|
|
||||||
|
if(newCount < getCount())
|
||||||
|
{
|
||||||
|
TExpType averageExperience = totalExperience / getCount();
|
||||||
|
totalExperience = averageExperience * newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
CStackBasicDescriptor::setCount(newCount);
|
||||||
|
nodeHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CStackInstance::bonusToString(const std::shared_ptr<Bonus> & bonus) const
|
||||||
|
{
|
||||||
|
if(!bonus->description.empty())
|
||||||
|
return bonus->description.toString();
|
||||||
|
else
|
||||||
|
return LIBRARY->getBth()->bonusToString(bonus, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImagePath CStackInstance::bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const
|
||||||
|
{
|
||||||
|
if(!bonus->customIconPath.empty())
|
||||||
|
return bonus->customIconPath;
|
||||||
|
return LIBRARY->getBth()->bonusToGraphics(bonus);
|
||||||
|
}
|
||||||
|
|
||||||
|
CArmedInstance * CStackInstance::getArmy()
|
||||||
|
{
|
||||||
|
return armyInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CArmedInstance * CStackInstance::getArmy() const
|
||||||
|
{
|
||||||
|
return armyInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackInstance::setArmy(CArmedInstance * ArmyObj)
|
||||||
|
{
|
||||||
|
auto oldArmy = getArmy();
|
||||||
|
|
||||||
|
if(oldArmy)
|
||||||
|
{
|
||||||
|
detachFrom(*oldArmy);
|
||||||
|
armyInstance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ArmyObj)
|
||||||
|
{
|
||||||
|
attachTo(const_cast<CArmedInstance &>(*ArmyObj));
|
||||||
|
armyInstance = ArmyObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CStackInstance::getQuantityTXT(bool capitalized) const
|
||||||
|
{
|
||||||
|
CCreature::CreatureQuantityId quantity = getQuantityID();
|
||||||
|
|
||||||
|
if((int)quantity)
|
||||||
|
{
|
||||||
|
if(settings["gameTweaks"]["numericCreaturesQuantities"].Bool())
|
||||||
|
return CCreature::getQuantityRangeStringForId(quantity);
|
||||||
|
|
||||||
|
return LIBRARY->generaltexth->arraytxt[174 + (int)quantity * 3 - 1 - capitalized];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CStackInstance::valid(bool allowUnrandomized) const
|
||||||
|
{
|
||||||
|
if(!randomStack)
|
||||||
|
{
|
||||||
|
return (getType() && getType() == getId().toEntity(LIBRARY));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return allowUnrandomized;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CStackInstance::nodeName() const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Stack of " << getCount() << " of ";
|
||||||
|
if(getType())
|
||||||
|
oss << getType()->getNamePluralTextID();
|
||||||
|
else
|
||||||
|
oss << "[UNDEFINED TYPE]";
|
||||||
|
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerColor CStackInstance::getOwner() const
|
||||||
|
{
|
||||||
|
auto army = getArmy();
|
||||||
|
return army ? army->getOwner() : PlayerColor::NEUTRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CStackInstance::getInitiative(int turn) const
|
||||||
|
{
|
||||||
|
if(turn == 0)
|
||||||
|
return initiative.getValue();
|
||||||
|
|
||||||
|
return ACreature::getInitiative(turn);
|
||||||
|
}
|
||||||
|
|
||||||
|
TerrainId CStackInstance::getNativeTerrain() const
|
||||||
|
{
|
||||||
|
if(nativeTerrain.hasBonus())
|
||||||
|
return TerrainId::ANY_TERRAIN;
|
||||||
|
|
||||||
|
return getFactionID().toEntity(LIBRARY)->getNativeTerrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
TerrainId CStackInstance::getCurrentTerrain() const
|
||||||
|
{
|
||||||
|
assert(getArmy() != nullptr);
|
||||||
|
return getArmy()->getCurrentTerrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatureID CStackInstance::getCreatureID() const
|
||||||
|
{
|
||||||
|
if(getType())
|
||||||
|
return getType()->getId();
|
||||||
|
else
|
||||||
|
return CreatureID::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CStackInstance::getName() const
|
||||||
|
{
|
||||||
|
return (getCount() > 1) ? getType()->getNamePluralTranslated() : getType()->getNameSingularTranslated();
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 CStackInstance::getPower() const
|
||||||
|
{
|
||||||
|
assert(getType());
|
||||||
|
return static_cast<ui64>(getType()->getAIValue()) * getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ui64 CStackInstance::getMarketValue() const
|
||||||
|
{
|
||||||
|
assert(getType());
|
||||||
|
return getType()->getFullRecruitCost().marketValue() * getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArtBearer CStackInstance::bearerType() const
|
||||||
|
{
|
||||||
|
return ArtBearer::CREATURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CStackInstance::ArtPlacementMap CStackInstance::putArtifact(const ArtifactPosition & pos, const CArtifactInstance * art)
|
||||||
|
{
|
||||||
|
assert(!getArt(pos));
|
||||||
|
assert(art->canBePutAt(this, pos));
|
||||||
|
|
||||||
|
attachToSource(*art);
|
||||||
|
return CArtifactSet::putArtifact(pos, art);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackInstance::removeArtifact(const ArtifactPosition & pos)
|
||||||
|
{
|
||||||
|
assert(getArt(pos));
|
||||||
|
|
||||||
|
detachFromSource(*getArt(pos));
|
||||||
|
CArtifactSet::removeArtifact(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStackInstance::serializeJson(JsonSerializeFormat & handler)
|
||||||
|
{
|
||||||
|
//todo: artifacts
|
||||||
|
CStackBasicDescriptor::serializeJson(handler); //must be first
|
||||||
|
|
||||||
|
if(handler.saving)
|
||||||
|
{
|
||||||
|
if(randomStack)
|
||||||
|
{
|
||||||
|
int level = randomStack->level;
|
||||||
|
int upgrade = randomStack->upgrade;
|
||||||
|
|
||||||
|
handler.serializeInt("level", level, 0);
|
||||||
|
handler.serializeInt("upgraded", upgrade, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//type set by CStackBasicDescriptor::serializeJson
|
||||||
|
if(getType() == nullptr)
|
||||||
|
{
|
||||||
|
uint8_t level = 0;
|
||||||
|
uint8_t upgrade = 0;
|
||||||
|
|
||||||
|
handler.serializeInt("level", level, 0);
|
||||||
|
handler.serializeInt("upgrade", upgrade, 0);
|
||||||
|
|
||||||
|
randomStack = RandomStackInfo{level, upgrade};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FactionID CStackInstance::getFactionID() const
|
||||||
|
{
|
||||||
|
if(getType())
|
||||||
|
return getType()->getFactionID();
|
||||||
|
|
||||||
|
return FactionID::NEUTRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IBonusBearer * CStackInstance::getBonusBearer() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
134
lib/mapObjects/army/CStackInstance.h
Normal file
134
lib/mapObjects/army/CStackInstance.h
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* CStackInstance.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CStackBasicDescriptor.h"
|
||||||
|
|
||||||
|
#include "CCreatureHandler.h"
|
||||||
|
#include "bonuses/BonusCache.h"
|
||||||
|
#include "bonuses/CBonusSystemNode.h"
|
||||||
|
#include "callback/GameCallbackHolder.h"
|
||||||
|
#include "entities/artifact/CArtifactSet.h"
|
||||||
|
#include "mapObjects/CGObjectInstance.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class JsonNode;
|
||||||
|
class CCreature;
|
||||||
|
class CGHeroInstance;
|
||||||
|
class CArmedInstance;
|
||||||
|
class CCreatureArtifactSet;
|
||||||
|
class JsonSerializeFormat;
|
||||||
|
|
||||||
|
class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CArtifactSet, public ACreature, public GameCallbackHolder
|
||||||
|
{
|
||||||
|
BonusValueCache nativeTerrain;
|
||||||
|
BonusValueCache initiative;
|
||||||
|
|
||||||
|
CArmedInstance * armyInstance = nullptr; //stack must be part of some army, army must be part of some object
|
||||||
|
|
||||||
|
IGameInfoCallback * getCallback() const final
|
||||||
|
{
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
TExpType totalExperience; //commander needs same amount of exp as hero
|
||||||
|
public:
|
||||||
|
struct RandomStackInfo
|
||||||
|
{
|
||||||
|
uint8_t level;
|
||||||
|
uint8_t upgrade;
|
||||||
|
};
|
||||||
|
// helper variable used during loading map, when object (hero or town) have creatures that must have same alignment.
|
||||||
|
std::optional<RandomStackInfo> randomStack;
|
||||||
|
|
||||||
|
CArmedInstance * getArmy();
|
||||||
|
const CArmedInstance * getArmy() const; //stack must be part of some army, army must be part of some object
|
||||||
|
void setArmy(CArmedInstance * ArmyObj);
|
||||||
|
|
||||||
|
TExpType getTotalExperience() const;
|
||||||
|
TExpType getAverageExperience() const;
|
||||||
|
virtual bool canGainExperience() const;
|
||||||
|
|
||||||
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
|
{
|
||||||
|
h & static_cast<CBonusSystemNode &>(*this);
|
||||||
|
h & static_cast<CStackBasicDescriptor &>(*this);
|
||||||
|
h & static_cast<CArtifactSet &>(*this);
|
||||||
|
|
||||||
|
if(h.hasFeature(Handler::Version::STACK_INSTANCE_ARMY_FIX))
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
if(h.hasFeature(Handler::Version::NO_RAW_POINTERS_IN_SERIALIZER))
|
||||||
|
{
|
||||||
|
ObjectInstanceID dummyID;
|
||||||
|
h & dummyID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::shared_ptr<CGObjectInstance> army;
|
||||||
|
h & army;
|
||||||
|
}
|
||||||
|
|
||||||
|
h & totalExperience;
|
||||||
|
if(!h.hasFeature(Handler::Version::STACK_INSTANCE_EXPERIENCE_FIX))
|
||||||
|
{
|
||||||
|
totalExperience *= getCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
|
|
||||||
|
//overrides CBonusSystemNode
|
||||||
|
std::string bonusToString(const std::shared_ptr<Bonus> & bonus) const override; // how would bonus description look for this particular type of node
|
||||||
|
ImagePath bonusToGraphics(const std::shared_ptr<Bonus> & bonus) const; //file name of graphics from StackSkills , in future possibly others
|
||||||
|
|
||||||
|
//IConstBonusProvider
|
||||||
|
const IBonusBearer * getBonusBearer() const override;
|
||||||
|
//INativeTerrainProvider
|
||||||
|
FactionID getFactionID() const override;
|
||||||
|
|
||||||
|
virtual ui64 getPower() const;
|
||||||
|
/// Returns total market value of resources needed to recruit this unit
|
||||||
|
virtual ui64 getMarketValue() const;
|
||||||
|
CCreature::CreatureQuantityId getQuantityID() const;
|
||||||
|
std::string getQuantityTXT(bool capitalized = true) const;
|
||||||
|
virtual int getExpRank() const;
|
||||||
|
virtual int getLevel() const; //different for regular stack and commander
|
||||||
|
CreatureID getCreatureID() const; //-1 if not available
|
||||||
|
std::string getName() const; //plural or singular
|
||||||
|
CStackInstance(IGameInfoCallback * cb);
|
||||||
|
CStackInstance(IGameInfoCallback * cb, BonusNodeType nodeType, bool isHypothetic = false);
|
||||||
|
CStackInstance(IGameInfoCallback * cb, const CreatureID & id, TQuantity count, bool isHypothetic = false);
|
||||||
|
virtual ~CStackInstance() = default;
|
||||||
|
|
||||||
|
void setType(const CreatureID & creID);
|
||||||
|
void setType(const CCreature * c) final;
|
||||||
|
void setCount(TQuantity amount) final;
|
||||||
|
|
||||||
|
/// Gives specified amount of stack experience that will not be scaled by unit size
|
||||||
|
void giveAverageStackExperience(TExpType exp);
|
||||||
|
void giveTotalStackExperience(TExpType exp);
|
||||||
|
|
||||||
|
bool valid(bool allowUnrandomized) const;
|
||||||
|
ArtPlacementMap putArtifact(const ArtifactPosition & pos, const CArtifactInstance * art) override; //from CArtifactSet
|
||||||
|
void removeArtifact(const ArtifactPosition & pos) override;
|
||||||
|
ArtBearer bearerType() const override; //from CArtifactSet
|
||||||
|
std::string nodeName() const override; //from CBonusSystemnode
|
||||||
|
PlayerColor getOwner() const override;
|
||||||
|
|
||||||
|
int32_t getInitiative(int turn = 0) const final;
|
||||||
|
TerrainId getNativeTerrain() const final;
|
||||||
|
TerrainId getCurrentTerrain() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
37
lib/mapping/CCastleEvent.h
Normal file
37
lib/mapping/CCastleEvent.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* CCastleEvent.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CMapEvent.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/// The castle event builds/adds buildings/creatures for a specific town.
|
||||||
|
class DLL_LINKAGE CCastleEvent : public CMapEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCastleEvent() = default;
|
||||||
|
|
||||||
|
std::set<BuildingID> buildings;
|
||||||
|
std::vector<si32> creatures;
|
||||||
|
|
||||||
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
|
{
|
||||||
|
h & static_cast<CMapEvent &>(*this);
|
||||||
|
h & buildings;
|
||||||
|
h & creatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "CMapEditManager.h"
|
#include "CMapEditManager.h"
|
||||||
#include "CMapOperation.h"
|
#include "CMapOperation.h"
|
||||||
|
#include "CCastleEvent.h"
|
||||||
|
|
||||||
#include "../CCreatureHandler.h"
|
#include "../CCreatureHandler.h"
|
||||||
#include "../CSkillHandler.h"
|
#include "../CSkillHandler.h"
|
||||||
|
@ -10,8 +10,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CMapDefines.h"
|
#include "CMapEvent.h"
|
||||||
#include "CMapHeader.h"
|
#include "CMapHeader.h"
|
||||||
|
#include "TerrainTile.h"
|
||||||
|
|
||||||
#include "../mapObjects/CGObjectInstance.h"
|
#include "../mapObjects/CGObjectInstance.h"
|
||||||
#include "../callback/GameCallbackHolder.h"
|
#include "../callback/GameCallbackHolder.h"
|
||||||
|
59
lib/mapping/CMapEvent.h
Normal file
59
lib/mapping/CMapEvent.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* CMapEvent.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../ResourceSet.h"
|
||||||
|
#include "../texts/MetaString.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class JsonSerializeFormat;
|
||||||
|
|
||||||
|
/// The map event is an event which e.g. gives or takes resources of a specific
|
||||||
|
/// amount to/from players and can appear regularly or once a time.
|
||||||
|
class DLL_LINKAGE CMapEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMapEvent();
|
||||||
|
virtual ~CMapEvent() = default;
|
||||||
|
|
||||||
|
bool occursToday(int currentDay) const;
|
||||||
|
bool affectsPlayer(PlayerColor player, bool isHuman) const;
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
MetaString message;
|
||||||
|
TResources resources;
|
||||||
|
std::set<PlayerColor> players;
|
||||||
|
bool humanAffected;
|
||||||
|
bool computerAffected;
|
||||||
|
ui32 firstOccurrence;
|
||||||
|
ui32 nextOccurrence; /// specifies after how many days the event will occur the next time; 0 if event occurs only one time
|
||||||
|
|
||||||
|
std::vector<ObjectInstanceID> deletedObjectsInstances;
|
||||||
|
|
||||||
|
template<typename Handler>
|
||||||
|
void serialize(Handler & h)
|
||||||
|
{
|
||||||
|
h & name;
|
||||||
|
h & message;
|
||||||
|
h & resources;
|
||||||
|
h & players;
|
||||||
|
h & humanAffected;
|
||||||
|
h & computerAffected;
|
||||||
|
h & firstOccurrence;
|
||||||
|
h & nextOccurrence;
|
||||||
|
h & deletedObjectsInstances;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void serializeJson(JsonSerializeFormat & handler);
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -11,6 +11,7 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "MapFormatH3M.h"
|
#include "MapFormatH3M.h"
|
||||||
|
|
||||||
|
#include "CCastleEvent.h"
|
||||||
#include "CMap.h"
|
#include "CMap.h"
|
||||||
#include "MapReaderH3M.h"
|
#include "MapReaderH3M.h"
|
||||||
#include "MapFormatSettings.h"
|
#include "MapFormatSettings.h"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* CMapDefines.h, part of VCMI engine
|
* TerrainTile.h, part of VCMI engine
|
||||||
*
|
*
|
||||||
* Authors: listed in file AUTHORS in main folder
|
* Authors: listed in file AUTHORS in main folder
|
||||||
*
|
*
|
||||||
@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../ResourceSet.h"
|
|
||||||
#include "../texts/MetaString.h"
|
|
||||||
#include "../GameLibrary.h"
|
#include "../GameLibrary.h"
|
||||||
#include "../TerrainHandler.h"
|
#include "../TerrainHandler.h"
|
||||||
#include "../mapObjects/CGObjectInstance.h"
|
#include "../mapObjects/CGObjectInstance.h"
|
||||||
@ -22,67 +20,6 @@ class TerrainType;
|
|||||||
class RiverType;
|
class RiverType;
|
||||||
class RoadType;
|
class RoadType;
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
class CGTownInstance;
|
|
||||||
class JsonSerializeFormat;
|
|
||||||
|
|
||||||
/// The map event is an event which e.g. gives or takes resources of a specific
|
|
||||||
/// amount to/from players and can appear regularly or once a time.
|
|
||||||
class DLL_LINKAGE CMapEvent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CMapEvent();
|
|
||||||
virtual ~CMapEvent() = default;
|
|
||||||
|
|
||||||
bool occursToday(int currentDay) const;
|
|
||||||
bool affectsPlayer(PlayerColor player, bool isHuman) const;
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
MetaString message;
|
|
||||||
TResources resources;
|
|
||||||
std::set<PlayerColor> players;
|
|
||||||
bool humanAffected;
|
|
||||||
bool computerAffected;
|
|
||||||
ui32 firstOccurrence;
|
|
||||||
ui32 nextOccurrence; /// specifies after how many days the event will occur the next time; 0 if event occurs only one time
|
|
||||||
|
|
||||||
std::vector<ObjectInstanceID> deletedObjectsInstances;
|
|
||||||
|
|
||||||
template <typename Handler>
|
|
||||||
void serialize(Handler & h)
|
|
||||||
{
|
|
||||||
h & name;
|
|
||||||
h & message;
|
|
||||||
h & resources;
|
|
||||||
h & players;
|
|
||||||
h & humanAffected;
|
|
||||||
h & computerAffected;
|
|
||||||
h & firstOccurrence;
|
|
||||||
h & nextOccurrence;
|
|
||||||
h & deletedObjectsInstances;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void serializeJson(JsonSerializeFormat & handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The castle event builds/adds buildings/creatures for a specific town.
|
|
||||||
class DLL_LINKAGE CCastleEvent: public CMapEvent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCastleEvent() = default;
|
|
||||||
|
|
||||||
std::set<BuildingID> buildings;
|
|
||||||
std::vector<si32> creatures;
|
|
||||||
|
|
||||||
template <typename Handler>
|
|
||||||
void serialize(Handler & h)
|
|
||||||
{
|
|
||||||
h & static_cast<CMapEvent &>(*this);
|
|
||||||
h & buildings;
|
|
||||||
h & creatures;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serializeJson(JsonSerializeFormat & handler) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The terrain tile describes the terrain type and the visual representation of the terrain.
|
/// The terrain tile describes the terrain type and the visual representation of the terrain.
|
||||||
/// Furthermore the struct defines whether the tile is visitable or/and blocked and which objects reside in it.
|
/// Furthermore the struct defines whether the tile is visitable or/and blocked and which objects reside in it.
|
||||||
@ -156,8 +93,6 @@ struct DLL_LINKAGE TerrainTile
|
|||||||
for(const auto & ptr : objectPtrs)
|
for(const auto & ptr : objectPtrs)
|
||||||
blockingObjects.push_back(ptr->id);
|
blockingObjects.push_back(ptr->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -17,16 +17,16 @@
|
|||||||
#include "NetPacksBase.h"
|
#include "NetPacksBase.h"
|
||||||
#include "ObjProperty.h"
|
#include "ObjProperty.h"
|
||||||
|
|
||||||
#include "../CCreatureSet.h"
|
|
||||||
#include "../ResourceSet.h"
|
#include "../ResourceSet.h"
|
||||||
#include "../TurnTimerInfo.h"
|
#include "../TurnTimerInfo.h"
|
||||||
|
#include "../bonuses/Bonus.h"
|
||||||
#include "../gameState/EVictoryLossCheckResult.h"
|
#include "../gameState/EVictoryLossCheckResult.h"
|
||||||
#include "../gameState/RumorState.h"
|
#include "../gameState/RumorState.h"
|
||||||
#include "../gameState/QuestInfo.h"
|
#include "../gameState/QuestInfo.h"
|
||||||
#include "../gameState/TavernSlot.h"
|
#include "../gameState/TavernSlot.h"
|
||||||
#include "../gameState/GameStatistics.h"
|
#include "../gameState/GameStatistics.h"
|
||||||
#include "../int3.h"
|
#include "../int3.h"
|
||||||
#include "../mapping/CMapDefines.h"
|
#include "../mapObjects/army/CSimpleArmy.h"
|
||||||
#include "../spells/ViewSpellInt.h"
|
#include "../spells/ViewSpellInt.h"
|
||||||
|
|
||||||
class CClient;
|
class CClient;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "../battle/BattleInfo.h"
|
#include "../battle/BattleInfo.h"
|
||||||
#include "../battle/BattleHexArray.h"
|
#include "../battle/BattleHexArray.h"
|
||||||
#include "../battle/BattleUnitTurnReason.h"
|
#include "../battle/BattleUnitTurnReason.h"
|
||||||
|
#include "../mapObjects/army/CStackBasicDescriptor.h"
|
||||||
#include "../texts/MetaString.h"
|
#include "../texts/MetaString.h"
|
||||||
|
|
||||||
class CClient;
|
class CClient;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include "../callback/IGameInfoCallback.h"
|
#include "../callback/IGameInfoCallback.h"
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
#include "../mapping/CMapDefines.h"
|
#include "../mapping/TerrainTile.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../mapObjects/CGObjectInstance.h"
|
#include "../mapObjects/CGObjectInstance.h"
|
||||||
#include "../mapping/CMapDefines.h"
|
#include "../mapping/TerrainTile.h"
|
||||||
#include "../callback/IGameInfoCallback.h"
|
#include "../callback/IGameInfoCallback.h"
|
||||||
#include "CGPathNode.h"
|
#include "CGPathNode.h"
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
#include "../mapObjects/MiscObjects.h"
|
#include "../mapObjects/MiscObjects.h"
|
||||||
#include "../mapping/CMapDefines.h"
|
#include "../mapping/TerrainTile.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
#include "Limiter.h"
|
#include "Limiter.h"
|
||||||
#include "Reward.h"
|
#include "Reward.h"
|
||||||
|
|
||||||
#include "../callback/IGameRandomizer.h"
|
#include "../CCreatureHandler.h"
|
||||||
#include "../texts/CGeneralTextHandler.h"
|
|
||||||
#include "../json/JsonRandom.h"
|
|
||||||
#include "../GameLibrary.h"
|
#include "../GameLibrary.h"
|
||||||
|
#include "../callback/IGameRandomizer.h"
|
||||||
|
#include "../json/JsonRandom.h"
|
||||||
#include "../mapObjects/IObjectInterface.h"
|
#include "../mapObjects/IObjectInterface.h"
|
||||||
#include "../modding/IdentifierStorage.h"
|
#include "../modding/IdentifierStorage.h"
|
||||||
|
#include "../texts/CGeneralTextHandler.h"
|
||||||
|
|
||||||
#include <vstd/RNG.h>
|
#include <vstd/RNG.h>
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "../spells/ISpellMechanics.h"
|
#include "../spells/ISpellMechanics.h"
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
#include "../mapObjects/MiscObjects.h"
|
#include "../mapObjects/MiscObjects.h"
|
||||||
#include "../mapping/CMapDefines.h"
|
#include "../mapping/TerrainTile.h"
|
||||||
#include "../networkPacks/StackLocation.h"
|
#include "../networkPacks/StackLocation.h"
|
||||||
#include "../networkPacks/PacksForClient.h"
|
#include "../networkPacks/PacksForClient.h"
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class IObjectInterface;
|
class IObjectInterface;
|
||||||
|
class IGameEventCallback;
|
||||||
|
class CArmedInstance;
|
||||||
|
|
||||||
namespace Rewardable
|
namespace Rewardable
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "../GameConstants.h"
|
#include "../GameConstants.h"
|
||||||
#include "../ResourceSet.h"
|
#include "../ResourceSet.h"
|
||||||
|
#include "../mapObjects/army/CStackBasicDescriptor.h"
|
||||||
#include "../serializer/Serializeable.h"
|
#include "../serializer/Serializeable.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include "../ResourceSet.h"
|
#include "../ResourceSet.h"
|
||||||
#include "../bonuses/Bonus.h"
|
#include "../bonuses/Bonus.h"
|
||||||
#include "../CCreatureSet.h"
|
|
||||||
#include "../networkPacks/Component.h"
|
#include "../networkPacks/Component.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "../../CCreatureHandler.h"
|
#include "../../CCreatureHandler.h"
|
||||||
#include "../../mapObjectConstructors/AObjectTypeHandler.h"
|
#include "../../mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
#include "../../mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../../mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
|
#include "../../mapObjects/army/CStackInstance.h"
|
||||||
#include "../../mapObjects/CGCreature.h"
|
#include "../../mapObjects/CGCreature.h"
|
||||||
#include "../../mapping/CMap.h"
|
#include "../../mapping/CMap.h"
|
||||||
#include "../../mapping/CMapEditManager.h"
|
#include "../../mapping/CMapEditManager.h"
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "../entities/hero/CHero.h"
|
#include "../entities/hero/CHero.h"
|
||||||
#include "../mapObjects/ObjectTemplate.h"
|
#include "../mapObjects/ObjectTemplate.h"
|
||||||
#include "../mapping/CMapInfo.h"
|
#include "../mapping/CMapInfo.h"
|
||||||
|
#include "../mapping/CCastleEvent.h"
|
||||||
#include "../rmg/CMapGenOptions.h"
|
#include "../rmg/CMapGenOptions.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
@ -1,782 +0,0 @@
|
|||||||
/*
|
|
||||||
* AdventureSpellMechanics.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 "AdventureSpellMechanics.h"
|
|
||||||
|
|
||||||
#include "CSpellHandler.h"
|
|
||||||
#include "Problem.h"
|
|
||||||
|
|
||||||
#include "../CPlayerState.h"
|
|
||||||
#include "../IGameSettings.h"
|
|
||||||
#include "../callback/IGameInfoCallback.h"
|
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
|
||||||
#include "../mapObjects/CGTownInstance.h"
|
|
||||||
#include "../mapObjects/MiscObjects.h"
|
|
||||||
#include "../mapping/CMap.h"
|
|
||||||
#include "../networkPacks/PacksForClient.h"
|
|
||||||
|
|
||||||
#include <vstd/RNG.h>
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
///AdventureSpellMechanics
|
|
||||||
AdventureSpellMechanics::AdventureSpellMechanics(const CSpell * s):
|
|
||||||
IAdventureSpellMechanics(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AdventureSpellMechanics::canBeCast(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
|
||||||
{
|
|
||||||
if(!owner->isAdventure())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto * heroCaster = dynamic_cast<const CGHeroInstance *>(caster);
|
|
||||||
|
|
||||||
if (heroCaster)
|
|
||||||
{
|
|
||||||
if(heroCaster->isGarrisoned())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto level = heroCaster->getSpellSchoolLevel(owner);
|
|
||||||
const auto cost = owner->getCost(level);
|
|
||||||
|
|
||||||
if(!heroCaster->canCastThisSpell(owner))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(heroCaster->mana < cost)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return canBeCastImpl(problem, cb, caster);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AdventureSpellMechanics::canBeCastAt(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
|
|
||||||
{
|
|
||||||
return canBeCast(problem, cb, caster) && canBeCastAtImpl(problem, cb, caster, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AdventureSpellMechanics::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AdventureSpellMechanics::canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AdventureSpellMechanics::adventureCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
spells::detail::ProblemImpl problem;
|
|
||||||
|
|
||||||
if (!canBeCastAt(problem, env->getCb(), parameters.caster, parameters.pos))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ESpellCastResult result = beginCast(env, parameters);
|
|
||||||
|
|
||||||
if(result == ESpellCastResult::OK)
|
|
||||||
performCast(env, parameters);
|
|
||||||
|
|
||||||
return result != ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
if(owner->hasEffects())
|
|
||||||
{
|
|
||||||
//todo: cumulative effects support
|
|
||||||
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
|
||||||
|
|
||||||
std::vector<Bonus> bonuses;
|
|
||||||
|
|
||||||
owner->getEffects(bonuses, schoolLevel, false, parameters.caster->getEnchantPower(owner));
|
|
||||||
|
|
||||||
for(const Bonus & b : bonuses)
|
|
||||||
{
|
|
||||||
GiveBonus gb;
|
|
||||||
gb.id = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
|
||||||
gb.bonus = b;
|
|
||||||
env->apply(gb);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//There is no generic algorithm of adventure cast
|
|
||||||
env->complain("Unimplemented adventure spell");
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ESpellCastResult AdventureSpellMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdventureSpellMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
// no-op, only for implementation in derived classes
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdventureSpellMechanics::performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
const auto level = parameters.caster->getSpellSchoolLevel(owner);
|
|
||||||
const auto cost = owner->getCost(level);
|
|
||||||
|
|
||||||
AdvmapSpellCast asc;
|
|
||||||
asc.casterID = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
|
||||||
asc.spellID = owner->id;
|
|
||||||
env->apply(asc);
|
|
||||||
|
|
||||||
ESpellCastResult result = applyAdventureEffects(env, parameters);
|
|
||||||
|
|
||||||
switch(result)
|
|
||||||
{
|
|
||||||
case ESpellCastResult::OK:
|
|
||||||
parameters.caster->spendMana(env, cost);
|
|
||||||
endCast(env, parameters);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///SummonBoatMechanics
|
|
||||||
SummonBoatMechanics::SummonBoatMechanics(const CSpell * s):
|
|
||||||
AdventureSpellMechanics(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SummonBoatMechanics::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
|
||||||
{
|
|
||||||
if(!caster->getHeroCaster())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(caster->getHeroCaster()->inBoat())
|
|
||||||
{
|
|
||||||
MetaString message = MetaString::createFromTextID("core.genrltxt.333");
|
|
||||||
caster->getCasterName(message);
|
|
||||||
problem.add(std::move(message));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int3 summonPos = caster->getHeroCaster()->bestLocation();
|
|
||||||
|
|
||||||
if(summonPos.x < 0)
|
|
||||||
{
|
|
||||||
MetaString message = MetaString::createFromTextID("core.genrltxt.334");
|
|
||||||
caster->getCasterName(message);
|
|
||||||
problem.add(std::move(message));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
|
||||||
|
|
||||||
//check if spell works at all
|
|
||||||
if(env->getRNG()->nextInt(0, 99) >= owner->getLevelPower(schoolLevel)) //power is % chance of success
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
|
|
||||||
parameters.caster->getCasterName(iw.text);
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
//try to find unoccupied boat to summon
|
|
||||||
const CGBoat * nearest = nullptr;
|
|
||||||
double dist = 0;
|
|
||||||
for(const auto & b : env->getMap()->getObjects<CGBoat>())
|
|
||||||
{
|
|
||||||
if(b->getBoardedHero() || b->layer != EPathfindingLayer::SAIL)
|
|
||||||
continue; //we're looking for unoccupied boat
|
|
||||||
|
|
||||||
double nDist = b->visitablePos().dist2d(parameters.caster->getHeroCaster()->visitablePos());
|
|
||||||
if(!nearest || nDist < dist) //it's first boat or closer than previous
|
|
||||||
{
|
|
||||||
nearest = b;
|
|
||||||
dist = nDist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int3 summonPos = parameters.caster->getHeroCaster()->bestLocation();
|
|
||||||
|
|
||||||
if(nullptr != nearest) //we found boat to summon
|
|
||||||
{
|
|
||||||
ChangeObjPos cop;
|
|
||||||
cop.objid = nearest->id;
|
|
||||||
cop.nPos = summonPos;
|
|
||||||
cop.initiator = parameters.caster->getCasterOwner();
|
|
||||||
env->apply(cop);
|
|
||||||
}
|
|
||||||
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 335); //There are no boats to summon.
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
else //create boat
|
|
||||||
{
|
|
||||||
env->createBoat(summonPos, BoatId::NECROPOLIS, parameters.caster->getCasterOwner());
|
|
||||||
}
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
///ScuttleBoatMechanics
|
|
||||||
ScuttleBoatMechanics::ScuttleBoatMechanics(const CSpell * s):
|
|
||||||
AdventureSpellMechanics(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScuttleBoatMechanics::canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
|
|
||||||
{
|
|
||||||
if(!cb->isInTheMap(pos))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (caster->getHeroCaster())
|
|
||||||
{
|
|
||||||
int3 casterPosition = caster->getHeroCaster()->getSightCenter();
|
|
||||||
|
|
||||||
if(!isInScreenRange(casterPosition, pos))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!cb->isVisibleFor(pos, caster->getCasterOwner()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const TerrainTile * t = cb->getTile(pos);
|
|
||||||
if(!t || t->visitableObjects.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const CGObjectInstance * topObject = cb->getObj(t->visitableObjects.back());
|
|
||||||
if (topObject->ID != Obj::BOAT)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
|
||||||
//check if spell works at all
|
|
||||||
if(env->getRNG()->nextInt(0, 99) >= owner->getLevelPower(schoolLevel)) //power is % chance of success
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed
|
|
||||||
parameters.caster->getCasterName(iw.text);
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TerrainTile & t = env->getMap()->getTile(parameters.pos);
|
|
||||||
|
|
||||||
RemoveObject ro;
|
|
||||||
ro.initiator = parameters.caster->getCasterOwner();
|
|
||||||
ro.objectID = t.visitableObjects.back();
|
|
||||||
env->apply(ro);
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
///DimensionDoorMechanics
|
|
||||||
DimensionDoorMechanics::DimensionDoorMechanics(const CSpell * s):
|
|
||||||
AdventureSpellMechanics(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DimensionDoorMechanics::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
|
||||||
{
|
|
||||||
if(!caster->getHeroCaster())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(caster->getHeroCaster()->movementPointsRemaining() <= 0) //unlike town portal non-zero MP is enough
|
|
||||||
{
|
|
||||||
problem.add(MetaString::createFromTextID("core.genrltxt.125"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto schoolLevel = caster->getSpellSchoolLevel(owner);
|
|
||||||
|
|
||||||
std::stringstream cachingStr;
|
|
||||||
cachingStr << "source_" << vstd::to_underlying(BonusSource::SPELL_EFFECT) << "id_" << owner->id.num;
|
|
||||||
|
|
||||||
int castsAlreadyPerformedThisTurn = caster->getHeroCaster()->getBonuses(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(owner->id)), cachingStr.str())->size();
|
|
||||||
int castsLimit = owner->getLevelPower(schoolLevel);
|
|
||||||
|
|
||||||
bool isTournamentRulesLimitEnabled = cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_TOURNAMENT_RULES_LIMIT);
|
|
||||||
if(isTournamentRulesLimitEnabled)
|
|
||||||
{
|
|
||||||
int3 mapSize = cb->getMapSize();
|
|
||||||
|
|
||||||
bool meetsTournamentRulesTwoCastsRequirements = mapSize.x * mapSize.y * mapSize.z >= GameConstants::TOURNAMENT_RULES_DD_MAP_TILES_THRESHOLD
|
|
||||||
&& schoolLevel == MasteryLevel::EXPERT;
|
|
||||||
|
|
||||||
castsLimit = meetsTournamentRulesTwoCastsRequirements ? 2 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(castsAlreadyPerformedThisTurn >= castsLimit) //limit casts per turn
|
|
||||||
{
|
|
||||||
MetaString message = MetaString::createFromTextID("core.genrltxt.338");
|
|
||||||
caster->getCasterName(message);
|
|
||||||
problem.add(std::move(message));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DimensionDoorMechanics::canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
|
|
||||||
{
|
|
||||||
if(!cb->isInTheMap(pos))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_ONLY_TO_UNCOVERED_TILES))
|
|
||||||
{
|
|
||||||
if(!cb->isVisibleFor(pos, caster->getCasterOwner()))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int3 casterPosition = caster->getHeroCaster()->getSightCenter();
|
|
||||||
|
|
||||||
const TerrainTile * dest = cb->getTileUnchecked(pos);
|
|
||||||
const TerrainTile * curr = cb->getTileUnchecked(casterPosition);
|
|
||||||
|
|
||||||
if(!dest)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(!curr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(!isInScreenRange(casterPosition, pos))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_EXPOSES_TERRAIN_TYPE))
|
|
||||||
{
|
|
||||||
if(!dest->isClear(curr))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dest->blocked())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
|
||||||
const int baseCost = env->getCb()->getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
|
|
||||||
const int movementCost = baseCost * ((schoolLevel >= 3) ? 2 : 3);
|
|
||||||
|
|
||||||
int3 casterPosition = parameters.caster->getHeroCaster()->getSightCenter();
|
|
||||||
const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
|
|
||||||
const TerrainTile * curr = env->getCb()->getTile(casterPosition);
|
|
||||||
|
|
||||||
if(!dest->isClear(curr))
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
|
|
||||||
// tile is either blocked or not possible to move (e.g. water <-> land)
|
|
||||||
if(env->getCb()->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_FAILURE_SPENDS_POINTS))
|
|
||||||
{
|
|
||||||
// SOD: DD to such "wrong" terrain results in mana and move points spending, but fails to move hero
|
|
||||||
iw.text = MetaString::createFromTextID("core.genrltxt.70"); // Dimension Door failed!
|
|
||||||
env->apply(iw);
|
|
||||||
// no return - resources will be spent
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// HotA: game will show error message without taking mana or move points, even when DD into terra incognita
|
|
||||||
iw.text = MetaString::createFromTextID("vcmi.dimensionDoor.seaToLandError");
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::CANCEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GiveBonus gb;
|
|
||||||
gb.id = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
|
||||||
gb.bonus = Bonus(BonusDuration::ONE_DAY, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, BonusSourceID(owner->id));
|
|
||||||
env->apply(gb);
|
|
||||||
|
|
||||||
SetMovePoints smp;
|
|
||||||
smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
|
||||||
if(movementCost < static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()))
|
|
||||||
smp.val = parameters.caster->getHeroCaster()->movementPointsRemaining() - movementCost;
|
|
||||||
else
|
|
||||||
smp.val = 0;
|
|
||||||
env->apply(smp);
|
|
||||||
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DimensionDoorMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
int3 casterPosition = parameters.caster->getHeroCaster()->getSightCenter();
|
|
||||||
const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
|
|
||||||
const TerrainTile * curr = env->getCb()->getTile(casterPosition);
|
|
||||||
|
|
||||||
if(dest->isClear(curr))
|
|
||||||
env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(parameters.pos), EMovementMode::DIMENSION_DOOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
///TownPortalMechanics
|
|
||||||
TownPortalMechanics::TownPortalMechanics(const CSpell * s):
|
|
||||||
AdventureSpellMechanics(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
const CGTownInstance * destination = nullptr;
|
|
||||||
const int moveCost = movementCost(env, parameters);
|
|
||||||
|
|
||||||
if(!parameters.caster->getHeroCaster())
|
|
||||||
{
|
|
||||||
env->complain("Not a hero caster!");
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(parameters.caster->getSpellSchoolLevel(owner) < 2)
|
|
||||||
{
|
|
||||||
std::vector <const CGTownInstance*> pool = getPossibleTowns(env, parameters);
|
|
||||||
destination = findNearestTown(env, parameters, pool);
|
|
||||||
|
|
||||||
if(nullptr == destination)
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
|
|
||||||
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
|
|
||||||
if(destination->getVisitingHero())
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 123);
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::CANCEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(env->getMap()->isInTheMap(parameters.pos))
|
|
||||||
{
|
|
||||||
const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
|
|
||||||
|
|
||||||
ObjectInstanceID topObjID = tile.topVisitableObj(false);
|
|
||||||
const CGObjectInstance * topObj = env->getMap()->getObject(topObjID);
|
|
||||||
|
|
||||||
if(!topObj)
|
|
||||||
{
|
|
||||||
env->complain("Destination tile is not visitable" + parameters.pos.toString());
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
else if(topObj->ID == Obj::HERO)
|
|
||||||
{
|
|
||||||
env->complain("Can't teleport to occupied town at " + parameters.pos.toString());
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
else if(topObj->ID != Obj::TOWN)
|
|
||||||
{
|
|
||||||
env->complain("No town at destination tile " + parameters.pos.toString());
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
destination = dynamic_cast<const CGTownInstance*>(topObj);
|
|
||||||
|
|
||||||
if(nullptr == destination)
|
|
||||||
{
|
|
||||||
env->complain("[Internal error] invalid town object at " + parameters.pos.toString());
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto relations = env->getCb()->getPlayerRelations(destination->tempOwner, parameters.caster->getCasterOwner());
|
|
||||||
|
|
||||||
if(relations == PlayerRelations::ENEMIES)
|
|
||||||
{
|
|
||||||
env->complain("Can't teleport to enemy!");
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
|
|
||||||
{
|
|
||||||
env->complain("This hero has not enough movement points!");
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(destination->getVisitingHero())
|
|
||||||
{
|
|
||||||
env->complain("[Internal error] Can't teleport to occupied town");
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
env->complain("Invalid destination tile");
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TerrainTile & from = env->getMap()->getTile(parameters.caster->getHeroCaster()->visitablePos());
|
|
||||||
const TerrainTile & dest = env->getMap()->getTile(destination->visitablePos());
|
|
||||||
|
|
||||||
if(!dest.entrableTerrain(&from))
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 135);
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TownPortalMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
const int moveCost = movementCost(env, parameters);
|
|
||||||
const CGTownInstance * destination = nullptr;
|
|
||||||
|
|
||||||
if(parameters.caster->getSpellSchoolLevel(owner) < 2)
|
|
||||||
{
|
|
||||||
std::vector <const CGTownInstance*> pool = getPossibleTowns(env, parameters);
|
|
||||||
destination = findNearestTown(env, parameters, pool);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
|
|
||||||
ObjectInstanceID topObjID = tile.topVisitableObj(false);
|
|
||||||
const CGObjectInstance * topObj = env->getMap()->getObject(topObjID);
|
|
||||||
|
|
||||||
destination = dynamic_cast<const CGTownInstance*>(topObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(destination->visitablePos()), EMovementMode::TOWN_PORTAL))
|
|
||||||
{
|
|
||||||
SetMovePoints smp;
|
|
||||||
smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
|
||||||
smp.val = std::max<ui32>(0, parameters.caster->getHeroCaster()->movementPointsRemaining() - moveCost);
|
|
||||||
env->apply(smp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
std::vector<const CGTownInstance *> towns = getPossibleTowns(env, parameters);
|
|
||||||
|
|
||||||
if(!parameters.caster->getHeroCaster())
|
|
||||||
{
|
|
||||||
env->complain("Not a hero caster!");
|
|
||||||
return ESpellCastResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(towns.empty())
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 124);
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int moveCost = movementCost(env, parameters);
|
|
||||||
|
|
||||||
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 125);
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!parameters.pos.isValid() && parameters.caster->getSpellSchoolLevel(owner) >= 2)
|
|
||||||
{
|
|
||||||
auto queryCallback = [this, env, parameters](std::optional<int32_t> reply) -> void
|
|
||||||
{
|
|
||||||
if(reply.has_value())
|
|
||||||
{
|
|
||||||
ObjectInstanceID townId(*reply);
|
|
||||||
|
|
||||||
const CGObjectInstance * o = env->getCb()->getObj(townId, true);
|
|
||||||
if(o == nullptr)
|
|
||||||
{
|
|
||||||
env->complain("Invalid object instance selected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!dynamic_cast<const CGTownInstance *>(o))
|
|
||||||
{
|
|
||||||
env->complain("Object instance is not town");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AdventureSpellCastParameters p;
|
|
||||||
p.caster = parameters.caster;
|
|
||||||
p.pos = o->visitablePos();
|
|
||||||
performCast(env, p);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MapObjectSelectDialog request;
|
|
||||||
|
|
||||||
for(const auto * t : towns)
|
|
||||||
{
|
|
||||||
if(t->getVisitingHero() == nullptr) //empty town
|
|
||||||
request.objects.push_back(t->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(request.objects.empty())
|
|
||||||
{
|
|
||||||
InfoWindow iw;
|
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
|
||||||
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 124);
|
|
||||||
env->apply(iw);
|
|
||||||
return ESpellCastResult::CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
request.player = parameters.caster->getCasterOwner();
|
|
||||||
request.title.appendLocalString(EMetaText::JK_TXT, 40);
|
|
||||||
request.description.appendLocalString(EMetaText::JK_TXT, 41);
|
|
||||||
request.icon = Component(ComponentType::SPELL, owner->id);
|
|
||||||
|
|
||||||
env->genericQuery(&request, request.player, queryCallback);
|
|
||||||
|
|
||||||
return ESpellCastResult::PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CGTownInstance * TownPortalMechanics::findNearestTown(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const std::vector <const CGTownInstance *> & pool) const
|
|
||||||
{
|
|
||||||
if(pool.empty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if(!parameters.caster->getHeroCaster())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto nearest = pool.cbegin(); //nearest town's iterator
|
|
||||||
si32 dist = (*nearest)->visitablePos().dist2dSQ(parameters.caster->getHeroCaster()->visitablePos());
|
|
||||||
|
|
||||||
for(auto i = nearest + 1; i != pool.cend(); ++i)
|
|
||||||
{
|
|
||||||
si32 curDist = (*i)->visitablePos().dist2dSQ(parameters.caster->getHeroCaster()->visitablePos());
|
|
||||||
|
|
||||||
if(curDist < dist)
|
|
||||||
{
|
|
||||||
nearest = i;
|
|
||||||
dist = curDist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *nearest;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector <const CGTownInstance*> TownPortalMechanics::getPossibleTowns(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
std::vector <const CGTownInstance*> ret;
|
|
||||||
|
|
||||||
const TeamState * team = env->getCb()->getPlayerTeam(parameters.caster->getCasterOwner());
|
|
||||||
|
|
||||||
for(const auto & color : team->players)
|
|
||||||
{
|
|
||||||
for(auto currTown : env->getCb()->getPlayerState(color)->getTowns())
|
|
||||||
{
|
|
||||||
ret.push_back(currTown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t TownPortalMechanics::movementCost(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
if(parameters.caster != parameters.caster->getHeroCaster()) //if caster is not hero
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int baseMovementCost = env->getCb()->getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
|
|
||||||
return baseMovementCost * ((parameters.caster->getSpellSchoolLevel(owner) >= 3) ? 2 : 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
///ViewMechanics
|
|
||||||
ViewMechanics::ViewMechanics(const CSpell * s):
|
|
||||||
AdventureSpellMechanics(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
|
||||||
{
|
|
||||||
ShowWorldViewEx pack;
|
|
||||||
|
|
||||||
pack.player = parameters.caster->getCasterOwner();
|
|
||||||
|
|
||||||
const auto spellLevel = parameters.caster->getSpellSchoolLevel(owner);
|
|
||||||
|
|
||||||
const auto & fowMap = env->getCb()->getPlayerTeam(parameters.caster->getCasterOwner())->fogOfWarMap;
|
|
||||||
|
|
||||||
for(const auto & obj : env->getMap()->getObjects())
|
|
||||||
{
|
|
||||||
//deleted object remain as empty pointer
|
|
||||||
if(obj && filterObject(obj, spellLevel))
|
|
||||||
{
|
|
||||||
ObjectPosInfo posInfo(obj);
|
|
||||||
|
|
||||||
if(fowMap[posInfo.pos.z][posInfo.pos.x][posInfo.pos.y] == 0)
|
|
||||||
pack.objectPositions.push_back(posInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pack.showTerrain = showTerrain(spellLevel);
|
|
||||||
|
|
||||||
env->apply(pack);
|
|
||||||
|
|
||||||
return ESpellCastResult::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
///ViewAirMechanics
|
|
||||||
ViewAirMechanics::ViewAirMechanics(const CSpell * s):
|
|
||||||
ViewMechanics(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ViewAirMechanics::filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const
|
|
||||||
{
|
|
||||||
return (obj->ID == Obj::ARTIFACT) || (spellLevel > 1 && obj->ID == Obj::HERO) || (spellLevel > 2 && obj->ID == Obj::TOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ViewAirMechanics::showTerrain(const int32_t spellLevel) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
///ViewEarthMechanics
|
|
||||||
ViewEarthMechanics::ViewEarthMechanics(const CSpell * s):
|
|
||||||
ViewMechanics(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ViewEarthMechanics::filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const
|
|
||||||
{
|
|
||||||
return (obj->ID == Obj::RESOURCE) || (spellLevel > 1 && obj->ID == Obj::MINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ViewEarthMechanics::showTerrain(const int32_t spellLevel) const
|
|
||||||
{
|
|
||||||
return spellLevel > 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* AdventureSpellMechanics.h, part of VCMI engine
|
|
||||||
*
|
|
||||||
* Authors: listed in file AUTHORS in main folder
|
|
||||||
*
|
|
||||||
* License: GNU General Public License v2.0 or later
|
|
||||||
* Full text of license available in license.txt file, in main folder
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ISpellMechanics.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
class CGTownInstance;
|
|
||||||
|
|
||||||
enum class ESpellCastResult
|
|
||||||
{
|
|
||||||
OK, // cast successful
|
|
||||||
CANCEL, // cast failed but it is not an error, no mana has been spent
|
|
||||||
PENDING,
|
|
||||||
ERROR// error occurred, for example invalid request from player
|
|
||||||
};
|
|
||||||
|
|
||||||
class AdventureSpellMechanics : public IAdventureSpellMechanics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AdventureSpellMechanics(const CSpell * s);
|
|
||||||
|
|
||||||
bool canBeCast(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const final;
|
|
||||||
bool canBeCastAt(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const final;
|
|
||||||
|
|
||||||
bool adventureCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override final;
|
|
||||||
protected:
|
|
||||||
///actual adventure cast implementation
|
|
||||||
virtual ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
|
||||||
virtual ESpellCastResult beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
|
||||||
virtual void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
|
||||||
virtual bool canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const;
|
|
||||||
virtual bool canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const;
|
|
||||||
|
|
||||||
void performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SummonBoatMechanics final : public AdventureSpellMechanics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SummonBoatMechanics(const CSpell * s);
|
|
||||||
protected:
|
|
||||||
bool canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const override;
|
|
||||||
|
|
||||||
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ScuttleBoatMechanics final : public AdventureSpellMechanics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ScuttleBoatMechanics(const CSpell * s);
|
|
||||||
protected:
|
|
||||||
bool canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const override;
|
|
||||||
|
|
||||||
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DimensionDoorMechanics final : public AdventureSpellMechanics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DimensionDoorMechanics(const CSpell * s);
|
|
||||||
protected:
|
|
||||||
bool canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const override;
|
|
||||||
bool canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const override;
|
|
||||||
|
|
||||||
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
|
||||||
void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TownPortalMechanics final : public AdventureSpellMechanics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TownPortalMechanics(const CSpell * s);
|
|
||||||
protected:
|
|
||||||
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
|
||||||
ESpellCastResult beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
|
||||||
void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
|
||||||
private:
|
|
||||||
const CGTownInstance * findNearestTown(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const std::vector <const CGTownInstance*> & pool) const;
|
|
||||||
int32_t movementCost(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
|
||||||
std::vector <const CGTownInstance*> getPossibleTowns(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ViewMechanics : public AdventureSpellMechanics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ViewMechanics(const CSpell * s);
|
|
||||||
protected:
|
|
||||||
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
|
||||||
virtual bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const = 0;
|
|
||||||
virtual bool showTerrain(const int32_t spellLevel) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ViewAirMechanics final : public ViewMechanics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ViewAirMechanics(const CSpell * s);
|
|
||||||
protected:
|
|
||||||
bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override;
|
|
||||||
bool showTerrain(const int32_t spellLevel) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ViewEarthMechanics final : public ViewMechanics
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ViewEarthMechanics(const CSpell * s);
|
|
||||||
protected:
|
|
||||||
bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override;
|
|
||||||
bool showTerrain(const int32_t spellLevel) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
|
@ -26,7 +26,13 @@
|
|||||||
#include "TargetCondition.h"
|
#include "TargetCondition.h"
|
||||||
#include "Problem.h"
|
#include "Problem.h"
|
||||||
|
|
||||||
#include "AdventureSpellMechanics.h"
|
#include "adventure/AdventureSpellMechanics.h"
|
||||||
|
#include "adventure/DimensionDoorMechanics.h"
|
||||||
|
#include "adventure/ScuttleBoatMechanics.h"
|
||||||
|
#include "adventure/SummonBoatMechanics.h"
|
||||||
|
#include "adventure/TownPortalMechanics.h"
|
||||||
|
#include "adventure/ViewWorldMechanics.h"
|
||||||
|
|
||||||
#include "BattleSpellMechanics.h"
|
#include "BattleSpellMechanics.h"
|
||||||
|
|
||||||
#include "effects/Effects.h"
|
#include "effects/Effects.h"
|
||||||
|
144
lib/spells/adventure/AdventureSpellMechanics.cpp
Normal file
144
lib/spells/adventure/AdventureSpellMechanics.cpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* AdventureSpellMechanics.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 "AdventureSpellMechanics.h"
|
||||||
|
|
||||||
|
#include "../CSpellHandler.h"
|
||||||
|
#include "../Problem.h"
|
||||||
|
|
||||||
|
#include "../../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../networkPacks/PacksForClient.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
AdventureSpellMechanics::AdventureSpellMechanics(const CSpell * s)
|
||||||
|
: IAdventureSpellMechanics(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdventureSpellMechanics::canBeCast(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
||||||
|
{
|
||||||
|
if(!owner->isAdventure())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto * heroCaster = dynamic_cast<const CGHeroInstance *>(caster);
|
||||||
|
|
||||||
|
if(heroCaster)
|
||||||
|
{
|
||||||
|
if(heroCaster->isGarrisoned())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto level = heroCaster->getSpellSchoolLevel(owner);
|
||||||
|
const auto cost = owner->getCost(level);
|
||||||
|
|
||||||
|
if(!heroCaster->canCastThisSpell(owner))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(heroCaster->mana < cost)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return canBeCastImpl(problem, cb, caster);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdventureSpellMechanics::canBeCastAt(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
|
||||||
|
{
|
||||||
|
return canBeCast(problem, cb, caster) && canBeCastAtImpl(problem, cb, caster, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdventureSpellMechanics::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdventureSpellMechanics::canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AdventureSpellMechanics::adventureCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
spells::detail::ProblemImpl problem;
|
||||||
|
|
||||||
|
if(!canBeCastAt(problem, env->getCb(), parameters.caster, parameters.pos))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ESpellCastResult result = beginCast(env, parameters);
|
||||||
|
|
||||||
|
if(result == ESpellCastResult::OK)
|
||||||
|
performCast(env, parameters);
|
||||||
|
|
||||||
|
return result != ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
if(owner->hasEffects())
|
||||||
|
{
|
||||||
|
//todo: cumulative effects support
|
||||||
|
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
||||||
|
|
||||||
|
std::vector<Bonus> bonuses;
|
||||||
|
|
||||||
|
owner->getEffects(bonuses, schoolLevel, false, parameters.caster->getEnchantPower(owner));
|
||||||
|
|
||||||
|
for(const Bonus & b : bonuses)
|
||||||
|
{
|
||||||
|
GiveBonus gb;
|
||||||
|
gb.id = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
||||||
|
gb.bonus = b;
|
||||||
|
env->apply(gb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//There is no generic algorithm of adventure cast
|
||||||
|
env->complain("Unimplemented adventure spell");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESpellCastResult AdventureSpellMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdventureSpellMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
// no-op, only for implementation in derived classes
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdventureSpellMechanics::performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
const auto level = parameters.caster->getSpellSchoolLevel(owner);
|
||||||
|
const auto cost = owner->getCost(level);
|
||||||
|
|
||||||
|
AdvmapSpellCast asc;
|
||||||
|
asc.casterID = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
||||||
|
asc.spellID = owner->id;
|
||||||
|
env->apply(asc);
|
||||||
|
|
||||||
|
ESpellCastResult result = applyAdventureEffects(env, parameters);
|
||||||
|
|
||||||
|
switch(result)
|
||||||
|
{
|
||||||
|
case ESpellCastResult::OK:
|
||||||
|
parameters.caster->spendMana(env, cost);
|
||||||
|
endCast(env, parameters);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
46
lib/spells/adventure/AdventureSpellMechanics.h
Normal file
46
lib/spells/adventure/AdventureSpellMechanics.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* AdventureSpellMechanics.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../ISpellMechanics.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
enum class ESpellCastResult
|
||||||
|
{
|
||||||
|
OK, // cast successful
|
||||||
|
CANCEL, // cast failed but it is not an error, no mana has been spent
|
||||||
|
PENDING,
|
||||||
|
ERROR // error occurred, for example invalid request from player
|
||||||
|
};
|
||||||
|
|
||||||
|
class AdventureSpellMechanics : public IAdventureSpellMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AdventureSpellMechanics(const CSpell * s);
|
||||||
|
|
||||||
|
bool canBeCast(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const final;
|
||||||
|
bool canBeCastAt(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const final;
|
||||||
|
|
||||||
|
bool adventureCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override final;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///actual adventure cast implementation
|
||||||
|
virtual ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
||||||
|
virtual ESpellCastResult beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
||||||
|
virtual void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
||||||
|
virtual bool canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const;
|
||||||
|
virtual bool canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const;
|
||||||
|
|
||||||
|
void performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
166
lib/spells/adventure/DimensionDoorMechanics.cpp
Normal file
166
lib/spells/adventure/DimensionDoorMechanics.cpp
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* DimensionDoorMechanics.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 "DimensionDoorMechanics.h"
|
||||||
|
|
||||||
|
#include "../CSpellHandler.h"
|
||||||
|
|
||||||
|
#include "../../IGameSettings.h"
|
||||||
|
#include "../../callback/IGameInfoCallback.h"
|
||||||
|
#include "../../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../mapping/TerrainTile.h"
|
||||||
|
#include "../../networkPacks/PacksForClient.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
DimensionDoorMechanics::DimensionDoorMechanics(const CSpell * s)
|
||||||
|
: AdventureSpellMechanics(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DimensionDoorMechanics::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
||||||
|
{
|
||||||
|
if(!caster->getHeroCaster())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(caster->getHeroCaster()->movementPointsRemaining() <= 0) //unlike town portal non-zero MP is enough
|
||||||
|
{
|
||||||
|
problem.add(MetaString::createFromTextID("core.genrltxt.125"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto schoolLevel = caster->getSpellSchoolLevel(owner);
|
||||||
|
|
||||||
|
std::stringstream cachingStr;
|
||||||
|
cachingStr << "source_" << vstd::to_underlying(BonusSource::SPELL_EFFECT) << "id_" << owner->id.num;
|
||||||
|
|
||||||
|
int castsAlreadyPerformedThisTurn = caster->getHeroCaster()->getBonuses(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(owner->id)), cachingStr.str())->size();
|
||||||
|
int castsLimit = owner->getLevelPower(schoolLevel);
|
||||||
|
|
||||||
|
bool isTournamentRulesLimitEnabled = cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_TOURNAMENT_RULES_LIMIT);
|
||||||
|
if(isTournamentRulesLimitEnabled)
|
||||||
|
{
|
||||||
|
int3 mapSize = cb->getMapSize();
|
||||||
|
|
||||||
|
bool meetsTournamentRulesTwoCastsRequirements = mapSize.x * mapSize.y * mapSize.z >= GameConstants::TOURNAMENT_RULES_DD_MAP_TILES_THRESHOLD && schoolLevel == MasteryLevel::EXPERT;
|
||||||
|
|
||||||
|
castsLimit = meetsTournamentRulesTwoCastsRequirements ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(castsAlreadyPerformedThisTurn >= castsLimit) //limit casts per turn
|
||||||
|
{
|
||||||
|
MetaString message = MetaString::createFromTextID("core.genrltxt.338");
|
||||||
|
caster->getCasterName(message);
|
||||||
|
problem.add(std::move(message));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DimensionDoorMechanics::canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
|
||||||
|
{
|
||||||
|
if(!cb->isInTheMap(pos))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_ONLY_TO_UNCOVERED_TILES))
|
||||||
|
{
|
||||||
|
if(!cb->isVisibleFor(pos, caster->getCasterOwner()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int3 casterPosition = caster->getHeroCaster()->getSightCenter();
|
||||||
|
|
||||||
|
const TerrainTile * dest = cb->getTileUnchecked(pos);
|
||||||
|
const TerrainTile * curr = cb->getTileUnchecked(casterPosition);
|
||||||
|
|
||||||
|
if(!dest)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!curr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!isInScreenRange(casterPosition, pos))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_EXPOSES_TERRAIN_TYPE))
|
||||||
|
{
|
||||||
|
if(!dest->isClear(curr))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(dest->blocked())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
||||||
|
const int baseCost = env->getCb()->getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
|
||||||
|
const int movementCost = baseCost * ((schoolLevel >= 3) ? 2 : 3);
|
||||||
|
|
||||||
|
int3 casterPosition = parameters.caster->getHeroCaster()->getSightCenter();
|
||||||
|
const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
|
||||||
|
const TerrainTile * curr = env->getCb()->getTile(casterPosition);
|
||||||
|
|
||||||
|
if(!dest->isClear(curr))
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
|
||||||
|
// tile is either blocked or not possible to move (e.g. water <-> land)
|
||||||
|
if(env->getCb()->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_FAILURE_SPENDS_POINTS))
|
||||||
|
{
|
||||||
|
// SOD: DD to such "wrong" terrain results in mana and move points spending, but fails to move hero
|
||||||
|
iw.text = MetaString::createFromTextID("core.genrltxt.70"); // Dimension Door failed!
|
||||||
|
env->apply(iw);
|
||||||
|
// no return - resources will be spent
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// HotA: game will show error message without taking mana or move points, even when DD into terra incognita
|
||||||
|
iw.text = MetaString::createFromTextID("vcmi.dimensionDoor.seaToLandError");
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::CANCEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GiveBonus gb;
|
||||||
|
gb.id = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
||||||
|
gb.bonus = Bonus(BonusDuration::ONE_DAY, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, BonusSourceID(owner->id));
|
||||||
|
env->apply(gb);
|
||||||
|
|
||||||
|
SetMovePoints smp;
|
||||||
|
smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
||||||
|
if(movementCost < static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()))
|
||||||
|
smp.val = parameters.caster->getHeroCaster()->movementPointsRemaining() - movementCost;
|
||||||
|
else
|
||||||
|
smp.val = 0;
|
||||||
|
env->apply(smp);
|
||||||
|
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DimensionDoorMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
int3 casterPosition = parameters.caster->getHeroCaster()->getSightCenter();
|
||||||
|
const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
|
||||||
|
const TerrainTile * curr = env->getCb()->getTile(casterPosition);
|
||||||
|
|
||||||
|
if(dest->isClear(curr))
|
||||||
|
env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(parameters.pos), EMovementMode::DIMENSION_DOOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
30
lib/spells/adventure/DimensionDoorMechanics.h
Normal file
30
lib/spells/adventure/DimensionDoorMechanics.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* DimensionDoorMechanics.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AdventureSpellMechanics.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class DimensionDoorMechanics final : public AdventureSpellMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DimensionDoorMechanics(const CSpell * s);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const override;
|
||||||
|
bool canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const override;
|
||||||
|
|
||||||
|
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
||||||
|
void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
78
lib/spells/adventure/ScuttleBoatMechanics.cpp
Normal file
78
lib/spells/adventure/ScuttleBoatMechanics.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* ScuttleBoatMechanics.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 "ScuttleBoatMechanics.h"
|
||||||
|
|
||||||
|
#include "../CSpellHandler.h"
|
||||||
|
|
||||||
|
#include "../../callback/IGameInfoCallback.h"
|
||||||
|
#include "../../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../mapping/CMap.h"
|
||||||
|
#include "../../networkPacks/PacksForClient.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
ScuttleBoatMechanics::ScuttleBoatMechanics(const CSpell * s)
|
||||||
|
: AdventureSpellMechanics(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScuttleBoatMechanics::canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
|
||||||
|
{
|
||||||
|
if(!cb->isInTheMap(pos))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(caster->getHeroCaster())
|
||||||
|
{
|
||||||
|
int3 casterPosition = caster->getHeroCaster()->getSightCenter();
|
||||||
|
|
||||||
|
if(!isInScreenRange(casterPosition, pos))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!cb->isVisibleFor(pos, caster->getCasterOwner()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const TerrainTile * t = cb->getTile(pos);
|
||||||
|
if(!t || t->visitableObjects.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const CGObjectInstance * topObject = cb->getObj(t->visitableObjects.back());
|
||||||
|
if(topObject->ID != Obj::BOAT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
||||||
|
//check if spell works at all
|
||||||
|
if(env->getRNG()->nextInt(0, 99) >= owner->getLevelPower(schoolLevel)) //power is % chance of success
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed
|
||||||
|
parameters.caster->getCasterName(iw.text);
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TerrainTile & t = env->getMap()->getTile(parameters.pos);
|
||||||
|
|
||||||
|
RemoveObject ro;
|
||||||
|
ro.initiator = parameters.caster->getCasterOwner();
|
||||||
|
ro.objectID = t.visitableObjects.back();
|
||||||
|
env->apply(ro);
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
28
lib/spells/adventure/ScuttleBoatMechanics.h
Normal file
28
lib/spells/adventure/ScuttleBoatMechanics.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* ScuttleBoatMechanics.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AdventureSpellMechanics.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class ScuttleBoatMechanics final : public AdventureSpellMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScuttleBoatMechanics(const CSpell * s);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const override;
|
||||||
|
|
||||||
|
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
111
lib/spells/adventure/SummonBoatMechanics.cpp
Normal file
111
lib/spells/adventure/SummonBoatMechanics.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* SummonBoatMechanics.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 "SummonBoatMechanics.h"
|
||||||
|
|
||||||
|
#include "../CSpellHandler.h"
|
||||||
|
|
||||||
|
#include "../../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../mapObjects/MiscObjects.h"
|
||||||
|
#include "../../mapping/CMap.h"
|
||||||
|
#include "../../networkPacks/PacksForClient.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
SummonBoatMechanics::SummonBoatMechanics(const CSpell * s)
|
||||||
|
: AdventureSpellMechanics(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SummonBoatMechanics::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
||||||
|
{
|
||||||
|
if(!caster->getHeroCaster())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(caster->getHeroCaster()->inBoat())
|
||||||
|
{
|
||||||
|
MetaString message = MetaString::createFromTextID("core.genrltxt.333");
|
||||||
|
caster->getCasterName(message);
|
||||||
|
problem.add(std::move(message));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int3 summonPos = caster->getHeroCaster()->bestLocation();
|
||||||
|
|
||||||
|
if(summonPos.x < 0)
|
||||||
|
{
|
||||||
|
MetaString message = MetaString::createFromTextID("core.genrltxt.334");
|
||||||
|
caster->getCasterName(message);
|
||||||
|
problem.add(std::move(message));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
||||||
|
|
||||||
|
//check if spell works at all
|
||||||
|
if(env->getRNG()->nextInt(0, 99) >= owner->getLevelPower(schoolLevel)) //power is % chance of success
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
|
||||||
|
parameters.caster->getCasterName(iw.text);
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//try to find unoccupied boat to summon
|
||||||
|
const CGBoat * nearest = nullptr;
|
||||||
|
double dist = 0;
|
||||||
|
for(const auto & b : env->getMap()->getObjects<CGBoat>())
|
||||||
|
{
|
||||||
|
if(b->getBoardedHero() || b->layer != EPathfindingLayer::SAIL)
|
||||||
|
continue; //we're looking for unoccupied boat
|
||||||
|
|
||||||
|
double nDist = b->visitablePos().dist2d(parameters.caster->getHeroCaster()->visitablePos());
|
||||||
|
if(!nearest || nDist < dist) //it's first boat or closer than previous
|
||||||
|
{
|
||||||
|
nearest = b;
|
||||||
|
dist = nDist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int3 summonPos = parameters.caster->getHeroCaster()->bestLocation();
|
||||||
|
|
||||||
|
if(nullptr != nearest) //we found boat to summon
|
||||||
|
{
|
||||||
|
ChangeObjPos cop;
|
||||||
|
cop.objid = nearest->id;
|
||||||
|
cop.nPos = summonPos;
|
||||||
|
cop.initiator = parameters.caster->getCasterOwner();
|
||||||
|
env->apply(cop);
|
||||||
|
}
|
||||||
|
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 335); //There are no boats to summon.
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
else //create boat
|
||||||
|
{
|
||||||
|
env->createBoat(summonPos, BoatId::NECROPOLIS, parameters.caster->getCasterOwner());
|
||||||
|
}
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
28
lib/spells/adventure/SummonBoatMechanics.h
Normal file
28
lib/spells/adventure/SummonBoatMechanics.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* SummonBoatMechanics.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AdventureSpellMechanics.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class SummonBoatMechanics final : public AdventureSpellMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SummonBoatMechanics(const CSpell * s);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const override;
|
||||||
|
|
||||||
|
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
299
lib/spells/adventure/TownPortalMechanics.cpp
Normal file
299
lib/spells/adventure/TownPortalMechanics.cpp
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
* TownPortalMechanics.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 "TownPortalMechanics.h"
|
||||||
|
|
||||||
|
#include "../CSpellHandler.h"
|
||||||
|
|
||||||
|
#include "../../CPlayerState.h"
|
||||||
|
#include "../../IGameSettings.h"
|
||||||
|
#include "../../callback/IGameInfoCallback.h"
|
||||||
|
#include "../../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../mapObjects/CGTownInstance.h"
|
||||||
|
#include "../../mapping/CMap.h"
|
||||||
|
#include "../../networkPacks/PacksForClient.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
TownPortalMechanics::TownPortalMechanics(const CSpell * s):
|
||||||
|
AdventureSpellMechanics(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
const CGTownInstance * destination = nullptr;
|
||||||
|
const int moveCost = movementCost(env, parameters);
|
||||||
|
|
||||||
|
if(!parameters.caster->getHeroCaster())
|
||||||
|
{
|
||||||
|
env->complain("Not a hero caster!");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(parameters.caster->getSpellSchoolLevel(owner) < 2)
|
||||||
|
{
|
||||||
|
std::vector<const CGTownInstance *> pool = getPossibleTowns(env, parameters);
|
||||||
|
destination = findNearestTown(env, parameters, pool);
|
||||||
|
|
||||||
|
if(nullptr == destination)
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
|
||||||
|
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
|
||||||
|
if(destination->getVisitingHero())
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 123);
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::CANCEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(env->getMap()->isInTheMap(parameters.pos))
|
||||||
|
{
|
||||||
|
const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
|
||||||
|
|
||||||
|
ObjectInstanceID topObjID = tile.topVisitableObj(false);
|
||||||
|
const CGObjectInstance * topObj = env->getMap()->getObject(topObjID);
|
||||||
|
|
||||||
|
if(!topObj)
|
||||||
|
{
|
||||||
|
env->complain("Destination tile is not visitable" + parameters.pos.toString());
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
else if(topObj->ID == Obj::HERO)
|
||||||
|
{
|
||||||
|
env->complain("Can't teleport to occupied town at " + parameters.pos.toString());
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
else if(topObj->ID != Obj::TOWN)
|
||||||
|
{
|
||||||
|
env->complain("No town at destination tile " + parameters.pos.toString());
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
destination = dynamic_cast<const CGTownInstance *>(topObj);
|
||||||
|
|
||||||
|
if(nullptr == destination)
|
||||||
|
{
|
||||||
|
env->complain("[Internal error] invalid town object at " + parameters.pos.toString());
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto relations = env->getCb()->getPlayerRelations(destination->tempOwner, parameters.caster->getCasterOwner());
|
||||||
|
|
||||||
|
if(relations == PlayerRelations::ENEMIES)
|
||||||
|
{
|
||||||
|
env->complain("Can't teleport to enemy!");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
|
||||||
|
{
|
||||||
|
env->complain("This hero has not enough movement points!");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(destination->getVisitingHero())
|
||||||
|
{
|
||||||
|
env->complain("[Internal error] Can't teleport to occupied town");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
env->complain("Invalid destination tile");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TerrainTile & from = env->getMap()->getTile(parameters.caster->getHeroCaster()->visitablePos());
|
||||||
|
const TerrainTile & dest = env->getMap()->getTile(destination->visitablePos());
|
||||||
|
|
||||||
|
if(!dest.entrableTerrain(&from))
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 135);
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TownPortalMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
const int moveCost = movementCost(env, parameters);
|
||||||
|
const CGTownInstance * destination = nullptr;
|
||||||
|
|
||||||
|
if(parameters.caster->getSpellSchoolLevel(owner) < 2)
|
||||||
|
{
|
||||||
|
std::vector<const CGTownInstance *> pool = getPossibleTowns(env, parameters);
|
||||||
|
destination = findNearestTown(env, parameters, pool);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const TerrainTile & tile = env->getMap()->getTile(parameters.pos);
|
||||||
|
ObjectInstanceID topObjID = tile.topVisitableObj(false);
|
||||||
|
const CGObjectInstance * topObj = env->getMap()->getObject(topObjID);
|
||||||
|
|
||||||
|
destination = dynamic_cast<const CGTownInstance *>(topObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(destination->visitablePos()), EMovementMode::TOWN_PORTAL))
|
||||||
|
{
|
||||||
|
SetMovePoints smp;
|
||||||
|
smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
||||||
|
smp.val = std::max<ui32>(0, parameters.caster->getHeroCaster()->movementPointsRemaining() - moveCost);
|
||||||
|
env->apply(smp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
std::vector<const CGTownInstance *> towns = getPossibleTowns(env, parameters);
|
||||||
|
|
||||||
|
if(!parameters.caster->getHeroCaster())
|
||||||
|
{
|
||||||
|
env->complain("Not a hero caster!");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(towns.empty())
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 124);
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int moveCost = movementCost(env, parameters);
|
||||||
|
|
||||||
|
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 125);
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!parameters.pos.isValid() && parameters.caster->getSpellSchoolLevel(owner) >= 2)
|
||||||
|
{
|
||||||
|
auto queryCallback = [this, env, parameters](std::optional<int32_t> reply) -> void
|
||||||
|
{
|
||||||
|
if(reply.has_value())
|
||||||
|
{
|
||||||
|
ObjectInstanceID townId(*reply);
|
||||||
|
|
||||||
|
const CGObjectInstance * o = env->getCb()->getObj(townId, true);
|
||||||
|
if(o == nullptr)
|
||||||
|
{
|
||||||
|
env->complain("Invalid object instance selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!dynamic_cast<const CGTownInstance *>(o))
|
||||||
|
{
|
||||||
|
env->complain("Object instance is not town");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdventureSpellCastParameters p;
|
||||||
|
p.caster = parameters.caster;
|
||||||
|
p.pos = o->visitablePos();
|
||||||
|
performCast(env, p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MapObjectSelectDialog request;
|
||||||
|
|
||||||
|
for(const auto * t : towns)
|
||||||
|
{
|
||||||
|
if(t->getVisitingHero() == nullptr) //empty town
|
||||||
|
request.objects.push_back(t->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(request.objects.empty())
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
|
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 124);
|
||||||
|
env->apply(iw);
|
||||||
|
return ESpellCastResult::CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.player = parameters.caster->getCasterOwner();
|
||||||
|
request.title.appendLocalString(EMetaText::JK_TXT, 40);
|
||||||
|
request.description.appendLocalString(EMetaText::JK_TXT, 41);
|
||||||
|
request.icon = Component(ComponentType::SPELL, owner->id);
|
||||||
|
|
||||||
|
env->genericQuery(&request, request.player, queryCallback);
|
||||||
|
|
||||||
|
return ESpellCastResult::PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CGTownInstance * TownPortalMechanics::findNearestTown(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const std::vector <const CGTownInstance *> & pool) const
|
||||||
|
{
|
||||||
|
if(pool.empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if(!parameters.caster->getHeroCaster())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto nearest = pool.cbegin(); //nearest town's iterator
|
||||||
|
si32 dist = (*nearest)->visitablePos().dist2dSQ(parameters.caster->getHeroCaster()->visitablePos());
|
||||||
|
|
||||||
|
for(auto i = nearest + 1; i != pool.cend(); ++i)
|
||||||
|
{
|
||||||
|
si32 curDist = (*i)->visitablePos().dist2dSQ(parameters.caster->getHeroCaster()->visitablePos());
|
||||||
|
|
||||||
|
if(curDist < dist)
|
||||||
|
{
|
||||||
|
nearest = i;
|
||||||
|
dist = curDist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const CGTownInstance *> TownPortalMechanics::getPossibleTowns(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
std::vector<const CGTownInstance *> ret;
|
||||||
|
|
||||||
|
const TeamState * team = env->getCb()->getPlayerTeam(parameters.caster->getCasterOwner());
|
||||||
|
|
||||||
|
for(const auto & color : team->players)
|
||||||
|
{
|
||||||
|
for(auto currTown : env->getCb()->getPlayerState(color)->getTowns())
|
||||||
|
{
|
||||||
|
ret.push_back(currTown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t TownPortalMechanics::movementCost(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
if(parameters.caster != parameters.caster->getHeroCaster()) //if caster is not hero
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int baseMovementCost = env->getCb()->getSettings().getInteger(EGameSettings::HEROES_MOVEMENT_COST_BASE);
|
||||||
|
return baseMovementCost * ((parameters.caster->getSpellSchoolLevel(owner) >= 3) ? 2 : 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
35
lib/spells/adventure/TownPortalMechanics.h
Normal file
35
lib/spells/adventure/TownPortalMechanics.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* TownPortalMechanics.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AdventureSpellMechanics.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class CGTownInstance;
|
||||||
|
|
||||||
|
class TownPortalMechanics final : public AdventureSpellMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TownPortalMechanics(const CSpell * s);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
||||||
|
ESpellCastResult beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
||||||
|
void endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const CGTownInstance * findNearestTown(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const std::vector<const CGTownInstance *> & pool) const;
|
||||||
|
int32_t movementCost(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
||||||
|
std::vector<const CGTownInstance *> getPossibleTowns(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
90
lib/spells/adventure/ViewWorldMechanics.cpp
Normal file
90
lib/spells/adventure/ViewWorldMechanics.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* ViewWorldMechanics.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 "ViewWorldMechanics.h"
|
||||||
|
|
||||||
|
#include "../CSpellHandler.h"
|
||||||
|
|
||||||
|
#include "../../CPlayerState.h"
|
||||||
|
#include "../../callback/IGameInfoCallback.h"
|
||||||
|
#include "../../mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../mapping/CMap.h"
|
||||||
|
#include "../../networkPacks/PacksForClient.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
ViewMechanics::ViewMechanics(const CSpell * s):
|
||||||
|
AdventureSpellMechanics(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
|
{
|
||||||
|
ShowWorldViewEx pack;
|
||||||
|
|
||||||
|
pack.player = parameters.caster->getCasterOwner();
|
||||||
|
|
||||||
|
const auto spellLevel = parameters.caster->getSpellSchoolLevel(owner);
|
||||||
|
|
||||||
|
const auto & fowMap = env->getCb()->getPlayerTeam(parameters.caster->getCasterOwner())->fogOfWarMap;
|
||||||
|
|
||||||
|
for(const auto & obj : env->getMap()->getObjects())
|
||||||
|
{
|
||||||
|
//deleted object remain as empty pointer
|
||||||
|
if(obj && filterObject(obj, spellLevel))
|
||||||
|
{
|
||||||
|
ObjectPosInfo posInfo(obj);
|
||||||
|
|
||||||
|
if(fowMap[posInfo.pos.z][posInfo.pos.x][posInfo.pos.y] == 0)
|
||||||
|
pack.objectPositions.push_back(posInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pack.showTerrain = showTerrain(spellLevel);
|
||||||
|
|
||||||
|
env->apply(pack);
|
||||||
|
|
||||||
|
return ESpellCastResult::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
///ViewAirMechanics
|
||||||
|
ViewAirMechanics::ViewAirMechanics(const CSpell * s)
|
||||||
|
: ViewMechanics(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ViewAirMechanics::filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const
|
||||||
|
{
|
||||||
|
return (obj->ID == Obj::ARTIFACT) || (spellLevel > 1 && obj->ID == Obj::HERO) || (spellLevel > 2 && obj->ID == Obj::TOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ViewAirMechanics::showTerrain(const int32_t spellLevel) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///ViewEarthMechanics
|
||||||
|
ViewEarthMechanics::ViewEarthMechanics(const CSpell * s)
|
||||||
|
: ViewMechanics(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ViewEarthMechanics::filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const
|
||||||
|
{
|
||||||
|
return (obj->ID == Obj::RESOURCE) || (spellLevel > 1 && obj->ID == Obj::MINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ViewEarthMechanics::showTerrain(const int32_t spellLevel) const
|
||||||
|
{
|
||||||
|
return spellLevel > 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
48
lib/spells/adventure/ViewWorldMechanics.h
Normal file
48
lib/spells/adventure/ViewWorldMechanics.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* ViewWorldMechanics.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AdventureSpellMechanics.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class ViewMechanics : public AdventureSpellMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ViewMechanics(const CSpell * s);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ESpellCastResult applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const override;
|
||||||
|
virtual bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const = 0;
|
||||||
|
virtual bool showTerrain(const int32_t spellLevel) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ViewAirMechanics final : public ViewMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ViewAirMechanics(const CSpell * s);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override;
|
||||||
|
bool showTerrain(const int32_t spellLevel) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ViewEarthMechanics final : public ViewMechanics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ViewEarthMechanics(const CSpell * s);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const override;
|
||||||
|
bool showTerrain(const int32_t spellLevel) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -11,7 +11,6 @@
|
|||||||
#include "MetaString.h"
|
#include "MetaString.h"
|
||||||
|
|
||||||
#include "CCreatureHandler.h"
|
#include "CCreatureHandler.h"
|
||||||
#include "CCreatureSet.h"
|
|
||||||
#include "entities/artifact/CArtifact.h"
|
#include "entities/artifact/CArtifact.h"
|
||||||
#include "entities/faction/CFaction.h"
|
#include "entities/faction/CFaction.h"
|
||||||
#include "entities/hero/CHero.h"
|
#include "entities/hero/CHero.h"
|
||||||
@ -19,6 +18,7 @@
|
|||||||
#include "CSkillHandler.h"
|
#include "CSkillHandler.h"
|
||||||
#include "GameConstants.h"
|
#include "GameConstants.h"
|
||||||
#include "GameLibrary.h"
|
#include "GameLibrary.h"
|
||||||
|
#include "mapObjects/army/CStackBasicDescriptor.h"
|
||||||
#include "mapObjectConstructors/CObjectClassesHandler.h"
|
#include "mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "spells/CSpellHandler.h"
|
#include "spells/CSpellHandler.h"
|
||||||
#include "serializer/JsonSerializeFormat.h"
|
#include "serializer/JsonSerializeFormat.h"
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "CCreatureHandler.h"
|
#include "CCreatureHandler.h"
|
||||||
|
|
||||||
#include "../../lib/GameLibrary.h"
|
#include "../../lib/GameLibrary.h"
|
||||||
|
#include "../../lib/mapObjects/army/CStackInstance.h"
|
||||||
|
|
||||||
ArmyWidget::ArmyWidget(CArmedInstance & a, QWidget *parent) :
|
ArmyWidget::ArmyWidget(CArmedInstance & a, QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "../StdInc.h"
|
#include "../StdInc.h"
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include "baseinspectoritemdelegate.h"
|
#include "baseinspectoritemdelegate.h"
|
||||||
#include "../lib/mapObjects/CArmedInstance.h"
|
#include "../lib/mapObjects/army/CArmedInstance.h"
|
||||||
|
|
||||||
const int TOTAL_SLOTS = 7;
|
const int TOTAL_SLOTS = 7;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "mapsettings/eventsettings.h"
|
#include "mapsettings/eventsettings.h"
|
||||||
#include "../../lib/constants/NumericConstants.h"
|
#include "../../lib/constants/NumericConstants.h"
|
||||||
#include "../../lib/constants/StringConstants.h"
|
#include "../../lib/constants/StringConstants.h"
|
||||||
|
#include "../../lib/mapping/CCastleEvent.h"
|
||||||
|
|
||||||
TownEventsWidget::TownEventsWidget(CGTownInstance & town, QWidget * parent) :
|
TownEventsWidget::TownEventsWidget(CGTownInstance & town, QWidget * parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "../StdInc.h"
|
#include "../StdInc.h"
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include "baseinspectoritemdelegate.h"
|
#include "baseinspectoritemdelegate.h"
|
||||||
#include "../lib/mapping/CMapDefines.h"
|
|
||||||
#include "../lib/mapObjects/CGTownInstance.h"
|
#include "../lib/mapObjects/CGTownInstance.h"
|
||||||
#include "../mapcontroller.h"
|
#include "../mapcontroller.h"
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "timedevent.h"
|
#include "timedevent.h"
|
||||||
#include "ui_eventsettings.h"
|
#include "ui_eventsettings.h"
|
||||||
#include "../mapcontroller.h"
|
#include "../mapcontroller.h"
|
||||||
#include "../../lib/mapping/CMapDefines.h"
|
|
||||||
#include "../../lib/constants/NumericConstants.h"
|
#include "../../lib/constants/NumericConstants.h"
|
||||||
#include "../../lib/constants/StringConstants.h"
|
#include "../../lib/constants/StringConstants.h"
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include "../LuaWrapper.h"
|
#include "../LuaWrapper.h"
|
||||||
|
|
||||||
#include "../../../lib/CCreatureSet.h"
|
#include "../../../lib/mapObjects/army/CStackInstance.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "../lib/CConfigHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
#include "../lib/CCreatureHandler.h"
|
#include "../lib/CCreatureHandler.h"
|
||||||
#include "../lib/CCreatureSet.h"
|
|
||||||
#include "../lib/CPlayerState.h"
|
#include "../lib/CPlayerState.h"
|
||||||
#include "../lib/CSoundBase.h"
|
#include "../lib/CSoundBase.h"
|
||||||
#include "../lib/GameConstants.h"
|
#include "../lib/GameConstants.h"
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "processors/PlayerMessageProcessor.h"
|
#include "processors/PlayerMessageProcessor.h"
|
||||||
|
|
||||||
#include "../lib/CThreadHelper.h"
|
#include "../lib/CThreadHelper.h"
|
||||||
|
#include "../lib/GameLibrary.h"
|
||||||
#include "../lib/campaign/CampaignState.h"
|
#include "../lib/campaign/CampaignState.h"
|
||||||
#include "../lib/entities/hero/CHeroHandler.h"
|
#include "../lib/entities/hero/CHeroHandler.h"
|
||||||
#include "../lib/entities/hero/CHeroClass.h"
|
#include "../lib/entities/hero/CHeroClass.h"
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "CGameHandler.h"
|
#include "CGameHandler.h"
|
||||||
|
|
||||||
#include "../lib/StartInfo.h"
|
#include "../lib/StartInfo.h"
|
||||||
|
#include "../lib/GameLibrary.h"
|
||||||
|
|
||||||
#include "../lib/CRandomGenerator.h"
|
#include "../lib/CRandomGenerator.h"
|
||||||
#include "../lib/campaign/CampaignState.h"
|
#include "../lib/campaign/CampaignState.h"
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "../queries/QueriesProcessor.h"
|
#include "../queries/QueriesProcessor.h"
|
||||||
#include "../queries/BattleQueries.h"
|
#include "../queries/BattleQueries.h"
|
||||||
|
|
||||||
|
#include "../../lib/GameLibrary.h"
|
||||||
#include "../../lib/CStack.h"
|
#include "../../lib/CStack.h"
|
||||||
#include "../../lib/CPlayerState.h"
|
#include "../../lib/CPlayerState.h"
|
||||||
#include "../../lib/IGameSettings.h"
|
#include "../../lib/IGameSettings.h"
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "../../lib/entities/hero/CHero.h"
|
#include "../../lib/entities/hero/CHero.h"
|
||||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../lib/mapping/TerrainTile.h"
|
||||||
#include "../../lib/networkPacks/PacksForClient.h"
|
#include "../../lib/networkPacks/PacksForClient.h"
|
||||||
#include "../../lib/gameState/CGameState.h"
|
#include "../../lib/gameState/CGameState.h"
|
||||||
#include "../../lib/gameState/TavernHeroesPool.h"
|
#include "../../lib/gameState/TavernHeroesPool.h"
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||||
#include "../../lib/mapObjects/IOwnableObject.h"
|
#include "../../lib/mapObjects/IOwnableObject.h"
|
||||||
#include "../../lib/mapping/CMap.h"
|
#include "../../lib/mapping/CMap.h"
|
||||||
|
#include "../../lib/mapping/CCastleEvent.h"
|
||||||
#include "../../lib/networkPacks/PacksForClient.h"
|
#include "../../lib/networkPacks/PacksForClient.h"
|
||||||
#include "../../lib/networkPacks/StackLocation.h"
|
#include "../../lib/networkPacks/StackLocation.h"
|
||||||
#include "../../lib/pathfinder/TurnInfo.h"
|
#include "../../lib/pathfinder/TurnInfo.h"
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user