mirror of
https://github.com/vcmi/vcmi.git
synced 2025-05-23 22:40:07 +02:00
Fix inability of unit to cast spell after receiving morale
This commit is contained in:
parent
5433b07e5f
commit
5550edeb9a
@ -568,7 +568,7 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
|
||||
ourTurnSpan++;
|
||||
}
|
||||
|
||||
state->nextTurn(unit->unitId());
|
||||
state->nextTurn(unit->unitId(), BattleUnitTurnReason::TURN_QUEUE);
|
||||
|
||||
PotentialTargets potentialTargets(unit, damageCache, state);
|
||||
|
||||
|
@ -342,14 +342,14 @@ void HypotheticBattle::nextRound()
|
||||
}
|
||||
}
|
||||
|
||||
void HypotheticBattle::nextTurn(uint32_t unitId)
|
||||
void HypotheticBattle::nextTurn(uint32_t unitId, BattleUnitTurnReason reason)
|
||||
{
|
||||
activeUnitId = unitId;
|
||||
auto unit = getForUpdate(unitId);
|
||||
|
||||
unit->removeUnitBonus(Bonus::UntilGetsTurn);
|
||||
|
||||
unit->afterGetsTurn();
|
||||
unit->afterGetsTurn(reason);
|
||||
}
|
||||
|
||||
void HypotheticBattle::addUnit(uint32_t id, const JsonNode & data)
|
||||
|
@ -137,7 +137,7 @@ public:
|
||||
battle::Units getUnitsIf(const battle::UnitFilter & predicate) const override;
|
||||
|
||||
void nextRound() override;
|
||||
void nextTurn(uint32_t unitId) override;
|
||||
void nextTurn(uint32_t unitId, BattleUnitTurnReason reason) override;
|
||||
|
||||
void addUnit(uint32_t id, const JsonNode & data) override;
|
||||
void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) override;
|
||||
|
@ -769,7 +769,7 @@ void ApplyClientNetPackVisitor::visitBattleNextRound(BattleNextRound & pack)
|
||||
|
||||
void ApplyClientNetPackVisitor::visitBattleSetActiveStack(BattleSetActiveStack & pack)
|
||||
{
|
||||
if(!pack.askPlayerInterface)
|
||||
if(pack.reason == BattleUnitTurnReason::AUTOMATIC_ACTION)
|
||||
return;
|
||||
|
||||
const CStack *activated = gs.getBattle(pack.battleID)->battleGetStackByID(pack.stack);
|
||||
|
@ -418,6 +418,7 @@ set(lib_MAIN_HEADERS
|
||||
battle/BattleSide.h
|
||||
battle/BattleStateInfoForRetreat.h
|
||||
battle/BattleProxy.h
|
||||
battle/BattleUnitTurnReason.h
|
||||
battle/CBattleInfoCallback.h
|
||||
battle/CBattleInfoEssentials.h
|
||||
battle/CObstacleInstance.h
|
||||
|
@ -666,7 +666,7 @@ void BattleInfo::nextRound()
|
||||
obst->battleTurnPassed();
|
||||
}
|
||||
|
||||
void BattleInfo::nextTurn(uint32_t unitId)
|
||||
void BattleInfo::nextTurn(uint32_t unitId, BattleUnitTurnReason reason)
|
||||
{
|
||||
activeStack = unitId;
|
||||
|
||||
@ -675,7 +675,7 @@ void BattleInfo::nextTurn(uint32_t unitId)
|
||||
//remove bonuses that last until when stack gets new turn
|
||||
st->removeBonusesRecursive(Bonus::UntilGetsTurn);
|
||||
|
||||
st->afterGetsTurn();
|
||||
st->afterGetsTurn(reason);
|
||||
}
|
||||
|
||||
void BattleInfo::addUnit(uint32_t id, const JsonNode & data)
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
// IBattleState
|
||||
|
||||
void nextRound() override;
|
||||
void nextTurn(uint32_t unitId) override;
|
||||
void nextTurn(uint32_t unitId, BattleUnitTurnReason reason) override;
|
||||
|
||||
void addUnit(uint32_t id, const JsonNode & data) override;
|
||||
void moveUnit(uint32_t id, const BattleHex & destination) override;
|
||||
|
28
lib/battle/BattleUnitTurnReason.h
Normal file
28
lib/battle/BattleUnitTurnReason.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* BattleUnitTurnReason.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
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
enum class BattleUnitTurnReason : int8_t
|
||||
{
|
||||
/// Unit gained turn due to becoming first unit in turn queue
|
||||
TURN_QUEUE,
|
||||
/// Unit gained turn due to morale triggering
|
||||
MORALE,
|
||||
/// Unit (re)gained turn due to hero casting a spell while this unit is active
|
||||
HERO_SPELLCAST,
|
||||
/// Unit gained turn due to casting a spell while having ability to cast spells without spending turn
|
||||
UNIT_SPELLCAST,
|
||||
/// Unit gained turn for automatic action, player can not select action for this unit
|
||||
AUTOMATIC_ACTION
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
@ -920,11 +920,13 @@ void CUnitState::afterNewRound()
|
||||
makeGhost();
|
||||
}
|
||||
|
||||
void CUnitState::afterGetsTurn()
|
||||
void CUnitState::afterGetsTurn(BattleUnitTurnReason reason)
|
||||
{
|
||||
//if moving second time this round it must be high morale bonus
|
||||
if(movedThisRound)
|
||||
if(reason == BattleUnitTurnReason::MORALE)
|
||||
{
|
||||
hadMorale = true;
|
||||
castSpellThisTurn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CUnitState::makeGhost()
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BattleUnitTurnReason.h"
|
||||
#include "Unit.h"
|
||||
#include "../bonuses/BonusCache.h"
|
||||
|
||||
@ -254,7 +255,7 @@ public:
|
||||
|
||||
void afterNewRound();
|
||||
|
||||
void afterGetsTurn();
|
||||
void afterGetsTurn(BattleUnitTurnReason reason);
|
||||
|
||||
void makeGhost();
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "CBattleInfoEssentials.h"
|
||||
#include "BattleUnitTurnReason.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@ -80,7 +81,7 @@ class DLL_LINKAGE IBattleState : public IBattleInfo
|
||||
{
|
||||
public:
|
||||
virtual void nextRound() = 0;
|
||||
virtual void nextTurn(uint32_t unitId) = 0;
|
||||
virtual void nextTurn(uint32_t unitId, BattleUnitTurnReason reason) = 0;
|
||||
|
||||
virtual void addUnit(uint32_t id, const JsonNode & data) = 0;
|
||||
virtual void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) = 0;
|
||||
|
@ -2007,7 +2007,7 @@ void BattleNextRound::applyGs(CGameState *gs)
|
||||
|
||||
void BattleSetActiveStack::applyGs(CGameState *gs)
|
||||
{
|
||||
gs->getBattle(battleID)->nextTurn(stack);
|
||||
gs->getBattle(battleID)->nextTurn(stack, reason);
|
||||
}
|
||||
|
||||
void BattleTriggerEffect::applyGs(CGameState *gs)
|
||||
|
@ -12,9 +12,10 @@
|
||||
#include "NetPacksBase.h"
|
||||
#include "BattleChanges.h"
|
||||
#include "PacksForClient.h"
|
||||
#include "../battle/BattleHexArray.h"
|
||||
#include "../battle/BattleAction.h"
|
||||
#include "../battle/BattleInfo.h"
|
||||
#include "../battle/BattleHexArray.h"
|
||||
#include "../battle/BattleUnitTurnReason.h"
|
||||
#include "../texts/MetaString.h"
|
||||
|
||||
class CClient;
|
||||
@ -63,8 +64,8 @@ struct DLL_LINKAGE BattleSetActiveStack : public CPackForClient
|
||||
void applyGs(CGameState * gs) override;
|
||||
|
||||
BattleID battleID = BattleID::NONE;
|
||||
ui32 stack = 0;
|
||||
ui8 askPlayerInterface = true;
|
||||
uint32_t stack = 0;
|
||||
BattleUnitTurnReason reason;
|
||||
|
||||
void visitTyped(ICPackVisitor & visitor) override;
|
||||
|
||||
@ -72,7 +73,7 @@ struct DLL_LINKAGE BattleSetActiveStack : public CPackForClient
|
||||
{
|
||||
h & battleID;
|
||||
h & stack;
|
||||
h & askPlayerInterface;
|
||||
h & reason;
|
||||
assert(battleID != BattleID::NONE);
|
||||
}
|
||||
};
|
||||
|
@ -334,7 +334,7 @@ void BattleFlowProcessor::activateNextStack(const CBattleInfoCallback & battle)
|
||||
if (!tryMakeAutomaticAction(battle, next))
|
||||
{
|
||||
if(next->alive()) {
|
||||
setActiveStack(battle, next);
|
||||
setActiveStack(battle, next, BattleUnitTurnReason::TURN_QUEUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -576,7 +576,7 @@ void BattleFlowProcessor::onActionMade(const CBattleInfoCallback & battle, const
|
||||
// NOTE: in case of random spellcaster, (e.g. Master Genie) spell has been selected by server and was not present in action received from player
|
||||
if(actedStack->castSpellThisTurn && ba.spell.hasValue() && ba.spell.toSpell()->canCastWithoutSkip())
|
||||
{
|
||||
setActiveStack(battle, actedStack);
|
||||
setActiveStack(battle, actedStack, BattleUnitTurnReason::UNIT_SPELLCAST);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -589,7 +589,7 @@ void BattleFlowProcessor::onActionMade(const CBattleInfoCallback & battle, const
|
||||
if (rollGoodMorale(battle, actedStack))
|
||||
{
|
||||
// Good morale - same stack makes 2nd turn
|
||||
setActiveStack(battle, actedStack);
|
||||
setActiveStack(battle, actedStack, BattleUnitTurnReason::MORALE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -599,7 +599,7 @@ void BattleFlowProcessor::onActionMade(const CBattleInfoCallback & battle, const
|
||||
{
|
||||
// this is action made by hero AND unit is alive (e.g. not killed by casted spell)
|
||||
// keep current active stack for next action
|
||||
setActiveStack(battle, activeStack);
|
||||
setActiveStack(battle, activeStack, BattleUnitTurnReason::HERO_SPELLCAST);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -622,7 +622,7 @@ bool BattleFlowProcessor::makeAutomaticAction(const CBattleInfoCallback & battle
|
||||
BattleSetActiveStack bsa;
|
||||
bsa.battleID = battle.getBattle()->getBattleID();
|
||||
bsa.stack = stack->unitId();
|
||||
bsa.askPlayerInterface = false;
|
||||
bsa.reason = BattleUnitTurnReason::AUTOMATIC_ACTION;
|
||||
gameHandler->sendAndApply(bsa);
|
||||
|
||||
bool ret = owner->makeAutomaticBattleAction(battle, ba);
|
||||
@ -809,12 +809,13 @@ void BattleFlowProcessor::stackTurnTrigger(const CBattleInfoCallback & battle, c
|
||||
}
|
||||
}
|
||||
|
||||
void BattleFlowProcessor::setActiveStack(const CBattleInfoCallback & battle, const battle::Unit * stack)
|
||||
void BattleFlowProcessor::setActiveStack(const CBattleInfoCallback & battle, const battle::Unit * stack, BattleUnitTurnReason reason)
|
||||
{
|
||||
assert(stack);
|
||||
|
||||
BattleSetActiveStack sas;
|
||||
sas.battleID = battle.getBattle()->getBattleID();
|
||||
sas.stack = stack->unitId();
|
||||
sas.reason = reason;
|
||||
gameHandler->sendAndApply(sas);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../lib/battle/BattleSide.h"
|
||||
#include "../lib/battle/BattleUnitTurnReason.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class CStack;
|
||||
@ -48,7 +49,7 @@ class BattleFlowProcessor : boost::noncopyable
|
||||
void stackEnchantedTrigger(const CBattleInfoCallback & battle, const CStack * stack);
|
||||
void removeObstacle(const CBattleInfoCallback & battle, const CObstacleInstance & obstacle);
|
||||
void stackTurnTrigger(const CBattleInfoCallback & battle, const CStack * stack);
|
||||
void setActiveStack(const CBattleInfoCallback & battle, const battle::Unit * stack);
|
||||
void setActiveStack(const CBattleInfoCallback & battle, const battle::Unit * stack, BattleUnitTurnReason reason);
|
||||
|
||||
void makeStackDoNothing(const CBattleInfoCallback & battle, const CStack * next);
|
||||
bool makeAutomaticAction(const CBattleInfoCallback & battle, const CStack * stack, BattleAction & ba); //used when action is taken by stack without volition of player (eg. unguided catapult attack)
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
MOCK_CONST_METHOD1(getUsedSpells, std::vector<SpellID>(BattleSide));
|
||||
|
||||
MOCK_METHOD0(nextRound, void());
|
||||
MOCK_METHOD1(nextTurn, void(uint32_t));
|
||||
MOCK_METHOD2(nextTurn, void(uint32_t, BattleUnitTurnReason));
|
||||
MOCK_METHOD2(addUnit, void(uint32_t, const JsonNode &));
|
||||
MOCK_METHOD3(setUnitState, void(uint32_t, const JsonNode &, int64_t));
|
||||
MOCK_METHOD2(moveUnit, void(uint32_t, const BattleHex &));
|
||||
|
Loading…
x
Reference in New Issue
Block a user