diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index b64cca03e..92efa6cec 100644 --- a/client/CBattleInterface.cpp +++ b/client/CBattleInterface.cpp @@ -1106,6 +1106,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe pos = myRect; strongInterest = true; givenCommand = new CondSh(NULL); + tacticsMode = curInt->cb->battleGetTacticDist(); //create stack queue bool embedQueue = screen->h < 700; @@ -1214,7 +1215,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe console->pos.y = 560 + pos.y; console->pos.w = 406; console->pos.h = 38; - if(curInt->cb->battleGetTacticDist()) + if(tacticsMode) { btactNext = new AdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bTacticNextStack,this), 213 + pos.x, 560 + pos.y, "icm011.def", SDLK_SPACE); btactEnd = new AdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bEndTacticPhase,this), 419 + pos.x, 560 + pos.y, "icm012.def", SDLK_RETURN); @@ -2347,9 +2348,19 @@ void CBattleInterface::giveCommand(ui8 action, THex tile, ui32 stack, si32 addit break; } - myTurn = false; - activeStack = NULL; - givenCommand->setn(ba); + if(!tacticsMode) + { + myTurn = false; + activeStack = NULL; + givenCommand->setn(ba); + } + else + { + curInt->cb->battleMakeTacticAction(ba); + delNull(ba); + // TODO: + // activate next stack + } } bool CBattleInterface::isTileAttackable(const THex & number) const diff --git a/client/CBattleInterface.h b/client/CBattleInterface.h index 875e90ca5..c39602bd5 100644 --- a/client/CBattleInterface.h +++ b/client/CBattleInterface.h @@ -400,6 +400,7 @@ private: float getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group std::map standingFrame; //number of frame in standing animation by stack ID, helps in showing 'random moves' + bool tacticsMode; bool spellDestSelectMode; //if true, player is choosing destination for his spell int spellSelMode; //0 - any location, 1 - any friendly creature, 2 - any hostile creature, 3 - any creature, //4 - obstacle, 5 - teleport -1 - no location diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index f40f5c954..b38b25f38 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -647,6 +647,7 @@ void CPlayerInterface::battleCatapultAttacked(const CatapultAttack & ca) return; } + boost::unique_lock un(*pim); battleInt->stackIsCatapulting(ca); } @@ -657,6 +658,7 @@ void CPlayerInterface::battleStacksRemoved(const BattleStacksRemoved & bsr) return; } + boost::unique_lock un(*pim); for(std::set::const_iterator it = bsr.stackIDs.begin(); it != bsr.stackIDs.end(); ++it) //for each removed stack { battleInt->stackRemoved(LOCPLINT->cb->battleGetStackByID(*it)); diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index 671e4e6be..4a78d7c85 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -1604,6 +1604,8 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const curB->tacticsSide = diff < 0; curB->tacticDistance = std::abs(diff)*2 + 1; } + else + curB->tacticDistance = 0; return curB; } @@ -1611,8 +1613,8 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const bool BattleInfo::isInTacticRange( THex dest ) const { - return ((tacticsSide && dest.getX() > 0 && dest.getX() <= tacticDistance) - || (!tacticsSide && dest.getX() < BFIELD_WIDTH - 1 && dest.getX() >= BFIELD_WIDTH - tacticDistance - 1)); + return ((!tacticsSide && dest.getX() > 0 && dest.getX() <= tacticDistance) + || (tacticsSide && dest.getX() < BFIELD_WIDTH - 1 && dest.getX() >= BFIELD_WIDTH - tacticDistance - 1)); } CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index f8a597bb3..8d6ac606e 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -331,6 +331,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer const CArmedInstance *bEndArmy2 = gs->curB->belligerents[1]; resultsApplied.player1 = bEndArmy1->tempOwner; resultsApplied.player2 = bEndArmy2->tempOwner; + const CGHeroInstance *victoriousHero = gs->curB->heroes[battleResult.data->winner]; if(!duel) { @@ -356,60 +357,56 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer ui8 loser = sides[!battleResult.data->winner]; CasualtiesAfterBattle cab1(bEndArmy1, gs->curB), cab2(bEndArmy2, gs->curB); //calculate casualties before deleting battle + ChangeSpells cs; //for Eagle Eye + if(victoriousHero) + { + if(int eagleEyeLevel = victoriousHero->getSecSkillLevel(CGHeroInstance::EAGLE_EYE)) + { + int maxLevel = eagleEyeLevel + 1; + double eagleEyeChance = victoriousHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, CGHeroInstance::EAGLE_EYE); + BOOST_FOREACH(const CSpell *sp, gs->curB->usedSpellsHistory[!battleResult.data->winner]) + if(sp->level <= maxLevel && !vstd::contains(victoriousHero->spells, sp->id) && rand() % 100 < eagleEyeChance) + cs.spells.insert(sp->id); + } + } sendAndApply(battleResult.data); //Eagle Eye secondary skill handling - /*const CGHeroInstance *vistoriousHero = gs->curB->heroes[battleResult.data->winner]; - if(0 && vistoriousHero) + /*if(cs.spells.size()) { - if(int eagleEyeLevel = vistoriousHero->getSecSkillLevel(CGHeroInstance::EAGLE_EYE)) + cs.learn = 1; + cs.hid = victoriousHero->id; + + InfoWindow iw; + iw.text.addTxt(MetaString::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s + iw.text.addReplacement(victoriousHero->name); + + std::ostringstream names; + for(int i = 0; i < cs.spells.size(); i++) { - int maxLevel = eagleEyeLevel + 1; - double eagleEyeChance = vistoriousHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, CGHeroInstance::EAGLE_EYE); - - ChangeSpells cs; - cs.learn = 1; - cs.hid = vistoriousHero->id; - - BOOST_FOREACH(const CSpell *sp, gs->curB->usedSpellsHistory[!battleResult.data->winner]) - if(rand() % 100 < eagleEyeChance) - cs.spells.insert(sp->id); - - if(cs.spells.size()) - { - InfoWindow iw; - iw.text.addTxt(MetaString::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s - iw.text.addReplacement(vistoriousHero->name); - - std::ostringstream names; - for(int i = 0; i < cs.spells.size(); i++) - { - names << "%s"; - if(i < cs.spells.size() - 2) - names << ", "; - else if(i < cs.spells.size() - 1) - names << "%s"; - } - - iw.text.addReplacement(names.str()); - - std::set::iterator it = cs.spells.begin(); - for(int i = 0; i < cs.spells.size(); i++, it++) - { - iw.text.addReplacement(MetaString::SPELL_NAME, *it); - if(i == cs.spells.size() - 2) //we just added pre-last name - iw.text.addReplacement(MetaString::GENERAL_TXT, 141); // " and " - iw.components.push_back(Component(Component::SPELL, *it, 0, 0)); - } - - sendAndApply(&iw); - sendAndApply(&cs); - } + names << "%s"; + if(i < cs.spells.size() - 2) + names << ", "; + else if(i < cs.spells.size() - 1) + names << "%s"; } - } - */ + + iw.text.addReplacement(names.str()); + + std::set::iterator it = cs.spells.begin(); + for(int i = 0; i < cs.spells.size(); i++, it++) + { + iw.text.addReplacement(MetaString::SPELL_NAME, *it); + if(i == cs.spells.size() - 2) //we just added pre-last name + iw.text.addReplacement(MetaString::GENERAL_TXT, 141); // " and " + iw.components.push_back(Component(Component::SPELL, *it, 0, 0)); + } + + sendAndApply(&iw); + sendAndApply(&cs); + }*/ if(!duel) { diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index fe284e041..5c2c93ba4 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -208,16 +208,18 @@ bool QueryReply::applyGh( CGameHandler *gh ) bool MakeAction::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; - - if(GS(gh)->curB->tacticDistance) + const BattleInfo *b = GS(gh)->curB; + if(!b) ERROR_AND_RETURN; + + if(b->tacticDistance) { if(ba.actionType != BattleAction::WALK && ba.actionType != BattleAction::END_TACTIC_PHASE) ERROR_AND_RETURN; - if(gh->connections[GS(gh)->curB->sides[GS(gh)->curB->tacticsSide]] != c) + if(gh->connections[b->sides[b->tacticsSide]] != c) ERROR_AND_RETURN; } + else if(gh->connections[b->getStack(b->activeStack)->owner] != c) + ERROR_AND_RETURN; return gh->makeBattleAction(ba); }