1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

cast without skip

This commit is contained in:
Laserlicht 2024-09-14 14:49:52 +02:00
parent 75f8614f26
commit 0aaafc4c8a
10 changed files with 38 additions and 1 deletions

View File

@ -171,6 +171,10 @@
"type" : "boolean",
"description" : "If used as creature spell, unit can cast this spell on itself"
},
"canCastWithoutSkip" : {
"type" : "boolean",
"description" : "If used the creature will not skip the turn after casting a spell."
},
"gainChance" : {
"type" : "object",
"description" : "Chance for this spell to appear in Mage Guild of a specific faction",

View File

@ -64,6 +64,9 @@
// If true, then creature capable of casting this spell can cast this spell on itself
// If false, then creature can only cast this spell on other units
"canCastOnSelf" : false,
// If true the creature will not skip the turn after casting a spell
"canCastWithoutSkip": false,
// If true, spell won't be available on a map without water
"onlyOnWaterMap" : true,

View File

@ -45,6 +45,7 @@ public:
virtual bool hasSchool(SpellSchool school) const = 0;
virtual bool canCastOnSelf() const = 0;
virtual bool canCastWithoutSkip() const = 0;
virtual void forEachSchool(const SchoolCallback & cb) const = 0;
virtual int32_t getCost(const int32_t skillLevel) const = 0;

View File

@ -330,6 +330,7 @@ CUnitState::CUnitState():
drainedMana(false),
fear(false),
hadMorale(false),
usedSpell(SpellID::NONE),
ghost(false),
ghostPending(false),
movedThisRound(false),
@ -362,6 +363,7 @@ CUnitState & CUnitState::operator=(const CUnitState & other)
drainedMana = other.drainedMana;
fear = other.fear;
hadMorale = other.hadMorale;
usedSpell = other.usedSpell;
ghost = other.ghost;
ghostPending = other.ghostPending;
movedThisRound = other.movedThisRound;
@ -532,7 +534,7 @@ bool CUnitState::hasClone() const
bool CUnitState::canCast() const
{
return casts.canUse(1);//do not check specific cast abilities here
return casts.canUse(1) && usedSpell == SpellID::NONE;//do not check specific cast abilities here
}
bool CUnitState::isCaster() const
@ -748,6 +750,7 @@ void CUnitState::serializeJson(JsonSerializeFormat & handler)
handler.serializeBool("drainedMana", drainedMana);
handler.serializeBool("fear", fear);
handler.serializeBool("hadMorale", hadMorale);
handler.serializeInt("usedSpell", usedSpell);
handler.serializeBool("ghost", ghost);
handler.serializeBool("ghostPending", ghostPending);
handler.serializeBool("moved", movedThisRound);
@ -782,6 +785,7 @@ void CUnitState::reset()
drainedMana = false;
fear = false;
hadMorale = false;
usedSpell = SpellID::NONE;
ghost = false;
ghostPending = false;
movedThisRound = false;
@ -864,6 +868,7 @@ void CUnitState::afterNewRound()
waitedThisTurn = false;
movedThisRound = false;
hadMorale = false;
usedSpell = SpellID::NONE;
fear = false;
drainedMana = false;
counterAttacks.reset();

View File

@ -141,6 +141,7 @@ public:
bool drainedMana;
bool fear;
bool hadMorale;
SpellID usedSpell;
bool ghost;
bool ghostPending;
bool movedThisRound;

View File

@ -2209,6 +2209,7 @@ void StartAction::applyGs(CGameState *gs)
st->waiting = false;
st->defendingAnim = false;
st->movedThisRound = true;
st->usedSpell = ba.actionType == EActionType::MONSTER_SPELL ? ba.spell : SpellID::NONE;
break;
}
}

View File

@ -298,6 +298,11 @@ bool CSpell::canCastOnSelf() const
return castOnSelf;
}
bool CSpell::canCastWithoutSkip() const
{
return castWithoutSkip;
}
const std::string & CSpell::getIconImmune() const
{
return iconImmune;
@ -779,6 +784,7 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
}
spell->castOnSelf = json["canCastOnSelf"].Bool();
spell->castWithoutSkip = json["canCastWithoutSkip"].Bool();
spell->level = static_cast<si32>(json["level"].Integer());
spell->power = static_cast<si32>(json["power"].Integer());

View File

@ -167,6 +167,7 @@ public:
bool hasSchool(SpellSchool school) const override;
bool canCastOnSelf() const override;
bool canCastWithoutSkip() const override;
/**
* Calls cb for each school this spell belongs to
@ -296,6 +297,7 @@ private:
bool combat; //is this spell combat (true) or adventure (false)
bool creatureAbility; //if true, only creatures can use this spell
bool castOnSelf; // if set, creature caster can cast this spell on itself
bool castWithoutSkip; // if set the creature will not skip the turn after casting a spell
si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative
std::unique_ptr<spells::ISpellMechanicsFactory> mechanics;//(!) do not serialize

View File

@ -565,6 +565,19 @@ void BattleFlowProcessor::onActionMade(const CBattleInfoCallback & battle, const
if(battle.battleGetTacticDist() != 0)
return;
// creature will not skip the turn after casting a spell if spell uses canCastWithoutSkip
if(ba.actionType == EActionType::MONSTER_SPELL)
{
assert(activeStack != nullptr);
assert(actedStack != nullptr);
if(actedStack->usedSpell != SpellID::NONE && SpellID(actedStack->usedSpell).toSpell()->canCastWithoutSkip())
{
setActiveStack(battle, actedStack);
return;
}
}
if (ba.isUnitAction())
{
assert(activeStack != nullptr);

View File

@ -47,6 +47,7 @@ public:
MOCK_CONST_METHOD0(isSpecial, bool());
MOCK_CONST_METHOD0(isMagical, bool());
MOCK_CONST_METHOD0(canCastOnSelf, bool());
MOCK_CONST_METHOD0(canCastWithoutSkip, bool());
MOCK_CONST_METHOD1(hasSchool, bool(SpellSchool));
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
MOCK_CONST_METHOD0(getCastSound, const std::string &());