|
@@ -19,7 +19,7 @@
|
|
#include "../lib/VCMIDirs.h"
|
|
#include "../lib/VCMIDirs.h"
|
|
#include "../client/CSoundBase.h"
|
|
#include "../client/CSoundBase.h"
|
|
#include "CGameHandler.h"
|
|
#include "CGameHandler.h"
|
|
-
|
|
|
|
|
|
+#include <boost/format.hpp>
|
|
|
|
|
|
/*
|
|
/*
|
|
* CGameHandler.cpp, part of VCMI engine
|
|
* CGameHandler.cpp, part of VCMI engine
|
|
@@ -309,8 +309,6 @@ void CGameHandler::changeSecSkill( int ID, int which, int val, bool abs/*=false*
|
|
void CGameHandler::startBattle( const CArmedInstance *armies[2], int3 tile, const CGHeroInstance *heroes[2], bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town /*= NULL*/ )
|
|
void CGameHandler::startBattle( const CArmedInstance *armies[2], int3 tile, const CGHeroInstance *heroes[2], bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town /*= NULL*/ )
|
|
{
|
|
{
|
|
battleEndCallback = new boost::function<void(BattleResult*)>(cb);
|
|
battleEndCallback = new boost::function<void(BattleResult*)>(cb);
|
|
- bEndArmy1 = armies[0];
|
|
|
|
- bEndArmy2 = armies[1];
|
|
|
|
{
|
|
{
|
|
setupBattle(tile, armies, heroes, creatureBank, town); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
|
|
setupBattle(tile, armies, heroes, creatureBank, town); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
|
|
}
|
|
}
|
|
@@ -321,6 +319,9 @@ void CGameHandler::startBattle( const CArmedInstance *armies[2], int3 tile, cons
|
|
void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
|
|
void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
|
|
{
|
|
{
|
|
BattleResultsApplied resultsApplied;
|
|
BattleResultsApplied resultsApplied;
|
|
|
|
+
|
|
|
|
+ const CArmedInstance *bEndArmy1 = gs->curB->belligerents[0];
|
|
|
|
+ const CArmedInstance *bEndArmy2 = gs->curB->belligerents[0];
|
|
resultsApplied.player1 = bEndArmy1->tempOwner;
|
|
resultsApplied.player1 = bEndArmy1->tempOwner;
|
|
resultsApplied.player2 = bEndArmy2->tempOwner;
|
|
resultsApplied.player2 = bEndArmy2->tempOwner;
|
|
|
|
|
|
@@ -425,33 +426,6 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
|
delete battleResult.data;
|
|
delete battleResult.data;
|
|
}
|
|
}
|
|
|
|
|
|
-void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, const CStack *def)
|
|
|
|
-{
|
|
|
|
- bsa.killedAmount = bsa.damageAmount / def->MaxHealth();
|
|
|
|
- unsigned damageFirst = bsa.damageAmount % def->MaxHealth();
|
|
|
|
-
|
|
|
|
- if( def->firstHPleft <= damageFirst )
|
|
|
|
- {
|
|
|
|
- bsa.killedAmount++;
|
|
|
|
- bsa.newHP = def->firstHPleft + def->MaxHealth() - damageFirst;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- bsa.newHP = def->firstHPleft - damageFirst;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if(def->count <= bsa.killedAmount) //stack killed
|
|
|
|
- {
|
|
|
|
- bsa.newAmount = 0;
|
|
|
|
- bsa.flags |= 1;
|
|
|
|
- bsa.killedAmount = def->count; //we cannot kill more creatures than we have
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- bsa.newAmount = def->count - bsa.killedAmount;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CStack *def, int distance)
|
|
void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CStack *def, int distance)
|
|
{
|
|
{
|
|
bat.bsa.clear();
|
|
bat.bsa.clear();
|
|
@@ -480,7 +454,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
|
|
|
|
|
|
|
|
|
int dmg = bsa->damageAmount;
|
|
int dmg = bsa->damageAmount;
|
|
- prepareAttacked(*bsa, def);
|
|
|
|
|
|
+ def->prepareAttacked(*bsa);
|
|
|
|
|
|
//life drain handling
|
|
//life drain handling
|
|
if (att->hasBonusOfType(Bonus::LIFE_DRAIN))
|
|
if (att->hasBonusOfType(Bonus::LIFE_DRAIN))
|
|
@@ -515,7 +489,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
|
bsa->effect = 11;
|
|
bsa->effect = 11;
|
|
|
|
|
|
bsa->damageAmount = (dmg * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100;
|
|
bsa->damageAmount = (dmg * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100;
|
|
- prepareAttacked(*bsa, att);
|
|
|
|
|
|
+ att->prepareAttacked(*bsa);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
@@ -3026,21 +3000,21 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|
bool ok = true;
|
|
bool ok = true;
|
|
switch(ba.actionType)
|
|
switch(ba.actionType)
|
|
{
|
|
{
|
|
- case 2: //walk
|
|
|
|
|
|
+ case BattleAction::WALK: //walk
|
|
{
|
|
{
|
|
sendAndApply(&StartAction(ba)); //start movement
|
|
sendAndApply(&StartAction(ba)); //start movement
|
|
moveStack(ba.stackNumber,ba.destinationTile); //move
|
|
moveStack(ba.stackNumber,ba.destinationTile); //move
|
|
sendAndApply(&EndAction());
|
|
sendAndApply(&EndAction());
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case 3: //defend
|
|
|
|
- case 8: //wait
|
|
|
|
|
|
+ case BattleAction::DEFEND: //defend
|
|
|
|
+ case BattleAction::WAIT: //wait
|
|
{
|
|
{
|
|
sendAndApply(&StartAction(ba));
|
|
sendAndApply(&StartAction(ba));
|
|
sendAndApply(&EndAction());
|
|
sendAndApply(&EndAction());
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case 4: //retreat/flee
|
|
|
|
|
|
+ case BattleAction::RETREAT: //retreat/flee
|
|
{
|
|
{
|
|
if( !gs->curB->battleCanFlee(ba.side ? gs->curB->side2 : gs->curB->side1) )
|
|
if( !gs->curB->battleCanFlee(ba.side ? gs->curB->side2 : gs->curB->side1) )
|
|
break;
|
|
break;
|
|
@@ -3053,7 +3027,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|
battleResult.set(br);
|
|
battleResult.set(br);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case 6: //walk or attack
|
|
|
|
|
|
+ case BattleAction::WALK_AND_ATTACK: //walk or attack
|
|
{
|
|
{
|
|
sendAndApply(&StartAction(ba)); //start movement and attack
|
|
sendAndApply(&StartAction(ba)); //start movement and attack
|
|
int startingPos = gs->curB->getStack(ba.stackNumber)->position;
|
|
int startingPos = gs->curB->getStack(ba.stackNumber)->position;
|
|
@@ -3075,37 +3049,20 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- if(curStack->ID == stackAtEnd->ID) //we should just move, it will be handled by following check
|
|
|
|
|
|
+ if(stackAtEnd && curStack->ID == stackAtEnd->ID) //we should just move, it will be handled by following check
|
|
{
|
|
{
|
|
stackAtEnd = NULL;
|
|
stackAtEnd = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
if(!stackAtEnd)
|
|
if(!stackAtEnd)
|
|
{
|
|
{
|
|
- std::ostringstream problem;
|
|
|
|
- problem << "There is no stack on " << ba.additionalInfo << " tile (no attack)!";
|
|
|
|
- std::string probl = problem.str();
|
|
|
|
- tlog3 << probl << std::endl;
|
|
|
|
- complain(probl);
|
|
|
|
|
|
+ complain(boost::str(boost::format("walk and attack error: no stack at additionalInfo tile (%d)!\n") % ba.additionalInfo));
|
|
ok = false;
|
|
ok = false;
|
|
sendAndApply(&EndAction());
|
|
sendAndApply(&EndAction());
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- ui16 curpos = curStack->position,
|
|
|
|
- enemypos = stackAtEnd->position;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- if( !(
|
|
|
|
- (THex::mutualPosition(curpos, enemypos) >= 0) //front <=> front
|
|
|
|
- || (curStack->doubleWide() //back <=> front
|
|
|
|
- && THex::mutualPosition(curpos + (curStack->attackerOwned ? -1 : 1), enemypos) >= 0)
|
|
|
|
- || (stackAtEnd->doubleWide() //front <=> back
|
|
|
|
- && THex::mutualPosition(curpos, enemypos + (stackAtEnd->attackerOwned ? -1 : 1)) >= 0)
|
|
|
|
- || (stackAtEnd->doubleWide() && curStack->doubleWide()//back <=> back
|
|
|
|
- && THex::mutualPosition(curpos + (curStack->attackerOwned ? -1 : 1), enemypos + (stackAtEnd->attackerOwned ? -1 : 1)) >= 0)
|
|
|
|
- )
|
|
|
|
- )
|
|
|
|
|
|
+ if( !CStack::isMeleeAttackPossible(curStack, stackAtEnd) )
|
|
{
|
|
{
|
|
tlog3 << "Attack cannot be performed!";
|
|
tlog3 << "Attack cannot be performed!";
|
|
sendAndApply(&EndAction());
|
|
sendAndApply(&EndAction());
|
|
@@ -3152,7 +3109,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|
sendAndApply(&EndAction());
|
|
sendAndApply(&EndAction());
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case 7: //shoot
|
|
|
|
|
|
+ case BattleAction::SHOOT: //shoot
|
|
{
|
|
{
|
|
CStack *curStack = gs->curB->getStack(ba.stackNumber),
|
|
CStack *curStack = gs->curB->getStack(ba.stackNumber),
|
|
*destStack= gs->curB->getStackT(ba.destinationTile);
|
|
*destStack= gs->curB->getStackT(ba.destinationTile);
|
|
@@ -3180,7 +3137,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|
sendAndApply(&EndAction());
|
|
sendAndApply(&EndAction());
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case 9: //catapult
|
|
|
|
|
|
+ case BattleAction::CATAPULT: //catapult
|
|
{
|
|
{
|
|
sendAndApply(&StartAction(ba));
|
|
sendAndApply(&StartAction(ba));
|
|
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
|
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
|
@@ -3282,7 +3239,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|
sendAndApply(&EndAction());
|
|
sendAndApply(&EndAction());
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- case 12: //healing
|
|
|
|
|
|
+ case BattleAction::STACK_HEAL: //healing
|
|
{
|
|
{
|
|
sendAndApply(&StartAction(ba));
|
|
sendAndApply(&StartAction(ba));
|
|
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
|
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
|
@@ -3609,7 +3566,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|
bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
|
|
bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
|
|
bsa.stackAttacked = (*it)->ID;
|
|
bsa.stackAttacked = (*it)->ID;
|
|
bsa.attackerID = -1;
|
|
bsa.attackerID = -1;
|
|
- prepareAttacked(bsa,*it);
|
|
|
|
|
|
+ (*it)->prepareAttacked(bsa);
|
|
si.stacks.push_back(bsa);
|
|
si.stacks.push_back(bsa);
|
|
}
|
|
}
|
|
if(!si.stacks.empty())
|
|
if(!si.stacks.empty())
|