mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-19 21:10:12 +02:00
Merge pull request #4595 from Laserlicht/cast_without_skip
Bonus for spell: cast without skip the turn
This commit is contained in:
commit
65355925e9
@ -171,6 +171,10 @@
|
|||||||
"type" : "boolean",
|
"type" : "boolean",
|
||||||
"description" : "If used as creature spell, unit can cast this spell on itself"
|
"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" : {
|
"gainChance" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"description" : "Chance for this spell to appear in Mage Guild of a specific faction",
|
"description" : "Chance for this spell to appear in Mage Guild of a specific faction",
|
||||||
|
@ -64,6 +64,9 @@
|
|||||||
// If true, then creature capable of casting this spell can cast this spell on itself
|
// 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
|
// If false, then creature can only cast this spell on other units
|
||||||
"canCastOnSelf" : false,
|
"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
|
// If true, spell won't be available on a map without water
|
||||||
"onlyOnWaterMap" : true,
|
"onlyOnWaterMap" : true,
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
|
|
||||||
virtual bool hasSchool(SpellSchool school) const = 0;
|
virtual bool hasSchool(SpellSchool school) const = 0;
|
||||||
virtual bool canCastOnSelf() const = 0;
|
virtual bool canCastOnSelf() const = 0;
|
||||||
|
virtual bool canCastWithoutSkip() const = 0;
|
||||||
virtual void forEachSchool(const SchoolCallback & cb) const = 0;
|
virtual void forEachSchool(const SchoolCallback & cb) const = 0;
|
||||||
virtual int32_t getCost(const int32_t skillLevel) const = 0;
|
virtual int32_t getCost(const int32_t skillLevel) const = 0;
|
||||||
|
|
||||||
|
@ -330,6 +330,7 @@ CUnitState::CUnitState():
|
|||||||
drainedMana(false),
|
drainedMana(false),
|
||||||
fear(false),
|
fear(false),
|
||||||
hadMorale(false),
|
hadMorale(false),
|
||||||
|
castSpellThisTurn(false),
|
||||||
ghost(false),
|
ghost(false),
|
||||||
ghostPending(false),
|
ghostPending(false),
|
||||||
movedThisRound(false),
|
movedThisRound(false),
|
||||||
@ -362,6 +363,7 @@ CUnitState & CUnitState::operator=(const CUnitState & other)
|
|||||||
drainedMana = other.drainedMana;
|
drainedMana = other.drainedMana;
|
||||||
fear = other.fear;
|
fear = other.fear;
|
||||||
hadMorale = other.hadMorale;
|
hadMorale = other.hadMorale;
|
||||||
|
castSpellThisTurn = other.castSpellThisTurn;
|
||||||
ghost = other.ghost;
|
ghost = other.ghost;
|
||||||
ghostPending = other.ghostPending;
|
ghostPending = other.ghostPending;
|
||||||
movedThisRound = other.movedThisRound;
|
movedThisRound = other.movedThisRound;
|
||||||
@ -532,7 +534,7 @@ bool CUnitState::hasClone() const
|
|||||||
|
|
||||||
bool CUnitState::canCast() const
|
bool CUnitState::canCast() const
|
||||||
{
|
{
|
||||||
return casts.canUse(1);//do not check specific cast abilities here
|
return casts.canUse(1) && !castSpellThisTurn;//do not check specific cast abilities here
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUnitState::isCaster() const
|
bool CUnitState::isCaster() const
|
||||||
@ -748,6 +750,7 @@ void CUnitState::serializeJson(JsonSerializeFormat & handler)
|
|||||||
handler.serializeBool("drainedMana", drainedMana);
|
handler.serializeBool("drainedMana", drainedMana);
|
||||||
handler.serializeBool("fear", fear);
|
handler.serializeBool("fear", fear);
|
||||||
handler.serializeBool("hadMorale", hadMorale);
|
handler.serializeBool("hadMorale", hadMorale);
|
||||||
|
handler.serializeBool("castSpellThisTurn", castSpellThisTurn);
|
||||||
handler.serializeBool("ghost", ghost);
|
handler.serializeBool("ghost", ghost);
|
||||||
handler.serializeBool("ghostPending", ghostPending);
|
handler.serializeBool("ghostPending", ghostPending);
|
||||||
handler.serializeBool("moved", movedThisRound);
|
handler.serializeBool("moved", movedThisRound);
|
||||||
@ -782,6 +785,7 @@ void CUnitState::reset()
|
|||||||
drainedMana = false;
|
drainedMana = false;
|
||||||
fear = false;
|
fear = false;
|
||||||
hadMorale = false;
|
hadMorale = false;
|
||||||
|
castSpellThisTurn = false;
|
||||||
ghost = false;
|
ghost = false;
|
||||||
ghostPending = false;
|
ghostPending = false;
|
||||||
movedThisRound = false;
|
movedThisRound = false;
|
||||||
@ -864,6 +868,7 @@ void CUnitState::afterNewRound()
|
|||||||
waitedThisTurn = false;
|
waitedThisTurn = false;
|
||||||
movedThisRound = false;
|
movedThisRound = false;
|
||||||
hadMorale = false;
|
hadMorale = false;
|
||||||
|
castSpellThisTurn = false;
|
||||||
fear = false;
|
fear = false;
|
||||||
drainedMana = false;
|
drainedMana = false;
|
||||||
counterAttacks.reset();
|
counterAttacks.reset();
|
||||||
|
@ -141,6 +141,7 @@ public:
|
|||||||
bool drainedMana;
|
bool drainedMana;
|
||||||
bool fear;
|
bool fear;
|
||||||
bool hadMorale;
|
bool hadMorale;
|
||||||
|
bool castSpellThisTurn;
|
||||||
bool ghost;
|
bool ghost;
|
||||||
bool ghostPending;
|
bool ghostPending;
|
||||||
bool movedThisRound;
|
bool movedThisRound;
|
||||||
|
@ -2209,6 +2209,7 @@ void StartAction::applyGs(CGameState *gs)
|
|||||||
st->waiting = false;
|
st->waiting = false;
|
||||||
st->defendingAnim = false;
|
st->defendingAnim = false;
|
||||||
st->movedThisRound = true;
|
st->movedThisRound = true;
|
||||||
|
st->castSpellThisTurn = ba.actionType == EActionType::MONSTER_SPELL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,6 +298,11 @@ bool CSpell::canCastOnSelf() const
|
|||||||
return castOnSelf;
|
return castOnSelf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSpell::canCastWithoutSkip() const
|
||||||
|
{
|
||||||
|
return castWithoutSkip;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string & CSpell::getIconImmune() const
|
const std::string & CSpell::getIconImmune() const
|
||||||
{
|
{
|
||||||
return iconImmune;
|
return iconImmune;
|
||||||
@ -779,6 +784,7 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
spell->castOnSelf = json["canCastOnSelf"].Bool();
|
spell->castOnSelf = json["canCastOnSelf"].Bool();
|
||||||
|
spell->castWithoutSkip = json["canCastWithoutSkip"].Bool();
|
||||||
spell->level = static_cast<si32>(json["level"].Integer());
|
spell->level = static_cast<si32>(json["level"].Integer());
|
||||||
spell->power = static_cast<si32>(json["power"].Integer());
|
spell->power = static_cast<si32>(json["power"].Integer());
|
||||||
|
|
||||||
|
@ -167,6 +167,7 @@ public:
|
|||||||
|
|
||||||
bool hasSchool(SpellSchool school) const override;
|
bool hasSchool(SpellSchool school) const override;
|
||||||
bool canCastOnSelf() const override;
|
bool canCastOnSelf() const override;
|
||||||
|
bool canCastWithoutSkip() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls cb for each school this spell belongs to
|
* 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 combat; //is this spell combat (true) or adventure (false)
|
||||||
bool creatureAbility; //if true, only creatures can use this spell
|
bool creatureAbility; //if true, only creatures can use this spell
|
||||||
bool castOnSelf; // if set, creature caster can cast this spell on itself
|
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
|
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
|
std::unique_ptr<spells::ISpellMechanicsFactory> mechanics;//(!) do not serialize
|
||||||
|
@ -565,6 +565,19 @@ void BattleFlowProcessor::onActionMade(const CBattleInfoCallback & battle, const
|
|||||||
if(battle.battleGetTacticDist() != 0)
|
if(battle.battleGetTacticDist() != 0)
|
||||||
return;
|
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->castSpellThisTurn && SpellID(ba.spell).toSpell()->canCastWithoutSkip())
|
||||||
|
{
|
||||||
|
setActiveStack(battle, actedStack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ba.isUnitAction())
|
if (ba.isUnitAction())
|
||||||
{
|
{
|
||||||
assert(activeStack != nullptr);
|
assert(activeStack != nullptr);
|
||||||
|
@ -47,6 +47,7 @@ public:
|
|||||||
MOCK_CONST_METHOD0(isSpecial, bool());
|
MOCK_CONST_METHOD0(isSpecial, bool());
|
||||||
MOCK_CONST_METHOD0(isMagical, bool());
|
MOCK_CONST_METHOD0(isMagical, bool());
|
||||||
MOCK_CONST_METHOD0(canCastOnSelf, bool());
|
MOCK_CONST_METHOD0(canCastOnSelf, bool());
|
||||||
|
MOCK_CONST_METHOD0(canCastWithoutSkip, bool());
|
||||||
MOCK_CONST_METHOD1(hasSchool, bool(SpellSchool));
|
MOCK_CONST_METHOD1(hasSchool, bool(SpellSchool));
|
||||||
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
|
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
|
||||||
MOCK_CONST_METHOD0(getCastSound, const std::string &());
|
MOCK_CONST_METHOD0(getCastSound, const std::string &());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user