mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Code cleanup
This commit is contained in:
parent
c516b5a64e
commit
013417fb7e
@ -18,6 +18,7 @@
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "../../lib/spells/ISpellMechanics.h"
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
#include "../../lib/battle/BattleStateInfoForRetreat.h"
|
||||
#include "../../lib/battle/CObstacleInstance.h"
|
||||
#include "../../lib/CStack.h" // TODO: remove
|
||||
@ -781,7 +782,7 @@ bool CBattleAI::attemptCastingSpell()
|
||||
LOGFL("Best spell is %s (value %d). Will cast.", castToPerform.spell->getNameTranslated() % castToPerform.value);
|
||||
BattleAction spellcast;
|
||||
spellcast.actionType = EActionType::HERO_SPELL;
|
||||
spellcast.actionSubtype = castToPerform.spell->id;
|
||||
spellcast.spell = castToPerform.spell->getId();
|
||||
spellcast.setTarget(castToPerform.dest);
|
||||
spellcast.side = side;
|
||||
spellcast.stackNumber = (!side) ? -1 : -2;
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "../../lib/CRandomGenerator.h"
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
|
||||
void CEmptyAI::saveGame(BinarySerializer & h, const int version)
|
||||
{
|
||||
@ -73,3 +74,8 @@ void CEmptyAI::showMapObjectSelectDialog(QueryID askID, const Component & icon,
|
||||
{
|
||||
cb->selectionMade(0, askID);
|
||||
}
|
||||
|
||||
std::optional<BattleAction> CEmptyAI::makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
};
|
||||
|
||||
#define NAME "EmptyAI 0.1"
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
|
||||
static std::shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
|
@ -2890,4 +2890,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::optional<BattleAction> VCAI::makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -203,6 +203,7 @@ public:
|
||||
|
||||
void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed) override;
|
||||
void battleEnd(const BattleResult * br, QueryID queryID) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
|
||||
void makeTurn();
|
||||
void mainLoop();
|
||||
|
@ -128,7 +128,6 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player):
|
||||
destinationTeleportPos = int3(-1);
|
||||
GH.defActionsDef = 0;
|
||||
LOCPLINT = this;
|
||||
curAction = nullptr;
|
||||
playerID=Player;
|
||||
human=true;
|
||||
battleInt = nullptr;
|
||||
@ -769,8 +768,7 @@ void CPlayerInterface::actionStarted(const BattleAction &action)
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
curAction = new BattleAction(action);
|
||||
battleInt->startAction(curAction);
|
||||
battleInt->startAction(action);
|
||||
}
|
||||
|
||||
void CPlayerInterface::actionFinished(const BattleAction &action)
|
||||
@ -778,9 +776,7 @@ void CPlayerInterface::actionFinished(const BattleAction &action)
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
battleInt->endAction(curAction);
|
||||
delete curAction;
|
||||
curAction = nullptr;
|
||||
battleInt->endAction(action);
|
||||
}
|
||||
|
||||
void CPlayerInterface::activeStack(const CStack * stack) //called when it's turn of that stack
|
||||
@ -935,8 +931,6 @@ void CPlayerInterface::battleAttack(const BattleAttack * ba)
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
assert(curAction);
|
||||
|
||||
StackAttackInfo info;
|
||||
info.attacker = cb->battleGetStackByID(ba->stackAttacking);
|
||||
info.defender = nullptr;
|
||||
@ -2110,3 +2104,8 @@ void CPlayerInterface::showWorldViewEx(const std::vector<ObjectPosInfo>& objectP
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->openWorldView(objectPositions, showTerrain );
|
||||
}
|
||||
|
||||
std::optional<BattleAction> CPlayerInterface::makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -66,7 +66,6 @@ class CPlayerInterface : public CGameInterface, public IUpdateable
|
||||
int autosaveCount;
|
||||
|
||||
std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
|
||||
const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)
|
||||
|
||||
ObjectInstanceID destinationTeleport; //contain -1 or object id if teleportation
|
||||
int3 destinationTeleportPos;
|
||||
@ -173,6 +172,7 @@ protected: // Call-ins from server, should not be called directly, but only via
|
||||
void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
|
||||
void battleGateStateChanged(const EGateState state) override;
|
||||
void yourTacticPhase(int distance) override;
|
||||
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) override;
|
||||
|
||||
public: // public interface for use by client via LOCPLINT access
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <vcmi/Environment.h>
|
||||
|
||||
#include "../lib/IGameCallback.h"
|
||||
#include "../lib/battle/BattleAction.h"
|
||||
#include "../lib/battle/CBattleInfoCallback.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@ -25,6 +24,7 @@ class CBattleGameInterface;
|
||||
class CGameInterface;
|
||||
class BinaryDeserializer;
|
||||
class BinarySerializer;
|
||||
class BattleAction;
|
||||
|
||||
template<typename T> class CApplier;
|
||||
|
||||
@ -118,7 +118,7 @@ public:
|
||||
|
||||
std::map<PlayerColor, std::vector<std::shared_ptr<IBattleEventsReceiver>>> additionalBattleInts;
|
||||
|
||||
std::optional<BattleAction> curbaction;
|
||||
std::unique_ptr<BattleAction> currentBattleAction;
|
||||
|
||||
CClient();
|
||||
~CClient();
|
||||
|
@ -784,7 +784,7 @@ void ApplyClientNetPackVisitor::visitBattleAttack(BattleAttack & pack)
|
||||
|
||||
void ApplyFirstClientNetPackVisitor::visitStartAction(StartAction & pack)
|
||||
{
|
||||
cl.curbaction = std::make_optional(pack.ba);
|
||||
cl.currentBattleAction = std::make_unique<BattleAction>(pack.ba);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionStarted, pack.ba);
|
||||
}
|
||||
|
||||
@ -830,8 +830,8 @@ void ApplyClientNetPackVisitor::visitCatapultAttack(CatapultAttack & pack)
|
||||
|
||||
void ApplyClientNetPackVisitor::visitEndAction(EndAction & pack)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionFinished, *cl.curbaction);
|
||||
cl.curbaction.reset();
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::actionFinished, *cl.currentBattleAction);
|
||||
cl.currentBattleAction.reset();
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitPackageApplied(PackageApplied & pack)
|
||||
|
@ -286,7 +286,7 @@ void BattleActionsController::castThisSpell(SpellID spellID)
|
||||
{
|
||||
heroSpellToCast = std::make_shared<BattleAction>();
|
||||
heroSpellToCast->actionType = EActionType::HERO_SPELL;
|
||||
heroSpellToCast->actionSubtype = spellID; //spell number
|
||||
heroSpellToCast->spell = spellID;
|
||||
heroSpellToCast->stackNumber = (owner.attackingHeroInstance->tempOwner == owner.curInt->playerID) ? -1 : -2;
|
||||
heroSpellToCast->side = owner.defendingHeroInstance ? (owner.curInt->playerID == owner.defendingHeroInstance->tempOwner) : false;
|
||||
|
||||
@ -314,7 +314,7 @@ void BattleActionsController::castThisSpell(SpellID spellID)
|
||||
const CSpell * BattleActionsController::getHeroSpellToCast( ) const
|
||||
{
|
||||
if (heroSpellToCast)
|
||||
return SpellID(heroSpellToCast->actionSubtype).toSpell();
|
||||
return heroSpellToCast->spell.toSpell();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -94,13 +94,13 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
|
||||
owner.waitForAnimations();
|
||||
}
|
||||
|
||||
void BattleEffectsController::startAction(const BattleAction* action)
|
||||
void BattleEffectsController::startAction(const BattleAction & action)
|
||||
{
|
||||
owner.checkForAnimations();
|
||||
|
||||
const CStack *stack = owner.curInt->cb->battleGetStackByID(action->stackNumber);
|
||||
const CStack *stack = owner.curInt->cb->battleGetStackByID(action.stackNumber);
|
||||
|
||||
switch(action->actionType)
|
||||
switch(action.actionType)
|
||||
{
|
||||
case EActionType::WAIT:
|
||||
owner.appendBattleLog(stack->formatGeneralMessage(136));
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
|
||||
BattleEffectsController(BattleInterface & owner);
|
||||
|
||||
void startAction(const BattleAction* action);
|
||||
void startAction(const BattleAction & action);
|
||||
|
||||
//displays custom effect on the battlefield
|
||||
void displayEffect(EBattleEffect effect, const BattleHex & destTile);
|
||||
|
@ -234,7 +234,7 @@ void BattleInterface::newRound(int number)
|
||||
console->addText(CGI->generaltexth->allTexts[412]);
|
||||
}
|
||||
|
||||
void BattleInterface::giveCommand(EActionType action, BattleHex tile, si32 additional)
|
||||
void BattleInterface::giveCommand(EActionType action, BattleHex tile, SpellID spell)
|
||||
{
|
||||
const CStack * actor = nullptr;
|
||||
if(action != EActionType::HERO_SPELL && action != EActionType::RETREAT && action != EActionType::SURRENDER)
|
||||
@ -253,7 +253,7 @@ void BattleInterface::giveCommand(EActionType action, BattleHex tile, si32 addit
|
||||
ba.side = side.value();
|
||||
ba.actionType = action;
|
||||
ba.aimToHex(tile);
|
||||
ba.actionSubtype = additional;
|
||||
ba.spell = spell;
|
||||
|
||||
sendCommand(ba, actor);
|
||||
}
|
||||
@ -567,12 +567,12 @@ bool BattleInterface::makingTurn() const
|
||||
return stacksController->getActiveStack() != nullptr;
|
||||
}
|
||||
|
||||
void BattleInterface::endAction(const BattleAction* action)
|
||||
void BattleInterface::endAction(const BattleAction &action)
|
||||
{
|
||||
// it is possible that tactics mode ended while opening music is still playing
|
||||
waitForAnimations();
|
||||
|
||||
const CStack *stack = curInt->cb->battleGetStackByID(action->stackNumber);
|
||||
const CStack *stack = curInt->cb->battleGetStackByID(action.stackNumber);
|
||||
|
||||
// Activate stack from stackToActivate because this might have been temporary disabled, e.g., during spell cast
|
||||
activateStack();
|
||||
@ -585,7 +585,7 @@ void BattleInterface::endAction(const BattleAction* action)
|
||||
tacticNextStack(stack);
|
||||
|
||||
//we have activated next stack after sending request that has been just realized -> blockmap due to movement has changed
|
||||
if(action->actionType == EActionType::HERO_SPELL)
|
||||
if(action.actionType == EActionType::HERO_SPELL)
|
||||
fieldController->redrawBackgroundWithHexes();
|
||||
}
|
||||
|
||||
@ -594,15 +594,15 @@ void BattleInterface::appendBattleLog(const std::string & newEntry)
|
||||
console->addText(newEntry);
|
||||
}
|
||||
|
||||
void BattleInterface::startAction(const BattleAction* action)
|
||||
void BattleInterface::startAction(const BattleAction & action)
|
||||
{
|
||||
if(action->actionType == EActionType::END_TACTIC_PHASE)
|
||||
if(action.actionType == EActionType::END_TACTIC_PHASE)
|
||||
{
|
||||
windowObject->tacticPhaseEnded();
|
||||
return;
|
||||
}
|
||||
|
||||
const CStack *stack = curInt->cb->battleGetStackByID(action->stackNumber);
|
||||
const CStack *stack = curInt->cb->battleGetStackByID(action.stackNumber);
|
||||
|
||||
if (stack)
|
||||
{
|
||||
@ -610,17 +610,17 @@ void BattleInterface::startAction(const BattleAction* action)
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(action->actionType == EActionType::HERO_SPELL); //only cast spell is valid action without acting stack number
|
||||
assert(action.actionType == EActionType::HERO_SPELL); //only cast spell is valid action without acting stack number
|
||||
}
|
||||
|
||||
stacksController->startAction(action);
|
||||
|
||||
if(action->actionType == EActionType::HERO_SPELL) //when hero casts spell
|
||||
if(action.actionType == EActionType::HERO_SPELL) //when hero casts spell
|
||||
return;
|
||||
|
||||
if (!stack)
|
||||
{
|
||||
logGlobal->error("Something wrong with stackNumber in actionStarted. Stack number: %d", action->stackNumber);
|
||||
logGlobal->error("Something wrong with stackNumber in actionStarted. Stack number: %d", action.stackNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ public:
|
||||
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
|
||||
void requestAutofightingAIToTakeAction();
|
||||
|
||||
void giveCommand(EActionType action, BattleHex tile = BattleHex(), si32 additional = -1);
|
||||
void giveCommand(EActionType action, BattleHex tile = BattleHex(), SpellID spell = SpellID::NONE);
|
||||
void sendCommand(BattleAction command, const CStack * actor = nullptr);
|
||||
|
||||
const CGHeroInstance *getActiveHero(); //returns hero that can currently cast a spell
|
||||
@ -188,7 +188,7 @@ public:
|
||||
void addToAnimationStage( EAnimationEvents event, const AwaitingAnimationAction & action);
|
||||
|
||||
//call-ins
|
||||
void startAction(const BattleAction* action);
|
||||
void startAction(const BattleAction & action);
|
||||
void stackReset(const CStack * stack);
|
||||
void stackAdded(const CStack * stack); //new stack appeared on battlefield
|
||||
void stackRemoved(uint32_t stackID); //stack disappeared from batlefiled
|
||||
@ -211,7 +211,7 @@ public:
|
||||
void displaySpellEffect(const CSpell * spell, BattleHex destinationTile); //displays spell`s affected animation
|
||||
void displaySpellHit(const CSpell * spell, BattleHex destinationTile); //displays spell`s affected animation
|
||||
|
||||
void endAction(const BattleAction* action);
|
||||
void endAction(const BattleAction & action);
|
||||
|
||||
void obstaclePlaced(const std::vector<std::shared_ptr<const CObstacleInstance>> oi);
|
||||
void obstacleRemoved(const std::vector<ObstacleChanges> & obstacles);
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/spells/ISpellMechanics.h"
|
||||
#include "../../lib/battle/BattleAction.h"
|
||||
#include "../../lib/battle/BattleHex.h"
|
||||
#include "../../lib/CStack.h"
|
||||
#include "../../lib/CondSh.h"
|
||||
@ -663,7 +664,7 @@ bool BattleStacksController::shouldRotate(const CStack * stack, const BattleHex
|
||||
return false;
|
||||
}
|
||||
|
||||
void BattleStacksController::endAction(const BattleAction* action)
|
||||
void BattleStacksController::endAction(const BattleAction & action)
|
||||
{
|
||||
owner.checkForAnimations();
|
||||
|
||||
@ -688,7 +689,7 @@ void BattleStacksController::endAction(const BattleAction* action)
|
||||
removeExpiredColorFilters();
|
||||
}
|
||||
|
||||
void BattleStacksController::startAction(const BattleAction* action)
|
||||
void BattleStacksController::startAction(const BattleAction & action)
|
||||
{
|
||||
removeExpiredColorFilters();
|
||||
}
|
||||
|
@ -115,8 +115,8 @@ public:
|
||||
void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
||||
void stackAttacking(const StackAttackInfo & info); //called when stack with id ID is attacking something on hex dest
|
||||
|
||||
void startAction(const BattleAction* action);
|
||||
void endAction(const BattleAction* action);
|
||||
void startAction(const BattleAction & action);
|
||||
void endAction(const BattleAction & action);
|
||||
|
||||
void deactivateStack(); //copy activeStack to stackToActivate, then set activeStack to nullptr to temporary disable current stack
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "battle/BattleAction.h"
|
||||
#include "IGameEventsReceiver.h"
|
||||
|
||||
#include "spells/ViewSpellInt.h"
|
||||
@ -36,6 +35,7 @@ class CCreatureSet;
|
||||
class CArmedInstance;
|
||||
class IShipyard;
|
||||
class IMarket;
|
||||
class BattleAction;
|
||||
struct BattleResult;
|
||||
struct BattleAttack;
|
||||
struct BattleStackAttacked;
|
||||
@ -107,10 +107,7 @@ public:
|
||||
|
||||
virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain){};
|
||||
|
||||
virtual std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
virtual std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleStateInfoForRetreat & battleState) = 0;
|
||||
|
||||
virtual void saveGame(BinarySerializer & h, const int version) = 0;
|
||||
virtual void loadGame(BinaryDeserializer & h, const int version) = 0;
|
||||
|
@ -2289,7 +2289,7 @@ void StartAction::applyGs(CGameState *gs)
|
||||
assert(st || heroAction); // stack must exists for all non-hero actions
|
||||
|
||||
if(ba.actionType == EActionType::HERO_SPELL)
|
||||
gs->curB->sides[ba.side].usedSpellsHistory.emplace_back(ba.actionSubtype);
|
||||
gs->curB->sides[ba.side].usedSpellsHistory.push_back(ba.spell);
|
||||
|
||||
switch(ba.actionType)
|
||||
{
|
||||
|
@ -20,8 +20,7 @@ static const int32_t INVALID_UNIT_ID = -1000;
|
||||
BattleAction::BattleAction():
|
||||
side(-1),
|
||||
stackNumber(-1),
|
||||
actionType(EActionType::NO_ACTION),
|
||||
actionSubtype(-1)
|
||||
actionType(EActionType::NO_ACTION)
|
||||
{
|
||||
}
|
||||
|
||||
@ -80,7 +79,7 @@ BattleAction BattleAction::makeCreatureSpellcast(const battle::Unit * stack, con
|
||||
{
|
||||
BattleAction ba;
|
||||
ba.actionType = EActionType::MONSTER_SPELL;
|
||||
ba.actionSubtype = spellID;
|
||||
ba.spell = spellID;
|
||||
ba.setTarget(target);
|
||||
ba.side = stack->unitSide();
|
||||
ba.stackNumber = stack->unitId();
|
||||
@ -144,7 +143,7 @@ std::string BattleAction::toString() const
|
||||
}
|
||||
|
||||
boost::format fmt("{BattleAction: side '%d', stackNumber '%d', actionType '%s', actionSubtype '%d', target {%s}}");
|
||||
fmt % static_cast<int>(side) % stackNumber % actionTypeStream.str() % actionSubtype % targetStream.str();
|
||||
fmt % static_cast<int>(side) % stackNumber % actionTypeStream.str() % spell.getNum() % targetStream.str();
|
||||
return fmt.str();
|
||||
}
|
||||
|
||||
@ -183,7 +182,7 @@ battle::Target BattleAction::getTarget(const CBattleInfoCallback * cb) const
|
||||
|
||||
void BattleAction::setTarget(const battle::Target & target_)
|
||||
{
|
||||
target.clear();
|
||||
target.clear();
|
||||
for(const auto & destination : target_)
|
||||
{
|
||||
if(destination.unitValue == nullptr)
|
||||
@ -193,6 +192,44 @@ void BattleAction::setTarget(const battle::Target & target_)
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleAction::isUnitAction() const
|
||||
{
|
||||
static const std::array<EActionType, 9> actions = {
|
||||
EActionType::WALK,
|
||||
EActionType::WAIT,
|
||||
EActionType::DEFEND,
|
||||
EActionType::WALK_AND_ATTACK,
|
||||
EActionType::SHOOT,
|
||||
EActionType::CATAPULT,
|
||||
EActionType::MONSTER_SPELL,
|
||||
EActionType::BAD_MORALE,
|
||||
EActionType::STACK_HEAL
|
||||
};
|
||||
|
||||
return vstd::contains(actions, actionType);
|
||||
}
|
||||
|
||||
bool BattleAction::isSpellAction() const
|
||||
{
|
||||
static const std::array<EActionType, 2> actions = {
|
||||
EActionType::HERO_SPELL,
|
||||
EActionType::MONSTER_SPELL
|
||||
};
|
||||
|
||||
return vstd::contains(actions, actionType);
|
||||
}
|
||||
|
||||
bool BattleAction::isTacticsAction() const
|
||||
{
|
||||
static const std::array<EActionType, 9> actions = {
|
||||
EActionType::WALK,
|
||||
EActionType::END_TACTIC_PHASE,
|
||||
EActionType::RETREAT,
|
||||
EActionType::SURRENDER
|
||||
};
|
||||
|
||||
return vstd::contains(actions, actionType);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, const BattleAction & ba)
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
ui32 stackNumber; //stack ID, -1 left hero, -2 right hero,
|
||||
EActionType actionType; //use ActionType enum for values
|
||||
|
||||
si32 actionSubtype;
|
||||
SpellID spell;
|
||||
|
||||
BattleAction();
|
||||
|
||||
@ -43,6 +43,9 @@ public:
|
||||
static BattleAction makeRetreat(ui8 side);
|
||||
static BattleAction makeSurrender(ui8 side);
|
||||
|
||||
bool isTacticsAction() const;
|
||||
bool isUnitAction() const;
|
||||
bool isSpellAction() const;
|
||||
std::string toString() const;
|
||||
|
||||
void aimToHex(const BattleHex & destination);
|
||||
@ -56,7 +59,7 @@ public:
|
||||
h & side;
|
||||
h & stackNumber;
|
||||
h & actionType;
|
||||
h & actionSubtype;
|
||||
h & spell;
|
||||
h & target;
|
||||
}
|
||||
private:
|
||||
|
@ -58,16 +58,21 @@ bool BattleActionProcessor::doEmptyAction(const BattleAction & ba)
|
||||
|
||||
bool BattleActionProcessor::doEndTacticsAction(const BattleAction & ba)
|
||||
{
|
||||
if (gameHandler->gameState()->curB->tacticDistance == 0)
|
||||
{
|
||||
gameHandler->complain("Cannot end tactics mode - no tactics!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BattleActionProcessor::doWaitAction(const BattleAction & ba)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const CStack * stack = gameHandler->battleGetStackByID(ba.stackNumber);
|
||||
|
||||
if (!canStackAct(stack))
|
||||
return false;
|
||||
|
||||
bool BattleActionProcessor::doBadMoraleAction(const BattleAction & ba)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -113,10 +118,10 @@ bool BattleActionProcessor::doHeroSpellAction(const BattleAction & ba)
|
||||
return false;
|
||||
}
|
||||
|
||||
const CSpell * s = SpellID(ba.actionSubtype).toSpell();
|
||||
const CSpell * s = ba.spell.toSpell();
|
||||
if (!s)
|
||||
{
|
||||
logGlobal->error("Wrong spell id (%d)!", ba.actionSubtype);
|
||||
logGlobal->error("Wrong spell id (%d)!", ba.spell.getNum());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -411,7 +416,7 @@ bool BattleActionProcessor::doUnitSpellAction(const BattleAction & ba)
|
||||
{
|
||||
const CStack * stack = gameHandler->gameState()->curB->battleGetStackByID(ba.stackNumber);
|
||||
battle::Target target = ba.getTarget(gameHandler->gameState()->curB);
|
||||
SpellID spellID = SpellID(ba.actionSubtype);
|
||||
SpellID spellID = ba.spell;
|
||||
|
||||
if (!canStackAct(stack))
|
||||
return false;
|
||||
@ -479,8 +484,6 @@ bool BattleActionProcessor::doHealAction(const BattleAction & ba)
|
||||
|
||||
bool BattleActionProcessor::canStackAct(const CStack * stack)
|
||||
{
|
||||
const bool isAboutActiveStack = stack->unitId() == gameHandler->gameState()->curB->getActiveStackID();
|
||||
|
||||
if (!stack)
|
||||
{
|
||||
gameHandler->complain("No such stack!");
|
||||
@ -500,10 +503,13 @@ bool BattleActionProcessor::canStackAct(const CStack * stack)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!isAboutActiveStack)
|
||||
else
|
||||
{
|
||||
gameHandler->complain("Action has to be about active stack!");
|
||||
return false;
|
||||
if (stack->unitId() != gameHandler->gameState()->curB->getActiveStackID())
|
||||
{
|
||||
gameHandler->complain("Action has to be about active stack!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -536,8 +542,6 @@ bool BattleActionProcessor::dispatchBattleAction(const BattleAction & ba)
|
||||
return doCatapultAction(ba);
|
||||
case EActionType::MONSTER_SPELL:
|
||||
return doUnitSpellAction(ba);
|
||||
case EActionType::BAD_MORALE:
|
||||
return doBadMoraleAction(ba);
|
||||
case EActionType::STACK_HEAL:
|
||||
return doHealAction(ba);
|
||||
}
|
||||
@ -545,7 +549,7 @@ bool BattleActionProcessor::dispatchBattleAction(const BattleAction & ba)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BattleActionProcessor::makeBattleAction(const BattleAction &ba)
|
||||
bool BattleActionProcessor::makeBattleActionImpl(const BattleAction &ba)
|
||||
{
|
||||
logGlobal->trace("Making action: %s", ba.toString());
|
||||
const CStack * stack = gameHandler->gameState()->curB->battleGetStackByID(ba.stackNumber);
|
||||
@ -1394,3 +1398,53 @@ void BattleActionProcessor::addGenericKilledLog(BattleLogMessage & blm, const CS
|
||||
blm.lines.push_back(std::move(line));
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleActionProcessor::makeAutomaticBattleAction(const BattleAction & ba)
|
||||
{
|
||||
return makeBattleActionImpl(ba);
|
||||
}
|
||||
|
||||
bool BattleActionProcessor::makePlayerBattleAction(PlayerColor player, const BattleAction &ba)
|
||||
{
|
||||
const BattleInfo * battle = gameHandler->gameState()->curB;
|
||||
|
||||
if(!battle && gameHandler->complain("Can not make action - there is no battle ongoing!"))
|
||||
return false;
|
||||
|
||||
if (ba.side != 0 && ba.side != 1 && gameHandler->complain("Can not make action - invalid battle side!"))
|
||||
return false;
|
||||
|
||||
if(battle->tacticDistance != 0)
|
||||
{
|
||||
if(!ba.isTacticsAction())
|
||||
{
|
||||
gameHandler->complain("Can not make actions while in tactics mode!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(player != battle->sides[ba.side].color)
|
||||
{
|
||||
gameHandler->complain("Can not make actions in battles you are not part of!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ba.isUnitAction() && ba.stackNumber != battle->getActiveStackID())
|
||||
{
|
||||
gameHandler->complain("Can not make actions - stack is not active!");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto active = battle->battleActiveUnit();
|
||||
if(!active && gameHandler->complain("No active unit in battle!"))
|
||||
return false;
|
||||
|
||||
auto unitOwner = battle->battleGetOwner(active);
|
||||
|
||||
if(player != unitOwner && gameHandler->complain("Can not make actions in battles you are not part of!"))
|
||||
return false;
|
||||
}
|
||||
|
||||
return makeBattleActionImpl(ba);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ struct BattleAttack;
|
||||
class BattleAction;
|
||||
struct BattleHex;
|
||||
class CStack;
|
||||
class PlayerColor;
|
||||
enum class BonusType;
|
||||
|
||||
namespace battle
|
||||
@ -64,14 +65,15 @@ class BattleActionProcessor : boost::noncopyable
|
||||
bool doShootAction(const BattleAction & ba);
|
||||
bool doCatapultAction(const BattleAction & ba);
|
||||
bool doUnitSpellAction(const BattleAction & ba);
|
||||
bool doBadMoraleAction(const BattleAction & ba);
|
||||
bool doHealAction(const BattleAction & ba);
|
||||
|
||||
bool dispatchBattleAction(const BattleAction & ba);
|
||||
bool makeBattleActionImpl(const BattleAction & ba);
|
||||
|
||||
public:
|
||||
explicit BattleActionProcessor(BattleProcessor * owner);
|
||||
void setGameHandler(CGameHandler * newGameHandler);
|
||||
|
||||
bool makeBattleAction(const BattleAction & ba);
|
||||
bool makeAutomaticBattleAction(const BattleAction & ba);
|
||||
bool makePlayerBattleAction(PlayerColor player, const BattleAction & ba);
|
||||
};
|
||||
|
@ -126,12 +126,8 @@ void BattleFlowProcessor::summonGuardiansHelper(std::vector<BattleHex> & output,
|
||||
}
|
||||
}
|
||||
|
||||
void BattleFlowProcessor::onBattleStarted()
|
||||
void BattleFlowProcessor::tryPlaceMoats()
|
||||
{
|
||||
gameHandler->setBattle(gameHandler->gameState()->curB);
|
||||
assert(gameHandler->gameState()->curB);
|
||||
//TODO: pre-tactic stuff, call scripts etc.
|
||||
|
||||
//Moat should be initialized here, because only here we can use spellcasting
|
||||
if (gameHandler->gameState()->curB->town && gameHandler->gameState()->curB->town->fortLevel() >= CGTownInstance::CITADEL)
|
||||
{
|
||||
@ -142,6 +138,14 @@ void BattleFlowProcessor::onBattleStarted()
|
||||
auto target = spells::Target();
|
||||
cast.cast(gameHandler->spellEnv, target);
|
||||
}
|
||||
}
|
||||
|
||||
void BattleFlowProcessor::onBattleStarted()
|
||||
{
|
||||
gameHandler->setBattle(gameHandler->gameState()->curB);
|
||||
assert(gameHandler->gameState()->curB);
|
||||
|
||||
tryPlaceMoats();
|
||||
|
||||
if (gameHandler->gameState()->curB->tacticDistance == 0)
|
||||
onTacticsEnded();
|
||||
@ -330,11 +334,7 @@ void BattleFlowProcessor::activateNextStack()
|
||||
|
||||
if (!tryMakeAutomaticAction(next))
|
||||
{
|
||||
logGlobal->trace("Activating %s", next->nodeName());
|
||||
auto nextId = next->unitId();
|
||||
BattleSetActiveStack sas;
|
||||
sas.stack = nextId;
|
||||
gameHandler->sendAndApply(&sas);
|
||||
setActiveStack(next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -529,36 +529,25 @@ void BattleFlowProcessor::onActionMade(const BattleAction &ba)
|
||||
if(owner->checkBattleStateChanges())
|
||||
return;
|
||||
|
||||
bool heroAction = ba.actionType == EActionType::HERO_SPELL || ba.actionType ==EActionType::SURRENDER || ba.actionType ==EActionType::RETREAT;
|
||||
bool tacticsAction = ba.actionType == EActionType::END_TACTIC_PHASE;
|
||||
|
||||
if (activeStack == nullptr && !tacticsAction)
|
||||
{
|
||||
throw std::runtime_error("Unexpected action - no active stack!");
|
||||
}
|
||||
|
||||
if (heroAction || tacticsAction)
|
||||
{
|
||||
if (!tacticsAction && activeStack->alive())
|
||||
{
|
||||
// this is action made by hero AND unit is alive (e.g. not killed by casted spell)
|
||||
// keep current active stack for next action
|
||||
BattleSetActiveStack sas;
|
||||
sas.stack = activeStack->unitId();
|
||||
gameHandler->sendAndApply(&sas);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ba.isUnitAction())
|
||||
{
|
||||
assert(activeStack != nullptr);
|
||||
assert(actedStack != nullptr);
|
||||
|
||||
if (rollGoodMorale(actedStack))
|
||||
{
|
||||
// Good morale - same stack makes 2nd turn
|
||||
BattleSetActiveStack sas;
|
||||
sas.stack = actedStack->unitId();
|
||||
gameHandler->sendAndApply(&sas);
|
||||
setActiveStack(actedStack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activeStack && activeStack->alive())
|
||||
{
|
||||
// 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(actedStack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -752,3 +741,13 @@ void BattleFlowProcessor::stackTurnTrigger(const CStack *st)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BattleFlowProcessor::setActiveStack(const CStack * stack)
|
||||
{
|
||||
assert(stack);
|
||||
|
||||
logGlobal->trace("Activating %s", stack->nodeName());
|
||||
BattleSetActiveStack sas;
|
||||
sas.stack = stack->unitId();
|
||||
gameHandler->sendAndApply(&sas);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ class BattleFlowProcessor : boost::noncopyable
|
||||
|
||||
void summonGuardiansHelper(std::vector<BattleHex> & output, const BattleHex & targetPosition, ui8 side, bool targetIsTwoHex);
|
||||
void trySummonGuardians(const CStack * stack);
|
||||
void tryPlaceMoats();
|
||||
void castOpeningSpells();
|
||||
void activateNextStack();
|
||||
void startNextRound(bool isFirstRound);
|
||||
@ -39,6 +40,7 @@ class BattleFlowProcessor : boost::noncopyable
|
||||
void stackEnchantedTrigger(const CStack * stack);
|
||||
void removeObstacle(const CObstacleInstance & obstacle);
|
||||
void stackTurnTrigger(const CStack * stack);
|
||||
void setActiveStack(const CStack * stack);
|
||||
|
||||
void makeStackDoNothing(const CStack * next);
|
||||
bool makeAutomaticAction(const CStack * stack, BattleAction & ba); //used when action is taken by stack without volition of player (eg. unguided catapult attack)
|
||||
|
@ -151,7 +151,6 @@ void BattleProcessor::setupBattle(int3 tile, const CArmedInstance *armies[2], co
|
||||
if (heroes[0] && heroes[0]->boat && heroes[1] && heroes[1]->boat)
|
||||
terType = BattleField(*VLC->identifiers()->getIdentifier("core", "battlefield.ship_to_ship"));
|
||||
|
||||
|
||||
//send info about battles
|
||||
BattleStart bs;
|
||||
bs.info = BattleInfo::setupBattle(tile, terrain, terType, armies, heroes, creatureBank, town);
|
||||
@ -236,52 +235,9 @@ void BattleProcessor::updateGateState()
|
||||
gameHandler->sendAndApply(&db);
|
||||
}
|
||||
|
||||
bool BattleProcessor::makePlayerBattleAction(PlayerColor player, BattleAction &ba)
|
||||
bool BattleProcessor::makePlayerBattleAction(PlayerColor player, const BattleAction &ba)
|
||||
{
|
||||
const BattleInfo * b = gameHandler->gameState()->curB;
|
||||
|
||||
if(!b && gameHandler->complain("Can not make action - there is no battle ongoing!"))
|
||||
return false;
|
||||
|
||||
if (ba.side != 0 && ba.side != 1 && gameHandler->complain("Can not make action - invalid battle side!"))
|
||||
return false;
|
||||
|
||||
if(b->tacticDistance)
|
||||
{
|
||||
if(ba.actionType != EActionType::WALK && ba.actionType != EActionType::END_TACTIC_PHASE
|
||||
&& ba.actionType != EActionType::RETREAT && ba.actionType != EActionType::SURRENDER)
|
||||
{
|
||||
gameHandler->complain("Can not make actions while in tactics mode!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(player != b->sides[ba.side].color)
|
||||
{
|
||||
gameHandler->complain("Can not make actions in battles you are not part of!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool heroAction = ba.actionType == EActionType::HERO_SPELL || ba.actionType ==EActionType::SURRENDER || ba.actionType ==EActionType::RETREAT || ba.actionType == EActionType::END_TACTIC_PHASE;
|
||||
|
||||
if (ba.stackNumber != b->getActiveStackID() && heroAction == false)
|
||||
{
|
||||
gameHandler->complain("Can not make actions - stack is not active!");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto active = b->battleActiveUnit();
|
||||
if(!active && gameHandler->complain("No active unit in battle!"))
|
||||
return false;
|
||||
|
||||
auto unitOwner = b->battleGetOwner(active);
|
||||
|
||||
if(player != unitOwner && gameHandler->complain("Can not make actions in battles you are not part of!"))
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = actionsProcessor->makeBattleAction(ba);
|
||||
bool result = actionsProcessor->makePlayerBattleAction(player, ba);
|
||||
flowProcessor->onActionMade(ba);
|
||||
return result;
|
||||
}
|
||||
@ -294,7 +250,7 @@ void BattleProcessor::setBattleResult(EBattleResult resultType, int victoriusSid
|
||||
|
||||
bool BattleProcessor::makeAutomaticBattleAction(const BattleAction &ba)
|
||||
{
|
||||
return actionsProcessor->makeBattleAction(ba);
|
||||
return actionsProcessor->makeAutomaticBattleAction(ba);
|
||||
}
|
||||
|
||||
void BattleProcessor::endBattleConfirm(const BattleInfo * battleInfo)
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank = false);
|
||||
|
||||
/// Processing of incoming battle action netpack
|
||||
bool makePlayerBattleAction(PlayerColor player, BattleAction & ba);
|
||||
bool makePlayerBattleAction(PlayerColor player, const BattleAction & ba);
|
||||
|
||||
/// Applies results of a battle once player agrees to them
|
||||
void endBattleConfirm(const BattleInfo * battleInfo);
|
||||
|
Loading…
Reference in New Issue
Block a user