diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index 192c5b7a1..912c69e7f 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -1472,6 +1472,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const { CMP_stack cmpst; BattleInfo *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] == 254) @@ -1765,17 +1766,20 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const ////////////////////////////////////////////////////////////////////////// //tactics + bool isTacticsAllowed = !creatureBank; //no tactics in crebanks + int tacticLvls[2] = {0}; for(int i = 0; i < ARRAY_COUNT(tacticLvls); i++) { if(heroes[i]) tacticLvls[i] += heroes[i]->getSecSkillLevel(CGHeroInstance::TACTICS); } + int tacticsSkillDiff = tacticLvls[0] - tacticLvls[1]; - if(int diff = tacticLvls[0] - tacticLvls[1]) + if(tacticsSkillDiff && isTacticsAllowed) { - curB->tacticsSide = diff < 0; - curB->tacticDistance = std::abs(diff)*2 + 1; + curB->tacticsSide = tacticsSkillDiff < 0; + curB->tacticDistance = std::abs(tacticsSkillDiff)*2 + 1; } else curB->tacticDistance = 0; @@ -1820,6 +1824,8 @@ ESpellCastProblem::ESpellCastProblem BattleInfo::battleCanCastSpell(int player, { case ECastingMode::HERO_CASTING: { + if(tacticDistance) + return ESpellCastProblem::ONGOING_TACTIC_PHASE; if(castSpells[side] > 0) return ESpellCastProblem::ALREADY_CASTED_THIS_TURN; if(!heroes[side]) diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index a629678c4..77791ad02 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -2081,7 +2081,7 @@ int CGameState::victoryCheck( ui8 player ) const BOOST_FOREACH(const CGTownInstance *t, map->towns) if((t == map->victoryCondition.obj || !map->victoryCondition.obj) && t->tempOwner == player - && vstd::contains(t->builtBuildings, 26)) + && vstd::contains(t->builtBuildings, EBuilding::GRAIL)) return 1; break; diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 7f83eefb6..372108df1 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -145,7 +145,7 @@ namespace ESpellCastProblem OK, NO_HERO_TO_CAST_SPELL, ALREADY_CASTED_THIS_TURN, NO_SPELLBOOK, ANOTHER_ELEMENTAL_SUMMONED, HERO_DOESNT_KNOW_SPELL, NOT_ENOUGH_MANA, ADVMAP_SPELL_INSTEAD_OF_BATTLE_SPELL, SECOND_HEROS_SPELL_IMMUNITY, SPELL_LEVEL_LIMIT_EXCEEDED, NO_SPELLS_TO_DISPEL, - NO_APPROPRIATE_TARGET, STACK_IMMUNE_TO_SPELL, WRONG_SPELL_TARGET + NO_APPROPRIATE_TARGET, STACK_IMMUNE_TO_SPELL, WRONG_SPELL_TARGET, ONGOING_TACTIC_PHASE }; } diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index bed38abda..15ed8e64a 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -265,8 +265,12 @@ bool MakeAction::applyGh( CGameHandler *gh ) bool MakeCustomAction::applyGh( CGameHandler *gh ) { - if(!GS(gh)->curB) ERROR_AND_RETURN; - if(gh->connections[GS(gh)->curB->getStack(GS(gh)->curB->activeStack)->owner] != c) ERROR_AND_RETURN; + const BattleInfo *b = GS(gh)->curB; + if(!b) ERROR_AND_RETURN; + if(b->tacticDistance) ERROR_AND_RETURN; + const CStack *active = GS(gh)->curB->getStack(GS(gh)->curB->activeStack); + if(!active) ERROR_AND_RETURN; + if(gh->connections[active->owner] != c) ERROR_AND_RETURN; return gh->makeCustomAction(ba); }