mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Refactored player-specific data into single struct BattleState.
This commit is contained in:
parent
491bd557ef
commit
d8a27d8f3c
13
Global.h
13
Global.h
@ -329,13 +329,14 @@ namespace vstd
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Func(T1,T2) must say if these elements matches
|
||||
template <typename T1, typename T2, typename Func>
|
||||
int find_pos(const std::vector<T1> & c, const T2 &s, const Func &f)
|
||||
//Func f tells if element matches
|
||||
template <typename Container, typename Func>
|
||||
int find_pos_if(const Container & c, const Func &f)
|
||||
{
|
||||
for(size_t i=0; i < c.size(); ++i)
|
||||
if(f(c[i],s))
|
||||
return i;
|
||||
auto ret = boost::range::find_if(c, f);
|
||||
if(ret != std::end(c))
|
||||
return std::distance(std::begin(c), ret);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -570,51 +570,58 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
{
|
||||
for(auto &battleCb : battleCallbacks)
|
||||
{
|
||||
if(vstd::contains(info->sides, battleCb.first) || battleCb.first >= PlayerColor::PLAYER_LIMIT)
|
||||
if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; })
|
||||
|| battleCb.first >= PlayerColor::PLAYER_LIMIT)
|
||||
{
|
||||
battleCb.second->setBattle(info);
|
||||
}
|
||||
}
|
||||
// for(ui8 side : info->sides)
|
||||
// if(battleCallbacks.count(side))
|
||||
// battleCallbacks[side]->setBattle(info);
|
||||
|
||||
shared_ptr<CPlayerInterface> att, def;
|
||||
auto &leftSide = info->sides[0], &rightSide = info->sides[1];
|
||||
|
||||
|
||||
//If quick combat is not, do not prepare interfaces for battleint
|
||||
if(!settings["adventure"]["quickCombat"].Bool())
|
||||
{
|
||||
if(vstd::contains(playerint, info->sides[0]) && playerint[info->sides[0]]->human)
|
||||
att = std::dynamic_pointer_cast<CPlayerInterface>( playerint[info->sides[0]] );
|
||||
if(vstd::contains(playerint, leftSide.color) && playerint[leftSide.color]->human)
|
||||
att = std::dynamic_pointer_cast<CPlayerInterface>( playerint[leftSide.color] );
|
||||
|
||||
if(vstd::contains(playerint, info->sides[1]) && playerint[info->sides[1]]->human)
|
||||
def = std::dynamic_pointer_cast<CPlayerInterface>( playerint[info->sides[1]] );
|
||||
if(vstd::contains(playerint, rightSide.color) && playerint[rightSide.color]->human)
|
||||
def = std::dynamic_pointer_cast<CPlayerInterface>( playerint[rightSide.color] );
|
||||
}
|
||||
|
||||
if(!gNoGUI && (!!att || !!def || gs->scenarioOps->mode == StartInfo::DUEL))
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
new CBattleInterface(info->belligerents[0], info->belligerents[1], info->heroes[0], info->heroes[1],
|
||||
new CBattleInterface(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero,
|
||||
Rect((screen->w - 800)/2,
|
||||
(screen->h - 600)/2, 800, 600), att, def);
|
||||
}
|
||||
|
||||
if(vstd::contains(battleints,info->sides[0]))
|
||||
battleints[info->sides[0]]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 0);
|
||||
if(vstd::contains(battleints,info->sides[1]))
|
||||
battleints[info->sides[1]]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
|
||||
if(vstd::contains(battleints,PlayerColor::UNFLAGGABLE))
|
||||
battleints[PlayerColor::UNFLAGGABLE]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
|
||||
auto callBattleStart = [&](PlayerColor color, ui8 side){
|
||||
if(vstd::contains(battleints, color))
|
||||
battleints[color]->battleStart(leftSide.armyObject, rightSide.armyObject, info->tile, leftSide.hero, rightSide.hero, side);
|
||||
};
|
||||
|
||||
if(info->tacticDistance && vstd::contains(battleints,info->sides[info->tacticsSide]))
|
||||
callBattleStart(leftSide.color, 0);
|
||||
callBattleStart(leftSide.color, 1);
|
||||
callBattleStart(PlayerColor::UNFLAGGABLE, 1);
|
||||
|
||||
if(info->tacticDistance && vstd::contains(battleints,info->sides[info->tacticsSide].color))
|
||||
{
|
||||
boost::thread(&CClient::commenceTacticPhaseForInt, this, battleints[info->sides[info->tacticsSide]]);
|
||||
boost::thread(&CClient::commenceTacticPhaseForInt, this, battleints[info->sides[info->tacticsSide].color]);
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::battleFinished()
|
||||
{
|
||||
for(PlayerColor side : gs->curB->sides)
|
||||
if(battleCallbacks.count(side))
|
||||
battleCallbacks[side]->setBattle(nullptr);
|
||||
for(auto & side : gs->curB->sides)
|
||||
if(battleCallbacks.count(side.color))
|
||||
battleCallbacks[side.color]->setBattle(nullptr);
|
||||
}
|
||||
|
||||
void CClient::loadNeutralBattleAI()
|
||||
|
@ -90,8 +90,8 @@
|
||||
|
||||
|
||||
#define BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(function,...) \
|
||||
CALL_ONLY_THAT_BATTLE_INTERFACE(GS(cl)->curB->sides[0], function, __VA_ARGS__) \
|
||||
CALL_ONLY_THAT_BATTLE_INTERFACE(GS(cl)->curB->sides[1], function, __VA_ARGS__) \
|
||||
CALL_ONLY_THAT_BATTLE_INTERFACE(GS(cl)->curB->sides[0].color, function, __VA_ARGS__) \
|
||||
CALL_ONLY_THAT_BATTLE_INTERFACE(GS(cl)->curB->sides[1].color, function, __VA_ARGS__) \
|
||||
BATTLE_INTERFACE_CALL_RECEIVERS(function, __VA_ARGS__)
|
||||
/*
|
||||
* NetPacksClient.cpp, part of VCMI engine
|
||||
@ -624,7 +624,9 @@ void BattleSetActiveStack::applyCl( CClient *cl )
|
||||
PlayerColor playerToCall; //player that will move activated stack
|
||||
if( activated->hasBonusOfType(Bonus::HYPNOTIZED) )
|
||||
{
|
||||
playerToCall = ( GS(cl)->curB->sides[0] == activated->owner ? GS(cl)->curB->sides[1] : GS(cl)->curB->sides[0] );
|
||||
playerToCall = ( GS(cl)->curB->sides[0].color == activated->owner
|
||||
? GS(cl)->curB->sides[1].color
|
||||
: GS(cl)->curB->sides[0].color );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ void CBattleInterface::addNewAnim(CBattleAnimation * anim)
|
||||
}
|
||||
|
||||
CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2,
|
||||
CGHeroInstance *hero1, CGHeroInstance *hero2,
|
||||
const CGHeroInstance *hero1, const CGHeroInstance *hero2,
|
||||
const SDL_Rect & myRect,
|
||||
shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen)
|
||||
: background(nullptr), queue(nullptr), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0),
|
||||
|
@ -243,7 +243,7 @@ public:
|
||||
ui32 animIDhelper; //for giving IDs for animations
|
||||
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
|
||||
|
||||
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen); //c-tor
|
||||
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, const SDL_Rect & myRect, shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen); //c-tor
|
||||
~CBattleInterface(); //d-tor
|
||||
|
||||
//std::vector<TimeInterested*> timeinterested; //animation handling
|
||||
|
@ -140,7 +140,7 @@ int BattleInfo::calculateSpellDuration( const CSpell * spell, const CGHeroInstan
|
||||
CStack * BattleInfo::generateNewStack(const CStackInstance &base, bool attackerOwned, SlotID slot, BattleHex position) const
|
||||
{
|
||||
int stackID = getIdForNewStack();
|
||||
PlayerColor owner = attackerOwned ? sides[0] : sides[1];
|
||||
PlayerColor owner = sides[attackerOwned ? 0 : 1].color;
|
||||
assert((owner >= PlayerColor::PLAYER_LIMIT) ||
|
||||
(base.armyObj && base.armyObj->tempOwner == owner));
|
||||
|
||||
@ -153,7 +153,7 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, bool attackerO
|
||||
CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, SlotID slot, BattleHex position) const
|
||||
{
|
||||
int stackID = getIdForNewStack();
|
||||
PlayerColor owner = attackerOwned ? sides[0] : sides[1];
|
||||
PlayerColor owner = sides[attackerOwned ? 0 : 1].color;
|
||||
auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
|
||||
ret->position = position;
|
||||
ret->state.insert(EBattleStackState::ALIVE); //alive state indication
|
||||
@ -202,7 +202,7 @@ const CStack * BattleInfo::battleGetStack(BattleHex pos, bool onlyAlive)
|
||||
) )
|
||||
{
|
||||
if (elem->alive())
|
||||
return elem; //we prefer living stacks - there cna be only one stack on te tile, so return it imediately
|
||||
return elem; //we prefer living stacks - there can be only one stack on the tile, so return it immediately
|
||||
else if (!onlyAlive)
|
||||
stack = elem; //dead stacks are only accessible when there's no alive stack on this tile
|
||||
}
|
||||
@ -212,15 +212,17 @@ const CStack * BattleInfo::battleGetStack(BattleHex pos, bool onlyAlive)
|
||||
|
||||
const CGHeroInstance * BattleInfo::battleGetOwner(const CStack * stack) const
|
||||
{
|
||||
return heroes[!stack->attackerOwned];
|
||||
return sides[!stack->attackerOwned].hero;
|
||||
}
|
||||
|
||||
void BattleInfo::localInit()
|
||||
{
|
||||
belligerents[0]->battle = belligerents[1]->battle = this;
|
||||
|
||||
for(CArmedInstance *b : belligerents)
|
||||
b->attachTo(this);
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
auto armyObj = battleGetArmyObject(i);
|
||||
armyObj->battle = this;
|
||||
armyObj->attachTo(this);
|
||||
}
|
||||
|
||||
for(CStack *s : stacks)
|
||||
localInitStack(s);
|
||||
@ -237,7 +239,7 @@ void BattleInfo::localInitStack(CStack * s)
|
||||
}
|
||||
else //attach directly to obj to which stack belongs and creature type
|
||||
{
|
||||
CArmedInstance *army = belligerents[!s->attackerOwned];
|
||||
CArmedInstance *army = battleGetArmyObject(!s->attackerOwned);
|
||||
s->attachTo(army);
|
||||
assert(s->type);
|
||||
s->attachTo(const_cast<CCreature*>(s->type));
|
||||
@ -349,23 +351,17 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
{
|
||||
CMP_stack cmpst;
|
||||
auto curB = new BattleInfo;
|
||||
curB->castSpells[0] = curB->castSpells[1] = 0;
|
||||
curB->sides[0] = armies[0]->tempOwner;
|
||||
curB->sides[1] = armies[1]->tempOwner;
|
||||
if(curB->sides[1] == PlayerColor::UNFLAGGABLE)
|
||||
curB->sides[1] = PlayerColor::NEUTRAL;
|
||||
|
||||
for(auto i = 0u; i < curB->sides.size(); i++)
|
||||
curB->sides[i].init(heroes[i], armies[i]);
|
||||
|
||||
|
||||
std::vector<CStack*> & stacks = (curB->stacks);
|
||||
|
||||
curB->tile = tile;
|
||||
curB->battlefieldType = battlefieldType;
|
||||
curB->belligerents[0] = const_cast<CArmedInstance*>(armies[0]);
|
||||
curB->belligerents[1] = const_cast<CArmedInstance*>(armies[1]);
|
||||
curB->heroes[0] = const_cast<CGHeroInstance*>(heroes[0]);
|
||||
curB->heroes[1] = const_cast<CGHeroInstance*>(heroes[1]);
|
||||
curB->round = -2;
|
||||
curB->activeStack = -1;
|
||||
curB->enchanterCounter[0] = curB->enchanterCounter[1] = 0; //ready to cast
|
||||
|
||||
if(town)
|
||||
{
|
||||
@ -664,7 +660,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//tactics
|
||||
bool isTacticsAllowed = !creatureBank; //no tactics in crebanks
|
||||
bool isTacticsAllowed = !creatureBank; //no tactics in creature banks
|
||||
|
||||
int tacticLvls[2] = {0};
|
||||
for(int i = 0; i < ARRAY_COUNT(tacticLvls); i++)
|
||||
@ -687,7 +683,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
TNodes nodes;
|
||||
curB->belligerents[i]->getRedAncestors(nodes);
|
||||
curB->battleGetArmyObject(i)->getRedAncestors(nodes);
|
||||
for(CBonusSystemNode *n : nodes)
|
||||
{
|
||||
for(Bonus *b : n->getExportedBonusList())
|
||||
@ -697,7 +693,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
auto bCopy = new Bonus(*b);
|
||||
bCopy->effectRange = Bonus::NO_LIMIT;
|
||||
bCopy->propagator.reset();
|
||||
bCopy->limiter.reset(new StackOwnerLimiter(curB->sides[!i]));
|
||||
bCopy->limiter.reset(new StackOwnerLimiter(curB->sides[!i].color));
|
||||
curB->addNewBonus(bCopy);
|
||||
}
|
||||
}
|
||||
@ -709,11 +705,12 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
|
||||
const CGHeroInstance * BattleInfo::getHero( PlayerColor player ) const
|
||||
{
|
||||
assert(sides[0] == player || sides[1] == player);
|
||||
if(heroes[0] && heroes[0]->getOwner() == player)
|
||||
return heroes[0];
|
||||
for(int i = 0; i < sides.size(); i++)
|
||||
if(sides[i].color == player)
|
||||
return sides[i].hero;
|
||||
|
||||
return heroes[1];
|
||||
logGlobal->errorStream() << "Player " << player << " is not in battle!";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<ui32> BattleInfo::calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::vector<const CStack*> affectedCreatures, PlayerColor casterSideOwner, ECastingMode::ECastingMode mode, int usedSpellPower, int spellLevel) const
|
||||
@ -767,13 +764,13 @@ std::vector<ui32> BattleInfo::calculateResistedStacks(const CSpell * sp, const C
|
||||
|
||||
PlayerColor BattleInfo::theOtherPlayer(PlayerColor player) const
|
||||
{
|
||||
return sides[!whatSide(player)];
|
||||
return sides[!whatSide(player)].color;
|
||||
}
|
||||
|
||||
ui8 BattleInfo::whatSide(PlayerColor player) const
|
||||
{
|
||||
for(int i = 0; i < ARRAY_COUNT(sides); i++)
|
||||
if(sides[i] == player)
|
||||
for(int i = 0; i < sides.size(); i++)
|
||||
if(sides[i].color == player)
|
||||
return i;
|
||||
|
||||
logGlobal->warnStream() << "BattleInfo::whatSide: Player " << player << " is not in battle!";
|
||||
@ -841,6 +838,16 @@ BattleInfo::BattleInfo()
|
||||
setNodeType(BATTLE);
|
||||
}
|
||||
|
||||
CArmedInstance * BattleInfo::battleGetArmyObject(ui8 side) const
|
||||
{
|
||||
return const_cast<CArmedInstance*>(CBattleInfoEssentials::battleGetArmyObject(side));
|
||||
}
|
||||
|
||||
CGHeroInstance * BattleInfo::battleGetFightingHero(ui8 side) const
|
||||
{
|
||||
return const_cast<CGHeroInstance*>(CBattleInfoEssentials::battleGetFightingHero(side));
|
||||
}
|
||||
|
||||
CStack::CStack(const CStackInstance *Base, PlayerColor O, int I, bool AO, SlotID S)
|
||||
: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),
|
||||
counterAttacks(1)
|
||||
@ -1287,3 +1294,21 @@ CMP_stack::CMP_stack( int Phase /*= 1*/, int Turn )
|
||||
turn = Turn;
|
||||
}
|
||||
|
||||
|
||||
SideInBattle::SideInBattle()
|
||||
{
|
||||
hero = nullptr;
|
||||
armyObject = nullptr;
|
||||
castSpellsCount = 0;
|
||||
enchanterCounter = 0;
|
||||
}
|
||||
|
||||
void SideInBattle::init(const CGHeroInstance *Hero, const CArmedInstance *Army)
|
||||
{
|
||||
hero = Hero;
|
||||
armyObject = Army;
|
||||
color = armyObject->getOwner();
|
||||
|
||||
if(color == PlayerColor::UNFLAGGABLE)
|
||||
color = PlayerColor::NEUTRAL;
|
||||
}
|
||||
|
@ -41,22 +41,36 @@ struct DLL_LINKAGE SiegeInfo
|
||||
}
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE SideInBattle
|
||||
{
|
||||
PlayerColor color;
|
||||
const CGHeroInstance *hero; //may be NULL if army is not commanded by hero
|
||||
const CArmedInstance *armyObject; //adv. map object with army that participates in battle; may be same as hero
|
||||
|
||||
ui8 castSpellsCount; //how many spells each side has cast this turn
|
||||
std::vector<const CSpell *> usedSpellsHistory; //every time hero casts spell, it's inserted here -> eagle eye skill
|
||||
si16 enchanterCounter; //tends to pass through 0, so sign is needed
|
||||
|
||||
SideInBattle();
|
||||
void init(const CGHeroInstance *Hero, const CArmedInstance *Army);
|
||||
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & color & hero & armyObject;
|
||||
h & castSpellsCount & usedSpellsHistory & enchanterCounter;
|
||||
}
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallback
|
||||
{
|
||||
PlayerColor sides[2]; //sides[0] - attacker, sides[1] - defender
|
||||
std::array<SideInBattle, 2> sides; //sides[0] - attacker, sides[1] - defender
|
||||
si32 round, activeStack, selectedStack;
|
||||
CGTownInstance::EFortLevel siege;
|
||||
const CGTownInstance * town; //used during town siege - id of attacked town; -1 if not town defence
|
||||
int3 tile; //for background and bonuses
|
||||
CGHeroInstance* heroes[2];
|
||||
CArmedInstance *belligerents[2]; //may be same as heroes
|
||||
std::vector<CStack*> stacks;
|
||||
std::vector<shared_ptr<CObstacleInstance> > obstacles;
|
||||
ui8 castSpells[2]; //how many spells each side has cast this turn [0] - attacker, [1] - defender
|
||||
std::vector<const CSpell *> usedSpellsHistory[2]; //each time hero casts spell, it's inserted here -> eagle eye skill
|
||||
si16 enchanterCounter[2]; //tends to pass through 0, so sign is needed
|
||||
SiegeInfo si;
|
||||
|
||||
BFieldType battlefieldType; //like !!BA:B
|
||||
@ -67,10 +81,9 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & sides & round & activeStack & selectedStack & siege & town & tile & stacks & belligerents & obstacles
|
||||
& castSpells & si & battlefieldType & terrainType;
|
||||
h & heroes;
|
||||
h & usedSpellsHistory & enchanterCounter;
|
||||
h & sides;
|
||||
h & round & activeStack & selectedStack & siege & town & tile & stacks & obstacles
|
||||
& si & battlefieldType & terrainType;
|
||||
h & tacticsSide & tacticDistance;
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
}
|
||||
@ -82,6 +95,10 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CStack * getStackT(BattleHex tileID, bool onlyAlive = true);
|
||||
CStack * getStack(int stackID, bool onlyAlive = true);
|
||||
using CBattleInfoEssentials::battleGetArmyObject;
|
||||
CArmedInstance * battleGetArmyObject(ui8 side) const;
|
||||
using CBattleInfoEssentials::battleGetFightingHero;
|
||||
CGHeroInstance * battleGetFightingHero(ui8 side) const;
|
||||
|
||||
const CStack * getNextStack() const; //which stack will have turn after current one
|
||||
//void getStackQueue(std::vector<const CStack *> &out, int howMany, int turn = 0, int lastMoved = -1) const; //returns stack in order of their movement action
|
||||
@ -170,7 +187,7 @@ public:
|
||||
bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines
|
||||
ui32 Speed(int turn = 0, bool useBind = false) const; //get speed of creature with all modificators
|
||||
ui32 level() const;
|
||||
si32 magicResistance() const; //include aura of resistance
|
||||
si32 magicResistance() const override; //include aura of resistance
|
||||
static void stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse);
|
||||
std::vector<si32> activeSpells() const; //returns vector of active spell IDs sorted by time of cast
|
||||
const CGHeroInstance *getMyHero() const; //if stack belongs to hero (directly or was by him summoned) returns hero, nullptr otherwise
|
||||
|
@ -221,9 +221,9 @@ BattlePerspective::BattlePerspective CBattleInfoEssentials::battleGetMySide() co
|
||||
RETURN_IF_NOT_BATTLE(BattlePerspective::INVALID);
|
||||
if(!player)
|
||||
return BattlePerspective::ALL_KNOWING;
|
||||
if(*player == getBattle()->sides[0])
|
||||
if(*player == getBattle()->sides[0].color)
|
||||
return BattlePerspective::LEFT_SIDE;
|
||||
if(*player == getBattle()->sides[1])
|
||||
if(*player == getBattle()->sides[1].color)
|
||||
return BattlePerspective::RIGHT_SIDE;
|
||||
|
||||
logGlobal->errorStream() << "Cannot find player " << *player << " in battle!";
|
||||
@ -281,12 +281,30 @@ const CGHeroInstance * CBattleInfoEssentials::battleGetFightingHero(ui8 side) co
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return getBattle()->heroes[side];
|
||||
return getBattle()->sides[side].hero;
|
||||
}
|
||||
|
||||
const CArmedInstance * CBattleInfoEssentials::battleGetArmyObject(ui8 side) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(nullptr);
|
||||
if(side > 1)
|
||||
{
|
||||
logGlobal->errorStream() << "FIXME: " << __FUNCTION__ << " wrong argument!";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!battleDoWeKnowAbout(side))
|
||||
{
|
||||
logGlobal->errorStream() << "FIXME: " << __FUNCTION__ << " access check ";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return getBattle()->sides[side].armyObject;
|
||||
}
|
||||
|
||||
InfoAboutHero CBattleInfoEssentials::battleGetHeroInfo( ui8 side ) const
|
||||
{
|
||||
auto hero = getBattle()->heroes[side];
|
||||
auto hero = getBattle()->sides[side].hero;
|
||||
if(!hero)
|
||||
{
|
||||
logGlobal->warnStream() << __FUNCTION__ << ": side " << (int)side << " does not have hero!";
|
||||
@ -299,7 +317,7 @@ InfoAboutHero CBattleInfoEssentials::battleGetHeroInfo( ui8 side ) const
|
||||
int CBattleInfoEssentials::battleCastSpells(ui8 side) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(-1);
|
||||
return getBattle()->castSpells[side];
|
||||
return getBattle()->sides[side].castSpellsCount;
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastSpell(PlayerColor player, ECastingMode::ECastingMode mode) const
|
||||
@ -366,7 +384,7 @@ bool CBattleInfoEssentials::battleCanFlee(PlayerColor player) const
|
||||
ui8 CBattleInfoEssentials::playerToSide(PlayerColor player) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(-1);
|
||||
int ret = vstd::find_pos(getBattle()->sides, player);
|
||||
int ret = vstd::find_pos_if(getBattle()->sides, [=](const SideInBattle &side){ return side.color == player; });
|
||||
if(ret < 0)
|
||||
logGlobal->warnStream() << "Cannot find side for player " << player;
|
||||
|
||||
@ -390,7 +408,7 @@ bool CBattleInfoEssentials::battleHasHero(ui8 side) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(false);
|
||||
assert(side < 2);
|
||||
return getBattle()->heroes[side];
|
||||
return getBattle()->sides[side].hero;
|
||||
}
|
||||
|
||||
ui8 CBattleInfoEssentials::battleGetWallState(int partOfWall) const
|
||||
|
@ -20,6 +20,7 @@ struct BattleInfo;
|
||||
struct CObstacleInstance;
|
||||
class IBonusBearer;
|
||||
struct InfoAboutHero;
|
||||
class CArmedInstance;
|
||||
|
||||
namespace boost
|
||||
{class shared_mutex;}
|
||||
@ -182,6 +183,7 @@ public:
|
||||
bool battleHasHero(ui8 side) const;
|
||||
int battleCastSpells(ui8 side) const; //how many spells has given side casted
|
||||
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //depracated for players callback, easy to get wrong
|
||||
const CArmedInstance * battleGetArmyObject(ui8 side) const;
|
||||
InfoAboutHero battleGetHeroInfo(ui8 side) const;
|
||||
|
||||
//helpers
|
||||
|
@ -1015,10 +1015,10 @@ DLL_LINKAGE void BattleStart::applyGs( CGameState *gs )
|
||||
|
||||
DLL_LINKAGE void BattleNextRound::applyGs( CGameState *gs )
|
||||
{
|
||||
gs->curB->castSpells[0] = gs->curB->castSpells[1] = 0;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
vstd::amax(--gs->curB->enchanterCounter[i], 0);
|
||||
gs->curB->sides[i].castSpellsCount = 0;
|
||||
vstd::amax(--gs->curB->sides[i].enchanterCounter, 0);
|
||||
}
|
||||
|
||||
gs->curB->round = round;
|
||||
@ -1106,11 +1106,10 @@ void BattleResult::applyGs( CGameState *gs )
|
||||
for (auto & elem : gs->curB->stacks)
|
||||
delete elem;
|
||||
|
||||
CGHeroInstance *h;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
|
||||
for(int i = 0; i < 2; ++i)
|
||||
{
|
||||
h = gs->curB->heroes[i];
|
||||
if (h)
|
||||
if(auto h = gs->curB->battleGetFightingHero(i))
|
||||
{
|
||||
h->getBonusList().remove_if(Bonus::OneBattle); //remove any "until next battle" bonuses
|
||||
if (h->commander && h->commander->alive)
|
||||
@ -1123,17 +1122,18 @@ void BattleResult::applyGs( CGameState *gs )
|
||||
}
|
||||
}
|
||||
|
||||
if (VLC->modh->modules.STACK_EXP)
|
||||
if(VLC->modh->modules.STACK_EXP)
|
||||
{
|
||||
if (exp[0]) //checking local array is easier than dereferencing this crap twice
|
||||
gs->curB->belligerents[0]->giveStackExp(exp[0]);
|
||||
if (exp[1])
|
||||
gs->curB->belligerents[1]->giveStackExp(exp[1]);
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
if(exp[i])
|
||||
gs->curB->battleGetArmyObject(i)->giveStackExp(exp[i]);
|
||||
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
|
||||
gs->curB->belligerents[0]->battle = gs->curB->belligerents[1]->battle = nullptr;
|
||||
for(int i = 0; i < 2; i++)
|
||||
gs->curB->battleGetArmyObject(i)->battle = nullptr;
|
||||
|
||||
gs->curB.dellNull();
|
||||
}
|
||||
|
||||
@ -1246,7 +1246,7 @@ DLL_LINKAGE void StartAction::applyGs( CGameState *gs )
|
||||
}
|
||||
else
|
||||
{
|
||||
gs->curB->usedSpellsHistory[ba.side].push_back(SpellID(ba.additionalInfo).toSpell());
|
||||
gs->curB->sides[ba.side].usedSpellsHistory.push_back(SpellID(ba.additionalInfo).toSpell());
|
||||
}
|
||||
|
||||
switch(ba.actionType)
|
||||
@ -1273,8 +1273,8 @@ DLL_LINKAGE void BattleSpellCast::applyGs( CGameState *gs )
|
||||
assert(gs->curB);
|
||||
if (castedByHero)
|
||||
{
|
||||
CGHeroInstance * h = gs->curB->heroes[side];
|
||||
CGHeroInstance * enemy = gs->curB->heroes[1-side];
|
||||
CGHeroInstance * h = gs->curB->battleGetFightingHero(side);
|
||||
CGHeroInstance * enemy = gs->curB->battleGetFightingHero(!side);
|
||||
|
||||
h->mana -= spellCost;
|
||||
vstd::amax(h->mana, 0);
|
||||
@ -1282,7 +1282,7 @@ DLL_LINKAGE void BattleSpellCast::applyGs( CGameState *gs )
|
||||
enemy->mana += manaGained;
|
||||
if (side < 2)
|
||||
{
|
||||
gs->curB->castSpells[side]++;
|
||||
gs->curB->sides[side].castSpellsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1532,12 +1532,12 @@ DLL_LINKAGE void BattleSetStackProperty::applyGs(CGameState *gs)
|
||||
}
|
||||
case ENCHANTER_COUNTER:
|
||||
{
|
||||
int side = gs->curB->whatSide(stack->owner);
|
||||
auto & counter = gs->curB->sides[gs->curB->whatSide(stack->owner)].enchanterCounter;
|
||||
if (absolute)
|
||||
gs->curB->enchanterCounter[side] = val;
|
||||
counter = val;
|
||||
else
|
||||
gs->curB->enchanterCounter[side] += val;
|
||||
vstd::amax(gs->curB->enchanterCounter[side], 0);
|
||||
counter += val;
|
||||
vstd::amax(counter, 0);
|
||||
break;
|
||||
}
|
||||
case UNBIND:
|
||||
|
@ -428,8 +428,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
if (hero2)
|
||||
battleResult.data->exp[1] = hero2->calculateXp(battleResult.data->exp[1]);
|
||||
|
||||
const CArmedInstance *bEndArmy1 = gs->curB->belligerents[0];
|
||||
const CArmedInstance *bEndArmy2 = gs->curB->belligerents[1];
|
||||
const CArmedInstance *bEndArmy1 = gs->curB->sides[0].armyObject;
|
||||
const CArmedInstance *bEndArmy2 = gs->curB->sides[1].armyObject;
|
||||
const BattleResult::EResult result = battleResult.get()->result;
|
||||
|
||||
auto findBattleQuery = [this] () -> shared_ptr<CBattleQuery>
|
||||
@ -452,8 +452,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
battleQuery = make_shared<CBattleQuery>(gs->curB);
|
||||
}
|
||||
}
|
||||
if(battleQuery != queries.topQuery(gs->curB->sides[0]))
|
||||
complain("Player " + boost::lexical_cast<std::string>(gs->curB->sides[0]) + " although in battle has no battle query at the top!");
|
||||
if(battleQuery != queries.topQuery(gs->curB->sides[0].color))
|
||||
complain("Player " + boost::lexical_cast<std::string>(gs->curB->sides[0].color) + " although in battle has no battle query at the top!");
|
||||
|
||||
battleQuery->result = *battleResult.data;
|
||||
|
||||
@ -480,7 +480,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
{
|
||||
int maxLevel = eagleEyeLevel + 1;
|
||||
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::EAGLE_EYE);
|
||||
for(const CSpell *sp : gs->curB->usedSpellsHistory[!battleResult.data->winner])
|
||||
for(const CSpell *sp : gs->curB->sides[!battleResult.data->winner].usedSpellsHistory)
|
||||
if(sp->level <= maxLevel && !vstd::contains(finishingBattle->winnerHero->spells, sp->id) && rand() % 100 < eagleEyeChance)
|
||||
cs.spells.insert(sp->id);
|
||||
}
|
||||
@ -534,7 +534,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto armySlot : gs->curB->belligerents[!battleResult.data->winner]->stacks)
|
||||
for (auto armySlot : gs->curB->battleGetArmyObject(!battleResult.data->winner)->stacks)
|
||||
{
|
||||
auto artifactsWorn = armySlot.second->artifactsWorn;
|
||||
for (auto artSlot : artifactsWorn)
|
||||
@ -647,7 +647,7 @@ void CGameHandler::battleAfterLevelUp( const BattleResult &result )
|
||||
logGlobal->traceStream() << "Decremented queries count to " << finishingBattle->remainingBattleQueriesCount;
|
||||
|
||||
if(finishingBattle->remainingBattleQueriesCount > 0)
|
||||
//Battle results will be hndled when all battle queries are closed
|
||||
//Battle results will be handled when all battle queries are closed
|
||||
return;
|
||||
|
||||
//TODO consider if we really want it to work like above. ATM each player as unblocked as soon as possible
|
||||
@ -657,7 +657,7 @@ void CGameHandler::battleAfterLevelUp( const BattleResult &result )
|
||||
// Necromancy if applicable.
|
||||
const CStackBasicDescriptor raisedStack = finishingBattle->winnerHero ? finishingBattle->winnerHero->calculateNecromancy(*battleResult.data) : CStackBasicDescriptor();
|
||||
// Give raised units to winner and show dialog, if any were raised,
|
||||
// units will be given after casualities are taken
|
||||
// units will be given after casualties are taken
|
||||
const SlotID necroSlot = raisedStack.type ? finishingBattle->winnerHero->getSlotFor(raisedStack.type) : SlotID();
|
||||
|
||||
if (necroSlot != SlotID())
|
||||
@ -706,12 +706,11 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
||||
{
|
||||
bat.bsa.clear();
|
||||
bat.stackAttacking = att->ID;
|
||||
int attackerLuck = att->LuckVal();
|
||||
const CGHeroInstance * h0 = gs->curB->heroes[0],
|
||||
* h1 = gs->curB->heroes[1];
|
||||
const int attackerLuck = att->LuckVal();
|
||||
|
||||
auto sideHeroBlocksLuck = [](const SideInBattle &side){ return NBonus::hasOfType(side.hero, Bonus::BLOCK_LUCK); };
|
||||
|
||||
if(!(h0 && NBonus::hasOfType(h0, Bonus::BLOCK_LUCK)) &&
|
||||
!(h1 && NBonus::hasOfType(h1, Bonus::BLOCK_LUCK)))
|
||||
if(!vstd::contains_if(gs->curB->sides, sideHeroBlocksLuck))
|
||||
{
|
||||
if(attackerLuck > 0 && rand()%24 < attackerLuck)
|
||||
{
|
||||
@ -3339,7 +3338,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
}
|
||||
case Battle::RETREAT: //retreat/flee
|
||||
{
|
||||
if(!gs->curB->battleCanFlee(gs->curB->sides[ba.side]))
|
||||
if(!gs->curB->battleCanFlee(gs->curB->sides[ba.side].color))
|
||||
complain("Cannot retreat!");
|
||||
else
|
||||
setBattleResult(BattleResult::ESCAPE, !ba.side); //surrendering side loses
|
||||
@ -3347,7 +3346,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
}
|
||||
case Battle::SURRENDER:
|
||||
{
|
||||
PlayerColor player = gs->curB->sides[ba.side];
|
||||
PlayerColor player = gs->curB->sides[ba.side].color;
|
||||
int cost = gs->curB->battleGetSurrenderCost(player);
|
||||
if(cost < 0)
|
||||
complain("Cannot surrender!");
|
||||
@ -3477,7 +3476,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
|
||||
//second shot for ballista, only if hero has advanced artillery
|
||||
|
||||
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
||||
const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
|
||||
|
||||
if( destStack->alive()
|
||||
&& (stack->getCreature()->idNumber == CreatureID::BALLISTA)
|
||||
@ -3516,7 +3515,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
{
|
||||
StartAction start_action(ba);
|
||||
sendAndApply(&start_action);
|
||||
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
||||
const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
|
||||
CHeroHandler::SBallisticsLevelInfo sbi = VLC->heroh->ballistics[attackingHero->getSecSkillLevel(SecondarySkill::BALLISTICS)];
|
||||
|
||||
EWallParts::EWallParts attackedPart = gs->curB->battleHexToWallPart(ba.destinationTile);
|
||||
@ -3620,7 +3619,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
{
|
||||
StartAction start_action(ba);
|
||||
sendAndApply(&start_action);
|
||||
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
||||
const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
|
||||
const CStack *healer = gs->curB->battleGetStackByID(ba.stackNumber),
|
||||
*destStack = gs->curB->battleGetStackByPos(ba.destinationTile);
|
||||
|
||||
@ -4385,7 +4384,7 @@ void CGameHandler::handleSpellCasting( SpellID spellID, int spellLvl, BattleHex
|
||||
std::vector<CStack *> & battleStacks = gs->curB->stacks;
|
||||
for (auto & battleStack : battleStacks)
|
||||
{
|
||||
if(battleStack->owner == gs->curB->sides[casterSide]) //get enemy stacks which can be affected by this spell
|
||||
if(battleStack->owner == gs->curB->sides[casterSide].color) //get enemy stacks which can be affected by this spell
|
||||
{
|
||||
if (!gs->curB->battleIsImmune(nullptr, spell, ECastingMode::MAGIC_MIRROR, battleStack->position))
|
||||
mirrorTargets.push_back(battleStack);
|
||||
@ -4410,8 +4409,8 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
COMPLAIN_RET_FALSE_IF(ba.side > 1, "Side must be 0 or 1!");
|
||||
|
||||
|
||||
const CGHeroInstance *h = gs->curB->heroes[ba.side];
|
||||
const CGHeroInstance *secondHero = gs->curB->heroes[!ba.side];
|
||||
const CGHeroInstance *h = gs->curB->battleGetFightingHero(ba.side);
|
||||
const CGHeroInstance *secondHero = gs->curB->battleGetFightingHero(!ba.side);
|
||||
if(!h)
|
||||
{
|
||||
logGlobal->warnStream() << "Wrong caster!";
|
||||
@ -4534,10 +4533,11 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
|
||||
if (st->hasBonusOfType(Bonus::MANA_DRAIN) && !vstd::contains(st->state, EBattleStackState::DRAINED_MANA))
|
||||
{
|
||||
const CGHeroInstance * enemy = gs->curB->getHero(gs->curB->theOtherPlayer(st->owner));
|
||||
const CGHeroInstance * owner = gs->curB->getHero(st->owner);
|
||||
if (enemy)
|
||||
{
|
||||
ui32 manaDrained = st->valOfBonuses(Bonus::MANA_DRAIN);
|
||||
vstd::amin (manaDrained, gs->curB->heroes[0]->mana);
|
||||
vstd::amin(manaDrained, gs->curB->battleGetFightingHero(0)->mana);
|
||||
if (manaDrained)
|
||||
{
|
||||
bte.effect = Bonus::MANA_DRAIN;
|
||||
@ -4569,7 +4569,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
|
||||
}
|
||||
BonusList bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTER)));
|
||||
int side = gs->curB->whatSide(st->owner);
|
||||
if (bl.size() && st->casts && !gs->curB->enchanterCounter[side])
|
||||
if (bl.size() && st->casts && !gs->curB->sides[side].enchanterCounter)
|
||||
{
|
||||
int index = rand() % bl.size();
|
||||
SpellID spellID = SpellID(bl[index]->subtype);
|
||||
@ -4624,7 +4624,7 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, c
|
||||
//helper info
|
||||
const SpellCreatedObstacle *spellObstacle = dynamic_cast<const SpellCreatedObstacle*>(&obstacle); //not nice but we may need spell params
|
||||
const ui8 side = curStack->attackerOwned; //if enemy is defending (false = 0), side of our hero is also 0 (attacker)
|
||||
const CGHeroInstance *hero = gs->curB->heroes[side];
|
||||
const CGHeroInstance *hero = gs->curB->battleGetFightingHero(side);
|
||||
|
||||
if(obstacle.obstacleType == CObstacleInstance::MOAT)
|
||||
{
|
||||
@ -5819,14 +5819,15 @@ void CGameHandler::runBattle()
|
||||
}
|
||||
|
||||
//spells opening battle
|
||||
for(int i=0; i<ARRAY_COUNT(gs->curB->heroes); ++i)
|
||||
for(int i = 0; i < 2; ++i)
|
||||
{
|
||||
if(gs->curB->heroes[i] && gs->curB->heroes[i]->hasBonusOfType(Bonus::OPENING_BATTLE_SPELL))
|
||||
auto h = gs->curB->battleGetFightingHero(i);
|
||||
if(h && h->hasBonusOfType(Bonus::OPENING_BATTLE_SPELL))
|
||||
{
|
||||
TBonusListPtr bl = gs->curB->heroes[i]->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
|
||||
TBonusListPtr bl = h->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
|
||||
for (Bonus *b : *bl)
|
||||
{
|
||||
handleSpellCasting(SpellID(b->subtype), 3, -1, 0, gs->curB->heroes[i]->tempOwner, nullptr, gs->curB->heroes[1-i], b->val, ECastingMode::HERO_CASTING, nullptr);
|
||||
handleSpellCasting(SpellID(b->subtype), 3, -1, 0, h->tempOwner, nullptr, gs->curB->battleGetFightingHero(1-i), b->val, ECastingMode::HERO_CASTING, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5853,7 +5854,8 @@ void CGameHandler::runBattle()
|
||||
//check for bad morale => freeze
|
||||
int nextStackMorale = next->MoraleVal();
|
||||
if( nextStackMorale < 0 &&
|
||||
!(NBonus::hasOfType(gs->curB->heroes[0], Bonus::BLOCK_MORALE) || NBonus::hasOfType(gs->curB->heroes[1], Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses)
|
||||
!(NBonus::hasOfType(gs->curB->battleGetFightingHero(0), Bonus::BLOCK_MORALE)
|
||||
|| NBonus::hasOfType(gs->curB->battleGetFightingHero(1), Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses)
|
||||
)
|
||||
{
|
||||
if( rand()%24 < -2 * nextStackMorale)
|
||||
@ -6005,7 +6007,8 @@ void CGameHandler::runBattle()
|
||||
&& !vstd::contains(next->state, EBattleStackState::FEAR)
|
||||
&& next->alive()
|
||||
&& nextStackMorale > 0
|
||||
&& !(NBonus::hasOfType(gs->curB->heroes[0], Bonus::BLOCK_MORALE) || NBonus::hasOfType(gs->curB->heroes[1], Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses
|
||||
&& !(NBonus::hasOfType(gs->curB->battleGetFightingHero(0), Bonus::BLOCK_MORALE)
|
||||
|| NBonus::hasOfType(gs->curB->battleGetFightingHero(1), Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses
|
||||
)
|
||||
{
|
||||
if(rand()%24 < nextStackMorale) //this stack hasn't got morale this turn
|
||||
@ -6033,7 +6036,7 @@ void CGameHandler::runBattle()
|
||||
}
|
||||
}
|
||||
|
||||
endBattle(gs->curB->tile, gs->curB->heroes[0], gs->curB->heroes[1]);
|
||||
endBattle(gs->curB->tile, gs->curB->battleGetFightingHero(0), gs->curB->battleGetFightingHero(1));
|
||||
}
|
||||
|
||||
bool CGameHandler::makeAutomaticAction(const CStack *stack, BattleAction &ba)
|
||||
@ -6210,7 +6213,7 @@ bool CGameHandler::isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, con
|
||||
void CGameHandler::duelFinished()
|
||||
{
|
||||
auto si = getStartInfo();
|
||||
auto getName = [&](int i){ return si->getIthPlayersSettings(gs->curB->sides[i]).name; };
|
||||
auto getName = [&](int i){ return si->getIthPlayersSettings(gs->curB->sides[i].color).name; };
|
||||
|
||||
int casualtiesPoints = 0;
|
||||
logGlobal->debugStream() << boost::format("Winner side %d\nWinner casualties:")
|
||||
@ -6310,10 +6313,10 @@ CGameHandler::FinishingBattleHelper::FinishingBattleHelper(shared_ptr<const CBat
|
||||
auto &result = *Query->result;
|
||||
auto &info = *Query->bi;
|
||||
|
||||
winnerHero = result.winner != 0 ? info.heroes[1] : info.heroes[0];
|
||||
loserHero = result.winner != 0 ? info.heroes[0] : info.heroes[1];
|
||||
victor = info.sides[result.winner];
|
||||
loser = info.sides[!result.winner];
|
||||
winnerHero = result.winner != 0 ? info.sides[1].hero : info.sides[0].hero;
|
||||
loserHero = result.winner != 0 ? info.sides[0].hero : info.sides[1].hero;
|
||||
victor = info.sides[result.winner].color;
|
||||
loser = info.sides[!result.winner].color;
|
||||
duel = Duel;
|
||||
remainingBattleQueriesCount = RemainingBattleQueriesCount;
|
||||
}
|
||||
|
@ -222,13 +222,13 @@ void CBattleQuery::notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit
|
||||
|
||||
CBattleQuery::CBattleQuery(const BattleInfo *Bi)
|
||||
{
|
||||
belligerents[0] = Bi->belligerents[0];
|
||||
belligerents[1] = Bi->belligerents[1];
|
||||
belligerents[0] = Bi->sides[0].armyObject;
|
||||
belligerents[1] = Bi->sides[1].armyObject;
|
||||
|
||||
bi = Bi;
|
||||
|
||||
for(PlayerColor side : bi->sides)
|
||||
addPlayer(side);
|
||||
for(auto &side : bi->sides)
|
||||
addPlayer(side.color);
|
||||
}
|
||||
|
||||
CBattleQuery::CBattleQuery()
|
||||
|
@ -249,7 +249,7 @@ bool MakeAction::applyGh( CGameHandler *gh )
|
||||
if(ba.actionType != Battle::WALK && ba.actionType != Battle::END_TACTIC_PHASE
|
||||
&& ba.actionType != Battle::RETREAT && ba.actionType != Battle::SURRENDER)
|
||||
ERROR_AND_RETURN;
|
||||
if(gh->connections[b->sides[b->tacticsSide]] != c)
|
||||
if(gh->connections[b->sides[b->tacticsSide].color] != c)
|
||||
ERROR_AND_RETURN;
|
||||
}
|
||||
else if(gh->connections[b->battleGetStackByID(b->activeStack)->owner] != c)
|
||||
|
Loading…
x
Reference in New Issue
Block a user