1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-17 20:58:07 +02:00

Code cleanup, fixes to discovered regressions

This commit is contained in:
Ivan Savenko 2025-01-05 15:41:42 +00:00
parent 83b9a8d750
commit 73d1675ae3
12 changed files with 75 additions and 80 deletions

View File

@ -26,6 +26,7 @@ public:
virtual ui32 getMovementRange(int turn) const; //get speed (in moving tiles) of creature with all modificators
virtual ui32 getMovementRange() const; //get speed (in moving tiles) of creature with all modificators
virtual ui32 getMaxHealth() const; //get max HP of stack with all modifiers
virtual int32_t getInitiative(int turn = 0) const;
};
template <typename IdType>

View File

@ -152,6 +152,19 @@ ui32 ACreature::getMovementRange() const
return getBonusBearer()->valOfBonuses(BonusType::STACKS_SPEED);
}
int32_t ACreature::getInitiative(int turn) const
{
if (turn == 0)
{
return getBonusBearer()->valOfBonuses(BonusType::STACKS_SPEED);
}
else
{
const std::string cachingStrSS = "type_STACKS_SPEED_turns_" + std::to_string(turn);
return getBonusBearer()->valOfBonuses(Selector::type()(BonusType::STACKS_SPEED).And(Selector::turns(turn)), cachingStrSS);
}
}
ui32 ACreature::getMovementRange(int turn) const
{
if (turn == 0)

View File

@ -335,7 +335,7 @@ CUnitState::CUnitState():
shots(this),
stackSpeedPerTurn(this, Selector::type()(BonusType::STACKS_SPEED), BonusCacheMode::VALUE),
immobilizedPerTurn(this, Selector::type()(BonusType::SIEGE_WEAPON).Or(Selector::type()(BonusType::BIND_EFFECT)), BonusCacheMode::PRESENCE),
bonusCache(this, generateBonusSelectors()),
bonusCache(this),
cloneID(-1)
{
@ -933,38 +933,6 @@ void CUnitState::onRemoved()
ghost = true;
}
const UnitBonusValuesProxy::SelectorsArray * CUnitState::generateBonusSelectors()
{
static const CSelector additionalAttack = Selector::type()(BonusType::ADDITIONAL_ATTACK);
static const CSelector selectorMelee = Selector::effectRange()(BonusLimitEffect::NO_LIMIT).Or(Selector::effectRange()(BonusLimitEffect::ONLY_MELEE_FIGHT));
static const CSelector selectorRanged = Selector::effectRange()(BonusLimitEffect::NO_LIMIT).Or(Selector::effectRange()(BonusLimitEffect::ONLY_DISTANCE_FIGHT));
static const CSelector minDamage = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin));
static const CSelector maxDamage = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax));
static const CSelector attack = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK));
static const CSelector defence = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE));
static const UnitBonusValuesProxy::SelectorsArray selectors = {
additionalAttack.And(selectorMelee), //TOTAL_ATTACKS_MELEE,
additionalAttack.And(selectorRanged), //TOTAL_ATTACKS_RANGED,
minDamage.And(selectorMelee), //MIN_DAMAGE_MELEE,
minDamage.And(selectorRanged), //MIN_DAMAGE_RANGED,
maxDamage.And(selectorMelee), //MAX_DAMAGE_MELEE,
maxDamage.And(selectorRanged), //MAX_DAMAGE_RANGED,
attack.And(selectorRanged),//ATTACK_MELEE,
attack.And(selectorRanged),//ATTACK_RANGED,
defence.And(selectorRanged),//DEFENCE_MELEE,
defence.And(selectorRanged),//DEFENCE_RANGED,
Selector::type()(BonusType::IN_FRENZY),//IN_FRENZY,
Selector::type()(BonusType::FORGETFULL),//FORGETFULL,
Selector::type()(BonusType::HYPNOTIZED),//HYPNOTIZED,
Selector::type()(BonusType::FREE_SHOOTING).Or(Selector::type()(BonusType::SIEGE_WEAPON)),//HAS_FREE_SHOOTING,
Selector::type()(BonusType::STACK_HEALTH),//STACK_HEALTH,
Selector::type()(BonusType::NONE).And(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(SpellID(SpellID::CLONE))))
};
return &selectors;
}
CUnitStateDetached::CUnitStateDetached(const IUnitInfo * unit_, const IBonusBearer * bonus_):
unit(unit_),
bonus(bonus_)

View File

@ -260,8 +260,6 @@ public:
void onRemoved();
private:
static const UnitBonusValuesProxy::SelectorsArray * generateBonusSelectors();
const IUnitEnvironment * env;
BonusCachePerTurn immobilizedPerTurn;

View File

@ -115,8 +115,6 @@ public:
virtual BattleHex getPosition() const = 0;
virtual void setPosition(BattleHex hex) = 0;
virtual int32_t getInitiative(int turn = 0) const = 0;
virtual bool canMove(int turn = 0) const = 0; //if stack can move
virtual bool defended(int turn = 0) const = 0;
virtual bool moved(int turn = 0) const = 0; //if stack was already moved this turn

View File

@ -43,7 +43,7 @@ int BonusCacheBase::getBonusValueImpl(BonusCacheEntry & currentValue, const CSel
}
}
BonusValueCache::BonusValueCache(const IBonusBearer * target, const CSelector selector)
BonusValueCache::BonusValueCache(const IBonusBearer * target, const CSelector & selector)
:BonusCacheBase(target),selector(selector)
{}
@ -177,4 +177,36 @@ int BonusCachePerTurn::getValue(int turns) const
}
}
const UnitBonusValuesProxy::SelectorsArray * UnitBonusValuesProxy::generateSelectors()
{
static const CSelector additionalAttack = Selector::type()(BonusType::ADDITIONAL_ATTACK);
static const CSelector selectorMelee = Selector::effectRange()(BonusLimitEffect::NO_LIMIT).Or(Selector::effectRange()(BonusLimitEffect::ONLY_MELEE_FIGHT));
static const CSelector selectorRanged = Selector::effectRange()(BonusLimitEffect::NO_LIMIT).Or(Selector::effectRange()(BonusLimitEffect::ONLY_DISTANCE_FIGHT));
static const CSelector minDamage = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin));
static const CSelector maxDamage = Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageBoth).Or(Selector::typeSubtype(BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax));
static const CSelector attack = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK));
static const CSelector defence = Selector::typeSubtype(BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE));
static const UnitBonusValuesProxy::SelectorsArray selectors = {
additionalAttack.And(selectorMelee), //TOTAL_ATTACKS_MELEE,
additionalAttack.And(selectorRanged), //TOTAL_ATTACKS_RANGED,
minDamage.And(selectorMelee), //MIN_DAMAGE_MELEE,
minDamage.And(selectorRanged), //MIN_DAMAGE_RANGED,
maxDamage.And(selectorMelee), //MAX_DAMAGE_MELEE,
maxDamage.And(selectorRanged), //MAX_DAMAGE_RANGED,
attack.And(selectorRanged),//ATTACK_MELEE,
attack.And(selectorRanged),//ATTACK_RANGED,
defence.And(selectorRanged),//DEFENCE_MELEE,
defence.And(selectorRanged),//DEFENCE_RANGED,
Selector::type()(BonusType::IN_FRENZY),//IN_FRENZY,
Selector::type()(BonusType::FORGETFULL),//FORGETFULL,
Selector::type()(BonusType::HYPNOTIZED),//HYPNOTIZED,
Selector::type()(BonusType::FREE_SHOOTING).Or(Selector::type()(BonusType::SIEGE_WEAPON)),//HAS_FREE_SHOOTING,
Selector::type()(BonusType::STACK_HEALTH),//STACK_HEALTH,
Selector::type()(BonusType::NONE).And(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(SpellID(SpellID::CLONE))))
};
return &selectors;
}
VCMI_LIB_NAMESPACE_END

View File

@ -45,7 +45,7 @@ class BonusValueCache : public BonusCacheBase
CSelector selector;
mutable BonusCacheEntry value;
public:
BonusValueCache(const IBonusBearer * target, const CSelector selector);
BonusValueCache(const IBonusBearer * target, const CSelector & selector);
int getValue() const;
bool hasBonus() const;
};
@ -112,8 +112,8 @@ public:
using SelectorsArray = BonusValuesArrayCache<KEYS_COUNT>::SelectorsArray;
UnitBonusValuesProxy(const IBonusBearer * Target, const SelectorsArray * selectors):
cache(Target, selectors)
UnitBonusValuesProxy(const IBonusBearer * Target):
cache(Target, generateSelectors())
{}
int getBonusValue(ECacheKeys which) const
@ -129,6 +129,8 @@ public:
}
private:
const SelectorsArray * generateSelectors();
BonusValuesArrayCache<KEYS_COUNT> cache;
};

View File

@ -82,7 +82,7 @@ ui32 CGHeroInstance::getTileMovementCost(const TerrainTile & dest, const Terrain
{
ret = from.getRoad()->movementCost;
}
else if(ti->hasNoTerrainPenalty(from.getTerrainID())) //no special movement bonus
else if(!ti->hasNoTerrainPenalty(from.getTerrainID())) //no special movement bonus
{
ret = VLC->terrainTypeHandler->getById(from.getTerrainID())->moveCost;
ret -= ti->getRoughTerrainDiscountValue();
@ -235,22 +235,19 @@ int CGHeroInstance::movementPointsLimit(bool onLand) const
int CGHeroInstance::getLowestCreatureSpeed() const
{
static const CSelector selectorSTACKS_SPEED = Selector::type()(BonusType::STACKS_SPEED);
static const std::string cachingStr = "type_" + std::to_string(static_cast<si32>(BonusType::STACKS_SPEED));
if(stacksCount() != 0)
{
int minimalSpeed = std::numeric_limits<int>::max();
//TODO? should speed modifiers (eg from artifacts) affect hero movement?
for(const auto & slot : Slots())
minimalSpeed = std::min(minimalSpeed, slot.second->valOfBonuses(selectorSTACKS_SPEED, cachingStr));
minimalSpeed = std::min(minimalSpeed, slot.second->getInitiative());
return minimalSpeed;
}
else
{
if(commander && commander->alive)
return commander->valOfBonuses(selectorSTACKS_SPEED, cachingStr);
return commander->getInitiative();
}
return 10;
@ -1348,13 +1345,6 @@ CBonusSystemNode & CGHeroInstance::whereShouldBeAttached(CGameState * gs)
int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark, const TurnInfo * ti) const
{
std::unique_ptr<TurnInfo> turnInfoLocal;
if(!ti)
{
turnInfoLocal = getTurnInfo(0);
ti = turnInfoLocal.get();
}
if(!ti->hasFreeShipBoarding())
return 0; // take all MPs by default

View File

@ -227,7 +227,7 @@ public:
//cached version is much faster, TurnInfo construction is costly
int movementPointsLimitCached(bool onLand, const TurnInfo * ti) const;
int movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark = false, const TurnInfo * ti = nullptr) const;
int movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark, const TurnInfo * ti) const;
std::unique_ptr<TurnInfo> getTurnInfo(int days) const;

View File

@ -572,7 +572,7 @@ void CPathfinderHelper::getNeighbours(
CMap * map = gs->map;
const TerrainType * sourceTerrain = sourceTile.getTerrain();
constexpr std::array dirs = {
static constexpr std::array dirs = {
int3(-1, +1, +0), int3(0, +1, +0), int3(+1, +1, +0),
int3(-1, +0, +0), /* source pos */ int3(+1, +0, +0),
int3(-1, -1, +0), int3(0, -1, +0), int3(+1, -1, +0)
@ -689,19 +689,6 @@ int CPathfinderHelper::getMovementCost(
if (pointsLeft < minimalNextMoveCost)
return remainingMovePoints;
// NeighbourTilesVector vec;
//
// getNeighbours(*dt, dst, vec, ct->isLand(), true);
// for(const auto & elem : vec)
// {
// int fcost = getMovementCost(dst, elem, nullptr, nullptr, pointsLeft, false);
// if(fcost <= pointsLeft)
// {
// return movementCost;
// }
// }
// movementCost = remainingMovePoints;
}
return movementCost;

View File

@ -93,7 +93,6 @@ public:
void updateTurnInfo(const int turn = 0);
bool isLayerAvailable(const EPathfindingLayer & layer) const;
const TurnInfo * getTurnInfo() const;
//bool hasBonusOfType(BonusType type) const;
int getMaxMovePoints(const EPathfindingLayer & layer) const;
TeleporterTilesVector getCastleGates(const PathNodeInfo & source) const;

View File

@ -80,8 +80,8 @@ int TurnInfo::getMovePointsLimitWater() const
}
TurnInfo::TurnInfo(TurnInfoCache * sharedCache, const CGHeroInstance * target, int Turn)
: noterrainPenalty(VLC->terrainTypeHandler->size())
, target(target)
: target(target)
, noterrainPenalty(VLC->terrainTypeHandler->size())
{
CSelector daySelector = Selector::days(Turn);
@ -100,27 +100,27 @@ TurnInfo::TurnInfo(TurnInfoCache * sharedCache, const CGHeroInstance * target, i
{
static const CSelector selector = Selector::type()(BonusType::WATER_WALKING);
const auto & bonuses = sharedCache->waterWalking.getBonusList(target, selector);
waterWalkingTest = bonuses->getFirst(selector) != nullptr;
waterWalkingValue = bonuses->valOfBonuses(selector);
waterWalkingTest = bonuses->getFirst(daySelector) != nullptr;
waterWalkingValue = bonuses->valOfBonuses(daySelector);
}
{
static const CSelector selector = Selector::type()(BonusType::FLYING_MOVEMENT);
const auto & bonuses = sharedCache->flyingMovement.getBonusList(target, selector);
flyingMovementTest = bonuses->getFirst(selector) != nullptr;
flyingMovementValue = bonuses->valOfBonuses(selector);
flyingMovementTest = bonuses->getFirst(daySelector) != nullptr;
flyingMovementValue = bonuses->valOfBonuses(daySelector);
}
{
static const CSelector selector = Selector::type()(BonusType::FREE_SHIP_BOARDING);
const auto & bonuses = sharedCache->freeShipBoarding.getBonusList(target, selector);
freeShipBoardingTest = bonuses->getFirst(selector) != nullptr;
freeShipBoardingTest = bonuses->getFirst(daySelector) != nullptr;
}
{
static const CSelector selector = Selector::type()(BonusType::ROUGH_TERRAIN_DISCOUNT);
const auto & bonuses = sharedCache->roughTerrainDiscount.getBonusList(target, selector);
roughTerrainDiscountValue = bonuses->getFirst(selector) != nullptr;
roughTerrainDiscountValue = bonuses->getFirst(daySelector) != nullptr;
}
{
@ -133,7 +133,7 @@ TurnInfo::TurnInfo(TurnInfoCache * sharedCache, const CGHeroInstance * target, i
else
baseMovementPointsSea = vectorSea.back().Integer();
movePointsLimitWater = bonuses->valOfBonuses(selector, baseMovementPointsSea);
movePointsLimitWater = bonuses->valOfBonuses(daySelector, baseMovementPointsSea);
}
{
@ -146,7 +146,7 @@ TurnInfo::TurnInfo(TurnInfoCache * sharedCache, const CGHeroInstance * target, i
else
baseMovementPointsLand = vectorLand.back().Integer();
movePointsLimitLand = bonuses->valOfBonuses(selector, baseMovementPointsLand);
movePointsLimitLand = bonuses->valOfBonuses(daySelector, baseMovementPointsLand);
}
{
@ -157,6 +157,13 @@ TurnInfo::TurnInfo(TurnInfoCache * sharedCache, const CGHeroInstance * target, i
TerrainId affectedTerrain = bonus->subtype.as<TerrainId>();
noterrainPenalty.at(affectedTerrain.num) = true;
}
const auto nativeTerrain = target->getNativeTerrain();
if (nativeTerrain.hasValue())
noterrainPenalty.at(nativeTerrain.num) = true;
if (nativeTerrain == ETerrainId::ANY_TERRAIN)
boost::range::fill(noterrainPenalty, true);
}
}