1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

* INFINITE_DIST is now enum, it should cause least trouble that way. Uh, it's so hard to fight magic values these days.

* Fixed crashes in battles after loading game
* Fixed crash in battle AI, when stack is blocked and stands next to an enemy
* Fixes problem when server's moveStack is called with dest==position
* Above should cover #1053.
This commit is contained in:
Michał W. Urbańczyk
2012-08-26 19:13:57 +00:00
parent d5f29d134f
commit 7c09f73402
5 changed files with 51 additions and 42 deletions

View File

@@ -935,6 +935,9 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
assert(gs->curB->isInTacticRange(dest));
}
if(curStack->position == dest)
return 0;
//initing necessary tables
auto accessibility = getAccesibility();
@@ -3255,7 +3258,10 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
{
StartAction start_action(ba);
sendAndApply(&start_action); //start movement
moveStack(ba.stackNumber,ba.destinationTile); //move
int walkedTiles = moveStack(ba.stackNumber,ba.destinationTile); //move
if(!walkedTiles)
complain("Stack failed movement!");
sendAndApply(&end_action);
break;
}
@@ -3306,26 +3312,25 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
{
StartAction start_action(ba);
sendAndApply(&start_action); //start movement and attack
int startingPos = gs->curB->battleGetStackByID(ba.stackNumber)->position;
int startingPos = stack->position;
int distance = moveStack(ba.stackNumber, ba.destinationTile);
const CStack *curStack = gs->curB->battleGetStackByID(ba.stackNumber),
*stackAtEnd = gs->curB->battleGetStackByPos(ba.additionalInfo);
const CStack *stackAtEnd = gs->curB->battleGetStackByPos(ba.additionalInfo);
if(!curStack || !stackAtEnd)
if(!stack || !stackAtEnd)
{
sendAndApply(&end_action);
break;
}
tlog5 << curStack->nodeName() << " will attack " << stackAtEnd->nodeName() << std::endl;
tlog5 << stack->nodeName() << " will attack " << stackAtEnd->nodeName() << std::endl;
if(curStack->position != ba.destinationTile //we wasn't able to reach destination tile
&& !(curStack->doubleWide()
&& ( curStack->position == ba.destinationTile + (curStack->attackerOwned ? +1 : -1 ) )
if(stack->position != ba.destinationTile //we wasn't able to reach destination tile
&& !(stack->doubleWide()
&& ( stack->position == ba.destinationTile + (stack->attackerOwned ? +1 : -1 ) )
) //nor occupy specified hex
)
{
std::string problem = "We cannot move this stack to its destination " + curStack->getCreature()->namePl;
std::string problem = "We cannot move this stack to its destination " + stack->getCreature()->namePl;
tlog3 << problem << std::endl;
complain(problem);
ok = false;
@@ -3333,7 +3338,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
break;
}
if(stackAtEnd && curStack->ID == stackAtEnd->ID) //we should just move, it will be handled by following check
if(stackAtEnd && stack->ID == stackAtEnd->ID) //we should just move, it will be handled by following check
{
stackAtEnd = NULL;
}
@@ -3346,7 +3351,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
break;
}
if( !CStack::isMeleeAttackPossible(curStack, stackAtEnd) )
if( !CStack::isMeleeAttackPossible(stack, stackAtEnd) )
{
complain("Attack cannot be performed!");
sendAndApply(&end_action);
@@ -3357,39 +3362,39 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
//attack
{
BattleAttack bat;
prepareAttack(bat, curStack, stackAtEnd, distance, ba.additionalInfo);
prepareAttack(bat, stack, stackAtEnd, distance, ba.additionalInfo);
handleAttackBeforeCasting(bat); //only before first attack
sendAndApply(&bat);
handleAfterAttackCasting(bat);
}
//counterattack
if(!curStack->hasBonusOfType(Bonus::BLOCKS_RETALIATION)
if(!stack->hasBonusOfType(Bonus::BLOCKS_RETALIATION)
&& stackAtEnd->ableToRetaliate()
&& curStack->alive()) //attacker may have died (fire shield)
&& stack->alive()) //attacker may have died (fire shield)
{
BattleAttack bat;
prepareAttack(bat, stackAtEnd, curStack, 0, curStack->position);
prepareAttack(bat, stackAtEnd, stack, 0, stack->position);
bat.flags |= BattleAttack::COUNTER;
sendAndApply(&bat);
handleAfterAttackCasting(bat);
}
//second attack
if(curStack //FIXME: clones tend to dissapear during actions
&& curStack->valOfBonuses(Bonus::ADDITIONAL_ATTACK) > 0
&& !curStack->hasBonusOfType(Bonus::SHOOTER)
&& curStack->alive()
if(stack //FIXME: clones tend to dissapear during actions
&& stack->valOfBonuses(Bonus::ADDITIONAL_ATTACK) > 0
&& !stack->hasBonusOfType(Bonus::SHOOTER)
&& stack->alive()
&& stackAtEnd->alive() )
{
BattleAttack bat;
prepareAttack(bat, curStack, stackAtEnd, 0, ba.additionalInfo);
prepareAttack(bat, stack, stackAtEnd, 0, ba.additionalInfo);
sendAndApply(&bat);
handleAfterAttackCasting(bat);
}
//return
if(curStack->hasBonusOfType(Bonus::RETURN_AFTER_STRIKE) && startingPos != curStack->position && curStack->alive())
if(stack->hasBonusOfType(Bonus::RETURN_AFTER_STRIKE) && startingPos != stack->position && stack->alive())
{
moveStack(ba.stackNumber, startingPos);
//NOTE: curStack->ID == ba.stackNumber (rev 1431)
@@ -3399,10 +3404,12 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
}
case BattleAction::SHOOT: //shoot
{
const CStack *curStack = gs->curB->battleGetStackByID(ba.stackNumber),
*destStack= gs->curB->battleGetStackByPos(ba.destinationTile);
if( !gs->curB->battleCanShoot(curStack, ba.destinationTile) )
const CStack *destStack= gs->curB->battleGetStackByPos(ba.destinationTile);
if( !gs->curB->battleCanShoot(stack, ba.destinationTile) )
{
complain("Cannot shoot!");
break;
}
StartAction start_action(ba);
sendAndApply(&start_action); //start shooting
@@ -3410,30 +3417,30 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
{
BattleAttack bat;
bat.flags |= BattleAttack::SHOT;
prepareAttack(bat, curStack, destStack, 0, ba.destinationTile);
prepareAttack(bat, stack, destStack, 0, ba.destinationTile);
handleAttackBeforeCasting(bat);
sendAndApply(&bat);
handleAfterAttackCasting(bat);
}
//ballista & artillery handling
if(destStack->alive() && curStack->getCreature()->idNumber == 146)
if(destStack->alive() && stack->getCreature()->idNumber == 146)
{
BattleAttack bat2;
bat2.flags |= BattleAttack::SHOT;
prepareAttack(bat2, curStack, destStack, 0, ba.destinationTile);
prepareAttack(bat2, stack, destStack, 0, ba.destinationTile);
sendAndApply(&bat2);
}
//TODO: allow more than one additional attack
if(curStack->valOfBonuses(Bonus::ADDITIONAL_ATTACK) > 0 //if unit shots twice let's make another shot
&& curStack->alive()
if(stack->valOfBonuses(Bonus::ADDITIONAL_ATTACK) > 0 //if unit shots twice let's make another shot
&& stack->alive()
&& destStack->alive()
&& curStack->shots
&& stack->shots
)
{
BattleAttack bat;
bat.flags |= BattleAttack::SHOT;
prepareAttack(bat, curStack, destStack, 0, ba.destinationTile);
prepareAttack(bat, stack, destStack, 0, ba.destinationTile);
sendAndApply(&bat);
handleAfterAttackCasting(bat);
}