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

Optimize Unit::getHexes method

This commit is contained in:
Ivan Savenko 2025-01-10 15:07:59 +00:00
parent 5375d61d1b
commit 3b35c679ce
5 changed files with 63 additions and 38 deletions

View File

@ -35,6 +35,7 @@ CStack::CStack(const CStackInstance * Base, const PlayerColor & O, int I, Battle
side(Side)
{
health.init(); //???
doubleWideCached = battle::CUnitState::doubleWide();
}
CStack::CStack():
@ -55,6 +56,7 @@ CStack::CStack(const CStackBasicDescriptor * stack, const PlayerColor & O, int I
side(Side)
{
health.init(); //???
doubleWideCached = battle::CUnitState::doubleWide();
}
void CStack::localInit(BattleInfo * battleInfo)
@ -404,4 +406,30 @@ void CStack::spendMana(ServerCallback * server, const int spellCost) const
server->apply(ssp);
}
void CStack::postDeserialize(const CArmedInstance * army, const SlotID & extSlot)
{
if(extSlot == SlotID::COMMANDER_SLOT_PLACEHOLDER)
{
const auto * hero = dynamic_cast<const CGHeroInstance *>(army);
assert(hero);
base = hero->commander;
}
else if(slot == SlotID::SUMMONED_SLOT_PLACEHOLDER || slot == SlotID::ARROW_TOWERS_SLOT || slot == SlotID::WAR_MACHINES_SLOT)
{
//no external slot possible, so no base stack
base = nullptr;
}
else if(!army || extSlot == SlotID() || !army->hasStackAtSlot(extSlot))
{
base = nullptr;
logGlobal->warn("%s doesn't have a base stack!", typeID.toEntity(VLC)->getNameSingularTranslated());
}
else
{
base = &army->getStack(extSlot);
}
doubleWideCached = battle::CUnitState::doubleWide();
}
VCMI_LIB_NAMESPACE_END

View File

@ -23,7 +23,7 @@ struct BattleStackAttacked;
class BattleInfo;
//Represents STACK_BATTLE nodes
class DLL_LINKAGE CStack : public CBonusSystemNode, public battle::CUnitState, public battle::IUnitEnvironment
class DLL_LINKAGE CStack final : public CBonusSystemNode, public battle::CUnitState, public battle::IUnitEnvironment
{
private:
ui32 ID = -1; //unique ID of stack
@ -36,6 +36,9 @@ private:
SlotID slot; //slot - position in garrison (may be 255 for neutrals/called creatures)
bool doubleWideCached = false;
void postDeserialize(const CArmedInstance * army, const SlotID & extSlot);
public:
const CStackInstance * base = nullptr; //garrison slot from which stack originates (nullptr for war machines, summoned cres, etc)
@ -77,6 +80,7 @@ public:
BattleSide unitSide() const override;
PlayerColor unitOwner() const override;
SlotID unitSlot() const override;
bool doubleWide() const override { return doubleWideCached;};
std::string getDescription() const override;
@ -119,26 +123,7 @@ public:
h & army;
h & extSlot;
if(extSlot == SlotID::COMMANDER_SLOT_PLACEHOLDER)
{
const auto * hero = dynamic_cast<const CGHeroInstance *>(army);
assert(hero);
base = hero->commander;
}
else if(slot == SlotID::SUMMONED_SLOT_PLACEHOLDER || slot == SlotID::ARROW_TOWERS_SLOT || slot == SlotID::WAR_MACHINES_SLOT)
{
//no external slot possible, so no base stack
base = nullptr;
}
else if(!army || extSlot == SlotID() || !army->hasStackAtSlot(extSlot))
{
base = nullptr;
logGlobal->warn("%s doesn't have a base stack!", typeID.toEntity(VLC)->getNameSingularTranslated());
}
else
{
base = &army->getStack(extSlot);
}
postDeserialize(army, extSlot);
}
}
@ -146,4 +131,4 @@ private:
const BattleInfo * battle; //do not serialize
};
VCMI_LIB_NAMESPACE_END
VCMI_LIB_NAMESPACE_END

View File

@ -269,7 +269,7 @@ private:
void reset();
};
class DLL_LINKAGE CUnitStateDetached : public CUnitState
class DLL_LINKAGE CUnitStateDetached final : public CUnitState
{
public:
explicit CUnitStateDetached(const IUnitInfo * unit_, const IBonusBearer * bonus_);

View File

@ -107,24 +107,34 @@ const BattleHexArray & Unit::getHexes(BattleHex assumedPos) const
return getHexes(assumedPos, doubleWide(), unitSide());
}
BattleHexArray::ArrayOfBattleHexArrays Unit::precomputeUnitHexes(BattleSide side, bool twoHex)
{
BattleHexArray::ArrayOfBattleHexArrays result;
for (BattleHex assumedPos = 0; assumedPos < GameConstants::BFIELD_SIZE; ++assumedPos)
{
BattleHexArray hexes;
hexes.insert(assumedPos);
if(twoHex)
hexes.insert(occupiedHex(assumedPos, twoHex, side));
result[assumedPos.toInt()] = std::move(hexes);
}
return result;
}
const BattleHexArray & Unit::getHexes(BattleHex assumedPos, bool twoHex, BattleSide side)
{
static BattleHexArray::ArrayOfBattleHexArrays precomputed[4];
static const std::array<BattleHexArray::ArrayOfBattleHexArrays, 4> precomputed = {
precomputeUnitHexes(BattleSide::ATTACKER, false),
precomputeUnitHexes(BattleSide::ATTACKER, true),
precomputeUnitHexes(BattleSide::DEFENDER, false),
precomputeUnitHexes(BattleSide::DEFENDER, true),
};
int index = side == BattleSide::ATTACKER ? 0 : 2;
if(!precomputed[index + twoHex][assumedPos.toInt()].empty())
return precomputed[index + twoHex][assumedPos.toInt()];
// first run, compute
BattleHexArray hexes;
hexes.insert(assumedPos);
if(twoHex)
hexes.insert(occupiedHex(assumedPos, twoHex, side));
precomputed[index + twoHex][assumedPos.toInt()] = std::move(hexes);
return precomputed[index + twoHex][assumedPos.toInt()];
}

View File

@ -64,6 +64,8 @@ class CUnitState;
class DLL_LINKAGE Unit : public IUnitInfo, public spells::Caster, public virtual IBonusBearer, public ACreature
{
static BattleHexArray::ArrayOfBattleHexArrays precomputeUnitHexes(BattleSide side, bool twoHex);
public:
virtual ~Unit();