1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-15 01:24:45 +02:00

Split CCreatureSet file on .h/.cpp per class basis

This commit is contained in:
Ivan Savenko
2025-07-07 19:12:31 +03:00
parent 2ad186130f
commit 8721bdd728
47 changed files with 899 additions and 753 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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
@ -299,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
@ -564,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
@ -587,6 +590,13 @@ 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/CCastleEvent.h mapping/CCastleEvent.h
mapping/CMapEditManager.h mapping/CMapEditManager.h
@ -758,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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@
*/ */
#pragma once #pragma once
#include "CCreatureSet.h" #include "../mapObjects/army/CStackBasicDescriptor.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@
*/ */
#pragma once #pragma once
#include "CArmedInstance.h" #include "army/CArmedInstance.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN

View File

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

View File

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

View File

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

View File

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

View File

@ -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 "../mapping/TerrainTile.h" #include "../../GameLibrary.h"
#include "../GameLibrary.h" #include "../../gameState/CGameState.h"
#include "../gameState/CGameState.h"
#include "../texts/CGeneralTextHandler.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN

View File

@ -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/CBonusSystemNode.h"
#include "../../bonuses/BonusCache.h"
#include <vcmi/Entity.h>
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN

View File

@ -0,0 +1,79 @@
/*
* 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

View File

@ -0,0 +1,51 @@
/*
* 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

View File

@ -10,22 +10,11 @@
#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
@ -707,483 +696,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

View File

@ -9,205 +9,18 @@
*/ */
#pragma once #pragma once
#include "CCreatureHandler.h" #include "CSimpleArmy.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> #include "serializer/Serializeable.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
class JsonNode; class CStackInstance;
class CCreature;
class CGHeroInstance;
class CArmedInstance; class CArmedInstance;
class CCreatureArtifactSet; class CStackBasicDescriptor;
class JsonSerializeFormat; 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 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 TPairCreatureSlot = std::pair<const CCreature *, SlotID>;
using TMapCreatureSlot = std::map<const CCreature *, SlotID>; using TMapCreatureSlot = std::map<const CCreature *, SlotID>;
@ -219,28 +32,6 @@ struct DLL_LINKAGE CreatureSlotComparer
using TCreatureQueue = std::priority_queue<TPairCreatureSlot, std::vector<TPairCreatureSlot>, CreatureSlotComparer>; 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 namespace NArmyFormation
{ {
static const std::vector<std::string> names{ "wide", "tight" }; static const std::vector<std::string> names{ "wide", "tight" };

View 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

View File

@ -0,0 +1,90 @@
/*
* 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

View File

@ -0,0 +1,64 @@
/*
* 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

View File

@ -0,0 +1,356 @@
/*
* 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

View File

@ -0,0 +1,130 @@
/*
* 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 "mapObjects/CGObjectInstance.h"
#include "entities/artifact/CArtifactSet.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

View File

@ -17,15 +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 "../mapObjects/army/CSimpleArmy.h"
#include "../spells/ViewSpellInt.h" #include "../spells/ViewSpellInt.h"
class CClient; class CClient;

View File

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

View File

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

View File

@ -16,6 +16,8 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
class IObjectInterface; class IObjectInterface;
class IGameEventCallback;
class CArmedInstance;
namespace Rewardable namespace Rewardable
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
class CGHeroInstance; class CGHeroInstance;
class CGObjectInstance; class CGObjectInstance;
class IObjectInterface; class IObjectInterface;
class CArmedInstance;
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END
//Created when player starts turn or when player puts game on [ause //Created when player starts turn or when player puts game on [ause