2009-01-15 19:01:08 +02:00
# include "CBattleInterface.h"
# include "CGameInfo.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CLodHandler.h"
2009-01-15 19:01:08 +02:00
# include "SDL_Extensions.h"
# include "CAdvmapInterface.h"
# include "AdventureMapButton.h"
2010-11-15 17:15:00 +02:00
# include "CAnimation.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CObjectHandler.h"
# include "../lib/CHeroHandler.h"
# include "CDefHandler.h"
# include "../lib/CSpellHandler.h"
# include "CMusicHandler.h"
2009-01-15 19:01:08 +02:00
# include "CMessage.h"
# include "CCursorHandler.h"
2009-05-20 13:08:56 +03:00
# include "../CCallback.h"
2010-12-25 21:23:30 +02:00
# include "../lib/BattleState.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CGeneralTextHandler.h"
2009-05-20 13:08:56 +03:00
# include "CCreatureAnimation.h"
# include "Graphics.h"
# include "CSpellWindow.h"
# include "CConfigHandler.h"
2009-01-15 19:01:08 +02:00
# include <queue>
# include <sstream>
2009-05-20 13:08:56 +03:00
# include "../lib/CondSh.h"
# include "../lib/NetPacks.h"
2009-05-20 12:02:50 +03:00
# include "CPlayerInterface.h"
2011-03-03 20:25:48 +02:00
# include "CCreatureWindow.h"
2010-12-20 23:22:53 +02:00
# include "CVideoHandler.h"
# include "../lib/CTownHandler.h"
2011-08-20 14:27:09 +03:00
# include "../lib/map.h"
2009-01-15 19:01:08 +02:00
# include <boost/assign/list_of.hpp>
2010-12-06 01:10:02 +02:00
# include <boost/foreach.hpp>
2009-09-20 15:47:40 +03:00
# include <boost/lexical_cast.hpp>
2009-11-13 18:02:25 +02:00
# include <boost/algorithm/string/replace.hpp>
2009-01-15 19:01:08 +02:00
# ifndef __GNUC__
const double M_PI = 3.14159265358979323846 ;
# else
# define _USE_MATH_DEFINES
# include <cmath>
# endif
2011-03-05 18:38:22 +02:00
# include <boost/format.hpp>
2009-01-15 19:01:08 +02:00
2009-04-15 17:03:31 +03:00
/*
* CBattleInterface . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2009-01-15 19:01:08 +02:00
extern SDL_Surface * screen ;
extern SDL_Color zwykly ;
2009-09-16 13:36:50 +03:00
CondSh < bool > CBattleInterface : : animsAreDisplayed ;
2009-03-28 20:46:20 +02:00
2009-01-15 19:01:08 +02:00
struct CMP_stack2
{
inline bool operator ( ) ( const CStack & a , const CStack & b )
{
2009-04-04 22:26:41 +03:00
return ( a . Speed ( ) ) > ( b . Speed ( ) ) ;
2009-01-15 19:01:08 +02:00
}
} cmpst2 ;
2009-08-01 14:55:40 +03:00
static void transformPalette ( SDL_Surface * surf , float rCor , float gCor , float bCor )
{
SDL_Color * colorsToChange = surf - > format - > palette - > colors ;
for ( int g = 0 ; g < surf - > format - > palette - > ncolors ; + + g )
{
if ( ( colorsToChange + g ) - > b ! = 132 & &
( colorsToChange + g ) - > g ! = 231 & &
( colorsToChange + g ) - > r ! = 255 ) //it's not yellow border
{
( colorsToChange + g ) - > r = ( float ) ( ( colorsToChange + g ) - > r ) * rCor ;
( colorsToChange + g ) - > g = ( float ) ( ( colorsToChange + g ) - > g ) * gCor ;
( colorsToChange + g ) - > b = ( float ) ( ( colorsToChange + g ) - > b ) * bCor ;
}
}
}
2009-09-10 14:28:34 +03:00
////////////////////////Battle helpers
//general anim
void CBattleAnimation : : endAnim ( )
{
for ( std : : list < std : : pair < CBattleAnimation * , bool > > : : iterator it = owner - > pendingAnims . begin ( ) ; it ! = owner - > pendingAnims . end ( ) ; + + it )
{
if ( it - > first = = this )
{
it - > first = NULL ;
}
}
2009-09-14 15:00:23 +03:00
2009-09-10 14:28:34 +03:00
}
2009-09-11 15:46:26 +03:00
bool CBattleAnimation : : isEarliest ( bool perStackConcurrency )
2009-09-10 14:28:34 +03:00
{
int lowestMoveID = owner - > animIDhelper + 5 ;
2011-02-09 17:19:53 +02:00
CBattleStackAnimation * thAnim = dynamic_cast < CBattleStackAnimation * > ( this ) ;
CSpellEffectAnim * thSen = dynamic_cast < CSpellEffectAnim * > ( this ) ;
2009-09-10 14:28:34 +03:00
for ( std : : list < std : : pair < CBattleAnimation * , bool > > : : iterator it = owner - > pendingAnims . begin ( ) ; it ! = owner - > pendingAnims . end ( ) ; + + it )
{
2009-09-11 15:46:26 +03:00
CBattleStackAnimation * stAnim = dynamic_cast < CBattleStackAnimation * > ( it - > first ) ;
2011-02-09 17:19:53 +02:00
CSpellEffectAnim * sen = dynamic_cast < CSpellEffectAnim * > ( it - > first ) ;
2010-12-24 23:44:48 +02:00
if ( perStackConcurrency & & stAnim & & thAnim & & stAnim - > stack - > ID ! = thAnim - > stack - > ID )
2009-09-11 15:46:26 +03:00
continue ;
2011-02-12 18:12:48 +02:00
if ( sen & & thSen & & sen ! = thSen & & perStackConcurrency )
2011-02-09 17:19:53 +02:00
continue ;
2009-09-14 15:00:23 +03:00
CReverseAnim * revAnim = dynamic_cast < CReverseAnim * > ( stAnim ) ;
2010-12-24 23:44:48 +02:00
if ( revAnim & & thAnim & & stAnim & & stAnim - > stack - > ID = = thAnim - > stack - > ID & & revAnim - > priority )
2009-09-11 15:46:26 +03:00
return false ;
2009-09-10 14:28:34 +03:00
if ( it - > first )
amin ( lowestMoveID , it - > first - > ID ) ;
}
2011-02-09 17:19:53 +02:00
return ID = = lowestMoveID | | lowestMoveID = = ( owner - > animIDhelper + 5 ) ;
2009-09-10 14:28:34 +03:00
}
CBattleAnimation : : CBattleAnimation ( CBattleInterface * _owner )
: owner ( _owner ) , ID ( _owner - > animIDhelper + + )
{ }
2010-01-28 19:23:01 +02:00
//Dummy animation
bool CDummyAnim : : init ( )
{
return true ;
}
void CDummyAnim : : nextFrame ( )
{
counter + + ;
if ( counter > howMany )
endAnim ( ) ;
}
void CDummyAnim : : endAnim ( )
{
CBattleAnimation : : endAnim ( ) ;
delete this ;
}
2010-10-31 00:53:41 +03:00
CDummyAnim : : CDummyAnim ( CBattleInterface * _owner , int howManyFrames ) : CBattleAnimation ( _owner ) , counter ( 0 ) , howMany ( howManyFrames )
2010-01-28 19:23:01 +02:00
{
}
2009-09-17 15:59:04 +03:00
//effect animation
bool CSpellEffectAnim : : init ( )
{
2011-02-09 17:19:53 +02:00
if ( ! isEarliest ( true ) )
2009-09-17 15:59:04 +03:00
return false ;
if ( effect = = 12 ) //armageddon
{
if ( effect = = - 1 | | graphics - > battleACToDef [ effect ] . size ( ) ! = 0 )
{
CDefHandler * anim ;
if ( customAnim . size ( ) )
anim = CDefHandler : : giveDef ( customAnim ) ;
else
anim = CDefHandler : : giveDef ( graphics - > battleACToDef [ effect ] [ 0 ] ) ;
2010-07-15 20:13:17 +03:00
if ( Vflip )
{
for ( int v = 0 ; v < anim - > ourImages . size ( ) ; + + v )
{
CSDL_Ext : : VflipSurf ( anim - > ourImages [ v ] . bitmap ) ;
}
}
2009-09-17 15:59:04 +03:00
for ( int i = 0 ; i * anim - > width < owner - > pos . w ; + + i )
{
for ( int j = 0 ; j * anim - > height < owner - > pos . h ; + + j )
{
SBattleEffect be ;
be . effectID = ID ;
be . anim = CDefHandler : : giveDef ( graphics - > battleACToDef [ effect ] [ 0 ] ) ;
2010-07-15 20:13:17 +03:00
if ( Vflip )
{
for ( int v = 0 ; v < be . anim - > ourImages . size ( ) ; + + v )
{
CSDL_Ext : : VflipSurf ( be . anim - > ourImages [ v ] . bitmap ) ;
}
}
2009-09-17 15:59:04 +03:00
be . frame = 0 ;
be . maxFrame = be . anim - > ourImages . size ( ) ;
2009-09-21 11:29:41 +03:00
be . x = i * anim - > width + owner - > pos . x ;
be . y = j * anim - > height + owner - > pos . y ;
2009-09-17 15:59:04 +03:00
owner - > battleEffects . push_back ( be ) ;
}
}
}
2009-09-23 16:22:40 +03:00
else //there is nothing to play
{
endAnim ( ) ;
return false ;
}
2009-09-17 15:59:04 +03:00
}
else // Effects targeted at a specific creature/hex.
{
if ( effect = = - 1 | | graphics - > battleACToDef [ effect ] . size ( ) ! = 0 )
{
2010-02-19 18:02:34 +02:00
const CStack * destStack = owner - > curInt - > cb - > battleGetStackByPos ( destTile , false ) ;
2009-09-17 15:59:04 +03:00
Rect & tilePos = owner - > bfield [ destTile ] . pos ;
SBattleEffect be ;
be . effectID = ID ;
if ( customAnim . size ( ) )
be . anim = CDefHandler : : giveDef ( customAnim ) ;
else
be . anim = CDefHandler : : giveDef ( graphics - > battleACToDef [ effect ] [ 0 ] ) ;
2010-07-15 20:13:17 +03:00
if ( Vflip )
{
for ( int v = 0 ; v < be . anim - > ourImages . size ( ) ; + + v )
{
CSDL_Ext : : VflipSurf ( be . anim - > ourImages [ v ] . bitmap ) ;
}
}
2009-09-17 15:59:04 +03:00
be . frame = 0 ;
be . maxFrame = be . anim - > ourImages . size ( ) ;
2009-09-23 16:22:40 +03:00
if ( effect = = 1 )
be . maxFrame = 3 ;
2009-09-17 15:59:04 +03:00
switch ( effect )
{
case - 1 :
be . x = x ;
be . y = y ;
break ;
case 0 : // Prayer and Lightning Bolt.
case 1 :
// Position effect with it's bottom center touching the bottom center of affected tile(s).
be . x = tilePos . x + tilePos . w / 2 - be . anim - > width / 2 ;
be . y = tilePos . y + tilePos . h - be . anim - > height ;
break ;
default :
// Position effect with it's center touching the top center of affected tile(s).
be . x = tilePos . x + tilePos . w / 2 - be . anim - > width / 2 ;
be . y = tilePos . y - be . anim - > height / 2 ;
break ;
}
// Correction for 2-hex creatures.
2010-05-02 21:20:26 +03:00
if ( destStack ! = NULL & & destStack - > doubleWide ( ) )
2009-09-17 15:59:04 +03:00
be . x + = ( destStack - > attackerOwned ? - 1 : 1 ) * tilePos . w / 2 ;
owner - > battleEffects . push_back ( be ) ;
}
2009-09-23 16:22:40 +03:00
else //there is nothing to play
{
endAnim ( ) ;
return false ;
}
2009-09-17 15:59:04 +03:00
}
//battleEffects
return true ;
}
void CSpellEffectAnim : : nextFrame ( )
{
2009-09-24 13:10:24 +03:00
//notice: there may be more than one effect in owner->battleEffects correcponding to this animation (ie. armageddon)
2009-09-17 15:59:04 +03:00
for ( std : : list < SBattleEffect > : : iterator it = owner - > battleEffects . begin ( ) ; it ! = owner - > battleEffects . end ( ) ; + + it )
{
2009-09-23 16:22:40 +03:00
if ( it - > effectID = = ID )
2009-09-17 15:59:04 +03:00
{
2009-09-23 16:22:40 +03:00
+ + ( it - > frame ) ;
if ( it - > frame = = it - > maxFrame )
{
endAnim ( ) ;
break ;
}
else
{
it - > x + = dx ;
it - > y + = dy ;
}
2009-09-17 15:59:04 +03:00
}
}
}
void CSpellEffectAnim : : endAnim ( )
{
CBattleAnimation : : endAnim ( ) ;
std : : vector < std : : list < SBattleEffect > : : iterator > toDel ;
for ( std : : list < SBattleEffect > : : iterator it = owner - > battleEffects . begin ( ) ; it ! = owner - > battleEffects . end ( ) ; + + it )
{
if ( it - > effectID = = ID )
{
toDel . push_back ( it ) ;
}
}
for ( int b = 0 ; b < toDel . size ( ) ; + + b )
{
2009-09-18 15:50:00 +03:00
delete toDel [ b ] - > anim ;
2009-09-17 15:59:04 +03:00
owner - > battleEffects . erase ( toDel [ b ] ) ;
}
delete this ;
}
2010-12-23 22:18:10 +02:00
CSpellEffectAnim : : CSpellEffectAnim ( CBattleInterface * _owner , ui32 _effect , THex _destTile , int _dx , int _dy , bool _Vflip )
2010-07-15 20:13:17 +03:00
: CBattleAnimation ( _owner ) , effect ( _effect ) , destTile ( _destTile ) , customAnim ( " " ) , dx ( _dx ) , dy ( _dy ) , Vflip ( _Vflip )
2009-09-17 15:59:04 +03:00
{
}
2010-07-15 20:13:17 +03:00
CSpellEffectAnim : : CSpellEffectAnim ( CBattleInterface * _owner , std : : string _customAnim , int _x , int _y , int _dx , int _dy , bool _Vflip )
: CBattleAnimation ( _owner ) , effect ( - 1 ) , destTile ( 0 ) , customAnim ( _customAnim ) , x ( _x ) , y ( _y ) , dx ( _dx ) , dy ( _dy ) , Vflip ( _Vflip )
2009-09-17 15:59:04 +03:00
{
}
2009-09-10 14:28:34 +03:00
//stack's aniamtion
2010-12-24 23:44:48 +02:00
CBattleStackAnimation : : CBattleStackAnimation ( CBattleInterface * _owner , const CStack * _stack )
: CBattleAnimation ( _owner ) , stack ( _stack )
2009-09-10 14:28:34 +03:00
{
}
2010-12-23 22:18:10 +02:00
bool CBattleStackAnimation : : isToReverseHlp ( THex hexFrom , THex hexTo , bool curDir )
2009-09-16 13:09:08 +03:00
{
int fromMod = hexFrom % BFIELD_WIDTH ;
int fromDiv = hexFrom / BFIELD_WIDTH ;
int toMod = hexTo % BFIELD_WIDTH ;
if ( curDir & & fromMod < toMod )
return false ;
else if ( curDir & & fromMod > toMod )
return true ;
else if ( curDir & & fromMod = = toMod )
{
return fromDiv % 2 = = 0 ;
}
else if ( ! curDir & & fromMod < toMod )
return true ;
else if ( ! curDir & & fromMod > toMod )
return false ;
else if ( ! curDir & & fromMod = = toMod )
{
return fromDiv % 2 = = 1 ;
}
tlog1 < < " Catastrope in CBattleStackAnimation::isToReverse! " < < std : : endl ;
return false ; //should never happen
}
2010-12-23 22:18:10 +02:00
bool CBattleStackAnimation : : isToReverse ( THex hexFrom , THex hexTo , bool curDir , bool toDoubleWide , bool toDir )
2009-09-16 13:09:08 +03:00
{
2009-09-24 16:44:55 +03:00
if ( hexTo < 0 ) //turret
return false ;
2009-09-16 13:09:08 +03:00
if ( toDoubleWide )
{
return isToReverseHlp ( hexFrom , hexTo , curDir ) & &
( toDir ? isToReverseHlp ( hexFrom , hexTo - 1 , curDir ) : isToReverseHlp ( hexFrom , hexTo + 1 , curDir ) ) ;
}
else
{
return isToReverseHlp ( hexFrom , hexTo , curDir ) ;
}
}
2009-09-10 14:28:34 +03:00
//revering animation
bool CReverseAnim : : init ( )
{
2010-12-24 23:44:48 +02:00
if ( owner - > creAnims [ stack - > ID ] = = NULL | | owner - > creAnims [ stack - > ID ] - > getType ( ) = = 5 )
2009-09-10 14:28:34 +03:00
{
endAnim ( ) ;
return false ; //there is no such creature
}
2009-09-14 15:00:23 +03:00
if ( ! priority & & ! isEarliest ( false ) )
return false ;
2009-09-10 14:28:34 +03:00
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : TURN_R ) ;
2009-09-10 14:28:34 +03:00
return true ;
}
void CReverseAnim : : nextFrame ( )
{
if ( partOfAnim = = 1 ) //first part of animation
{
2010-12-24 23:44:48 +02:00
if ( owner - > creAnims [ stack - > ID ] - > onLastFrameInGroup ( ) )
2009-09-10 14:28:34 +03:00
{
partOfAnim = 2 ;
}
}
else if ( partOfAnim = = 2 )
{
if ( ! secondPartSetup )
{
2010-12-24 23:44:48 +02:00
owner - > creDir [ stack - > ID ] = ! owner - > creDir [ stack - > ID ] ;
2009-09-10 14:28:34 +03:00
2010-12-24 23:44:48 +02:00
if ( ! stack )
2010-07-15 14:28:06 +03:00
{
endAnim ( ) ;
return ;
}
2009-09-11 15:46:26 +03:00
2010-12-24 23:44:48 +02:00
Point coords = CBattleHex : : getXYUnitAnim ( hex , owner - > creDir [ stack - > ID ] , stack , owner ) ;
owner - > creAnims [ stack - > ID ] - > pos . x = coords . x ;
2009-09-10 14:28:34 +03:00
//creAnims[stackID]->pos.y = coords.second;
2010-12-24 23:44:48 +02:00
if ( stack - > doubleWide ( ) )
2009-09-10 14:28:34 +03:00
{
2010-12-24 23:44:48 +02:00
if ( stack - > attackerOwned )
2009-09-10 14:28:34 +03:00
{
2010-12-24 23:44:48 +02:00
if ( ! owner - > creDir [ stack - > ID ] )
owner - > creAnims [ stack - > ID ] - > pos . x - = 44 ;
2009-09-10 14:28:34 +03:00
}
else
{
2010-12-24 23:44:48 +02:00
if ( owner - > creDir [ stack - > ID ] )
owner - > creAnims [ stack - > ID ] - > pos . x + = 44 ;
2009-09-10 14:28:34 +03:00
}
}
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : TURN_L ) ;
2009-09-10 14:28:34 +03:00
secondPartSetup = true ;
}
2010-12-24 23:44:48 +02:00
if ( owner - > creAnims [ stack - > ID ] - > onLastFrameInGroup ( ) )
2009-09-10 14:28:34 +03:00
{
endAnim ( ) ;
}
}
}
void CReverseAnim : : endAnim ( )
{
CBattleAnimation : : endAnim ( ) ;
2010-12-24 23:44:48 +02:00
if ( stack - > alive ( ) ) //don't do that if stack is dead
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : HOLDING ) ;
2009-09-10 14:28:34 +03:00
delete this ;
}
2010-12-24 23:44:48 +02:00
CReverseAnim : : CReverseAnim ( CBattleInterface * _owner , const CStack * stack , THex dest , bool _priority )
2010-10-31 00:53:41 +03:00
: CBattleStackAnimation ( _owner , stack ) , partOfAnim ( 1 ) , secondPartSetup ( false ) , hex ( dest ) , priority ( _priority )
2009-09-10 14:28:34 +03:00
{
}
//defence anim
bool CDefenceAnim : : init ( )
{
//checking initial conditions
//if(owner->creAnims[stackID]->getType() != 2)
//{
// return false;
//}
2010-12-24 23:44:48 +02:00
if ( attacker = = NULL & & owner - > battleEffects . size ( ) > 0 )
2009-09-17 15:59:04 +03:00
return false ;
2009-09-10 14:28:34 +03:00
int lowestMoveID = owner - > animIDhelper + 5 ;
for ( std : : list < std : : pair < CBattleAnimation * , bool > > : : iterator it = owner - > pendingAnims . begin ( ) ; it ! = owner - > pendingAnims . end ( ) ; + + it )
{
2009-09-24 13:10:24 +03:00
CDefenceAnim * defAnim = dynamic_cast < CDefenceAnim * > ( it - > first ) ;
2010-12-24 23:44:48 +02:00
if ( defAnim & & defAnim - > stack - > ID ! = stack - > ID )
2009-09-10 14:28:34 +03:00
continue ;
2009-09-16 13:09:08 +03:00
CBattleAttack * attAnim = dynamic_cast < CBattleAttack * > ( it - > first ) ;
2010-12-24 23:44:48 +02:00
if ( attAnim & & attAnim - > stack - > ID ! = stack - > ID )
2009-09-14 15:00:23 +03:00
continue ;
2009-09-10 14:28:34 +03:00
2010-12-24 23:44:48 +02:00
if ( attacker ! = NULL )
2009-09-17 15:59:04 +03:00
{
2010-12-24 23:44:48 +02:00
int attackerAnimType = owner - > creAnims [ attacker - > ID ] - > getType ( ) ;
if ( attackerAnimType = = 11 & & attackerAnimType = = 12 & & attackerAnimType = = 13 & & owner - > creAnims [ attacker - > ID ] - > getFrame ( ) < attacker - > getCreature ( ) - > attackClimaxFrame )
2009-09-17 15:59:04 +03:00
return false ;
}
2009-09-15 15:20:11 +03:00
CReverseAnim * animAsRev = dynamic_cast < CReverseAnim * > ( it - > first ) ;
if ( animAsRev & & animAsRev - > priority )
2009-09-11 15:46:26 +03:00
return false ;
2009-09-10 14:28:34 +03:00
if ( it - > first )
amin ( lowestMoveID , it - > first - > ID ) ;
}
if ( ID > lowestMoveID )
return false ;
2009-09-11 15:46:26 +03:00
2009-09-10 14:28:34 +03:00
2009-09-11 15:46:26 +03:00
//reverse unit if necessary
2010-12-24 23:44:48 +02:00
if ( attacker & & isToReverse ( stack - > position , attacker - > position , owner - > creDir [ stack - > ID ] , attacker - > doubleWide ( ) , owner - > creDir [ attacker - > ID ] ) )
2009-09-11 15:46:26 +03:00
{
2010-12-24 23:44:48 +02:00
owner - > addNewAnim ( new CReverseAnim ( owner , stack , stack - > position , true ) ) ;
2009-09-11 15:46:26 +03:00
return false ;
}
//unit reversed
if ( byShooting ) //delay hit animation
{
2009-09-10 14:28:34 +03:00
for ( std : : list < SProjectileInfo > : : const_iterator it = owner - > projectiles . begin ( ) ; it ! = owner - > projectiles . end ( ) ; + + it )
{
2010-11-20 19:36:02 +02:00
if ( it - > creID = = attacker - > getCreature ( ) - > idNumber )
2009-09-10 14:28:34 +03:00
{
return false ;
}
}
}
//initializing
if ( killed )
{
2010-12-24 23:44:48 +02:00
CCS - > soundh - > playSound ( battle_sound ( stack - > getCreature ( ) , killed ) ) ;
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : DEATH ) ; //death
2009-09-10 14:28:34 +03:00
}
else
{
// TODO: this block doesn't seems correct if the unit is defending.
2010-12-24 23:44:48 +02:00
CCS - > soundh - > playSound ( battle_sound ( stack - > getCreature ( ) , wince ) ) ;
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : HITTED ) ; //getting hit
2009-09-10 14:28:34 +03:00
}
return true ; //initialized successfuly
}
void CDefenceAnim : : nextFrame ( )
{
2011-02-09 15:56:30 +02:00
if ( ! killed & & owner - > creAnims [ stack - > ID ] - > getType ( ) ! = CCreatureAnim : : HITTED )
2009-09-16 13:09:08 +03:00
{
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : HITTED ) ;
2009-09-16 13:09:08 +03:00
}
2010-12-24 23:44:48 +02:00
if ( ! owner - > creAnims [ stack - > ID ] - > onLastFrameInGroup ( ) )
2009-09-10 14:28:34 +03:00
{
2011-02-09 15:56:30 +02:00
if ( owner - > creAnims [ stack - > ID ] - > getType ( ) = = CCreatureAnim : : DEATH & & ( owner - > animCount + 1 ) % ( 4 / owner - > curInt - > sysOpts . animSpeed ) = = 0
2010-12-24 23:44:48 +02:00
& & ! owner - > creAnims [ stack - > ID ] - > onLastFrameInGroup ( ) )
2009-09-10 14:28:34 +03:00
{
2010-12-24 23:44:48 +02:00
owner - > creAnims [ stack - > ID ] - > incrementFrame ( ) ;
2009-09-10 14:28:34 +03:00
}
}
else
{
endAnim ( ) ;
}
}
void CDefenceAnim : : endAnim ( )
{
//restoring animType
2011-02-09 15:56:30 +02:00
if ( owner - > creAnims [ stack - > ID ] - > getType ( ) = = CCreatureAnim : : HITTED )
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : HOLDING ) ;
2009-09-10 14:28:34 +03:00
//printing info to console
2011-08-12 22:38:30 +03:00
//if(attacker!=NULL)
// owner->printConsoleAttacked(stack, dmg, amountKilled, attacker);
2009-09-10 14:28:34 +03:00
2010-11-15 17:15:00 +02:00
//const CStack * attacker = owner->curInt->cb->battleGetStackByID(IDby, false);
//const CStack * attacked = owner->curInt->cb->battleGetStackByID(stackID, false);
2009-09-11 15:46:26 +03:00
2009-09-10 14:28:34 +03:00
CBattleAnimation : : endAnim ( ) ;
delete this ;
}
CDefenceAnim : : CDefenceAnim ( SStackAttackedInfo _attackedInfo , CBattleInterface * _owner )
2010-12-24 23:44:48 +02:00
: CBattleStackAnimation ( _owner , _attackedInfo . defender ) , dmg ( _attackedInfo . dmg ) ,
amountKilled ( _attackedInfo . amountKilled ) , attacker ( _attackedInfo . attacker ) , byShooting ( _attackedInfo . byShooting ) ,
2009-09-10 14:28:34 +03:00
killed ( _attackedInfo . killed )
{
}
////move anim
bool CBattleStackMoved : : init ( )
{
2009-09-11 15:46:26 +03:00
if ( ! isEarliest ( false ) )
2009-09-10 14:28:34 +03:00
return false ;
//a few useful variables
2011-02-09 15:56:30 +02:00
steps = owner - > creAnims [ stack - > ID ] - > framesInGroup ( CCreatureAnim : : MOVING ) * owner - > getAnimSpeedMultiplier ( ) - 1 ;
2010-03-09 13:19:08 +02:00
if ( steps = = 0 ) //this creature seems to have no move animation so we can end it immediately
{
endAnim ( ) ;
return false ;
}
2009-09-10 14:28:34 +03:00
whichStep = 0 ;
int hexWbase = 44 , hexHbase = 42 ;
2010-12-24 23:44:48 +02:00
const CStack * movedStack = stack ;
if ( ! movedStack | | owner - > creAnims [ stack - > ID ] - > getType ( ) = = 5 )
2009-09-10 14:28:34 +03:00
{
endAnim ( ) ;
return false ;
}
2010-11-15 17:15:00 +02:00
//bool twoTiles = movedStack->doubleWide();
2009-09-10 14:28:34 +03:00
2009-09-21 11:29:41 +03:00
Point begPosition = CBattleHex : : getXYUnitAnim ( curStackPos , movedStack - > attackerOwned , movedStack , owner ) ;
2011-08-01 20:36:18 +03:00
Point endPosition = CBattleHex : : getXYUnitAnim ( nextHex , movedStack - > attackerOwned , movedStack , owner ) ;
2009-09-10 14:28:34 +03:00
2011-08-01 20:36:18 +03:00
int mutPos = THex : : mutualPosition ( curStackPos , nextHex ) ;
2009-09-10 14:28:34 +03:00
//reverse unit if necessary
2010-12-24 23:44:48 +02:00
if ( ( begPosition . x > endPosition . x ) & & owner - > creDir [ stack - > ID ] = = true )
2009-09-10 14:28:34 +03:00
{
2010-12-24 23:44:48 +02:00
owner - > addNewAnim ( new CReverseAnim ( owner , stack , curStackPos , true ) ) ;
2009-09-10 14:28:34 +03:00
return false ;
}
2010-12-24 23:44:48 +02:00
else if ( ( begPosition . x < endPosition . x ) & & owner - > creDir [ stack - > ID ] = = false )
2009-09-10 14:28:34 +03:00
{
2010-12-24 23:44:48 +02:00
owner - > addNewAnim ( new CReverseAnim ( owner , stack , curStackPos , true ) ) ;
2009-09-10 14:28:34 +03:00
return false ;
}
2009-09-11 15:46:26 +03:00
2011-02-09 15:56:30 +02:00
if ( owner - > creAnims [ stack - > ID ] - > getType ( ) ! = CCreatureAnim : : MOVING )
2009-09-10 14:28:34 +03:00
{
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : MOVING ) ;
2009-09-10 14:28:34 +03:00
}
//unit reversed
2011-07-13 21:39:02 +03:00
// if(owner->moveSh <= 0)
// owner->moveSh = CCS->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
2009-09-11 15:46:26 +03:00
2009-09-10 14:28:34 +03:00
//step shift calculation
2010-12-24 23:44:48 +02:00
posX = owner - > creAnims [ stack - > ID ] - > pos . x , posY = owner - > creAnims [ stack - > ID ] - > pos . y ; // for precise calculations ;]
2010-05-02 21:20:26 +03:00
if ( mutPos = = - 1 & & movedStack - > hasBonusOfType ( Bonus : : FLYING ) )
2009-09-10 14:28:34 +03:00
{
steps * = distance ;
2009-09-21 11:29:41 +03:00
steps / = 2 ; //to make animation faster
2009-09-10 14:28:34 +03:00
2009-09-21 11:29:41 +03:00
stepX = ( endPosition . x - ( float ) begPosition . x ) / steps ;
stepY = ( endPosition . y - ( float ) begPosition . y ) / steps ;
2009-09-10 14:28:34 +03:00
}
else
{
switch ( mutPos )
{
case 0 :
stepX = ( - 1.0 ) * ( ( float ) hexWbase ) / ( 2.0f * steps ) ;
stepY = ( - 1.0 ) * ( ( float ) hexHbase ) / ( ( float ) steps ) ;
break ;
case 1 :
stepX = ( ( float ) hexWbase ) / ( 2.0f * steps ) ;
stepY = ( - 1.0 ) * ( ( float ) hexHbase ) / ( ( float ) steps ) ;
break ;
case 2 :
stepX = ( ( float ) hexWbase ) / ( ( float ) steps ) ;
stepY = 0.0 ;
break ;
case 3 :
stepX = ( ( float ) hexWbase ) / ( 2.0f * steps ) ;
stepY = ( ( float ) hexHbase ) / ( ( float ) steps ) ;
break ;
case 4 :
stepX = ( - 1.0 ) * ( ( float ) hexWbase ) / ( 2.0f * steps ) ;
stepY = ( ( float ) hexHbase ) / ( ( float ) steps ) ;
break ;
case 5 :
stepX = ( - 1.0 ) * ( ( float ) hexWbase ) / ( ( float ) steps ) ;
stepY = 0.0 ;
break ;
}
}
//step shifts calculated
return true ;
}
void CBattleStackMoved : : nextFrame ( )
{
//moving instructions
posX + = stepX ;
2010-12-24 23:44:48 +02:00
owner - > creAnims [ stack - > ID ] - > pos . x = posX ;
2009-09-10 14:28:34 +03:00
posY + = stepY ;
2010-12-24 23:44:48 +02:00
owner - > creAnims [ stack - > ID ] - > pos . y = posY ;
2009-09-10 14:28:34 +03:00
2011-08-01 20:36:18 +03:00
// Increments step count and check if we are finished with current animation
2009-09-10 14:28:34 +03:00
+ + whichStep ;
if ( whichStep = = steps )
{
2011-08-01 20:36:18 +03:00
// Sets the position of the creature animation sprites
Point coords = CBattleHex : : getXYUnitAnim ( nextHex , owner - > creDir [ stack - > ID ] , stack , owner ) ;
owner - > creAnims [ stack - > ID ] - > pos = coords ;
// true if creature haven't reached the final destination hex
if ( ( nextPos + 1 ) < destTiles . size ( ) )
{
// update the next hex field which has to be reached by the stack
nextPos + + ;
curStackPos = nextHex ;
nextHex = destTiles [ nextPos ] ;
// update position of double wide creatures
bool twoTiles = stack - > doubleWide ( ) ;
if ( twoTiles & & bool ( stack - > attackerOwned ) & & ( owner - > creDir [ stack - > ID ] ! = bool ( stack - > attackerOwned ) ) ) //big attacker creature is reversed
owner - > creAnims [ stack - > ID ] - > pos . x - = 44 ;
else if ( twoTiles & & ( ! bool ( stack - > attackerOwned ) ) & & ( owner - > creDir [ stack - > ID ] ! = bool ( stack - > attackerOwned ) ) ) //big defender creature is reversed
owner - > creAnims [ stack - > ID ] - > pos . x + = 44 ;
// re-init animation
for ( std : : list < std : : pair < CBattleAnimation * , bool > > : : iterator it = owner - > pendingAnims . begin ( ) ; it ! = owner - > pendingAnims . end ( ) ; + + it )
{
if ( it - > first = = this )
{
it - > second = false ;
break ;
}
}
}
else
endAnim ( ) ;
2009-09-10 14:28:34 +03:00
}
}
void CBattleStackMoved : : endAnim ( )
{
2010-12-24 23:44:48 +02:00
const CStack * movedStack = stack ;
2009-09-10 14:28:34 +03:00
CBattleAnimation : : endAnim ( ) ;
if ( movedStack )
2011-08-01 20:36:18 +03:00
owner - > addNewAnim ( new CBattleMoveEnd ( owner , stack , nextHex ) ) ;
2009-09-10 14:28:34 +03:00
2009-09-20 15:47:40 +03:00
if ( owner - > moveSh > = 0 )
{
2010-12-19 16:39:56 +02:00
CCS - > soundh - > stopSound ( owner - > moveSh ) ;
2009-09-20 15:47:40 +03:00
owner - > moveSh = - 1 ;
}
2009-09-10 14:28:34 +03:00
delete this ;
}
2011-08-01 20:36:18 +03:00
CBattleStackMoved : : CBattleStackMoved ( CBattleInterface * _owner , const CStack * _stack , std : : vector < THex > _destTiles , int _distance )
: CBattleStackAnimation ( _owner , _stack ) , destTiles ( _destTiles ) , nextPos ( 0 ) , distance ( _distance ) , stepX ( 0.0f ) , stepY ( 0.0f )
2009-09-10 14:28:34 +03:00
{
2010-12-24 23:44:48 +02:00
curStackPos = stack - > position ;
2011-08-01 20:36:18 +03:00
nextHex = destTiles . front ( ) ;
2009-09-10 14:28:34 +03:00
}
//move started
bool CBattleMoveStart : : init ( )
{
2009-09-11 15:46:26 +03:00
if ( ! isEarliest ( false ) )
2009-09-10 14:28:34 +03:00
return false ;
2010-12-24 23:44:48 +02:00
if ( ! stack | | owner - > creAnims [ stack - > ID ] - > getType ( ) = = 5 )
2009-09-10 14:28:34 +03:00
{
CBattleMoveStart : : endAnim ( ) ;
return false ;
}
2010-12-24 23:44:48 +02:00
CCS - > soundh - > playSound ( battle_sound ( stack - > getCreature ( ) , startMoving ) ) ;
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : MOVE_START ) ;
2009-09-10 14:28:34 +03:00
return true ;
}
void CBattleMoveStart : : nextFrame ( )
{
2010-12-24 23:44:48 +02:00
if ( owner - > creAnims [ stack - > ID ] - > onLastFrameInGroup ( ) )
2009-09-10 14:28:34 +03:00
{
endAnim ( ) ;
}
else
{
2011-02-09 15:56:30 +02:00
if ( ( owner - > animCount + 1 ) % ( 4 / owner - > curInt - > sysOpts . animSpeed ) = = 0 )
owner - > creAnims [ stack - > ID ] - > incrementFrame ( ) ;
2009-09-10 14:28:34 +03:00
}
}
void CBattleMoveStart : : endAnim ( )
{
CBattleAnimation : : endAnim ( ) ;
delete this ;
}
2010-12-24 23:44:48 +02:00
CBattleMoveStart : : CBattleMoveStart ( CBattleInterface * _owner , const CStack * _stack )
: CBattleStackAnimation ( _owner , _stack )
2009-09-10 14:28:34 +03:00
{
}
//move finished
bool CBattleMoveEnd : : init ( )
{
2009-09-11 15:46:26 +03:00
if ( ! isEarliest ( true ) )
2009-09-10 14:28:34 +03:00
return false ;
2011-02-09 15:56:30 +02:00
if ( ! stack | | owner - > creAnims [ stack - > ID ] - > framesInGroup ( CCreatureAnim : : MOVE_END ) = = 0 | |
owner - > creAnims [ stack - > ID ] - > getType ( ) = = CCreatureAnim : : DEATH )
2009-09-10 14:28:34 +03:00
{
endAnim ( ) ;
return false ;
}
2010-12-24 23:44:48 +02:00
CCS - > soundh - > playSound ( battle_sound ( stack - > getCreature ( ) , endMoving ) ) ;
2009-09-10 14:28:34 +03:00
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : MOVE_END ) ;
2009-09-10 14:28:34 +03:00
return true ;
}
void CBattleMoveEnd : : nextFrame ( )
{
2010-12-24 23:44:48 +02:00
if ( owner - > creAnims [ stack - > ID ] - > onLastFrameInGroup ( ) )
2009-09-10 14:28:34 +03:00
{
endAnim ( ) ;
}
}
void CBattleMoveEnd : : endAnim ( )
{
CBattleAnimation : : endAnim ( ) ;
2011-02-09 15:56:30 +02:00
if ( owner - > creAnims [ stack - > ID ] - > getType ( ) ! = CCreatureAnim : : DEATH )
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : HOLDING ) ; //resetting to default
2009-09-10 14:28:34 +03:00
2010-12-19 16:39:56 +02:00
CCS - > curh - > show ( ) ;
2009-09-10 14:28:34 +03:00
delete this ;
}
2010-12-24 23:44:48 +02:00
CBattleMoveEnd : : CBattleMoveEnd ( CBattleInterface * _owner , const CStack * _stack , THex destTile )
: CBattleStackAnimation ( _owner , _stack ) , destinationTile ( destTile )
2009-09-10 14:28:34 +03:00
{
}
//general attack anim
void CBattleAttack : : nextFrame ( )
{
2010-12-24 23:44:48 +02:00
if ( owner - > creAnims [ stack - > ID ] - > getType ( ) ! = group )
owner - > creAnims [ stack - > ID ] - > setType ( group ) ;
2009-09-10 14:28:34 +03:00
2010-12-24 23:44:48 +02:00
if ( owner - > creAnims [ stack - > ID ] - > onFirstFrameInGroup ( ) )
2009-09-10 14:28:34 +03:00
{
if ( shooting )
2010-12-19 16:39:56 +02:00
CCS - > soundh - > playSound ( battle_sound ( attackingStack - > getCreature ( ) , shoot ) ) ;
2009-09-10 14:28:34 +03:00
else
2010-12-19 16:39:56 +02:00
CCS - > soundh - > playSound ( battle_sound ( attackingStack - > getCreature ( ) , attack ) ) ;
2009-09-10 14:28:34 +03:00
}
2010-12-24 23:44:48 +02:00
else if ( owner - > creAnims [ stack - > ID ] - > onLastFrameInGroup ( ) )
2009-09-10 14:28:34 +03:00
{
2011-02-09 15:56:30 +02:00
owner - > creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : HOLDING ) ;
2009-09-10 14:28:34 +03:00
endAnim ( ) ;
return ; //execution of endAnim deletes this !!!
}
}
bool CBattleAttack : : checkInitialConditions ( )
{
2009-09-11 15:46:26 +03:00
return isEarliest ( false ) ;
2009-09-10 14:28:34 +03:00
}
2010-12-24 23:44:48 +02:00
CBattleAttack : : CBattleAttack ( CBattleInterface * _owner , const CStack * attacker , THex _dest , const CStack * defender )
: CBattleStackAnimation ( _owner , attacker ) , dest ( _dest ) , attackedStack ( defender ) , attackingStack ( attacker )
2009-09-10 14:28:34 +03:00
{
2009-10-18 17:39:53 +03:00
assert ( attackingStack & & " attackingStack is NULL in CBattleAttack::CBattleAttack ! \n " ) ;
2010-11-20 19:36:02 +02:00
if ( attackingStack - > getCreature ( ) - > idNumber ! = 145 ) //catapult is allowed to attack not-creature
2009-11-29 04:46:30 +02:00
{
assert ( attackedStack & & " attackedStack is NULL in CBattleAttack::CBattleAttack ! \n " ) ;
}
else //catapult can attack walls only
{
2010-02-19 18:02:34 +02:00
assert ( owner - > curInt - > cb - > battleGetWallUnderHex ( _dest ) > = 0 ) ;
2009-11-29 04:46:30 +02:00
}
2009-09-16 13:59:56 +03:00
attackingStackPosBeforeReturn = attackingStack - > position ;
2009-09-10 14:28:34 +03:00
}
////melee attack
bool CMeleeAttack : : init ( )
{
if ( ! CBattleAttack : : checkInitialConditions ( ) )
return false ;
//if(owner->creAnims[stackID]->getType()!=2)
//{
// return false;
//}
2010-12-24 23:44:48 +02:00
if ( ! attackingStack | | owner - > creAnims [ stack - > ID ] - > getType ( ) = = 5 )
2009-09-10 14:28:34 +03:00
{
endAnim ( ) ;
return false ;
}
2011-01-09 19:41:46 +02:00
bool toReverse = isToReverse ( attackingStackPosBeforeReturn , dest , owner - > creDir [ stack - > ID ] , attackedStack - > doubleWide ( ) , owner - > creDir [ attackedStack - > ID ] ) ;
2009-09-10 14:28:34 +03:00
2011-01-09 19:41:46 +02:00
if ( toReverse )
2009-09-10 14:28:34 +03:00
{
2011-01-09 19:41:46 +02:00
2010-12-24 23:44:48 +02:00
owner - > addNewAnim ( new CReverseAnim ( owner , stack , attackingStackPosBeforeReturn , true ) ) ;
2009-09-16 13:09:08 +03:00
return false ;
2009-09-10 14:28:34 +03:00
}
//reversed
shooting = false ;
2011-02-09 15:56:30 +02:00
static const CCreatureAnim : : EAnimType mutPosToGroup [ ] = { CCreatureAnim : : ATTACK_UP , CCreatureAnim : : ATTACK_UP ,
CCreatureAnim : : ATTACK_FRONT , CCreatureAnim : : ATTACK_DOWN , CCreatureAnim : : ATTACK_DOWN , CCreatureAnim : : ATTACK_FRONT } ;
2009-09-10 14:28:34 +03:00
2011-01-09 19:41:46 +02:00
int revShiftattacker = ( attackingStack - > attackerOwned ? - 1 : 1 ) ;
int mutPos = THex : : mutualPosition ( attackingStackPosBeforeReturn , dest ) ;
2011-01-18 20:54:53 +02:00
if ( mutPos = = - 1 & & attackingStack - > doubleWide ( ) )
2011-01-08 20:33:40 +02:00
{
2011-01-09 19:41:46 +02:00
mutPos = THex : : mutualPosition ( attackingStackPosBeforeReturn + revShiftattacker , attackedStack - > position ) ;
}
if ( mutPos = = - 1 & & attackedStack - > doubleWide ( ) )
{
mutPos = THex : : mutualPosition ( attackingStackPosBeforeReturn , attackedStack - > occupiedHex ( ) ) ;
}
if ( mutPos = = - 1 & & attackedStack - > doubleWide ( ) & & attackingStack - > doubleWide ( ) )
{
mutPos = THex : : mutualPosition ( attackingStackPosBeforeReturn + revShiftattacker , attackedStack - > occupiedHex ( ) ) ;
2011-01-08 20:33:40 +02:00
}
2011-01-09 19:41:46 +02:00
2009-09-10 14:28:34 +03:00
switch ( mutPos ) //attack direction
{
case 0 : case 1 : case 2 : case 3 : case 4 : case 5 :
group = mutPosToGroup [ mutPos ] ;
break ;
default :
2011-01-09 19:41:46 +02:00
tlog1 < < " Critical Error! Wrong dest in stackAttacking! dest: " < < dest < < " attacking stack pos: " < < attackingStackPosBeforeReturn < < " mutual pos: " < < mutPos < < std : : endl ;
2011-02-09 15:56:30 +02:00
group = CCreatureAnim : : ATTACK_FRONT ;
2011-01-08 20:33:40 +02:00
break ;
2009-09-10 14:28:34 +03:00
}
return true ;
}
void CMeleeAttack : : nextFrame ( )
{
/*for(std::list<std::pair<CBattleAnimation *, bool> >::const_iterator it = owner->pendingAnims.begin(); it != owner->pendingAnims.end(); ++it)
{
CBattleMoveStart * anim = dynamic_cast < CBattleMoveStart * > ( it - > first ) ;
CReverseAnim * anim2 = dynamic_cast < CReverseAnim * > ( it - > first ) ;
if ( ( anim & & anim - > stackID = = stackID ) | | ( anim2 & & anim2 - > stackID = = stackID ) )
return ;
} */
CBattleAttack : : nextFrame ( ) ;
}
void CMeleeAttack : : endAnim ( )
{
CBattleAnimation : : endAnim ( ) ;
delete this ;
}
2010-12-24 23:44:48 +02:00
CMeleeAttack : : CMeleeAttack ( CBattleInterface * _owner , const CStack * attacker , THex _dest , const CStack * _attacked )
: CBattleAttack ( _owner , attacker , _dest , _attacked )
2009-09-10 14:28:34 +03:00
{
}
//shooting anim
bool CShootingAnim : : init ( )
{
if ( ! CBattleAttack : : checkInitialConditions ( ) )
return false ;
2009-09-16 13:59:56 +03:00
const CStack * shooter = attackingStack ;
2009-09-11 15:46:26 +03:00
2010-12-24 23:44:48 +02:00
if ( ! shooter | | owner - > creAnims [ stack - > ID ] - > getType ( ) = = 5 )
2009-09-11 15:46:26 +03:00
{
endAnim ( ) ;
return false ;
}
2009-09-10 14:28:34 +03:00
2011-05-26 17:47:45 +03:00
// Create the projectile animation
2009-09-10 14:28:34 +03:00
float projectileAngle ; //in radians; if positive, projectiles goes up
float straightAngle = 0.2f ; //maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absoulte value)
2009-09-16 13:09:08 +03:00
int fromHex = shooter - > position ;
2011-05-26 17:47:45 +03:00
projectileAngle = atan2 ( float ( abs ( dest - fromHex ) / BFIELD_WIDTH ) , float ( abs ( dest - fromHex ) % BFIELD_WIDTH ) ) ;
2009-09-10 14:28:34 +03:00
if ( fromHex < dest )
projectileAngle = - projectileAngle ;
2011-05-26 17:47:45 +03:00
// Get further info about the shooter e.g. relative pos of projectile to unit.
// If the creature id is 149 then it's a arrow tower which has no additional info so get the
// actual arrow tower shooter instead.
const CCreature * shooterInfo = shooter - > getCreature ( ) ;
if ( shooterInfo - > idNumber = = 149 )
{
int creID = CGI - > creh - > factionToTurretCreature [ owner - > siegeH - > town - > town - > typeID ] ;
shooterInfo = CGI - > creh - > creatures [ creID ] ;
}
2009-09-10 14:28:34 +03:00
SProjectileInfo spi ;
2010-11-20 19:36:02 +02:00
spi . creID = shooter - > getCreature ( ) - > idNumber ;
2011-05-26 17:47:45 +03:00
spi . stackID = shooter - > ID ;
2009-09-11 15:46:26 +03:00
spi . reverse = ! shooter - > attackerOwned ;
2009-09-10 14:28:34 +03:00
spi . step = 0 ;
spi . frameNum = 0 ;
2011-05-26 17:47:45 +03:00
if ( vstd : : contains ( CGI - > creh - > idToProjectileSpin , shooterInfo - > idNumber ) )
spi . spin = CGI - > creh - > idToProjectileSpin [ shooterInfo - > idNumber ] ;
2010-10-31 21:56:37 +02:00
else
{
2011-05-26 17:47:45 +03:00
tlog2 < < " Warning - no projectile spin for spi.creID " < < shooterInfo - > idNumber < < std : : endl ;
2010-10-31 21:56:37 +02:00
spi . spin = false ;
}
2009-09-10 14:28:34 +03:00
2009-09-21 11:29:41 +03:00
Point xycoord = CBattleHex : : getXYUnitAnim ( shooter - > position , true , shooter , owner ) ;
2009-09-24 16:44:55 +03:00
Point destcoord ;
2011-07-13 21:39:02 +03:00
2011-05-30 17:16:34 +03:00
2011-05-26 17:47:45 +03:00
// The "master" point where all projectile positions relate to.
static const Point projectileOrigin ( 181 , 252 ) ;
2011-05-30 17:16:34 +03:00
if ( attackedStack )
2009-09-10 14:28:34 +03:00
{
2011-05-30 17:16:34 +03:00
destcoord = CBattleHex : : getXYUnitAnim ( dest , false , attackedStack , owner ) ;
destcoord . x + = 250 ; destcoord . y + = 210 ; //TODO: find a better place to shoot
// Calculate projectile start position. Offsets are read out of the CRANIM.TXT.
if ( projectileAngle > straightAngle )
{
//upper shot
spi . x = xycoord . x + projectileOrigin . x + shooterInfo - > upperRightMissleOffsetX ;
spi . y = xycoord . y + projectileOrigin . y + shooterInfo - > upperRightMissleOffsetY ;
}
else if ( projectileAngle < - straightAngle )
{
//lower shot
spi . x = xycoord . x + projectileOrigin . x + shooterInfo - > lowerRightMissleOffsetX ;
spi . y = xycoord . y + projectileOrigin . y + shooterInfo - > lowerRightMissleOffsetY ;
}
else
{
//straight shot
spi . x = xycoord . x + projectileOrigin . x + shooterInfo - > rightMissleOffsetX ;
spi . y = xycoord . y + projectileOrigin . y + shooterInfo - > rightMissleOffsetY ;
}
2011-07-13 21:39:02 +03:00
double animSpeed = 23.0 * owner - > getAnimSpeed ( ) ; // flight speed of projectile
2011-05-30 17:16:34 +03:00
spi . lastStep = sqrt ( ( float ) ( ( destcoord . x - spi . x ) * ( destcoord . x - spi . x ) + ( destcoord . y - spi . y ) * ( destcoord . y - spi . y ) ) ) / animSpeed ;
if ( spi . lastStep = = 0 )
spi . lastStep = 1 ;
spi . dx = ( destcoord . x - spi . x ) / spi . lastStep ;
spi . dy = ( destcoord . y - spi . y ) / spi . lastStep ;
spi . catapultInfo = 0 ;
2009-09-10 14:28:34 +03:00
}
2011-05-26 17:47:45 +03:00
else
2009-09-10 14:28:34 +03:00
{
2011-05-30 17:16:34 +03:00
// Catapult attack
// These are the values for equations of this kind: f(x) = ax^2 + bx + c
static const std : : vector < CatapultProjectileInfo * > trajectoryCurves = boost : : assign : : list_of < CatapultProjectileInfo * > ( new CatapultProjectileInfo ( 4.309 , - 3.198 , 569.2 , - 296 , 182 ) )
( new CatapultProjectileInfo ( 4.710 , - 3.11 , 558.68 , - 258 , 175 ) ) ( new CatapultProjectileInfo ( 5.056 , - 3.003 , 546.9 , - 236 , 174 ) )
( new CatapultProjectileInfo ( 4.760 , - 2.74 , 526.47 , - 216 , 215 ) ) ( new CatapultProjectileInfo ( 4.288 , - 2.496 , 508.98 , - 223 , 274 ) )
( new CatapultProjectileInfo ( 3.683 , - 3.018 , 558.39 , - 324 , 176 ) ) ( new CatapultProjectileInfo ( 2.884 , - 2.607 , 528.95 , - 366 , 312 ) )
( new CatapultProjectileInfo ( 3.783 , - 2.364 , 501.35 , - 227 , 318 ) ) ;
static std : : map < int , int > hexToCurve = boost : : assign : : map_list_of < int , int > ( 29 , 0 ) ( 62 , 1 ) ( 95 , 2 ) ( 130 , 3 ) ( 182 , 4 ) ( 12 , 5 ) ( 50 , 6 ) ( 183 , 7 ) ;
std : : map < int , int > : : iterator it = hexToCurve . find ( dest . hex ) ;
if ( it = = hexToCurve . end ( ) )
{
tlog1 < < " For the hex position " < < dest . hex < < " is no curve defined. " ;
endAnim ( ) ;
return false ;
}
else
{
int curveID = it - > second ;
spi . catapultInfo = trajectoryCurves [ curveID ] ;
2011-07-13 21:39:02 +03:00
double animSpeed = 3.318 * owner - > getAnimSpeed ( ) ;
2011-05-30 17:16:34 +03:00
spi . lastStep = ( spi . catapultInfo - > toX - spi . catapultInfo - > fromX ) / animSpeed ;
spi . dx = animSpeed ;
spi . dy = 0 ;
2011-07-13 21:39:02 +03:00
spi . x = xycoord . x + projectileOrigin . x + shooterInfo - > rightMissleOffsetX + 17. ;
spi . y = xycoord . y + projectileOrigin . y + shooterInfo - > rightMissleOffsetY + 10. ;
2011-05-30 17:16:34 +03:00
// Add explosion anim
int xEnd = spi . x + spi . lastStep * spi . dx ;
int yEnd = spi . catapultInfo - > calculateY ( xEnd ) ;
owner - > addNewAnim ( new CSpellEffectAnim ( owner , " SGEXPL.DEF " , xEnd - 126 , yEnd - 105 ) ) ;
}
2009-09-10 14:28:34 +03:00
}
2011-05-26 17:47:45 +03:00
2011-05-30 17:16:34 +03:00
// Set starting frame
2009-09-10 14:28:34 +03:00
if ( spi . spin )
{
spi . frameNum = 0 ;
}
else
{
spi . frameNum = ( ( M_PI / 2.0f - projectileAngle ) / ( 2.0f * M_PI ) + 1 / ( ( float ) ( 2 * ( owner - > idToProjectile [ spi . creID ] - > ourImages . size ( ) - 1 ) ) ) ) * ( owner - > idToProjectile [ spi . creID ] - > ourImages . size ( ) - 1 ) ;
}
2011-05-26 17:47:45 +03:00
// Set projectile animation start delay which is specified in frames
spi . animStartDelay = shooterInfo - > attackClimaxFrame ;
2009-09-10 14:28:34 +03:00
owner - > projectiles . push_back ( spi ) ;
2011-05-18 20:51:10 +03:00
//attack animation
2009-09-24 16:44:55 +03:00
2009-09-10 14:28:34 +03:00
shooting = true ;
if ( projectileAngle > straightAngle ) //upper shot
2011-02-09 15:56:30 +02:00
group = CCreatureAnim : : SHOOT_UP ;
2009-09-10 14:28:34 +03:00
else if ( projectileAngle < - straightAngle ) //lower shot
2011-02-09 15:56:30 +02:00
group = CCreatureAnim : : SHOOT_DOWN ;
2009-09-10 14:28:34 +03:00
else //straight shot
2011-02-09 15:56:30 +02:00
group = CCreatureAnim : : SHOOT_FRONT ;
2009-09-10 14:28:34 +03:00
return true ;
}
void CShootingAnim : : nextFrame ( )
{
for ( std : : list < std : : pair < CBattleAnimation * , bool > > : : const_iterator it = owner - > pendingAnims . begin ( ) ; it ! = owner - > pendingAnims . end ( ) ; + + it )
{
CBattleMoveStart * anim = dynamic_cast < CBattleMoveStart * > ( it - > first ) ;
CReverseAnim * anim2 = dynamic_cast < CReverseAnim * > ( it - > first ) ;
2010-12-24 23:44:48 +02:00
if ( ( anim & & anim - > stack - > ID = = stack - > ID ) | | ( anim2 & & anim2 - > stack - > ID = = stack - > ID & & anim2 - > priority ) )
2009-09-10 14:28:34 +03:00
return ;
}
CBattleAttack : : nextFrame ( ) ;
}
void CShootingAnim : : endAnim ( )
{
CBattleAnimation : : endAnim ( ) ;
delete this ;
}
2010-12-24 23:44:48 +02:00
CShootingAnim : : CShootingAnim ( CBattleInterface * _owner , const CStack * attacker , THex _dest , const CStack * _attacked , bool _catapult , int _catapultDmg )
: CBattleAttack ( _owner , attacker , _dest , _attacked ) , catapultDamage ( _catapultDmg ) , catapult ( _catapult )
2009-09-10 14:28:34 +03:00
{
2011-05-30 17:16:34 +03:00
2009-09-10 14:28:34 +03:00
}
////////////////////////
2009-08-01 14:55:40 +03:00
2009-09-16 13:36:50 +03:00
void CBattleInterface : : addNewAnim ( CBattleAnimation * anim )
{
pendingAnims . push_back ( std : : make_pair ( anim , false ) ) ;
animsAreDisplayed . setn ( true ) ;
}
2010-05-02 21:20:26 +03:00
CBattleInterface : : CBattleInterface ( const CCreatureSet * army1 , const CCreatureSet * army2 , CGHeroInstance * hero1 , CGHeroInstance * hero2 , const SDL_Rect & myRect , CPlayerInterface * att , CPlayerInterface * defen )
2010-10-31 00:53:41 +03:00
: queue ( NULL ) , attackingHeroInstance ( hero1 ) , defendingHeroInstance ( hero2 ) , animCount ( 0 ) ,
2010-12-24 23:44:48 +02:00
activeStack ( NULL ) , stackToActivate ( NULL ) , mouseHoveredStack ( - 1 ) , previouslyHoveredHex ( - 1 ) ,
2011-05-28 13:05:25 +03:00
currentlyHoveredHex ( - 1 ) , tacticianInterface ( NULL ) , spellDestSelectMode ( false ) , spellToCast ( NULL ) ,
siegeH ( NULL ) , attackerInt ( att ) , defenderInt ( defen ) , curInt ( att ) , animIDhelper ( 0 ) , givenCommand ( NULL ) ,
myTurn ( false ) , resWindow ( NULL ) , moveStarted ( false ) , moveSh ( - 1 ) , bresult ( NULL )
2009-01-15 19:01:08 +02:00
{
2009-09-20 15:47:40 +03:00
ObjectConstruction h__l__p ( this ) ;
2010-10-30 22:26:39 +03:00
if ( ! curInt ) curInt = LOCPLINT ; //may happen when we are defending during network MP game
2009-09-16 13:36:50 +03:00
animsAreDisplayed . setn ( false ) ;
2009-01-15 19:01:08 +02:00
pos = myRect ;
strongInterest = true ;
givenCommand = new CondSh < BattleAction * > ( NULL ) ;
2011-05-25 02:17:57 +03:00
if ( attackerInt & & attackerInt - > cb - > battleGetTacticDist ( ) ) //hotseat -> check tactics for both players (defender may be local human)
tacticianInterface = attackerInt ;
else if ( defenderInt & & defenderInt - > cb - > battleGetTacticDist ( ) )
tacticianInterface = defenderInt ;
tacticsMode = tacticianInterface ; //if we found interface of player with tactics, then enter tactics mode
2009-09-20 15:47:40 +03:00
//create stack queue
bool embedQueue = screen - > h < 700 ;
2010-02-19 18:02:34 +02:00
queue = new CStackQueue ( embedQueue , this ) ;
2011-04-24 05:02:41 +03:00
if ( ! embedQueue )
2009-09-20 15:47:40 +03:00
{
2011-04-24 05:02:41 +03:00
if ( curInt - > sysOpts . showQueue )
pos . y + = queue - > pos . h / 2 ; //center whole window
2009-09-20 15:47:40 +03:00
queue - > moveTo ( Point ( pos . x , pos . y - queue - > pos . h ) ) ;
// queue->pos.x = pos.x;
// queue->pos.y = pos.y - queue->pos.h;
// pos.h += queue->pos.h;
// center();
2010-08-04 14:18:13 +03:00
}
2009-09-20 15:47:40 +03:00
queue - > update ( ) ;
2009-09-04 17:11:42 +03:00
//preparing siege info
2010-02-19 18:02:34 +02:00
const CGTownInstance * town = curInt - > cb - > battleGetDefendedTown ( ) ;
2009-10-17 16:59:25 +03:00
if ( town & & town - > hasFort ( ) )
2009-09-04 17:11:42 +03:00
{
siegeH = new SiegeHelper ( town , this ) ;
}
2010-02-19 18:02:34 +02:00
curInt - > battleInt = this ;
2009-09-21 11:29:41 +03:00
2009-01-15 19:01:08 +02:00
//initializing armies
2010-12-06 01:10:02 +02:00
this - > army1 = army1 ;
this - > army2 = army2 ;
2011-02-14 22:31:53 +02:00
std : : vector < const CStack * > stacks = curInt - > cb - > battleGetAllStacks ( ) ;
2010-12-06 01:10:02 +02:00
BOOST_FOREACH ( const CStack * s , stacks )
2009-01-15 19:01:08 +02:00
{
2010-12-23 22:18:10 +02:00
newStack ( s ) ;
2009-01-15 19:01:08 +02:00
}
2009-08-24 15:55:05 +03:00
2009-01-15 19:01:08 +02:00
//preparing menu background and terrain
2009-08-24 15:55:05 +03:00
if ( siegeH )
{
2009-09-20 22:17:28 +03:00
background = BitmapHandler : : loadBitmap ( siegeH - > getSiegeName ( 0 ) , false ) ;
2010-02-19 18:02:34 +02:00
ui8 siegeLevel = curInt - > cb - > battleGetSiegeLevel ( ) ;
2009-09-02 17:10:19 +03:00
if ( siegeLevel > = 2 ) //citadel or castle
{
//print moat/mlip
SDL_Surface * moat = BitmapHandler : : loadBitmap ( siegeH - > getSiegeName ( 13 ) ) ,
* mlip = BitmapHandler : : loadBitmap ( siegeH - > getSiegeName ( 14 ) ) ;
2011-04-30 22:52:35 +03:00
Point moatPos = graphics - > wallPositions [ siegeH - > town - > town - > typeID ] [ 12 ] ,
mlipPos = graphics - > wallPositions [ siegeH - > town - > town - > typeID ] [ 13 ] ;
2009-09-07 15:30:10 +03:00
2009-09-05 17:10:26 +03:00
if ( moat ) //eg. tower has no moat
2010-08-16 12:54:09 +03:00
blitAt ( moat , moatPos . x , moatPos . y , background ) ;
2009-09-05 17:10:26 +03:00
if ( mlip ) //eg. tower has no mlip
2010-08-16 12:54:09 +03:00
blitAt ( mlip , mlipPos . x , mlipPos . y , background ) ;
2009-09-02 17:10:19 +03:00
SDL_FreeSurface ( moat ) ;
SDL_FreeSurface ( mlip ) ;
}
2009-08-24 15:55:05 +03:00
}
else
{
2010-02-19 18:02:34 +02:00
std : : vector < std : : string > & backref = graphics - > battleBacks [ curInt - > cb - > battleGetBattlefieldType ( ) ] ;
2009-09-20 22:17:28 +03:00
background = BitmapHandler : : loadBitmap ( backref [ rand ( ) % backref . size ( ) ] , false ) ;
2009-08-24 15:55:05 +03:00
}
2009-09-07 05:29:44 +03:00
//preparing menu background
2011-02-14 22:31:53 +02:00
//graphics->blueToPlayersAdv(menu, hero1->tempOwner);
2009-01-15 19:01:08 +02:00
//preparing graphics for displaying amounts of creatures
amountNormal = BitmapHandler : : loadBitmap ( " CMNUMWIN.BMP " ) ;
CSDL_Ext : : alphaTransform ( amountNormal ) ;
2009-08-01 14:55:40 +03:00
transformPalette ( amountNormal , 0.59f , 0.19f , 0.93f ) ;
2009-01-15 19:01:08 +02:00
amountPositive = BitmapHandler : : loadBitmap ( " CMNUMWIN.BMP " ) ;
CSDL_Ext : : alphaTransform ( amountPositive ) ;
2009-08-01 14:55:40 +03:00
transformPalette ( amountPositive , 0.18f , 1.00f , 0.18f ) ;
2009-01-15 19:01:08 +02:00
amountNegative = BitmapHandler : : loadBitmap ( " CMNUMWIN.BMP " ) ;
CSDL_Ext : : alphaTransform ( amountNegative ) ;
2009-08-01 14:55:40 +03:00
transformPalette ( amountNegative , 1.00f , 0.18f , 0.18f ) ;
2009-01-15 19:01:08 +02:00
amountEffNeutral = BitmapHandler : : loadBitmap ( " CMNUMWIN.BMP " ) ;
2009-08-01 14:55:40 +03:00
CSDL_Ext : : alphaTransform ( amountEffNeutral ) ;
transformPalette ( amountEffNeutral , 1.00f , 1.00f , 0.18f ) ;
2009-01-15 19:01:08 +02:00
////blitting menu background and terrain
2011-02-14 22:31:53 +02:00
// blitAt(background, pos.x, pos.y);
// blitAt(menu, pos.x, 556 + pos.y);
2009-01-15 19:01:08 +02:00
//preparing buttons and console
2009-01-29 20:07:31 +02:00
bOptions = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 381 ] . first , CGI - > generaltexth - > zelp [ 381 ] . second , boost : : bind ( & CBattleInterface : : bOptionsf , this ) , 3 + pos . x , 561 + pos . y , " icm003.def " , SDLK_o ) ;
bSurrender = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 379 ] . first , CGI - > generaltexth - > zelp [ 379 ] . second , boost : : bind ( & CBattleInterface : : bSurrenderf , this ) , 54 + pos . x , 561 + pos . y , " icm001.def " , SDLK_s ) ;
bFlee = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 380 ] . first , CGI - > generaltexth - > zelp [ 380 ] . second , boost : : bind ( & CBattleInterface : : bFleef , this ) , 105 + pos . x , 561 + pos . y , " icm002.def " , SDLK_r ) ;
2010-08-19 14:03:33 +03:00
bFlee - > block ( ! curInt - > cb - > battleCanFlee ( ) ) ;
2011-03-05 18:38:22 +02:00
bSurrender - > block ( curInt - > cb - > battleGetSurrenderCost ( ) < 0 ) ;
2009-01-29 20:07:31 +02:00
bAutofight = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 382 ] . first , CGI - > generaltexth - > zelp [ 382 ] . second , boost : : bind ( & CBattleInterface : : bAutofightf , this ) , 157 + pos . x , 561 + pos . y , " icm004.def " , SDLK_a ) ;
bSpell = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 385 ] . first , CGI - > generaltexth - > zelp [ 385 ] . second , boost : : bind ( & CBattleInterface : : bSpellf , this ) , 645 + pos . x , 561 + pos . y , " icm005.def " , SDLK_c ) ;
2010-01-28 16:14:43 +02:00
bSpell - > block ( true ) ;
2009-01-29 20:07:31 +02:00
bWait = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 386 ] . first , CGI - > generaltexth - > zelp [ 386 ] . second , boost : : bind ( & CBattleInterface : : bWaitf , this ) , 696 + pos . x , 561 + pos . y , " icm006.def " , SDLK_w ) ;
bDefence = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 387 ] . first , CGI - > generaltexth - > zelp [ 387 ] . second , boost : : bind ( & CBattleInterface : : bDefencef , this ) , 747 + pos . x , 561 + pos . y , " icm007.def " , SDLK_d ) ;
2009-01-15 19:01:08 +02:00
bDefence - > assignedKeys . insert ( SDLK_SPACE ) ;
bConsoleUp = new AdventureMapButton ( std : : string ( ) , std : : string ( ) , boost : : bind ( & CBattleInterface : : bConsoleUpf , this ) , 624 + pos . x , 561 + pos . y , " ComSlide.def " , SDLK_UP ) ;
bConsoleDown = new AdventureMapButton ( std : : string ( ) , std : : string ( ) , boost : : bind ( & CBattleInterface : : bConsoleDownf , this ) , 624 + pos . x , 580 + pos . y , " ComSlide.def " , SDLK_DOWN ) ;
2011-02-20 11:24:53 +02:00
bConsoleDown - > setOffset ( 2 ) ;
2009-01-15 19:01:08 +02:00
console = new CBattleConsole ( ) ;
console - > pos . x = 211 + pos . x ;
console - > pos . y = 560 + pos . y ;
console - > pos . w = 406 ;
console - > pos . h = 38 ;
2011-02-14 00:46:04 +02:00
if ( tacticsMode )
2011-02-12 18:12:48 +02:00
{
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 ) ;
bDefence - > block ( true ) ;
bWait - > block ( true ) ;
2011-02-14 22:31:53 +02:00
menu = BitmapHandler : : loadBitmap ( " COPLACBR.BMP " ) ;
2011-02-12 18:12:48 +02:00
}
2011-02-14 22:31:53 +02:00
else
{
menu = BitmapHandler : : loadBitmap ( " CBAR.BMP " ) ;
btactEnd = btactNext = NULL ;
}
graphics - > blueToPlayersAdv ( menu , curInt - > playerID ) ;
2009-01-15 19:01:08 +02:00
//loading hero animations
if ( hero1 ) // attacking hero
{
2010-08-25 17:57:58 +03:00
int type = hero1 - > type - > heroType ;
if ( type % 2 ) type - - ;
if ( hero1 - > sex ) type + + ;
attackingHero = new CBattleHero ( graphics - > battleHeroes [ type ] , 0 , 0 , false , hero1 - > tempOwner , hero1 - > tempOwner = = curInt - > playerID ? hero1 : NULL , this ) ;
2011-05-17 18:52:44 +03:00
attackingHero - > pos = genRect ( attackingHero - > dh - > ourImages [ 0 ] . bitmap - > h , attackingHero - > dh - > ourImages [ 0 ] . bitmap - > w , pos . x - 43 , pos . y - 19 ) ;
2009-01-15 19:01:08 +02:00
}
else
{
attackingHero = NULL ;
}
if ( hero2 ) // defending hero
{
2010-08-25 17:57:58 +03:00
int type = hero2 - > type - > heroType ;
if ( type % 2 ) type - - ;
if ( hero2 - > sex ) type + + ;
defendingHero = new CBattleHero ( graphics - > battleHeroes [ type ] , 0 , 0 , true , hero2 - > tempOwner , hero2 - > tempOwner = = curInt - > playerID ? hero2 : NULL , this ) ;
2011-05-17 18:52:44 +03:00
defendingHero - > pos = genRect ( defendingHero - > dh - > ourImages [ 0 ] . bitmap - > h , defendingHero - > dh - > ourImages [ 0 ] . bitmap - > w , pos . x + 693 , pos . y - 19 ) ;
2009-01-15 19:01:08 +02:00
}
else
{
defendingHero = NULL ;
}
//preparing cells and hexes
cellBorder = BitmapHandler : : loadBitmap ( " CCELLGRD.BMP " ) ;
CSDL_Ext : : alphaTransform ( cellBorder ) ;
cellShade = BitmapHandler : : loadBitmap ( " CCELLSHD.BMP " ) ;
CSDL_Ext : : alphaTransform ( cellShade ) ;
for ( int h = 0 ; h < BFIELD_SIZE ; + + h )
{
bfield [ h ] . myNumber = h ;
int x = 14 + ( ( h / BFIELD_WIDTH ) % 2 = = 0 ? 22 : 0 ) + 44 * ( h % BFIELD_WIDTH ) ;
int y = 86 + 42 * ( h / BFIELD_WIDTH ) ;
bfield [ h ] . pos = genRect ( cellShade - > h , cellShade - > w , x + pos . x , y + pos . y ) ;
2009-10-16 05:09:58 +03:00
bfield [ h ] . accessible = true ;
2009-01-15 19:01:08 +02:00
bfield [ h ] . myInterface = this ;
}
//locking occupied positions on batlefield
2010-12-06 01:10:02 +02:00
BOOST_FOREACH ( const CStack * s , stacks ) //stacks gained at top of this function
if ( s - > position > = 0 ) //turrets have position < 0
bfield [ s - > position ] . accessible = false ;
2009-01-15 19:01:08 +02:00
//loading projectiles for units
2010-12-06 01:10:02 +02:00
BOOST_FOREACH ( const CStack * s , stacks )
2009-01-15 19:01:08 +02:00
{
2010-12-06 01:10:02 +02:00
int creID = ( s - > getCreature ( ) - > idNumber = = 149 ) ? CGI - > creh - > factionToTurretCreature [ siegeH - > town - > town - > typeID ] : s - > getCreature ( ) - > idNumber ; //id of creature whose shots should be loaded
if ( s - > getCreature ( ) - > isShooting ( ) & & vstd : : contains ( CGI - > creh - > idToProjectile , creID ) )
{
CDefHandler * & projectile = idToProjectile [ s - > getCreature ( ) - > idNumber ] ;
projectile = CDefHandler : : giveDef ( CGI - > creh - > idToProjectile [ creID ] ) ;
2009-01-15 19:01:08 +02:00
2010-12-06 01:10:02 +02:00
if ( projectile - > ourImages . size ( ) > 2 ) //add symmetric images
2009-01-15 19:01:08 +02:00
{
2010-12-06 01:10:02 +02:00
for ( int k = projectile - > ourImages . size ( ) - 2 ; k > 1 ; - - k )
2009-01-15 19:01:08 +02:00
{
Cimage ci ;
2010-12-06 01:10:02 +02:00
ci . bitmap = CSDL_Ext : : rotate01 ( projectile - > ourImages [ k ] . bitmap ) ;
2009-01-15 19:01:08 +02:00
ci . groupNumber = 0 ;
ci . imName = std : : string ( ) ;
2010-12-06 01:10:02 +02:00
projectile - > ourImages . push_back ( ci ) ;
2009-01-15 19:01:08 +02:00
}
}
2010-12-06 01:10:02 +02:00
for ( int s = 0 ; s < projectile - > ourImages . size ( ) ; + + s ) //alpha transforming
2009-01-15 19:01:08 +02:00
{
2010-12-06 01:10:02 +02:00
CSDL_Ext : : alphaTransform ( projectile - > ourImages [ s ] . bitmap ) ;
2009-01-15 19:01:08 +02:00
}
}
}
//preparing graphic with cell borders
cellBorders = CSDL_Ext : : newSurface ( background - > w , background - > h , cellBorder ) ;
//copying palette
for ( int g = 0 ; g < cellBorder - > format - > palette - > ncolors ; + + g ) //we assume that cellBorders->format->palette->ncolors == 256
{
cellBorders - > format - > palette - > colors [ g ] = cellBorder - > format - > palette - > colors [ g ] ;
}
//palette copied
for ( int i = 0 ; i < BFIELD_HEIGHT ; + + i ) //rows
{
for ( int j = 0 ; j < BFIELD_WIDTH - 2 ; + + j ) //columns
{
int x = 58 + ( i % 2 = = 0 ? 22 : 0 ) + 44 * j ;
int y = 86 + 42 * i ;
for ( int cellX = 0 ; cellX < cellBorder - > w ; + + cellX )
{
for ( int cellY = 0 ; cellY < cellBorder - > h ; + + cellY )
{
if ( y + cellY < cellBorders - > h & & x + cellX < cellBorders - > w )
* ( ( Uint8 * ) cellBorders - > pixels + ( y + cellY ) * cellBorders - > pitch + ( x + cellX ) ) | = * ( ( Uint8 * ) cellBorder - > pixels + cellY * cellBorder - > pitch + cellX ) ;
}
}
}
}
backgroundWithHexes = CSDL_Ext : : newSurface ( background - > w , background - > h , screen ) ;
2009-02-09 16:50:32 +02:00
//preparing obstacle defs
2010-02-19 18:02:34 +02:00
std : : vector < CObstacleInstance > obst = curInt - > cb - > battleGetAllObstacles ( ) ;
2009-02-09 16:50:32 +02:00
for ( int t = 0 ; t < obst . size ( ) ; + + t )
{
2010-08-16 12:54:09 +03:00
idToObstacle [ obst [ t ] . ID ] = CDefHandler : : giveDef ( CGI - > heroh - > obstacles . find ( obst [ t ] . ID ) - > second . defName ) ;
2009-02-09 16:50:32 +02:00
for ( int n = 0 ; n < idToObstacle [ obst [ t ] . ID ] - > ourImages . size ( ) ; + + n )
{
SDL_SetColorKey ( idToObstacle [ obst [ t ] . ID ] - > ourImages [ n ] . bitmap , SDL_SRCCOLORKEY , SDL_MapRGB ( idToObstacle [ obst [ t ] . ID ] - > ourImages [ n ] . bitmap - > format , 0 , 255 , 255 ) ) ;
}
}
2009-09-20 22:17:28 +03:00
for ( int i = 0 ; i < ARRAY_COUNT ( bfield ) ; i + + )
{
children . push_back ( & bfield [ i ] ) ;
}
2011-02-12 18:12:48 +02:00
2011-02-14 22:31:53 +02:00
if ( tacticsMode )
2011-02-12 18:12:48 +02:00
{
2011-02-14 22:31:53 +02:00
active = 1 ;
bTacticNextStack ( ) ;
active = 0 ;
2011-02-12 18:12:48 +02:00
}
2011-08-20 14:27:09 +03:00
CCS - > musich - > stopMusic ( ) ;
int channel = CCS - > soundh - > playSoundFromSet ( CCS - > soundh - > battleIntroSounds ) ;
CCS - > soundh - > setCallback ( channel , boost : : bind ( & CMusicHandler : : playMusicFromSet , CCS - > musich , CCS - > musich - > battleMusics , - 1 ) ) ;
2009-01-15 19:01:08 +02:00
}
CBattleInterface : : ~ CBattleInterface ( )
{
2010-07-15 14:28:06 +03:00
if ( active ) //dirty fix for #485
{
deactivate ( ) ;
}
2009-01-15 19:01:08 +02:00
SDL_FreeSurface ( background ) ;
SDL_FreeSurface ( menu ) ;
SDL_FreeSurface ( amountNormal ) ;
SDL_FreeSurface ( amountNegative ) ;
SDL_FreeSurface ( amountPositive ) ;
SDL_FreeSurface ( amountEffNeutral ) ;
SDL_FreeSurface ( cellBorders ) ;
SDL_FreeSurface ( backgroundWithHexes ) ;
delete bOptions ;
delete bSurrender ;
delete bFlee ;
delete bAutofight ;
delete bSpell ;
delete bWait ;
delete bDefence ;
delete bConsoleUp ;
delete bConsoleDown ;
delete console ;
delete givenCommand ;
delete attackingHero ;
delete defendingHero ;
2009-09-20 15:47:40 +03:00
delete queue ;
2009-01-15 19:01:08 +02:00
SDL_FreeSurface ( cellBorder ) ;
SDL_FreeSurface ( cellShade ) ;
for ( std : : map < int , CCreatureAnimation * > : : iterator g = creAnims . begin ( ) ; g ! = creAnims . end ( ) ; + + g )
delete g - > second ;
for ( std : : map < int , CDefHandler * > : : iterator g = idToProjectile . begin ( ) ; g ! = idToProjectile . end ( ) ; + + g )
delete g - > second ;
2009-02-09 16:50:32 +02:00
for ( std : : map < int , CDefHandler * > : : iterator g = idToObstacle . begin ( ) ; g ! = idToObstacle . end ( ) ; + + g )
delete g - > second ;
2009-04-14 15:47:09 +03:00
2009-08-24 15:55:05 +03:00
delete siegeH ;
2010-02-19 18:02:34 +02:00
curInt - > battleInt = NULL ;
2011-08-19 22:50:24 +03:00
2011-08-20 14:27:09 +03:00
//TODO: play AI tracks if battle was during AI turn
//if (!curInt->makingTurn)
//CCS->musich->playMusicFromSet(CCS->musich->aiMusics, -1);
if ( adventureInt & & adventureInt - > selection )
{
int terrain = LOCPLINT - > cb - > getTile ( adventureInt - > selection - > visitablePos ( ) ) - > tertype ;
CCS - > musich - > playMusic ( CCS - > musich - > terrainMusics [ terrain ] , - 1 ) ;
}
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : setPrintCellBorders ( bool set )
{
2010-02-19 18:02:34 +02:00
curInt - > sysOpts . printCellBorders = set ;
curInt - > sysOpts . settingsChanged ( ) ;
2009-01-15 19:01:08 +02:00
redrawBackgroundWithHexes ( activeStack ) ;
2009-08-07 01:36:51 +03:00
GH . totalRedraw ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : setPrintStackRange ( bool set )
{
2010-02-19 18:02:34 +02:00
curInt - > sysOpts . printStackRange = set ;
curInt - > sysOpts . settingsChanged ( ) ;
2009-01-15 19:01:08 +02:00
redrawBackgroundWithHexes ( activeStack ) ;
2009-08-07 01:36:51 +03:00
GH . totalRedraw ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : setPrintMouseShadow ( bool set )
{
2010-02-19 18:02:34 +02:00
curInt - > sysOpts . printMouseShadow = set ;
curInt - > sysOpts . settingsChanged ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : activate ( )
{
2009-08-11 19:05:33 +03:00
activateKeys ( ) ;
activateMouseMove ( ) ;
activateRClick ( ) ;
2009-01-15 19:01:08 +02:00
bOptions - > activate ( ) ;
bSurrender - > activate ( ) ;
bFlee - > activate ( ) ;
bAutofight - > activate ( ) ;
bSpell - > activate ( ) ;
bWait - > activate ( ) ;
bDefence - > activate ( ) ;
for ( int b = 0 ; b < BFIELD_SIZE ; + + b )
{
bfield [ b ] . activate ( ) ;
}
if ( attackingHero )
attackingHero - > activate ( ) ;
if ( defendingHero )
defendingHero - > activate ( ) ;
2010-02-19 18:02:34 +02:00
if ( curInt - > sysOpts . showQueue )
2009-09-20 15:47:40 +03:00
queue - > activate ( ) ;
2009-04-03 18:55:26 +03:00
2011-02-14 22:31:53 +02:00
if ( tacticsMode )
{
btactNext - > activate ( ) ;
btactEnd - > activate ( ) ;
}
else
{
bConsoleUp - > activate ( ) ;
bConsoleDown - > activate ( ) ;
}
2009-04-03 18:55:26 +03:00
LOCPLINT - > cingconsole - > activate ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : deactivate ( )
{
2009-08-11 19:05:33 +03:00
deactivateKeys ( ) ;
deactivateMouseMove ( ) ;
deactivateRClick ( ) ;
2009-01-15 19:01:08 +02:00
bOptions - > deactivate ( ) ;
bSurrender - > deactivate ( ) ;
bFlee - > deactivate ( ) ;
bAutofight - > deactivate ( ) ;
bSpell - > deactivate ( ) ;
bWait - > deactivate ( ) ;
bDefence - > deactivate ( ) ;
for ( int b = 0 ; b < BFIELD_SIZE ; + + b )
{
bfield [ b ] . deactivate ( ) ;
}
if ( attackingHero )
attackingHero - > deactivate ( ) ;
if ( defendingHero )
defendingHero - > deactivate ( ) ;
2010-02-19 18:02:34 +02:00
if ( curInt - > sysOpts . showQueue )
2009-09-20 15:47:40 +03:00
queue - > deactivate ( ) ;
2009-04-03 18:55:26 +03:00
2011-02-14 22:31:53 +02:00
if ( tacticsMode )
{
btactNext - > deactivate ( ) ;
btactEnd - > deactivate ( ) ;
}
else
{
bConsoleUp - > deactivate ( ) ;
bConsoleDown - > deactivate ( ) ;
}
2009-04-03 18:55:26 +03:00
LOCPLINT - > cingconsole - > deactivate ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : show ( SDL_Surface * to )
{
2011-02-14 22:31:53 +02:00
std : : vector < const CStack * > stacks = curInt - > cb - > battleGetAllStacks ( ) ; //used in a few places
2009-01-15 19:01:08 +02:00
+ + animCount ;
if ( ! to ) //"evaluating" to
to = screen ;
SDL_Rect buf ;
SDL_GetClipRect ( to , & buf ) ;
SDL_SetClipRect ( to , & pos ) ;
2009-09-20 15:47:40 +03:00
2009-01-15 19:01:08 +02:00
//printing background and hexes
2010-12-24 23:44:48 +02:00
if ( activeStack ! = NULL & & creAnims [ activeStack - > ID ] - > getType ( ) ! = 0 ) //show everything with range
2009-01-15 19:01:08 +02:00
{
blitAt ( backgroundWithHexes , pos . x , pos . y , to ) ;
}
else
{
//showing background
blitAt ( background , pos . x , pos . y , to ) ;
2010-02-19 18:02:34 +02:00
if ( curInt - > sysOpts . printCellBorders )
2009-01-15 19:01:08 +02:00
{
CSDL_Ext : : blit8bppAlphaTo24bpp ( cellBorders , NULL , to , & pos ) ;
}
}
//printing hovered cell
2009-02-07 18:07:29 +02:00
for ( int b = 0 ; b < BFIELD_SIZE ; + + b )
2009-01-15 19:01:08 +02:00
{
2009-02-07 18:07:29 +02:00
if ( bfield [ b ] . strictHovered & & bfield [ b ] . hovered )
2009-01-15 19:01:08 +02:00
{
2009-02-07 18:07:29 +02:00
if ( previouslyHoveredHex = = - 1 ) previouslyHoveredHex = b ; //something to start with
if ( currentlyHoveredHex = = - 1 ) currentlyHoveredHex = b ; //something to start with
if ( currentlyHoveredHex ! = b ) //repair hover info
{
previouslyHoveredHex = currentlyHoveredHex ;
currentlyHoveredHex = b ;
}
//print shade
2009-04-15 17:03:31 +03:00
if ( spellToCast ) //when casting spell
{
2011-05-26 17:47:45 +03:00
//calculating spell school level
2010-12-19 16:39:56 +02:00
const CSpell & spToCast = * CGI - > spellh - > spells [ spellToCast - > additionalInfo ] ;
2009-04-15 17:03:31 +03:00
ui8 schoolLevel = 0 ;
2010-12-24 23:44:48 +02:00
if ( activeStack - > attackerOwned )
2009-04-15 17:03:31 +03:00
{
if ( attackingHeroInstance )
schoolLevel = attackingHeroInstance - > getSpellSchoolLevel ( & spToCast ) ;
}
else
{
if ( defendingHeroInstance )
schoolLevel = defendingHeroInstance - > getSpellSchoolLevel ( & spToCast ) ;
}
//obtaining range and printing it
std : : set < ui16 > shaded = spToCast . rangeInHexes ( b , schoolLevel ) ;
for ( std : : set < ui16 > : : iterator it = shaded . begin ( ) ; it ! = shaded . end ( ) ; + + it ) //for spells with range greater then one hex
{
2010-02-19 18:02:34 +02:00
if ( curInt - > sysOpts . printMouseShadow & & ( * it % BFIELD_WIDTH ! = 0 ) & & ( * it % BFIELD_WIDTH ! = 16 ) )
2009-04-15 17:03:31 +03:00
{
int x = 14 + ( ( * it / BFIELD_WIDTH ) % 2 = = 0 ? 22 : 0 ) + 44 * ( * it % BFIELD_WIDTH ) + pos . x ;
int y = 86 + 42 * ( * it / BFIELD_WIDTH ) + pos . y ;
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( cellShade - > h , cellShade - > w , x , y ) ;
CSDL_Ext : : blit8bppAlphaTo24bpp ( cellShade , NULL , to , & temp_rect ) ;
2009-04-15 17:03:31 +03:00
}
}
}
2010-02-19 18:02:34 +02:00
else if ( curInt - > sysOpts . printMouseShadow ) //when not casting spell
2009-01-15 19:01:08 +02:00
{
int x = 14 + ( ( b / BFIELD_WIDTH ) % 2 = = 0 ? 22 : 0 ) + 44 * ( b % BFIELD_WIDTH ) + pos . x ;
int y = 86 + 42 * ( b / BFIELD_WIDTH ) + pos . y ;
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( cellShade - > h , cellShade - > w , x , y ) ;
CSDL_Ext : : blit8bppAlphaTo24bpp ( cellShade , NULL , to , & temp_rect ) ;
2009-01-15 19:01:08 +02:00
}
}
}
SDL_SetClipRect ( to , & buf ) ; //restoring previous clip_rect
2009-04-16 17:01:27 +03:00
//prevents blitting outside this window
2009-01-15 19:01:08 +02:00
SDL_GetClipRect ( to , & buf ) ;
SDL_SetClipRect ( to , & pos ) ;
2009-09-25 14:38:18 +03:00
//preparing obstacles to be shown
2010-02-19 18:02:34 +02:00
std : : vector < CObstacleInstance > obstacles = curInt - > cb - > battleGetAllObstacles ( ) ;
2011-02-09 17:19:53 +02:00
std : : multimap < THex , int > hexToObstacle ;
2009-02-09 16:50:32 +02:00
for ( int b = 0 ; b < obstacles . size ( ) ; + + b )
{
2011-02-09 17:19:53 +02:00
THex position = CGI - > heroh - > obstacles . find ( obstacles [ b ] . ID ) - > second . getMaxBlocked ( obstacles [ b ] . pos ) ;
2009-09-25 14:38:18 +03:00
hexToObstacle . insert ( std : : make_pair ( position , b ) ) ;
2009-02-09 16:50:32 +02:00
}
2011-04-30 22:52:35 +03:00
2009-01-15 19:01:08 +02:00
////showing units //a lot of work...
2010-12-24 23:44:48 +02:00
std : : vector < const CStack * > stackAliveByHex [ BFIELD_SIZE ] ;
2009-01-15 19:01:08 +02:00
//double loop because dead stacks should be printed first
2011-06-25 16:53:15 +03:00
for ( int i = 0 ; i < stacks . size ( ) ; i + + )
2009-01-15 19:01:08 +02:00
{
2011-06-25 16:53:15 +03:00
const CStack * s = stacks [ i ] ;
2011-05-26 17:47:45 +03:00
if ( creAnims . find ( s - > ID ) = = creAnims . end ( ) ) //e.g. for summoned but not yet handled stacks
2010-01-28 19:23:01 +02:00
continue ;
2010-12-06 01:10:02 +02:00
if ( creAnims [ s - > ID ] - > getType ( ) ! = 5 & & s - > position > = 0 ) //don't show turrets here
2010-12-24 23:44:48 +02:00
stackAliveByHex [ s - > position ] . push_back ( s ) ;
2009-01-15 19:01:08 +02:00
}
2010-12-24 23:44:48 +02:00
std : : vector < const CStack * > stackDeadByHex [ BFIELD_SIZE ] ;
2011-06-25 16:53:15 +03:00
for ( int i = 0 ; i < stacks . size ( ) ; i + + )
2009-01-15 19:01:08 +02:00
{
2011-06-25 16:53:15 +03:00
const CStack * s = stacks [ i ] ;
2011-05-26 17:47:45 +03:00
if ( creAnims . find ( s - > ID ) = = creAnims . end ( ) ) //e.g. for summoned but not yet handled stacks
2010-01-28 19:23:01 +02:00
continue ;
2010-12-06 01:10:02 +02:00
if ( creAnims [ s - > ID ] - > getType ( ) = = 5 )
2010-12-24 23:44:48 +02:00
stackDeadByHex [ s - > position ] . push_back ( s ) ;
2009-01-15 19:01:08 +02:00
}
2009-09-10 14:28:34 +03:00
//handle animations
for ( std : : list < std : : pair < CBattleAnimation * , bool > > : : iterator it = pendingAnims . begin ( ) ; it ! = pendingAnims . end ( ) ; + + it )
{
if ( ! it - > first ) //this animation should be deleted
continue ;
if ( ! it - > second )
{
it - > second = it - > first - > init ( ) ;
}
if ( it - > second & & it - > first )
it - > first - > nextFrame ( ) ;
}
//delete anims
2009-09-14 15:00:23 +03:00
int preSize = pendingAnims . size ( ) ;
2009-09-10 14:28:34 +03:00
for ( std : : list < std : : pair < CBattleAnimation * , bool > > : : iterator it = pendingAnims . begin ( ) ; it ! = pendingAnims . end ( ) ; + + it )
{
if ( it - > first = = NULL )
{
pendingAnims . erase ( it ) ;
it = pendingAnims . begin ( ) ;
break ;
}
}
2009-01-15 19:01:08 +02:00
2009-09-14 15:00:23 +03:00
if ( preSize > 0 & & pendingAnims . size ( ) = = 0 )
{
2009-11-13 23:01:33 +02:00
//action finished, restore the interface
if ( ! active )
activate ( ) ;
2009-09-15 15:20:11 +03:00
//activation of next stack
2010-12-24 23:44:48 +02:00
if ( pendingAnims . size ( ) = = 0 & & stackToActivate ! = NULL )
2009-09-15 15:20:11 +03:00
{
activateStack ( ) ;
}
2009-09-16 13:36:50 +03:00
//anims ended
animsAreDisplayed . setn ( false ) ;
2009-09-14 15:00:23 +03:00
}
2009-01-15 19:01:08 +02:00
for ( int b = 0 ; b < BFIELD_SIZE ; + + b ) //showing dead stacks
{
for ( size_t v = 0 ; v < stackDeadByHex [ b ] . size ( ) ; + + v )
{
2010-12-24 23:44:48 +02:00
creAnims [ stackDeadByHex [ b ] [ v ] - > ID ] - > nextFrame ( to , creAnims [ stackDeadByHex [ b ] [ v ] - > ID ] - > pos . x , creAnims [ stackDeadByHex [ b ] [ v ] - > ID ] - > pos . y , creDir [ stackDeadByHex [ b ] [ v ] - > ID ] , animCount , false ) ; //increment always when moving, never if stack died
2009-01-15 19:01:08 +02:00
}
}
2010-12-06 01:10:02 +02:00
std : : vector < const CStack * > flyingStacks ; //flying stacks should be displayed later, over other stacks and obstacles
2011-05-15 20:18:36 +03:00
if ( ! siegeH )
2009-01-15 19:01:08 +02:00
{
2011-05-15 20:18:36 +03:00
for ( int b = 0 ; b < BFIELD_SIZE ; + + b ) //showing alive stacks
2009-01-15 19:01:08 +02:00
{
2011-05-15 20:18:36 +03:00
showAliveStacks ( stackAliveByHex , b , & flyingStacks , to ) ;
showObstacles ( & hexToObstacle , obstacles , b , to ) ;
showPieceOfWall ( to , b , stacks ) ;
2009-01-15 19:01:08 +02:00
}
2011-05-15 20:18:36 +03:00
}
// Siege drawing
else
{
for ( int i = 0 ; i < 4 ; i + + )
{
// xMin, xMax => go from hex x pos to hex x pos
// yMin, yMax => go from hex y pos to hex y pos
// xMove => 0: left side, 1: right side
// xMoveDir => 0: decrement, 1: increment, alters every second hex line either xMin or xMax depending on xMove
int xMin , xMax , yMin , yMax , xMove , xMoveDir = 0 ;
switch ( i )
{
// display units shown at the upper left side
case 0 :
xMin = 0 ;
yMin = 0 ;
xMax = 11 ;
yMax = 4 ;
xMove = 1 ;
break ;
// display wall/units shown at the upper wall area/right upper side
case 1 :
xMin = 12 ;
yMin = 0 ;
xMax = 16 ;
yMax = 4 ;
xMove = 0 ;
break ;
// display units shown at the lower wall area/right lower side
case 2 :
xMin = 10 ;
yMin = 5 ;
xMax = 16 ;
yMax = 10 ;
xMove = 0 ;
xMoveDir = 1 ;
break ;
// display units shown at the left lower side
case 3 :
xMin = 0 ;
yMin = 5 ;
xMax = 9 ;
yMax = 10 ;
xMove = 1 ;
xMoveDir = 1 ;
break ;
}
int runNum = 0 ;
for ( int j = yMin ; j < = yMax ; j + + )
{
if ( runNum > 0 )
{
if ( xMin = = xMax )
xMax = xMin = ( ( runNum % 2 ) = = 0 ) ? ( xMin + ( xMoveDir = = 0 ? - 1 : 1 ) ) : xMin ;
else if ( xMove = = 1 )
xMax = ( ( runNum % 2 ) = = 0 ) ? ( xMax + ( xMoveDir = = 0 ? - 1 : 1 ) ) : xMax ;
else if ( xMove = = 0 )
xMin = ( ( runNum % 2 ) = = 0 ) ? ( xMin + ( xMoveDir = = 0 ? - 1 : 1 ) ) : xMin ;
}
2009-08-26 17:09:55 +03:00
2011-05-15 20:18:36 +03:00
for ( int k = xMin ; k < = xMax ; k + + )
{
int hex = j * 17 + k ;
showAliveStacks ( stackAliveByHex , hex , & flyingStacks , to ) ;
showObstacles ( & hexToObstacle , obstacles , hex , to ) ;
showPieceOfWall ( to , hex , stacks ) ;
}
2009-09-25 14:38:18 +03:00
2011-05-15 20:18:36 +03:00
+ + runNum ;
}
2009-09-25 14:38:18 +03:00
}
2009-01-15 19:01:08 +02:00
}
2009-09-29 14:23:47 +03:00
2010-12-24 23:44:48 +02:00
for ( int b = 0 ; b < flyingStacks . size ( ) ; + + b ) //showing flying stacks
2010-12-06 01:10:02 +02:00
showAliveStack ( flyingStacks [ b ] , to ) ;
2009-09-29 14:23:47 +03:00
2009-01-15 19:01:08 +02:00
//units shown
2009-09-25 14:38:18 +03:00
2011-05-26 17:47:45 +03:00
// Show projectiles
projectileShowHelper ( to ) ;
2009-01-15 19:01:08 +02:00
//showing spell effects
if ( battleEffects . size ( ) )
{
for ( std : : list < SBattleEffect > : : iterator it = battleEffects . begin ( ) ; it ! = battleEffects . end ( ) ; + + it )
{
SDL_Surface * bitmapToBlit = it - > anim - > ourImages [ ( it - > frame ) % it - > anim - > ourImages . size ( ) ] . bitmap ;
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( bitmapToBlit - > h , bitmapToBlit - > w , it - > x , it - > y ) ;
SDL_BlitSurface ( bitmapToBlit , NULL , to , & temp_rect ) ;
2009-01-15 19:01:08 +02:00
}
}
2009-01-30 16:36:26 +02:00
SDL_SetClipRect ( to , & buf ) ; //restoring previous clip_rect
2009-09-04 17:11:42 +03:00
//showing menu background and console
blitAt ( menu , pos . x , 556 + pos . y , to ) ;
2011-02-14 22:31:53 +02:00
if ( tacticsMode )
{
2011-02-22 11:47:25 +02:00
btactNext - > showAll ( to ) ;
btactEnd - > showAll ( to ) ;
2011-02-14 22:31:53 +02:00
}
else
{
2011-02-22 11:47:25 +02:00
console - > showAll ( to ) ;
bConsoleUp - > showAll ( to ) ;
bConsoleDown - > showAll ( to ) ;
2011-02-14 22:31:53 +02:00
}
2009-09-04 17:11:42 +03:00
2009-11-28 03:42:08 +02:00
//showing buttons
2011-02-20 11:24:53 +02:00
bOptions - > showAll ( to ) ;
bSurrender - > showAll ( to ) ;
bFlee - > showAll ( to ) ;
bAutofight - > showAll ( to ) ;
bSpell - > showAll ( to ) ;
bWait - > showAll ( to ) ;
bDefence - > showAll ( to ) ;
2009-11-28 03:42:08 +02:00
2010-06-01 22:05:30 +03:00
//showing window with result of battle
if ( resWindow )
{
resWindow - > show ( to ) ;
}
2009-09-04 17:11:42 +03:00
//showing in-game console
2009-04-14 15:47:09 +03:00
LOCPLINT - > cingconsole - > show ( to ) ;
2009-01-15 19:01:08 +02:00
2009-09-20 15:47:40 +03:00
Rect posWithQueue = Rect ( pos . x , pos . y , 800 , 600 ) ;
2010-02-19 18:02:34 +02:00
if ( curInt - > sysOpts . showQueue )
2009-09-20 15:47:40 +03:00
{
if ( ! queue - > embedded )
{
posWithQueue . y - = queue - > pos . h ;
posWithQueue . h + = queue - > pos . h ;
}
//showing queue
if ( ! bresult )
queue - > showAll ( to ) ;
2009-09-21 11:29:41 +03:00
else
queue - > blitBg ( to ) ; //blit only background, stacks are deleted
2009-09-20 15:47:40 +03:00
}
2009-01-15 19:01:08 +02:00
//printing border around interface
2009-01-14 21:07:57 +02:00
if ( screen - > w ! = 800 | | screen - > h ! = 600 )
2009-09-20 15:47:40 +03:00
{
2010-02-19 18:02:34 +02:00
CMessage : : drawBorder ( curInt - > playerID , to , posWithQueue . w + 28 , posWithQueue . h + 28 , posWithQueue . x - 14 , posWithQueue . y - 15 ) ;
2009-09-20 15:47:40 +03:00
}
2009-01-15 19:01:08 +02:00
}
2011-05-15 20:18:36 +03:00
void CBattleInterface : : showAliveStacks ( std : : vector < const CStack * > * aliveStacks , int hex , std : : vector < const CStack * > * flyingStacks , SDL_Surface * to )
{
2011-05-15 20:36:39 +03:00
//showing hero animations
if ( hex = = 0 )
if ( attackingHero )
attackingHero - > show ( to ) ;
if ( hex = = 16 )
if ( defendingHero )
defendingHero - > show ( to ) ;
2011-05-15 20:18:36 +03:00
for ( int v = 0 ; v < aliveStacks [ hex ] . size ( ) ; + + v )
{
const CStack * s = aliveStacks [ hex ] [ v ] ;
if ( ! s - > hasBonusOfType ( Bonus : : FLYING ) | | creAnims [ s - > ID ] - > getType ( ) ! = 0 )
showAliveStack ( s , to ) ;
else
flyingStacks - > push_back ( s ) ;
}
}
void CBattleInterface : : showObstacles ( std : : multimap < THex , int > * hexToObstacle , std : : vector < CObstacleInstance > & obstacles , int hex , SDL_Surface * to )
{
std : : pair < std : : multimap < THex , int > : : const_iterator , std : : multimap < THex , int > : : const_iterator > obstRange =
hexToObstacle - > equal_range ( hex ) ;
for ( std : : multimap < THex , int > : : const_iterator it = obstRange . first ; it ! = obstRange . second ; + + it )
{
CObstacleInstance & curOb = obstacles [ it - > second ] ;
std : : pair < si16 , si16 > shift = CGI - > heroh - > obstacles . find ( curOb . ID ) - > second . posShift ;
int x = ( ( curOb . pos / BFIELD_WIDTH ) % 2 = = 0 ? 22 : 0 ) + 44 * ( curOb . pos % BFIELD_WIDTH ) + pos . x + shift . first ;
int y = 86 + 42 * ( curOb . pos / BFIELD_WIDTH ) + pos . y + shift . second ;
std : : vector < Cimage > & images = idToObstacle [ curOb . ID ] - > ourImages ; //reference to animation of obstacle
blitAt ( images [ ( ( animCount + 1 ) / ( 4 / curInt - > sysOpts . animSpeed ) ) % images . size ( ) ] . bitmap , x , y , to ) ;
}
}
2009-01-15 19:01:08 +02:00
void CBattleInterface : : keyPressed ( const SDL_KeyboardEvent & key )
{
2009-09-20 15:47:40 +03:00
if ( key . keysym . sym = = SDLK_q & & key . state = = SDL_PRESSED )
2009-01-15 19:01:08 +02:00
{
2010-02-19 18:02:34 +02:00
if ( curInt - > sysOpts . showQueue ) //hide queue
2009-09-20 15:47:40 +03:00
hideQueue ( ) ;
else
showQueue ( ) ;
2009-09-24 16:23:52 +03:00
2010-02-19 18:02:34 +02:00
curInt - > sysOpts . settingsChanged ( ) ;
2009-01-15 19:01:08 +02:00
}
2009-04-16 17:01:27 +03:00
else if ( key . keysym . sym = = SDLK_ESCAPE & & spellDestSelectMode )
{
endCastingSpell ( ) ;
}
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : mouseMoved ( const SDL_MouseMotionEvent & sEvent )
{
2010-12-24 23:44:48 +02:00
if ( activeStack ! = NULL & & ! spellDestSelectMode )
2009-01-15 19:01:08 +02:00
{
2009-02-21 17:43:28 +02:00
mouseHoveredStack = - 1 ;
2009-01-15 19:01:08 +02:00
int myNumber = - 1 ; //number of hovered tile
2011-07-16 16:57:25 +03:00
for ( int g = 0 ; g < BFIELD_SIZE ; + + g )
2009-01-15 19:01:08 +02:00
{
if ( bfield [ g ] . hovered & & bfield [ g ] . strictHovered )
{
myNumber = g ;
break ;
}
}
if ( myNumber = = - 1 )
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 6 ) ;
2009-01-29 20:07:31 +02:00
if ( console - > whoSetAlter = = 0 )
{
console - > alterTxt = " " ;
}
2009-01-15 19:01:08 +02:00
}
else
{
2011-02-26 19:32:56 +02:00
if ( std : : find ( occupyableHexes . begin ( ) , occupyableHexes . end ( ) , myNumber ) = = occupyableHexes . end ( ) )
2009-01-15 19:01:08 +02:00
{
2010-02-19 18:02:34 +02:00
const CStack * shere = curInt - > cb - > battleGetStackByPos ( myNumber ) ;
2010-12-24 23:44:48 +02:00
const CStack * sactive = activeStack ;
2009-01-15 19:01:08 +02:00
if ( shere )
{
2010-02-19 18:02:34 +02:00
if ( shere - > owner = = curInt - > playerID ) //our stack
2009-01-29 20:07:31 +02:00
{
2010-05-02 21:20:26 +03:00
if ( sactive - > hasBonusOfType ( Bonus : : HEALER ) )
2010-03-07 19:40:33 +02:00
{
//display the possibility to heal this creature
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 17 ) ;
2010-03-07 19:40:33 +02:00
}
else
{
//info about creature
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 5 ) ;
2010-03-07 19:40:33 +02:00
}
2009-01-29 20:07:31 +02:00
//setting console text
char buf [ 500 ] ;
2010-11-20 19:36:02 +02:00
sprintf ( buf , CGI - > generaltexth - > allTexts [ 297 ] . c_str ( ) , shere - > count = = 1 ? shere - > getCreature ( ) - > nameSing . c_str ( ) : shere - > getCreature ( ) - > namePl . c_str ( ) ) ;
2009-01-29 20:07:31 +02:00
console - > alterTxt = buf ;
console - > whoSetAlter = 0 ;
2009-02-21 17:43:28 +02:00
mouseHoveredStack = shere - > ID ;
2011-02-09 15:56:30 +02:00
if ( creAnims [ shere - > ID ] - > getType ( ) = = CCreatureAnim : : HOLDING & & creAnims [ shere - > ID ] - > framesInGroup ( CCreatureAnim : : MOUSEON ) > 0 )
2009-02-21 17:43:28 +02:00
{
2011-02-09 15:56:30 +02:00
creAnims [ shere - > ID ] - > playOnce ( CCreatureAnim : : MOUSEON ) ;
2009-02-21 17:43:28 +02:00
}
2010-03-07 19:40:33 +02:00
2009-01-29 20:07:31 +02:00
}
2011-01-07 12:48:31 +02:00
else if ( curInt - > cb - > battleCanShoot ( activeStack , myNumber ) ) //we can shoot enemy
2009-01-29 20:07:31 +02:00
{
2011-01-07 12:48:31 +02:00
if ( curInt - > cb - > battleHasDistancePenalty ( activeStack , myNumber ) | |
curInt - > cb - > battleHasWallPenalty ( activeStack , myNumber ) )
2010-04-06 16:19:54 +03:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 15 ) ;
2010-04-06 16:19:54 +03:00
}
else
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 3 ) ;
2010-04-06 16:19:54 +03:00
}
2009-01-29 20:07:31 +02:00
//setting console text
char buf [ 500 ] ;
2009-11-13 23:01:33 +02:00
//calculating estimated dmg
2011-01-08 20:33:40 +02:00
std : : pair < ui32 , ui32 > estimatedDmg = curInt - > cb - > battleEstimateDamage ( sactive , shere ) ;
2009-08-29 20:09:07 +03:00
std : : ostringstream estDmg ;
estDmg < < estimatedDmg . first < < " - " < < estimatedDmg . second ;
//printing
2010-11-20 19:36:02 +02:00
sprintf ( buf , CGI - > generaltexth - > allTexts [ 296 ] . c_str ( ) , shere - > count = = 1 ? shere - > getCreature ( ) - > nameSing . c_str ( ) : shere - > getCreature ( ) - > namePl . c_str ( ) , sactive - > shots , estDmg . str ( ) . c_str ( ) ) ;
2009-01-29 20:07:31 +02:00
console - > alterTxt = buf ;
console - > whoSetAlter = 0 ;
}
2009-01-15 19:01:08 +02:00
else if ( isTileAttackable ( myNumber ) ) //available enemy (melee attackable)
{
2010-12-19 16:39:56 +02:00
CCursorHandler * cursor = CCS - > curh ;
2009-08-13 04:55:00 +03:00
const CBattleHex & hoveredHex = bfield [ myNumber ] ;
const double subdividingAngle = 2.0 * M_PI / 6.0 ; // Divide a hex into six sectors.
const double hexMidX = hoveredHex . pos . x + hoveredHex . pos . w / 2 ;
const double hexMidY = hoveredHex . pos . y + hoveredHex . pos . h / 2 ;
const double cursorHexAngle = M_PI - atan2 ( hexMidY - cursor - > ypos , cursor - > xpos - hexMidX ) + subdividingAngle / 2 ;
2009-08-19 18:47:00 +03:00
const double sector = fmod ( cursorHexAngle / subdividingAngle , 6.0 ) ;
2009-08-13 04:55:00 +03:00
const int zigzagCorrection = ! ( ( myNumber / BFIELD_WIDTH ) % 2 ) ; // Off-by-one correction needed to deal with the odd battlefield rows.
2009-08-19 18:47:00 +03:00
std : : vector < int > sectorCursor ; // From left to bottom left.
sectorCursor . push_back ( 8 ) ;
sectorCursor . push_back ( 9 ) ;
sectorCursor . push_back ( 10 ) ;
sectorCursor . push_back ( 11 ) ;
sectorCursor . push_back ( 12 ) ;
sectorCursor . push_back ( 7 ) ;
2010-12-24 23:44:48 +02:00
const bool doubleWide = activeStack - > doubleWide ( ) ;
2009-08-19 18:47:00 +03:00
bool aboveAttackable = true , belowAttackable = true ;
2009-08-13 04:55:00 +03:00
// Exclude directions which cannot be attacked from.
// Check to the left.
2011-02-26 19:32:56 +02:00
if ( myNumber % BFIELD_WIDTH < = 1 | | ! vstd : : contains ( occupyableHexes , myNumber - 1 ) )
2009-11-13 23:01:33 +02:00
{
2009-08-13 04:55:00 +03:00
sectorCursor [ 0 ] = - 1 ;
}
2009-08-19 18:47:00 +03:00
// Check top left, top right as well as above for 2-hex creatures.
2009-11-13 23:01:33 +02:00
if ( myNumber / BFIELD_WIDTH = = 0 )
{
2009-08-13 04:55:00 +03:00
sectorCursor [ 1 ] = - 1 ;
sectorCursor [ 2 ] = - 1 ;
2009-08-19 18:47:00 +03:00
aboveAttackable = false ;
2009-11-13 23:01:33 +02:00
}
else
{
if ( doubleWide )
{
2009-08-19 18:47:00 +03:00
bool attackRow [ 4 ] = { true , true , true , true } ;
2011-02-26 19:32:56 +02:00
if ( myNumber % BFIELD_WIDTH < = 1 | | ! vstd : : contains ( occupyableHexes , myNumber - BFIELD_WIDTH - 2 + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
attackRow [ 0 ] = false ;
2011-02-26 19:32:56 +02:00
if ( ! vstd : : contains ( occupyableHexes , myNumber - BFIELD_WIDTH - 1 + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
attackRow [ 1 ] = false ;
2011-02-26 19:32:56 +02:00
if ( ! vstd : : contains ( occupyableHexes , myNumber - BFIELD_WIDTH + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
attackRow [ 2 ] = false ;
2011-02-26 19:32:56 +02:00
if ( myNumber % BFIELD_WIDTH > = BFIELD_WIDTH - 2 | | ! vstd : : contains ( occupyableHexes , myNumber - BFIELD_WIDTH + 1 + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
attackRow [ 3 ] = false ;
if ( ! ( attackRow [ 0 ] & & attackRow [ 1 ] ) )
sectorCursor [ 1 ] = - 1 ;
if ( ! ( attackRow [ 1 ] & & attackRow [ 2 ] ) )
aboveAttackable = false ;
if ( ! ( attackRow [ 2 ] & & attackRow [ 3 ] ) )
sectorCursor [ 2 ] = - 1 ;
2009-11-13 23:01:33 +02:00
}
else
{
2011-02-26 19:32:56 +02:00
if ( ! vstd : : contains ( occupyableHexes , myNumber - BFIELD_WIDTH - 1 + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
sectorCursor [ 1 ] = - 1 ;
2011-02-26 19:32:56 +02:00
if ( ! vstd : : contains ( occupyableHexes , myNumber - BFIELD_WIDTH + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
sectorCursor [ 2 ] = - 1 ;
}
2009-01-15 19:01:08 +02:00
}
2009-08-13 04:55:00 +03:00
// Check to the right.
2011-02-26 19:32:56 +02:00
if ( myNumber % BFIELD_WIDTH > = BFIELD_WIDTH - 2 | | ! vstd : : contains ( occupyableHexes , myNumber + 1 ) )
2009-11-13 23:01:33 +02:00
{
2009-08-13 04:55:00 +03:00
sectorCursor [ 3 ] = - 1 ;
}
2009-08-19 18:47:00 +03:00
// Check bottom right, bottom left as well as below for 2-hex creatures.
2009-11-13 23:01:33 +02:00
if ( myNumber / BFIELD_WIDTH = = BFIELD_HEIGHT - 1 )
{
2009-08-13 04:55:00 +03:00
sectorCursor [ 4 ] = - 1 ;
sectorCursor [ 5 ] = - 1 ;
2009-08-19 18:47:00 +03:00
belowAttackable = false ;
2009-11-13 23:01:33 +02:00
}
else
{
if ( doubleWide )
{
2009-08-19 18:47:00 +03:00
bool attackRow [ 4 ] = { true , true , true , true } ;
2011-02-26 19:32:56 +02:00
if ( myNumber % BFIELD_WIDTH < = 1 | | ! vstd : : contains ( occupyableHexes , myNumber + BFIELD_WIDTH - 2 + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
attackRow [ 0 ] = false ;
2011-02-26 19:32:56 +02:00
if ( ! vstd : : contains ( occupyableHexes , myNumber + BFIELD_WIDTH - 1 + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
attackRow [ 1 ] = false ;
2011-02-26 19:32:56 +02:00
if ( ! vstd : : contains ( occupyableHexes , myNumber + BFIELD_WIDTH + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
attackRow [ 2 ] = false ;
2011-02-26 19:32:56 +02:00
if ( myNumber % BFIELD_WIDTH > = BFIELD_WIDTH - 2 | | ! vstd : : contains ( occupyableHexes , myNumber + BFIELD_WIDTH + 1 + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
attackRow [ 3 ] = false ;
if ( ! ( attackRow [ 0 ] & & attackRow [ 1 ] ) )
sectorCursor [ 5 ] = - 1 ;
if ( ! ( attackRow [ 1 ] & & attackRow [ 2 ] ) )
belowAttackable = false ;
if ( ! ( attackRow [ 2 ] & & attackRow [ 3 ] ) )
sectorCursor [ 4 ] = - 1 ;
2009-11-13 23:01:33 +02:00
}
else
{
2011-02-26 19:32:56 +02:00
if ( ! vstd : : contains ( occupyableHexes , myNumber + BFIELD_WIDTH + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
sectorCursor [ 4 ] = - 1 ;
2011-02-26 19:32:56 +02:00
if ( ! vstd : : contains ( occupyableHexes , myNumber + BFIELD_WIDTH - 1 + zigzagCorrection ) )
2009-08-19 18:47:00 +03:00
sectorCursor [ 5 ] = - 1 ;
}
}
// Determine index from sector.
int cursorIndex ;
2009-11-13 23:01:33 +02:00
if ( doubleWide )
{
2009-08-19 18:47:00 +03:00
sectorCursor . insert ( sectorCursor . begin ( ) + 5 , belowAttackable ? 13 : - 1 ) ;
sectorCursor . insert ( sectorCursor . begin ( ) + 2 , aboveAttackable ? 14 : - 1 ) ;
if ( sector < 1.5 )
cursorIndex = sector ;
else if ( sector > = 1.5 & & sector < 2.5 )
cursorIndex = 2 ;
else if ( sector > = 2.5 & & sector < 4.5 )
cursorIndex = ( int ) sector + 1 ;
else if ( sector > = 4.5 & & sector < 5.5 )
cursorIndex = 6 ;
else
cursorIndex = ( int ) sector + 2 ;
2009-11-13 23:01:33 +02:00
}
else
{
2009-08-19 18:47:00 +03:00
cursorIndex = sector ;
2009-08-13 04:55:00 +03:00
}
// Find the closest direction attackable, starting with the right one.
// FIXME: Is this really how the original H3 client does it?
int i = 0 ;
2009-08-19 18:47:00 +03:00
while ( sectorCursor [ ( cursorIndex + i ) % sectorCursor . size ( ) ] = = - 1 )
2009-08-13 04:55:00 +03:00
i = i < = 0 ? 1 - i : - i ; // 0, 1, -1, 2, -2, 3, -3 etc..
2009-08-19 18:47:00 +03:00
cursor - > changeGraphic ( 1 , sectorCursor [ ( cursorIndex + i ) % sectorCursor . size ( ) ] ) ;
2009-08-29 20:09:07 +03:00
//setting console info
char buf [ 500 ] ;
2009-11-13 23:01:33 +02:00
//calculating estimated dmg
2011-01-08 20:33:40 +02:00
std : : pair < ui32 , ui32 > estimatedDmg = curInt - > cb - > battleEstimateDamage ( sactive , shere ) ;
2009-08-29 20:09:07 +03:00
std : : ostringstream estDmg ;
estDmg < < estimatedDmg . first < < " - " < < estimatedDmg . second ;
//printing
2010-11-20 19:36:02 +02:00
sprintf ( buf , CGI - > generaltexth - > allTexts [ 36 ] . c_str ( ) , shere - > count = = 1 ? shere - > getCreature ( ) - > nameSing . c_str ( ) : shere - > getCreature ( ) - > namePl . c_str ( ) , estDmg . str ( ) . c_str ( ) ) ;
2009-08-29 20:09:07 +03:00
console - > alterTxt = buf ;
console - > whoSetAlter = 0 ;
2009-01-15 19:01:08 +02:00
}
else //unavailable enemy
2009-01-29 20:07:31 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 0 ) ;
2009-01-29 20:07:31 +02:00
console - > alterTxt = " " ;
console - > whoSetAlter = 0 ;
}
2009-01-15 19:01:08 +02:00
}
2010-05-02 21:20:26 +03:00
else if ( sactive & & sactive - > hasBonusOfType ( Bonus : : CATAPULT ) & & isCatapultAttackable ( myNumber ) ) //catapulting
2009-09-01 16:54:13 +03:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 16 ) ;
2009-09-01 16:54:13 +03:00
console - > alterTxt = " " ;
console - > whoSetAlter = 0 ;
}
2009-01-15 19:01:08 +02:00
else //empty unavailable tile
2009-01-29 20:07:31 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 0 ) ;
2009-01-29 20:07:31 +02:00
console - > alterTxt = " " ;
console - > whoSetAlter = 0 ;
}
2009-01-15 19:01:08 +02:00
}
else //available tile
{
2009-09-10 14:28:34 +03:00
//setting console text and cursor
2010-12-24 23:44:48 +02:00
const CStack * sactive = activeStack ;
2009-09-28 18:05:35 +03:00
if ( sactive ) //there can be a moment when stack is dead ut next is not yet activated
2009-01-29 20:07:31 +02:00
{
2009-09-28 18:05:35 +03:00
char buf [ 500 ] ;
2010-05-02 21:20:26 +03:00
if ( sactive - > hasBonusOfType ( Bonus : : FLYING ) )
2009-09-28 18:05:35 +03:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 2 ) ;
2010-11-20 19:36:02 +02:00
sprintf ( buf , CGI - > generaltexth - > allTexts [ 295 ] . c_str ( ) , sactive - > count = = 1 ? sactive - > getCreature ( ) - > nameSing . c_str ( ) : sactive - > getCreature ( ) - > namePl . c_str ( ) ) ;
2009-09-28 18:05:35 +03:00
}
else
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 1 ) ;
2010-11-20 19:36:02 +02:00
sprintf ( buf , CGI - > generaltexth - > allTexts [ 294 ] . c_str ( ) , sactive - > count = = 1 ? sactive - > getCreature ( ) - > nameSing . c_str ( ) : sactive - > getCreature ( ) - > namePl . c_str ( ) ) ;
2009-09-28 18:05:35 +03:00
}
2009-01-29 20:07:31 +02:00
2009-09-28 18:05:35 +03:00
console - > alterTxt = buf ;
console - > whoSetAlter = 0 ;
}
2009-01-15 19:01:08 +02:00
}
}
}
else if ( spellDestSelectMode )
{
int myNumber = - 1 ; //number of hovered tile
for ( int g = 0 ; g < BFIELD_SIZE ; + + g )
{
if ( bfield [ g ] . hovered & & bfield [ g ] . strictHovered )
{
myNumber = g ;
break ;
}
}
if ( myNumber = = - 1 )
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 0 ) ;
2009-01-29 20:07:31 +02:00
//setting console text
console - > alterTxt = CGI - > generaltexth - > allTexts [ 23 ] ;
console - > whoSetAlter = 0 ;
2009-01-15 19:01:08 +02:00
}
else
{
2009-08-05 15:46:08 +03:00
//get dead stack if we cast resurrection or animate dead
2010-02-19 18:02:34 +02:00
const CStack * stackUnder = curInt - > cb - > battleGetStackByPos ( myNumber , spellToCast - > additionalInfo ! = 38 & & spellToCast - > additionalInfo ! = 39 ) ;
2009-08-05 15:46:08 +03:00
2010-05-02 21:20:26 +03:00
if ( stackUnder & & spellToCast - > additionalInfo = = 39 & & ! stackUnder - > hasBonusOfType ( Bonus : : UNDEAD ) ) //animate dead can be cast only on undead creatures
2009-08-05 15:46:08 +03:00
stackUnder = NULL ;
2009-08-01 14:55:40 +03:00
bool whichCase ; //for cases 1, 2 and 3
switch ( spellSelMode )
{
case 1 :
2010-02-19 18:02:34 +02:00
whichCase = stackUnder & & curInt - > playerID = = stackUnder - > owner ;
2009-08-01 14:55:40 +03:00
break ;
case 2 :
2010-02-19 18:02:34 +02:00
whichCase = stackUnder & & curInt - > playerID ! = stackUnder - > owner ;
2009-08-01 14:55:40 +03:00
break ;
case 3 :
whichCase = stackUnder ;
break ;
}
2009-01-15 19:01:08 +02:00
switch ( spellSelMode )
{
case 0 :
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 3 , 0 ) ;
2009-01-29 20:07:31 +02:00
//setting console text
char buf [ 500 ] ;
2010-12-19 16:39:56 +02:00
sprintf ( buf , CGI - > generaltexth - > allTexts [ 26 ] . c_str ( ) , CGI - > spellh - > spells [ spellToCast - > additionalInfo ] - > name . c_str ( ) ) ;
2009-01-29 20:07:31 +02:00
console - > alterTxt = buf ;
console - > whoSetAlter = 0 ;
2009-01-15 19:01:08 +02:00
break ;
2009-08-01 14:55:40 +03:00
case 1 : case 2 : case 3 :
if ( whichCase )
2009-01-29 20:07:31 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 3 , 0 ) ;
2009-01-29 20:07:31 +02:00
//setting console text
char buf [ 500 ] ;
2010-11-20 19:36:02 +02:00
std : : string creName = stackUnder - > count > 1 ? stackUnder - > getCreature ( ) - > namePl : stackUnder - > getCreature ( ) - > nameSing ;
2010-12-19 16:39:56 +02:00
sprintf ( buf , CGI - > generaltexth - > allTexts [ 27 ] . c_str ( ) , CGI - > spellh - > spells [ spellToCast - > additionalInfo ] - > name . c_str ( ) , creName . c_str ( ) ) ;
2009-01-29 20:07:31 +02:00
console - > alterTxt = buf ;
console - > whoSetAlter = 0 ;
break ;
}
2009-01-15 19:01:08 +02:00
else
2009-01-29 20:07:31 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 0 ) ;
2009-01-29 20:07:31 +02:00
//setting console text
console - > alterTxt = CGI - > generaltexth - > allTexts [ 23 ] ;
console - > whoSetAlter = 0 ;
}
2009-01-15 19:01:08 +02:00
break ;
case 4 : //TODO: implement this case
2009-08-19 13:59:42 +03:00
if ( blockedByObstacle ( myNumber ) )
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 3 , 0 ) ;
2009-08-19 13:59:42 +03:00
}
else
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 0 ) ;
2009-08-19 13:59:42 +03:00
}
2009-01-15 19:01:08 +02:00
break ;
}
}
}
}
2009-08-11 19:05:33 +03:00
void CBattleInterface : : clickRight ( tribool down , bool previousState )
2009-04-16 17:01:27 +03:00
{
if ( ! down & & spellDestSelectMode )
{
endCastingSpell ( ) ;
}
}
2009-01-15 19:01:08 +02:00
void CBattleInterface : : bOptionsf ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 0 , 0 ) ;
2009-01-15 19:01:08 +02:00
SDL_Rect temp_rect = genRect ( 431 , 481 , 160 , 84 ) ;
CBattleOptionsWindow * optionsWin = new CBattleOptionsWindow ( temp_rect , this ) ;
2009-08-07 01:36:51 +03:00
GH . pushInt ( optionsWin ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : bSurrenderf ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2011-03-05 18:38:22 +02:00
int cost = curInt - > cb - > battleGetSurrenderCost ( ) ;
if ( cost > = 0 )
{
const CGHeroInstance * opponent = curInt - > cb - > battleGetFightingHero ( 1 ) ;
std : : string enemyHeroName = opponent ? opponent - > name : " #ENEMY# " ; //TODO: should surrendering without enemy hero be enabled?
std : : string surrenderMessage = boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 32 ] ) % enemyHeroName % cost ) ; //%s states: "I will accept your surrender and grant you and your troops safe passage for the price of %d gold."
curInt - > showYesNoDialog ( surrenderMessage , std : : vector < SComponent * > ( ) , boost : : bind ( & CBattleInterface : : reallySurrender , this ) , 0 , false ) ;
}
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : bFleef ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2010-02-19 18:02:34 +02:00
if ( curInt - > cb - > battleCanFlee ( ) )
2009-08-16 16:44:17 +03:00
{
CFunctionList < void ( ) > ony = boost : : bind ( & CBattleInterface : : reallyFlee , this ) ;
2011-03-05 18:38:22 +02:00
curInt - > showYesNoDialog ( CGI - > generaltexth - > allTexts [ 28 ] , std : : vector < SComponent * > ( ) , ony , 0 , false ) ; //Are you sure you want to retreat?
2009-08-16 16:44:17 +03:00
}
else
{
std : : vector < SComponent * > comps ;
std : : string heroName ;
//calculating fleeing hero's name
if ( attackingHeroInstance )
2010-02-19 18:02:34 +02:00
if ( attackingHeroInstance - > tempOwner = = curInt - > cb - > getMyColor ( ) )
2009-08-16 16:44:17 +03:00
heroName = attackingHeroInstance - > name ;
if ( defendingHeroInstance )
2010-02-19 18:02:34 +02:00
if ( defendingHeroInstance - > tempOwner = = curInt - > cb - > getMyColor ( ) )
2009-08-16 16:44:17 +03:00
heroName = defendingHeroInstance - > name ;
//calculating text
char buffer [ 1000 ] ;
2011-03-05 18:38:22 +02:00
sprintf ( buffer , CGI - > generaltexth - > allTexts [ 340 ] . c_str ( ) , heroName . c_str ( ) ) ; //The Shackles of War are present. %s can not retreat!
2009-08-16 16:44:17 +03:00
//printing message
2010-02-19 18:02:34 +02:00
curInt - > showInfoDialog ( std : : string ( buffer ) , comps ) ;
2009-08-16 16:44:17 +03:00
}
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : reallyFlee ( )
{
2011-03-05 18:38:22 +02:00
giveCommand ( BattleAction : : RETREAT , 0 , 0 ) ;
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 0 , 0 ) ;
2009-01-15 19:01:08 +02:00
}
2011-03-05 18:38:22 +02:00
void CBattleInterface : : reallySurrender ( )
{
if ( curInt - > cb - > getResourceAmount ( Res : : GOLD ) < curInt - > cb - > battleGetSurrenderCost ( ) )
{
curInt - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 29 ] ) ; //You don't have enough gold!
}
else
{
giveCommand ( BattleAction : : SURRENDER , 0 , 0 ) ;
CCS - > curh - > changeGraphic ( 0 , 0 ) ;
}
}
2009-01-15 19:01:08 +02:00
void CBattleInterface : : bAutofightf ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : bSpellf ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 0 , 0 ) ;
2009-01-15 19:01:08 +02:00
const CGHeroInstance * chi = NULL ;
2010-02-19 18:02:34 +02:00
if ( attackingHeroInstance - > tempOwner = = curInt - > playerID )
2009-01-15 19:01:08 +02:00
chi = attackingHeroInstance ;
else
chi = defendingHeroInstance ;
2010-02-19 18:02:34 +02:00
CSpellWindow * spellWindow = new CSpellWindow ( genRect ( 595 , 620 , ( conf . cc . resx - 620 ) / 2 , ( conf . cc . resy - 595 ) / 2 ) , chi , curInt ) ;
2009-08-07 01:36:51 +03:00
GH . pushInt ( spellWindow ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : bWaitf ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2010-12-24 23:44:48 +02:00
if ( activeStack ! = NULL )
giveCommand ( 8 , 0 , activeStack - > ID ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : bDefencef ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2010-12-24 23:44:48 +02:00
if ( activeStack ! = NULL )
giveCommand ( 3 , 0 , activeStack - > ID ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : bConsoleUpf ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2009-01-15 19:01:08 +02:00
console - > scrollUp ( ) ;
2009-09-10 14:28:34 +03:00
}
2009-01-15 19:01:08 +02:00
2009-09-10 14:28:34 +03:00
void CBattleInterface : : bConsoleDownf ( )
{
2009-09-19 12:57:37 +03:00
if ( spellDestSelectMode ) //we are casting a spell
return ;
2009-09-10 14:28:34 +03:00
console - > scrollDown ( ) ;
2009-01-15 19:01:08 +02:00
}
2010-12-23 22:18:10 +02:00
void CBattleInterface : : newStack ( const CStack * stack )
2009-01-15 19:01:08 +02:00
{
2010-12-23 22:18:10 +02:00
Point coords = CBattleHex : : getXYUnitAnim ( stack - > position , stack - > owner = = attackingHeroInstance - > tempOwner , stack , this ) ; ;
2009-09-10 14:28:34 +03:00
2010-12-23 22:18:10 +02:00
if ( stack - > position < 0 ) //turret
2009-02-20 15:06:20 +02:00
{
2010-05-02 21:20:26 +03:00
const CCreature & turretCreature = * CGI - > creh - > creatures [ CGI - > creh - > factionToTurretCreature [ siegeH - > town - > town - > typeID ] ] ;
2010-12-23 22:18:10 +02:00
creAnims [ stack - > ID ] = new CCreatureAnimation ( turretCreature . animDefName ) ;
2011-04-30 22:52:35 +03:00
2011-05-26 17:47:45 +03:00
// Turret positions are read out of the /config/wall_pos.txt
2011-04-30 22:52:35 +03:00
int posID = 0 ;
switch ( stack - > position )
{
case - 2 : // keep creature
posID = 18 ;
break ;
case - 3 : // bottom creature
posID = 19 ;
break ;
case - 4 : // upper creature
posID = 20 ;
break ;
}
if ( posID ! = 0 )
{
coords . x = graphics - > wallPositions [ siegeH - > town - > town - > typeID ] [ posID - 1 ] . x + this - > pos . x ;
coords . y = graphics - > wallPositions [ siegeH - > town - > town - > typeID ] [ posID - 1 ] . y + this - > pos . y ;
}
2009-02-20 15:06:20 +02:00
}
2009-09-10 14:28:34 +03:00
else
2009-01-15 19:01:08 +02:00
{
2010-12-23 22:18:10 +02:00
creAnims [ stack - > ID ] = new CCreatureAnimation ( stack - > getCreature ( ) - > animDefName ) ;
2009-01-15 19:01:08 +02:00
}
2011-02-09 15:56:30 +02:00
creAnims [ stack - > ID ] - > setType ( CCreatureAnim : : HOLDING ) ;
2010-12-23 22:18:10 +02:00
creAnims [ stack - > ID ] - > pos = Rect ( coords . x , coords . y , creAnims [ stack - > ID ] - > fullWidth , creAnims [ stack - > ID ] - > fullHeight ) ;
creDir [ stack - > ID ] = stack - > attackerOwned ;
2009-09-10 14:28:34 +03:00
}
2011-05-30 02:49:25 +03:00
void CBattleInterface : : stackRemoved ( int stackID )
2009-09-10 14:28:34 +03:00
{
delete creAnims [ stackID ] ;
creAnims . erase ( stackID ) ;
creDir . erase ( stackID ) ;
}
2011-05-15 09:37:57 +03:00
void CBattleInterface : : stackActivated ( const CStack * stack ) //TODO: check it all before game state is changed due to abilities
2009-09-10 14:28:34 +03:00
{
2011-04-25 12:03:13 +03:00
//don't show animation when no HP is regenerated
if ( stack - > firstHPleft ! = stack - > MaxHealth ( ) )
{
if ( stack - > hasBonusOfType ( Bonus : : HP_REGENERATION ) | | stack - > hasBonusOfType ( Bonus : : FULL_HP_REGENERATION , 1 ) )
2011-05-15 09:37:57 +03:00
{
2011-04-25 12:03:13 +03:00
displayEffect ( 74 , stack - > position ) ;
2011-05-15 09:37:57 +03:00
CCS - > soundh - > playSound ( soundBase : : REGENER ) ;
}
2011-04-25 12:03:13 +03:00
if ( stack - > hasBonusOfType ( Bonus : : FULL_HP_REGENERATION , 0 ) )
2011-05-15 09:37:57 +03:00
{
displayEffect ( 74 , stack - > position ) ;
CCS - > soundh - > playSound ( soundBase : : REGENER ) ;
}
2011-04-25 12:03:13 +03:00
}
if ( stack - > hasBonusOfType ( Bonus : : MANA_DRAIN ) )
2011-05-15 09:37:57 +03:00
{
CGHeroInstance * enemy = NULL ; //probably could be smarter and not duplicated
if ( defendingHero )
if ( defendingHero - > myHero - > tempOwner ! = stack - > owner )
enemy = const_cast < CGHeroInstance * > ( defendingHero - > myHero ) ;
if ( attackingHero )
if ( attackingHero - > myHero - > tempOwner ! = stack - > owner )
enemy = const_cast < CGHeroInstance * > ( attackingHero - > myHero ) ;
if ( enemy )
{
ui32 manaDrained = stack - > valOfBonuses ( Bonus : : MANA_DRAIN ) ;
amin ( manaDrained , enemy - > mana ) ;
if ( manaDrained )
{
displayEffect ( 77 , stack - > position ) ;
CCS - > soundh - > playSound ( soundBase : : MANADRAI ) ;
}
}
}
2011-04-25 12:03:13 +03:00
if ( stack - > hasBonusOfType ( Bonus : : POISON ) )
2011-05-15 09:37:57 +03:00
{
displayEffect ( 67 , stack - > position ) ;
CCS - > soundh - > playSound ( soundBase : : POISON ) ;
}
2011-04-25 12:03:13 +03:00
2009-09-10 14:28:34 +03:00
//givenCommand = NULL;
2010-12-24 23:44:48 +02:00
stackToActivate = stack ;
2009-09-15 15:20:11 +03:00
if ( pendingAnims . size ( ) = = 0 )
activateStack ( ) ;
2009-09-10 14:28:34 +03:00
}
2009-01-15 19:01:08 +02:00
2011-08-01 20:36:18 +03:00
void CBattleInterface : : stackMoved ( const CStack * stack , std : : vector < THex > destHex , int distance )
2009-09-10 14:28:34 +03:00
{
2011-08-01 20:36:18 +03:00
addNewAnim ( new CBattleStackMoved ( this , stack , destHex , distance ) ) ;
2011-01-08 21:38:42 +02:00
waitForAnims ( ) ;
2009-09-10 14:28:34 +03:00
}
2009-01-15 19:01:08 +02:00
2009-09-10 14:28:34 +03:00
void CBattleInterface : : stacksAreAttacked ( std : : vector < SStackAttackedInfo > attackedInfos )
{
for ( int h = 0 ; h < attackedInfos . size ( ) ; + + h )
2009-01-15 19:01:08 +02:00
{
2009-09-16 13:36:50 +03:00
addNewAnim ( new CDefenceAnim ( attackedInfos [ h ] , this ) ) ;
2011-07-10 11:22:20 +03:00
if ( attackedInfos [ h ] . rebirth )
2011-07-10 12:03:46 +03:00
{
2011-07-10 11:22:20 +03:00
displayEffect ( 50 , attackedInfos [ h ] . defender - > position ) ; //TODO: play reverse death animation
2011-07-10 12:03:46 +03:00
CCS - > soundh - > playSound ( soundBase : : RESURECT ) ;
}
2009-01-15 19:01:08 +02:00
}
2011-01-08 21:38:42 +02:00
waitForAnims ( ) ;
2011-08-12 22:38:30 +03:00
int targets = 0 , killed = 0 , damage = 0 ;
for ( int h = 0 ; h < attackedInfos . size ( ) ; + + h )
{
+ + targets ;
killed + = attackedInfos [ h ] . killed ;
damage + = attackedInfos [ h ] . dmg ;
}
if ( targets > 1 )
printConsoleAttacked ( attackedInfos . front ( ) . defender , damage , killed , attackedInfos . front ( ) . attacker , true ) ; //creatures perish
else
printConsoleAttacked ( attackedInfos . front ( ) . defender , damage , killed , attackedInfos . front ( ) . attacker , false ) ;
2011-07-10 11:22:20 +03:00
for ( int h = 0 ; h < attackedInfos . size ( ) ; + + h )
{
if ( attackedInfos [ h ] . rebirth )
creAnims [ attackedInfos [ h ] . defender - > ID ] - > setType ( CCreatureAnim : : HOLDING ) ;
}
2009-01-15 19:01:08 +02:00
}
2010-12-23 22:18:10 +02:00
void CBattleInterface : : stackAttacking ( const CStack * attacker , THex dest , const CStack * attacked , bool shooting )
2009-09-10 14:28:34 +03:00
{
2010-12-23 22:18:10 +02:00
if ( shooting )
{
2010-12-24 23:44:48 +02:00
addNewAnim ( new CShootingAnim ( this , attacker , dest , attacked ) ) ;
2010-12-23 22:18:10 +02:00
}
else
{
2010-12-24 23:44:48 +02:00
addNewAnim ( new CMeleeAttack ( this , attacker , dest , attacked ) ) ;
2010-12-23 22:18:10 +02:00
}
2011-01-08 21:38:42 +02:00
waitForAnims ( ) ;
2009-09-10 14:28:34 +03:00
}
2010-05-07 15:29:41 +03:00
void CBattleInterface : : newRoundFirst ( int round )
2009-01-15 19:01:08 +02:00
{
2009-08-22 17:39:44 +03:00
//handle regeneration
2011-02-14 22:31:53 +02:00
std : : vector < const CStack * > stacks = curInt - > cb - > battleGetStacks ( ) ; //gets only alive stacks
2011-05-28 13:05:25 +03:00
// BOOST_FOREACH(const CStack *s, stacks)
// {
// }
2011-01-08 21:38:42 +02:00
waitForAnims ( ) ;
2009-01-15 19:01:08 +02:00
}
2010-05-07 15:29:41 +03:00
void CBattleInterface : : newRound ( int number )
{
console - > addText ( CGI - > generaltexth - > allTexts [ 412 ] ) ;
//unlock spellbook
//bSpell->block(!curInt->cb->battleCanCastSpell());
//don't unlock spellbook - this should be done when we have axctive creature
}
2011-02-09 17:19:53 +02:00
void CBattleInterface : : giveCommand ( ui8 action , THex tile , ui32 stack , si32 additional )
2009-01-15 19:01:08 +02:00
{
2010-02-19 18:02:34 +02:00
if ( ! curInt - > cb - > battleGetStackByID ( stack ) & & action ! = 1 & & action ! = 4 & & action ! = 5 )
2009-09-07 16:34:02 +03:00
{
return ;
}
2009-01-15 19:01:08 +02:00
BattleAction * ba = new BattleAction ( ) ; //is deleted in CPlayerInterface::activeStack()
2010-02-19 18:02:34 +02:00
ba - > side = defendingHeroInstance ? ( curInt - > playerID = = defendingHeroInstance - > tempOwner ) : false ;
2009-01-15 19:01:08 +02:00
ba - > actionType = action ;
ba - > destinationTile = tile ;
ba - > stackNumber = stack ;
ba - > additionalInfo = additional ;
2009-09-24 16:23:52 +03:00
//some basic validations
switch ( action )
{
case 6 :
2010-02-19 18:02:34 +02:00
assert ( curInt - > cb - > battleGetStackByPos ( additional ) ) ; //stack to attack must exist
2009-09-24 16:23:52 +03:00
case 2 : case 7 : case 9 :
assert ( tile < BFIELD_SIZE ) ;
break ;
}
2011-02-14 00:46:04 +02:00
if ( ! tacticsMode )
{
myTurn = false ;
activeStack = NULL ;
givenCommand - > setn ( ba ) ;
}
else
{
curInt - > cb - > battleMakeTacticAction ( ba ) ;
delNull ( ba ) ;
2011-02-14 22:31:53 +02:00
bTacticNextStack ( ) ;
2011-02-14 00:46:04 +02:00
}
2009-01-15 19:01:08 +02:00
}
2011-02-09 17:19:53 +02:00
bool CBattleInterface : : isTileAttackable ( const THex & number ) const
2009-01-15 19:01:08 +02:00
{
2011-02-26 19:32:56 +02:00
for ( size_t b = 0 ; b < occupyableHexes . size ( ) ; + + b )
2009-01-15 19:01:08 +02:00
{
2011-02-26 19:32:56 +02:00
if ( THex : : mutualPosition ( occupyableHexes [ b ] , number ) ! = - 1 | | occupyableHexes [ b ] = = number )
2009-01-15 19:01:08 +02:00
return true ;
}
return false ;
}
2011-02-09 17:19:53 +02:00
bool CBattleInterface : : blockedByObstacle ( THex hex ) const
2009-08-19 13:59:42 +03:00
{
2010-02-19 18:02:34 +02:00
std : : vector < CObstacleInstance > obstacles = curInt - > cb - > battleGetAllObstacles ( ) ;
2011-02-09 17:19:53 +02:00
std : : set < THex > coveredHexes ;
2009-08-19 13:59:42 +03:00
for ( int b = 0 ; b < obstacles . size ( ) ; + + b )
{
2011-02-09 17:19:53 +02:00
std : : vector < THex > blocked = CGI - > heroh - > obstacles . find ( obstacles [ b ] . ID ) - > second . getBlocked ( obstacles [ b ] . pos ) ;
2009-08-19 13:59:42 +03:00
for ( int w = 0 ; w < blocked . size ( ) ; + + w )
coveredHexes . insert ( blocked [ w ] ) ;
}
return vstd : : contains ( coveredHexes , hex ) ;
}
2011-02-09 17:19:53 +02:00
bool CBattleInterface : : isCatapultAttackable ( THex hex ) const
2009-09-01 16:54:13 +03:00
{
if ( ! siegeH )
return false ;
2010-02-19 18:02:34 +02:00
int wallUnder = curInt - > cb - > battleGetWallUnderHex ( hex ) ;
2009-09-01 16:54:13 +03:00
if ( wallUnder = = - 1 )
return false ;
2010-02-19 18:02:34 +02:00
return curInt - > cb - > battleGetWallState ( wallUnder ) < 3 ;
2009-09-01 16:54:13 +03:00
}
2010-05-07 17:05:48 +03:00
const CGHeroInstance * CBattleInterface : : getActiveHero ( )
{
2010-12-24 23:44:48 +02:00
const CStack * attacker = activeStack ;
2010-05-07 17:05:48 +03:00
if ( ! attacker )
{
return NULL ;
}
if ( attacker - > attackerOwned )
{
return attackingHeroInstance ;
}
return defendingHeroInstance ;
}
2009-01-15 19:01:08 +02:00
void CBattleInterface : : hexLclicked ( int whichOne )
{
2010-12-24 23:44:48 +02:00
const CStack * actSt = activeStack ;
2011-01-18 18:24:06 +02:00
const CStack * dest = curInt - > cb - > battleGetStackByPos ( whichOne ) ; //creature at destination tile; -1 if there is no one
2011-02-11 14:27:38 +02:00
if ( ! actSt )
{
tlog3 < < " Hex l-clicked when no active stack! \n " ;
return ;
}
2009-09-05 17:10:26 +03:00
if ( ( ( whichOne % BFIELD_WIDTH ) ! = 0 & & ( whichOne % BFIELD_WIDTH ) ! = ( BFIELD_WIDTH - 1 ) ) //if player is trying to attack enemey unit or move creature stack
2011-01-18 18:24:06 +02:00
| | ( actSt - > hasBonusOfType ( Bonus : : CATAPULT ) & & ! spellDestSelectMode | | dest ) //enemy's first aid tent can stand there and we want to shoot it
2009-09-05 17:10:26 +03:00
)
2009-01-15 19:01:08 +02:00
{
if ( ! myTurn )
return ; //we are not permit to do anything
if ( spellDestSelectMode )
{
//checking destination
bool allowCasting = true ;
2009-08-05 15:46:08 +03:00
bool onlyAlive = spellToCast - > additionalInfo ! = 38 & & spellToCast - > additionalInfo ! = 39 ; //when casting resurrection or animate dead we should be allow to select dead stack
2009-01-15 19:01:08 +02:00
switch ( spellSelMode )
{
case 1 :
2010-02-19 18:02:34 +02:00
if ( ! curInt - > cb - > battleGetStackByPos ( whichOne , onlyAlive ) | | curInt - > playerID ! = curInt - > cb - > battleGetStackByPos ( whichOne , onlyAlive ) - > owner )
2009-01-15 19:01:08 +02:00
allowCasting = false ;
break ;
case 2 :
2010-02-19 18:02:34 +02:00
if ( ! curInt - > cb - > battleGetStackByPos ( whichOne , onlyAlive ) | | curInt - > playerID = = curInt - > cb - > battleGetStackByPos ( whichOne , onlyAlive ) - > owner )
2009-01-15 19:01:08 +02:00
allowCasting = false ;
break ;
case 3 :
2010-02-19 18:02:34 +02:00
if ( ! curInt - > cb - > battleGetStackByPos ( whichOne , onlyAlive ) )
2009-01-15 19:01:08 +02:00
allowCasting = false ;
break ;
2009-08-19 13:59:42 +03:00
case 4 :
if ( ! blockedByObstacle ( whichOne ) )
allowCasting = false ;
2010-05-07 17:05:48 +03:00
case 5 : //teleport
2010-12-19 16:39:56 +02:00
const CSpell * s = CGI - > spellh - > spells [ spellToCast - > additionalInfo ] ;
2010-05-07 17:05:48 +03:00
ui8 skill = getActiveHero ( ) - > getSpellSchoolLevel ( s ) ; //skill level
2011-01-07 12:48:31 +02:00
if ( ! curInt - > cb - > battleCanTeleportTo ( activeStack , whichOne , skill ) )
2010-05-07 17:05:48 +03:00
{
allowCasting = false ;
}
2009-01-15 19:01:08 +02:00
break ;
}
//destination checked
if ( allowCasting )
{
spellToCast - > destinationTile = whichOne ;
2010-02-19 18:02:34 +02:00
curInt - > cb - > battleMakeAction ( spellToCast ) ;
2009-04-16 17:01:27 +03:00
endCastingSpell ( ) ;
2009-01-15 19:01:08 +02:00
}
}
2009-08-18 14:49:34 +03:00
else //we don't cast any spell
2009-01-15 19:01:08 +02:00
{
if ( ! dest | | ! dest - > alive ( ) ) //no creature at that tile
{
2011-02-26 19:32:56 +02:00
if ( std : : find ( occupyableHexes . begin ( ) , occupyableHexes . end ( ) , whichOne ) ! = occupyableHexes . end ( ) ) // and it's in our range
2009-01-15 19:01:08 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 6 ) ; //cursor should be changed
2010-12-24 23:44:48 +02:00
if ( activeStack - > doubleWide ( ) )
2009-02-05 16:44:27 +02:00
{
2011-01-07 12:48:31 +02:00
std : : vector < THex > acc = curInt - > cb - > battleGetAvailableHexes ( activeStack , false ) ;
2010-12-24 23:44:48 +02:00
int shiftedDest = whichOne + ( activeStack - > attackerOwned ? 1 : - 1 ) ;
2009-02-05 16:44:27 +02:00
if ( vstd : : contains ( acc , whichOne ) )
2010-12-24 23:44:48 +02:00
giveCommand ( 2 , whichOne , activeStack - > ID ) ;
2009-02-14 15:49:30 +02:00
else if ( vstd : : contains ( acc , shiftedDest ) )
2010-12-24 23:44:48 +02:00
giveCommand ( 2 , shiftedDest , activeStack - > ID ) ;
2009-02-05 16:44:27 +02:00
}
else
{
2010-12-24 23:44:48 +02:00
giveCommand ( 2 , whichOne , activeStack - > ID ) ;
2009-02-05 16:44:27 +02:00
}
2009-01-15 19:01:08 +02:00
}
2010-05-02 21:20:26 +03:00
else if ( actSt - > hasBonusOfType ( Bonus : : CATAPULT ) & & isCatapultAttackable ( whichOne ) ) //attacking (catapult)
2009-09-01 16:54:13 +03:00
{
2010-12-24 23:44:48 +02:00
giveCommand ( 9 , whichOne , activeStack - > ID ) ;
2009-09-01 16:54:13 +03:00
}
2009-01-15 19:01:08 +02:00
}
2009-12-28 06:08:24 +02:00
else if ( dest - > owner ! = actSt - > owner
2011-01-07 12:48:31 +02:00
& & curInt - > cb - > battleCanShoot ( activeStack , whichOne ) ) //shooting
2009-01-15 19:01:08 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 6 ) ; //cursor should be changed
2010-12-24 23:44:48 +02:00
giveCommand ( 7 , whichOne , activeStack - > ID ) ;
2009-01-15 19:01:08 +02:00
}
2009-12-28 06:08:24 +02:00
else if ( dest - > owner ! = actSt - > owner ) //attacking
2009-01-15 19:01:08 +02:00
{
2010-12-24 23:44:48 +02:00
const CStack * actStack = activeStack ;
2009-08-18 14:49:34 +03:00
int attackFromHex = - 1 ; //hex from which we will attack chosen stack
2010-12-19 16:39:56 +02:00
switch ( CCS - > curh - > number )
2009-01-15 19:01:08 +02:00
{
2009-04-07 20:51:50 +03:00
case 12 : //from bottom right
{
2010-05-02 21:20:26 +03:00
bool doubleWide = actStack - > doubleWide ( ) ;
2010-02-19 18:02:34 +02:00
int destHex = whichOne + ( ( whichOne / BFIELD_WIDTH ) % 2 ? BFIELD_WIDTH : BFIELD_WIDTH + 1 ) +
( actStack - > attackerOwned & & doubleWide ? 1 : 0 ) ;
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex ;
else if ( actStack - > attackerOwned ) //if we are attacker
2009-04-07 20:51:50 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex + 1 ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex + 1 ;
2009-04-07 20:51:50 +03:00
}
2009-08-19 18:47:00 +03:00
else //if we are defender
2009-04-07 20:51:50 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex - 1 ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex - 1 ;
2009-04-07 20:51:50 +03:00
}
break ;
}
case 7 : //from bottom left
{
int destHex = whichOne + ( ( whichOne / BFIELD_WIDTH ) % 2 ? BFIELD_WIDTH - 1 : BFIELD_WIDTH ) ;
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex ;
else if ( actStack - > attackerOwned ) //if we are attacker
2009-04-07 20:51:50 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex + 1 ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex + 1 ;
2009-04-07 20:51:50 +03:00
}
2009-08-19 18:47:00 +03:00
else //if we are defender
2009-04-07 20:51:50 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex - 1 ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex - 1 ;
2009-04-07 20:51:50 +03:00
}
break ;
}
case 8 : //from left
2009-02-05 16:44:27 +02:00
{
2010-05-02 21:20:26 +03:00
if ( actStack - > doubleWide ( ) & & ! actStack - > attackerOwned )
2009-09-10 14:28:34 +03:00
{
2011-01-07 12:48:31 +02:00
std : : vector < THex > acc = curInt - > cb - > battleGetAvailableHexes ( activeStack , false ) ;
2009-09-10 14:28:34 +03:00
if ( vstd : : contains ( acc , whichOne ) )
attackFromHex = whichOne - 1 ;
else
attackFromHex = whichOne - 2 ;
}
2009-02-05 16:44:27 +02:00
else
2009-09-10 14:28:34 +03:00
{
attackFromHex = whichOne - 1 ;
}
break ;
2009-02-05 16:44:27 +02:00
}
2009-04-07 20:51:50 +03:00
case 9 : //from top left
{
int destHex = whichOne - ( ( whichOne / BFIELD_WIDTH ) % 2 ? BFIELD_WIDTH + 1 : BFIELD_WIDTH ) ;
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex ;
else if ( actStack - > attackerOwned ) //if we are attacker
2009-04-07 20:51:50 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex + 1 ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex + 1 ;
2009-04-07 20:51:50 +03:00
}
2009-08-19 18:47:00 +03:00
else //if we are defender
2009-04-07 20:51:50 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex - 1 ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex - 1 ;
2009-04-07 20:51:50 +03:00
}
break ;
}
case 10 : //from top right
{
2010-05-02 21:20:26 +03:00
bool doubleWide = actStack - > doubleWide ( ) ;
2010-02-19 18:02:34 +02:00
int destHex = whichOne - ( ( whichOne / BFIELD_WIDTH ) % 2 ? BFIELD_WIDTH : BFIELD_WIDTH - 1 ) +
( actStack - > attackerOwned & & doubleWide ? 1 : 0 ) ;
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex ;
else if ( actStack - > attackerOwned ) //if we are attacker
2009-04-07 20:51:50 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex + 1 ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex + 1 ;
2009-04-07 20:51:50 +03:00
}
2009-08-19 18:47:00 +03:00
else //if we are defender
2009-04-07 20:51:50 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex - 1 ) )
2009-08-18 14:49:34 +03:00
attackFromHex = destHex - 1 ;
2009-04-07 20:51:50 +03:00
}
break ;
}
case 11 : //from right
2009-02-05 16:44:27 +02:00
{
2010-05-02 21:20:26 +03:00
if ( actStack - > doubleWide ( ) & & actStack - > attackerOwned )
2009-09-10 14:28:34 +03:00
{
2011-01-07 12:48:31 +02:00
std : : vector < THex > acc = curInt - > cb - > battleGetAvailableHexes ( activeStack , false ) ;
2009-09-10 14:28:34 +03:00
if ( vstd : : contains ( acc , whichOne ) )
attackFromHex = whichOne + 1 ;
else
attackFromHex = whichOne + 2 ;
}
2009-02-05 16:44:27 +02:00
else
2009-09-10 14:28:34 +03:00
{
attackFromHex = whichOne + 1 ;
}
break ;
2009-02-05 16:44:27 +02:00
}
2009-08-19 18:47:00 +03:00
case 13 : //from bottom
{
int destHex = whichOne + ( ( whichOne / BFIELD_WIDTH ) % 2 ? BFIELD_WIDTH : BFIELD_WIDTH + 1 ) ;
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex ) )
2009-09-10 14:28:34 +03:00
attackFromHex = destHex ;
2010-02-19 18:02:34 +02:00
else if ( attackingHeroInstance - > tempOwner = = curInt - > cb - > getMyColor ( ) ) //if we are attacker
2009-08-19 18:47:00 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex + 1 ) )
2009-09-10 14:28:34 +03:00
attackFromHex = destHex + 1 ;
2009-08-19 18:47:00 +03:00
}
else //if we are defender
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex - 1 ) )
2009-09-10 14:28:34 +03:00
attackFromHex = destHex - 1 ;
2009-08-19 18:47:00 +03:00
}
break ;
}
case 14 : //from top
{
int destHex = whichOne - ( ( whichOne / BFIELD_WIDTH ) % 2 ? BFIELD_WIDTH : BFIELD_WIDTH - 1 ) ;
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex ) )
2009-09-10 14:28:34 +03:00
attackFromHex = destHex ;
2010-02-19 18:02:34 +02:00
else if ( attackingHeroInstance - > tempOwner = = curInt - > cb - > getMyColor ( ) ) //if we are attacker
2009-08-19 18:47:00 +03:00
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex + 1 ) )
2009-09-10 14:28:34 +03:00
attackFromHex = destHex + 1 ;
2009-08-19 18:47:00 +03:00
}
else //if we are defender
{
2011-02-26 19:32:56 +02:00
if ( vstd : : contains ( occupyableHexes , destHex - 1 ) )
2009-09-10 14:28:34 +03:00
attackFromHex = destHex - 1 ;
2009-08-19 18:47:00 +03:00
}
break ;
}
2009-01-15 19:01:08 +02:00
}
2009-08-18 14:49:34 +03:00
2009-10-17 17:05:44 +03:00
if ( attackFromHex > = 0 ) //we can be in this line when unreachable creature is L - clicked (as of revision 1308)
{
2010-12-24 23:44:48 +02:00
giveCommand ( 6 , attackFromHex , activeStack - > ID , whichOne ) ;
2009-10-17 17:05:44 +03:00
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 6 ) ; //cursor should be changed
2009-10-17 17:05:44 +03:00
}
2009-08-18 14:49:34 +03:00
2009-01-15 19:01:08 +02:00
}
2010-05-02 21:20:26 +03:00
else if ( actSt - > hasBonusOfType ( Bonus : : HEALER ) & & actSt - > owner = = dest - > owner ) //friendly creature we can heal
2010-03-07 19:40:33 +02:00
{
2010-12-24 23:44:48 +02:00
giveCommand ( 12 , whichOne , activeStack - > ID ) ; //command healing
2010-03-07 19:40:33 +02:00
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 6 ) ; //cursor should be changed
2010-03-07 19:40:33 +02:00
}
2009-01-15 19:01:08 +02:00
}
}
}
2009-09-24 16:44:55 +03:00
void CBattleInterface : : stackIsCatapulting ( const CatapultAttack & ca )
{
for ( std : : set < std : : pair < std : : pair < ui8 , si16 > , ui8 > > : : const_iterator it = ca . attackedParts . begin ( ) ; it ! = ca . attackedParts . end ( ) ; + + it )
{
2010-12-24 23:44:48 +02:00
const CStack * stack = curInt - > cb - > battleGetStackByID ( ca . attacker ) ;
addNewAnim ( new CShootingAnim ( this , stack , it - > first . second , NULL , true , it - > second ) ) ;
2009-09-24 16:44:55 +03:00
SDL_FreeSurface ( siegeH - > walls [ it - > first . first + 2 ] ) ;
siegeH - > walls [ it - > first . first + 2 ] = BitmapHandler : : loadBitmap (
2010-02-19 18:02:34 +02:00
siegeH - > getSiegeName ( it - > first . first + 2 , curInt - > cb - > battleGetWallState ( it - > first . first ) ) ) ;
2009-09-24 16:44:55 +03:00
}
2011-01-08 21:38:42 +02:00
waitForAnims ( ) ;
2009-09-24 16:44:55 +03:00
}
2009-01-15 19:01:08 +02:00
void CBattleInterface : : battleFinished ( const BattleResult & br )
2009-09-15 15:20:11 +03:00
{
bresult = & br ;
2010-02-22 15:30:46 +02:00
LOCPLINT - > pim - > unlock ( ) ;
2009-09-20 15:47:40 +03:00
animsAreDisplayed . waitUntil ( false ) ;
2010-02-22 15:30:46 +02:00
LOCPLINT - > pim - > lock ( ) ;
2009-09-15 15:20:11 +03:00
displayBattleFinished ( ) ;
}
void CBattleInterface : : displayBattleFinished ( )
2009-01-15 19:01:08 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 0 , 0 ) ;
2009-01-15 19:01:08 +02:00
2009-02-07 18:07:29 +02:00
SDL_Rect temp_rect = genRect ( 561 , 470 , ( screen - > w - 800 ) / 2 + 165 , ( screen - > h - 600 ) / 2 + 19 ) ;
2009-09-15 15:20:11 +03:00
resWindow = new CBattleResultWindow ( * bresult , temp_rect , this ) ;
2009-08-07 01:36:51 +03:00
GH . pushInt ( resWindow ) ;
2009-01-15 19:01:08 +02:00
}
2010-12-04 21:44:23 +02:00
void CBattleInterface : : spellCast ( const BattleSpellCast * sc )
2009-01-15 19:01:08 +02:00
{
2010-12-19 16:39:56 +02:00
const CSpell & spell = * CGI - > spellh - > spells [ sc - > id ] ;
2009-05-14 07:49:04 +03:00
2010-05-19 21:06:16 +03:00
//spell opening battle is cast when no stack is active
2010-12-24 23:44:48 +02:00
if ( sc - > castedByHero & & ( activeStack = = NULL | | sc - > side = = ! activeStack - > attackerOwned ) )
2009-04-14 15:47:09 +03:00
bSpell - > block ( true ) ;
2009-01-15 19:01:08 +02:00
std : : vector < std : : string > anims ; //for magic arrow and ice bolt
2010-12-19 16:39:56 +02:00
if ( vstd : : contains ( CCS - > soundh - > spellSounds , & spell ) )
CCS - > soundh - > playSound ( CCS - > soundh - > spellSounds [ & spell ] ) ;
2009-05-14 07:49:04 +03:00
2009-01-15 19:01:08 +02:00
switch ( sc - > id )
{
case 15 : //magic arrow
{
//initialization of anims
anims . push_back ( " C20SPX0.DEF " ) ; anims . push_back ( " C20SPX1.DEF " ) ; anims . push_back ( " C20SPX2.DEF " ) ; anims . push_back ( " C20SPX3.DEF " ) ; anims . push_back ( " C20SPX4.DEF " ) ;
}
case 16 : //ice bolt
{
2009-05-12 06:35:51 +03:00
if ( anims . size ( ) = = 0 ) //initialization of anims
2009-01-15 19:01:08 +02:00
{
anims . push_back ( " C08SPW0.DEF " ) ; anims . push_back ( " C08SPW1.DEF " ) ; anims . push_back ( " C08SPW2.DEF " ) ; anims . push_back ( " C08SPW3.DEF " ) ; anims . push_back ( " C08SPW4.DEF " ) ;
}
} //end of ice bolt only part
{ //common ice bolt and magic arrow part
//initial variables
std : : string animToDisplay ;
2009-09-21 11:29:41 +03:00
Point srccoord = ( sc - > side ? Point ( 770 , 60 ) : Point ( 30 , 60 ) ) + pos ;
2010-02-19 18:02:34 +02:00
Point destcoord = CBattleHex : : getXYUnitAnim ( sc - > tile , ! sc - > side , curInt - > cb - > battleGetStackByPos ( sc - > tile ) , this ) ; //position attacked by arrow
2009-09-21 11:29:41 +03:00
destcoord . x + = 250 ; destcoord . y + = 240 ;
2009-01-15 19:01:08 +02:00
//animation angle
2009-09-21 11:29:41 +03:00
float angle = atan2 ( float ( destcoord . x - srccoord . x ) , float ( destcoord . y - srccoord . y ) ) ;
2010-07-15 20:13:17 +03:00
bool Vflip = false ;
if ( angle < 0 )
{
Vflip = true ;
angle = - angle ;
}
2009-01-15 19:01:08 +02:00
//choosing animation by angle
if ( angle > 1.50 )
animToDisplay = anims [ 0 ] ;
else if ( angle > 1.20 )
animToDisplay = anims [ 1 ] ;
else if ( angle > 0.90 )
animToDisplay = anims [ 2 ] ;
else if ( angle > 0.60 )
animToDisplay = anims [ 3 ] ;
else
animToDisplay = anims [ 4 ] ;
//displaying animation
2009-09-17 15:59:04 +03:00
CDefEssential * animDef = CDefHandler : : giveDefEss ( animToDisplay ) ;
2010-07-15 20:13:17 +03:00
2009-09-21 11:29:41 +03:00
int steps = sqrt ( ( float ) ( ( destcoord . x - srccoord . x ) * ( destcoord . x - srccoord . x ) + ( destcoord . y - srccoord . y ) * ( destcoord . y - srccoord . y ) ) ) / 40 ;
2009-01-15 19:01:08 +02:00
if ( steps < = 0 )
steps = 1 ;
2009-09-21 11:29:41 +03:00
int dx = ( destcoord . x - srccoord . x - animDef - > ourImages [ 0 ] . bitmap - > w ) / steps , dy = ( destcoord . y - srccoord . y - animDef - > ourImages [ 0 ] . bitmap - > h ) / steps ;
2009-01-15 19:01:08 +02:00
2009-09-17 15:59:04 +03:00
delete animDef ;
2010-07-15 20:13:17 +03:00
addNewAnim ( new CSpellEffectAnim ( this , animToDisplay , srccoord . x , srccoord . y , dx , dy , Vflip ) ) ;
2009-09-17 15:59:04 +03:00
2009-01-15 19:01:08 +02:00
break ; //for 15 and 16 cases
}
2009-04-22 13:03:13 +03:00
case 17 : //lightning bolt
2011-07-06 17:25:12 +03:00
case 57 : //Titan's Thunder
2010-02-23 17:39:31 +02:00
case 77 : //thunderbolt
2009-04-22 13:03:13 +03:00
displayEffect ( 1 , sc - > tile ) ;
2009-05-14 07:49:04 +03:00
displayEffect ( spell . mainEffectAnim , sc - > tile ) ;
2009-08-04 20:05:49 +03:00
break ;
2009-04-21 20:32:43 +03:00
case 35 : //dispel
2009-08-04 20:05:49 +03:00
case 37 : //cure
2009-08-05 15:46:08 +03:00
case 38 : //resurrection
case 39 : //animate dead
2009-08-04 20:05:49 +03:00
for ( std : : set < ui32 > : : const_iterator it = sc - > affectedCres . begin ( ) ; it ! = sc - > affectedCres . end ( ) ; + + it )
{
2010-02-19 18:02:34 +02:00
displayEffect ( spell . mainEffectAnim , curInt - > cb - > battleGetStackByID ( * it , false ) - > position ) ;
2009-08-04 20:05:49 +03:00
}
break ;
2010-01-28 19:23:01 +02:00
case 66 : case 67 : case 68 : case 69 : //summon elemental
addNewAnim ( new CDummyAnim ( this , 2 ) ) ;
break ;
2009-04-21 20:32:43 +03:00
} //switch(sc->id)
2009-07-26 15:15:38 +03:00
//support for resistance
for ( int j = 0 ; j < sc - > resisted . size ( ) ; + + j )
{
2010-02-19 18:02:34 +02:00
int tile = curInt - > cb - > battleGetStackByID ( sc - > resisted [ j ] ) - > position ;
2009-07-26 15:15:38 +03:00
displayEffect ( 78 , tile ) ;
}
2009-11-08 16:44:58 +02:00
//displaying message in console
2011-04-23 20:10:54 +03:00
bool customSpell = false ;
2011-04-26 10:57:26 +03:00
bool plural = false ; //add singular / plural form of creature text if this is true
int textID = 0 ;
2009-11-08 16:44:58 +02:00
if ( sc - > affectedCres . size ( ) = = 1 )
{
std : : string text = CGI - > generaltexth - > allTexts [ 195 ] ;
2010-03-02 13:40:29 +02:00
if ( sc - > castedByHero )
{
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetFightingHero ( sc - > side ) - > name ) ;
2011-07-06 17:25:12 +03:00
boost : : algorithm : : replace_first ( text , " %s " , CGI - > spellh - > spells [ sc - > id ] - > name ) ; //spell name
2011-04-23 20:10:54 +03:00
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) , false ) - > getCreature ( ) - > namePl ) ; //target
2010-03-02 13:40:29 +02:00
}
else
{
2011-04-25 12:03:13 +03:00
switch ( sc - > id )
2011-04-23 20:10:54 +03:00
{
2011-04-26 10:57:26 +03:00
case 70 : //Stone Gaze
customSpell = true ;
plural = true ;
textID = 558 ;
break ;
2011-04-25 12:03:13 +03:00
case 71 : //Poison
2011-04-26 10:57:26 +03:00
customSpell = true ;
plural = true ;
textID = 561 ;
break ;
case 72 : //Bind
customSpell = true ;
text = CGI - > generaltexth - > allTexts [ 560 ] ;
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) , false ) - > getCreature ( ) - > namePl ) ;
break ; //Roots and vines bind the %s to the ground!
case 73 : //Disease
customSpell = true ;
plural = true ;
textID = 553 ;
break ;
case 74 : //Paralyze
customSpell = true ;
plural = true ;
textID = 563 ;
break ;
2011-05-21 10:07:07 +03:00
case 75 : // Aging
{
2011-04-26 10:57:26 +03:00
customSpell = true ;
2011-05-21 10:07:07 +03:00
if ( curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > count > 1 )
{
text = CGI - > generaltexth - > allTexts [ 552 ] ;
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > type - > namePl ) ;
}
else
{
text = CGI - > generaltexth - > allTexts [ 551 ] ;
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > type - > nameSing ) ;
}
//The %s shrivel with age, and lose %d hit points."
2011-06-25 16:53:15 +03:00
boost : : shared_ptr < BonusList > bl = curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) , false ) - > getBonuses ( Selector : : type ( Bonus : : STACK_HEALTH ) ) ;
bl - > remove_if ( Selector : : source ( Bonus : : SPELL_EFFECT , 75 ) ) ;
boost : : algorithm : : replace_first ( text , " %d " , boost : : lexical_cast < std : : string > ( bl - > totalValue ( ) / 2 ) ) ;
2011-05-21 10:07:07 +03:00
}
2011-04-26 10:57:26 +03:00
break ;
2011-07-08 10:00:11 +03:00
case 77 : //Thunderbolt
text = CGI - > generaltexth - > allTexts [ 367 ] ;
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > type - > namePl ) ;
console - > addText ( text ) ;
text = CGI - > generaltexth - > allTexts [ 343 ] . substr ( 1 , CGI - > generaltexth - > allTexts [ 343 ] . size ( ) - 1 ) ; //Does %d points of damage.
boost : : algorithm : : replace_first ( text , " %d " , boost : : lexical_cast < std : : string > ( sc - > dmgToDisplay ) ) ; //no more text afterwards
console - > addText ( text ) ;
customSpell = true ;
text = " " ; //yeah, it's a terrible mess
break ;
2011-04-26 10:57:26 +03:00
case 78 : //Dispell helpful spells
text = CGI - > generaltexth - > allTexts [ 555 ] ;
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > type - > namePl ) ;
2011-04-25 12:03:13 +03:00
customSpell = true ;
break ;
case 79 : // Death Stare
customSpell = true ;
2011-04-26 10:57:26 +03:00
if ( sc - > dmgToDisplay )
2011-04-25 12:03:13 +03:00
{
2011-04-26 10:57:26 +03:00
if ( sc - > dmgToDisplay > 1 )
{
text = CGI - > generaltexth - > allTexts [ 119 ] ; //%d %s die under the terrible gaze of the %s.
boost : : algorithm : : replace_first ( text , " %d " , boost : : lexical_cast < std : : string > ( sc - > dmgToDisplay ) ) ;
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) , false ) - > getCreature ( ) - > namePl ) ;
}
else
{
text = CGI - > generaltexth - > allTexts [ 118 ] ; //One %s dies under the terrible gaze of the %s.
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > type - > nameSing ) ;
}
2011-05-13 13:45:36 +03:00
boost : : algorithm : : replace_first ( text , " %s " , CGI - > creh - > creatures [ sc - > attackerType ] - > namePl ) ; //casting stack
2011-04-25 12:03:13 +03:00
}
else
2011-04-26 10:57:26 +03:00
text = " " ;
2011-04-25 12:03:13 +03:00
break ;
default :
2011-05-13 17:33:48 +03:00
text = CGI - > generaltexth - > allTexts [ 565 ] ; //The %s casts %s
2011-05-13 13:45:36 +03:00
boost : : algorithm : : replace_first ( text , " %s " , CGI - > creh - > creatures [ sc - > attackerType ] - > namePl ) ; //casting stack
2011-04-23 20:10:54 +03:00
}
2011-04-26 10:57:26 +03:00
if ( plural )
{
if ( curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > count > 1 )
{
text = CGI - > generaltexth - > allTexts [ textID + 1 ] ;
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > type - > namePl ) ;
}
else
{
text = CGI - > generaltexth - > allTexts [ textID ] ;
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetStackByID ( * sc - > affectedCres . begin ( ) ) - > type - > nameSing ) ;
}
}
2010-03-02 13:40:29 +02:00
}
2011-07-08 10:00:11 +03:00
if ( ! customSpell & & ! sc - > dmgToDisplay )
2011-05-13 17:33:48 +03:00
boost : : algorithm : : replace_first ( text , " %s " , CGI - > spellh - > spells [ sc - > id ] - > name ) ; //simple spell name
2011-04-26 10:57:26 +03:00
if ( text . size ( ) )
console - > addText ( text ) ;
2009-11-08 16:44:58 +02:00
}
else
{
std : : string text = CGI - > generaltexth - > allTexts [ 196 ] ;
2010-03-02 13:40:29 +02:00
if ( sc - > castedByHero )
{
boost : : algorithm : : replace_first ( text , " %s " , curInt - > cb - > battleGetFightingHero ( sc - > side ) - > name ) ;
}
2011-06-01 21:26:44 +03:00
else if ( sc - > attackerType < CGI - > creh - > creatures . size ( ) )
2010-03-02 13:40:29 +02:00
{
2011-05-13 17:33:48 +03:00
boost : : algorithm : : replace_first ( text , " %s " , CGI - > creh - > creatures [ sc - > attackerType ] - > namePl ) ; //creature caster
2010-03-02 13:40:29 +02:00
}
2011-06-01 21:26:44 +03:00
else
{
//TODO artifacts that cast spell; scripts some day
boost : : algorithm : : replace_first ( text , " Something " , CGI - > creh - > creatures [ sc - > attackerType ] - > namePl ) ; //creature caster
}
2010-12-19 16:39:56 +02:00
boost : : algorithm : : replace_first ( text , " %s " , CGI - > spellh - > spells [ sc - > id ] - > name ) ;
2009-11-08 16:44:58 +02:00
console - > addText ( text ) ;
}
2011-04-23 20:10:54 +03:00
if ( sc - > dmgToDisplay & & ! customSpell )
2009-11-08 16:44:58 +02:00
{
2011-07-08 10:00:11 +03:00
std : : string dmgInfo = CGI - > generaltexth - > allTexts [ 376 ] ;
boost : : algorithm : : replace_first ( dmgInfo , " %s " , CGI - > spellh - > spells [ sc - > id ] - > name ) ; //simple spell name
2009-11-08 16:44:58 +02:00
boost : : algorithm : : replace_first ( dmgInfo , " %d " , boost : : lexical_cast < std : : string > ( sc - > dmgToDisplay ) ) ;
2011-07-08 10:00:11 +03:00
console - > addText ( dmgInfo ) ; //todo: casualties (?)
2009-11-08 16:44:58 +02:00
}
2011-01-08 21:38:42 +02:00
waitForAnims ( ) ;
2009-03-21 18:03:07 +02:00
}
void CBattleInterface : : battleStacksEffectsSet ( const SetStackEffect & sse )
{
2011-02-20 20:32:39 +02:00
int effID = sse . effect . back ( ) . sid ;
2011-01-20 21:57:12 +02:00
if ( effID ! = - 1 ) //can be -1 for defensive stance effect
2009-03-21 18:03:07 +02:00
{
2011-01-18 19:23:31 +02:00
for ( std : : vector < ui32 > : : const_iterator ci = sse . stacks . begin ( ) ; ci ! = sse . stacks . end ( ) ; + + ci )
{
2011-01-20 21:57:12 +02:00
displayEffect ( CGI - > spellh - > spells [ effID ] - > mainEffectAnim , curInt - > cb - > battleGetStackByID ( * ci ) - > position ) ;
2011-01-18 19:23:31 +02:00
}
}
2011-07-16 19:40:38 +03:00
else if ( sse . stacks . size ( ) = = 1 & & sse . effect . size ( ) = = 2 )
2011-01-18 19:23:31 +02:00
{
2011-07-16 19:40:38 +03:00
const Bonus & bns = sse . effect . front ( ) ;
2011-01-20 21:57:12 +02:00
if ( bns . source = = Bonus : : OTHER & & bns . type = = Bonus : : PRIMARY_SKILL )
{
2011-07-16 19:40:38 +03:00
//defensive stance
2011-01-20 21:57:12 +02:00
const CStack * stack = LOCPLINT - > cb - > battleGetStackByID ( * sse . stacks . begin ( ) ) ;
int txtid = 120 ;
2011-01-18 19:23:31 +02:00
2011-01-20 21:57:12 +02:00
if ( stack - > count ! = 1 )
txtid + + ; //move to plural text
2011-01-18 19:23:31 +02:00
2011-01-20 21:57:12 +02:00
char txt [ 4000 ] ;
2011-07-16 19:40:38 +03:00
BonusList defenseBonuses = * ( stack - > getBonuses ( Selector : : typeSubtype ( Bonus : : PRIMARY_SKILL , PrimarySkill : : DEFENSE ) ) ) ;
defenseBonuses . remove_if ( Selector : : durationType ( Bonus : : STACK_GETS_TURN ) ) ; //remove bonuses gained from defensive stance
int val = stack - > Defense ( ) - defenseBonuses . totalValue ( ) ;
2011-01-20 21:57:12 +02:00
sprintf ( txt , CGI - > generaltexth - > allTexts [ txtid ] . c_str ( ) , ( stack - > count ! = 1 ) ? stack - > getCreature ( ) - > namePl . c_str ( ) : stack - > getCreature ( ) - > nameSing . c_str ( ) , val ) ;
console - > addText ( txt ) ;
}
2009-01-15 19:01:08 +02:00
}
2011-01-18 19:23:31 +02:00
2010-12-24 23:44:48 +02:00
if ( activeStack ! = NULL ) //it can be -1 when a creature casts effect
2010-03-02 13:40:29 +02:00
{
redrawBackgroundWithHexes ( activeStack ) ;
}
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : castThisSpell ( int spellID )
{
BattleAction * ba = new BattleAction ;
2010-12-04 21:15:20 +02:00
ba - > actionType = BattleAction : : HERO_SPELL ;
2009-01-15 19:01:08 +02:00
ba - > additionalInfo = spellID ; //spell number
ba - > destinationTile = - 1 ;
2010-02-19 18:02:34 +02:00
ba - > stackNumber = ( attackingHeroInstance - > tempOwner = = curInt - > playerID ) ? - 1 : - 2 ;
ba - > side = defendingHeroInstance ? ( curInt - > playerID = = defendingHeroInstance - > tempOwner ) : false ;
2009-01-15 19:01:08 +02:00
spellToCast = ba ;
spellDestSelectMode = true ;
//choosing possible tragets
2010-07-28 13:09:15 +03:00
const CGHeroInstance * castingHero = ( attackingHeroInstance - > tempOwner = = curInt - > playerID ) ? attackingHeroInstance : defendingHeroInstance ;
2010-12-19 16:39:56 +02:00
const CSpell & spell = * CGI - > spellh - > spells [ spellID ] ;
2009-01-15 19:01:08 +02:00
spellSelMode = 0 ;
2011-02-21 18:53:23 +02:00
if ( spell . getTargetType ( ) = = CSpell : : CREATURE )
2009-01-15 19:01:08 +02:00
{
2010-05-07 17:05:48 +03:00
switch ( spell . positiveness )
2009-01-15 19:01:08 +02:00
{
case - 1 :
spellSelMode = 2 ;
break ;
case 0 :
spellSelMode = 3 ;
break ;
case 1 :
spellSelMode = 1 ;
break ;
}
}
2011-02-21 18:53:23 +02:00
if ( spell . getTargetType ( ) = = CSpell : : CREATURE_EXPERT_MASSIVE )
2009-01-15 19:01:08 +02:00
{
2010-07-28 13:09:15 +03:00
if ( castingHero & & castingHero - > getSpellSchoolLevel ( & spell ) < 3 )
2009-01-15 19:01:08 +02:00
{
2010-05-07 17:05:48 +03:00
switch ( spell . positiveness )
2009-01-15 19:01:08 +02:00
{
case - 1 :
spellSelMode = 2 ;
break ;
case 0 :
spellSelMode = 3 ;
break ;
case 1 :
spellSelMode = 1 ;
break ;
}
}
else
{
spellSelMode = - 1 ;
}
}
2011-02-21 18:53:23 +02:00
if ( spell . getTargetType ( ) = = CSpell : : OBSTACLE )
2009-08-19 13:59:42 +03:00
{
spellSelMode = 4 ;
}
2010-05-07 17:05:48 +03:00
if ( spell . range [ castingHero - > getSpellSchoolLevel ( & spell ) ] = = " X " ) //spell has no range
2010-01-28 19:23:01 +02:00
{
spellSelMode = - 1 ;
}
2010-05-07 17:05:48 +03:00
if ( spell . id = = 63 ) //teleport
{
spellSelMode = 5 ;
}
2010-08-05 12:47:12 +03:00
if ( spell . range [ castingHero - > getSpellSchoolLevel ( & spell ) ] . size ( ) > 1 ) //spell has many-hex range
{
spellSelMode = 0 ;
}
2009-01-16 19:58:41 +02:00
if ( spellSelMode = = - 1 ) //user does not have to select location
{
spellToCast - > destinationTile = - 1 ;
2010-02-19 18:02:34 +02:00
curInt - > cb - > battleMakeAction ( spellToCast ) ;
2010-01-28 19:23:01 +02:00
endCastingSpell ( ) ;
2009-01-16 19:58:41 +02:00
}
else
{
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 3 , 0 ) ;
2009-01-16 19:58:41 +02:00
}
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : displayEffect ( ui32 effect , int destTile )
{
2009-09-17 15:59:04 +03:00
addNewAnim ( new CSpellEffectAnim ( this , effect , destTile ) ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleInterface : : setAnimSpeed ( int set )
{
2010-02-19 18:02:34 +02:00
curInt - > sysOpts . animSpeed = set ;
curInt - > sysOpts . settingsChanged ( ) ;
2009-01-15 19:01:08 +02:00
}
int CBattleInterface : : getAnimSpeed ( ) const
{
2010-02-19 18:02:34 +02:00
return curInt - > sysOpts . animSpeed ;
2009-01-15 19:01:08 +02:00
}
2009-09-15 15:20:11 +03:00
void CBattleInterface : : activateStack ( )
{
activeStack = stackToActivate ;
2010-12-24 23:44:48 +02:00
stackToActivate = NULL ;
const CStack * s = activeStack ;
2010-02-19 18:02:34 +02:00
2009-09-15 15:20:11 +03:00
myTurn = true ;
2010-10-30 22:26:39 +03:00
if ( attackerInt & & defenderInt ) //hotseat -> need to pick which interface "takes over" as active
2010-10-31 23:29:39 +02:00
curInt = attackerInt - > playerID = = s - > owner ? attackerInt : defenderInt ;
2010-02-19 18:02:34 +02:00
2009-09-24 16:23:52 +03:00
queue - > update ( ) ;
2009-09-15 15:20:11 +03:00
redrawBackgroundWithHexes ( activeStack ) ;
2010-10-31 23:29:39 +02:00
bWait - > block ( vstd : : contains ( s - > state , WAITING ) ) ; //block waiting button if stack has been already waiting
2009-09-15 15:20:11 +03:00
//block cast spell button if hero doesn't have a spellbook
2010-02-19 18:02:34 +02:00
bSpell - > block ( ! curInt - > cb - > battleCanCastSpell ( ) ) ;
2010-10-31 23:29:39 +02:00
bSurrender - > block ( ( curInt = = attackerInt ? defendingHeroInstance : attackingHeroInstance ) = = NULL ) ;
2010-08-19 14:03:33 +03:00
bFlee - > block ( ! curInt - > cb - > battleCanFlee ( ) ) ;
2011-03-05 18:38:22 +02:00
bSurrender - > block ( curInt - > cb - > battleGetSurrenderCost ( ) < 0 ) ;
2010-01-28 16:14:43 +02:00
2009-10-01 23:00:21 +03:00
GH . fakeMouseMove ( ) ;
2009-11-13 23:01:33 +02:00
if ( ! pendingAnims . size ( ) & & ! active )
activate ( ) ;
2009-09-15 15:20:11 +03:00
}
2009-01-15 19:01:08 +02:00
float CBattleInterface : : getAnimSpeedMultiplier ( ) const
{
2010-02-19 18:02:34 +02:00
switch ( curInt - > sysOpts . animSpeed )
2009-01-15 19:01:08 +02:00
{
case 1 :
return 3.5f ;
case 2 :
return 2.2f ;
case 4 :
return 1.0f ;
default :
return 0.0f ;
}
}
2009-04-16 17:01:27 +03:00
void CBattleInterface : : endCastingSpell ( )
{
assert ( spellDestSelectMode ) ;
delete spellToCast ;
spellToCast = NULL ;
spellDestSelectMode = false ;
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 1 , 6 ) ;
2009-04-16 17:01:27 +03:00
}
2010-12-06 01:10:02 +02:00
void CBattleInterface : : showAliveStack ( const CStack * stack , SDL_Surface * to )
2009-08-26 17:09:55 +03:00
{
2010-12-06 01:10:02 +02:00
int ID = stack - > ID ;
2009-08-26 17:09:55 +03:00
if ( creAnims . find ( ID ) = = creAnims . end ( ) ) //eg. for summoned but not yet handled stacks
return ;
2011-06-27 20:11:17 +03:00
const CCreature * creature = stack - > getCreature ( ) ;
SDL_Rect unitRect = { creAnims [ ID ] - > pos . x , creAnims [ ID ] - > pos . y , creAnims [ ID ] - > fullWidth , creAnims [ ID ] - > fullHeight } ;
2009-08-26 17:09:55 +03:00
int animType = creAnims [ ID ] - > getType ( ) ;
2010-02-19 18:02:34 +02:00
int affectingSpeed = curInt - > sysOpts . animSpeed ;
2009-08-26 17:09:55 +03:00
if ( animType = = 1 | | animType = = 2 ) //standing stacks should not stand faster :)
affectingSpeed = 2 ;
2009-09-11 15:46:26 +03:00
bool incrementFrame = ( animCount % ( 4 / affectingSpeed ) = = 0 ) & & animType ! = 5 & & animType ! = 20 & & animType ! = 2 ;
2009-08-26 17:09:55 +03:00
2011-06-27 20:11:17 +03:00
if ( creature - > idNumber = = 149 )
{
// a turret creature has a limited height, so cut it at a certain position; turret creature has no standing anim
unitRect . h = graphics - > wallPositions [ siegeH - > town - > town - > typeID ] [ 20 ] . y ;
}
else
2009-08-26 17:09:55 +03:00
{
2011-06-27 20:11:17 +03:00
// standing animation
if ( animType = = 2 )
2009-08-26 17:09:55 +03:00
{
2011-06-27 20:11:17 +03:00
if ( standingFrame . find ( ID ) ! = standingFrame . end ( ) )
2009-08-26 17:09:55 +03:00
{
2011-06-27 20:11:17 +03:00
incrementFrame = ( animCount % ( 8 / affectingSpeed ) = = 0 ) ;
if ( incrementFrame )
2009-08-26 17:09:55 +03:00
{
2011-06-27 20:11:17 +03:00
+ + standingFrame [ ID ] ;
if ( standingFrame [ ID ] = = creAnims [ ID ] - > framesInGroup ( CCreatureAnim : : HOLDING ) )
{
standingFrame . erase ( standingFrame . find ( ID ) ) ;
}
2009-08-26 17:09:55 +03:00
}
}
2011-06-27 20:11:17 +03:00
else
2009-08-26 17:09:55 +03:00
{
2011-06-27 20:11:17 +03:00
if ( ( rand ( ) % 50 ) = = 0 )
{
standingFrame . insert ( std : : make_pair ( ID , 0 ) ) ;
}
2009-08-26 17:09:55 +03:00
}
}
}
2011-05-30 17:16:34 +03:00
// As long as the projectile of the shooter-stack is flying incrementFrame should be false
bool shootingFinished = true ;
for ( std : : list < SProjectileInfo > : : iterator it = projectiles . begin ( ) ; it ! = projectiles . end ( ) ; + + it )
{
if ( it - > stackID = = ID )
{
shootingFinished = false ;
if ( it - > animStartDelay = = 0 )
incrementFrame = false ;
}
}
2011-06-27 20:11:17 +03:00
2011-05-30 17:16:34 +03:00
// Increment always when moving, never if stack died
2011-06-27 20:11:17 +03:00
creAnims [ ID ] - > nextFrame ( to , unitRect . x , unitRect . y , creDir [ ID ] , animCount , incrementFrame , activeStack & & ID = = activeStack - > ID , ID = = mouseHoveredStack , & unitRect ) ;
2009-08-26 17:09:55 +03:00
//printing amount
2010-12-06 01:10:02 +02:00
if ( stack - > count > 0 //don't print if stack is not alive
2010-02-19 18:02:34 +02:00
& & ( ! curInt - > curAction
| | ( curInt - > curAction - > stackNumber ! = ID //don't print if stack is currently taking an action
2010-12-06 01:26:56 +02:00
& & ( curInt - > curAction - > actionType ! = BattleAction : : WALK_AND_ATTACK | | stack - > position ! = curInt - > curAction - > additionalInfo ) //nor if it's an object of attack
2010-12-06 01:10:02 +02:00
& & ( curInt - > curAction - > destinationTile ! = stack - > position ) //nor if it's on destination tile for current action
2009-08-26 17:09:55 +03:00
)
)
2010-12-06 01:10:02 +02:00
& & ! stack - > hasBonusOfType ( Bonus : : SIEGE_WEAPON ) //and not a war machine...
2009-08-26 17:09:55 +03:00
)
{
2010-12-06 01:10:02 +02:00
int xAdd = stack - > attackerOwned ? 220 : 202 ;
2009-08-26 17:09:55 +03:00
2011-05-15 20:18:36 +03:00
//blitting amount background box
2009-08-26 17:09:55 +03:00
SDL_Surface * amountBG = NULL ;
2011-06-25 16:53:15 +03:00
boost : : shared_ptr < BonusList > spellEffects = stack - > getSpellBonuses ( ) ;
if ( ! spellEffects - > size ( ) )
2009-08-26 17:09:55 +03:00
{
amountBG = amountNormal ;
}
else
{
int pos = 0 ; //determining total positiveness of effects
2010-12-06 01:10:02 +02:00
std : : vector < si32 > spellIds = stack - > activeSpells ( ) ;
2010-08-31 13:22:21 +03:00
for ( std : : vector < si32 > : : const_iterator it = spellIds . begin ( ) ; it ! = spellIds . end ( ) ; it + + )
2009-08-26 17:09:55 +03:00
{
2010-12-19 16:39:56 +02:00
pos + = CGI - > spellh - > spells [ * it ] - > positiveness ;
2009-08-26 17:09:55 +03:00
}
if ( pos > 0 )
{
amountBG = amountPositive ;
}
else if ( pos < 0 )
{
amountBG = amountNegative ;
}
else
{
amountBG = amountEffNeutral ;
}
}
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( amountNormal - > h , amountNormal - > w , creAnims [ ID ] - > pos . x + xAdd , creAnims [ ID ] - > pos . y + 260 ) ;
SDL_BlitSurface ( amountBG , NULL , to , & temp_rect ) ;
2009-08-26 17:09:55 +03:00
//blitting amount
2009-09-07 05:29:44 +03:00
CSDL_Ext : : printAtMiddle (
2010-12-06 01:10:02 +02:00
makeNumberShort ( stack - > count ) ,
2009-09-20 22:17:28 +03:00
creAnims [ ID ] - > pos . x + xAdd + 15 ,
creAnims [ ID ] - > pos . y + 260 + 5 ,
2009-09-07 05:29:44 +03:00
FONT_TINY ,
2009-08-26 17:09:55 +03:00
zwykly ,
to
2010-08-04 14:18:13 +03:00
) ;
2009-08-26 17:09:55 +03:00
}
}
2010-12-06 01:10:02 +02:00
void CBattleInterface : : showPieceOfWall ( SDL_Surface * to , int hex , const std : : vector < const CStack * > & stacks )
2009-08-26 17:09:55 +03:00
{
if ( ! siegeH )
return ;
2011-05-15 20:18:36 +03:00
using namespace boost : : assign ;
2011-05-27 16:49:18 +03:00
static const std : : map < int , std : : list < int > > hexToPart = map_list_of < int , std : : list < int > > ( 12 , list_of < int > ( 8 ) ( 1 ) ( 7 ) ) ( 45 , list_of < int > ( 12 ) ( 6 ) )
2011-05-15 20:18:36 +03:00
/*gate (78, list_of<int>(9))*/ ( 101 , list_of < int > ( 10 ) ) ( 118 , list_of < int > ( 2 ) ) ( 165 , list_of < int > ( 11 ) ) ( 186 , list_of < int > ( 3 ) ) ;
2009-08-26 17:09:55 +03:00
2011-05-27 16:49:18 +03:00
std : : map < int , std : : list < int > > : : const_iterator it = hexToPart . find ( hex ) ;
2009-08-26 17:09:55 +03:00
if ( it ! = hexToPart . end ( ) )
{
2011-05-15 20:18:36 +03:00
BOOST_FOREACH ( int wallNum , it - > second )
2009-09-04 17:11:42 +03:00
{
2011-05-15 20:18:36 +03:00
siegeH - > printPartOfWall ( to , wallNum ) ;
2009-09-04 17:11:42 +03:00
2011-05-15 20:18:36 +03:00
//print creature in turret
int posToSeek = - 1 ;
switch ( wallNum )
{
case 3 : //bottom turret
posToSeek = - 3 ;
break ;
case 8 : //upper turret
posToSeek = - 4 ;
break ;
case 2 : //keep
posToSeek = - 2 ;
break ;
}
2010-12-06 01:10:02 +02:00
2011-05-15 20:18:36 +03:00
if ( posToSeek ! = - 1 )
2009-09-04 17:11:42 +03:00
{
2011-05-15 20:18:36 +03:00
const CStack * turret = NULL ;
BOOST_FOREACH ( const CStack * s , stacks )
2009-09-04 17:11:42 +03:00
{
2011-05-15 20:18:36 +03:00
if ( s - > position = = posToSeek )
{
turret = s ;
break ;
}
2009-09-04 17:11:42 +03:00
}
2010-12-06 01:10:02 +02:00
2011-05-15 20:18:36 +03:00
if ( turret )
2009-09-05 17:10:26 +03:00
{
2011-05-15 20:18:36 +03:00
showAliveStack ( turret , to ) ;
//blitting creature cover
switch ( posToSeek )
{
case - 3 : //bottom turret
siegeH - > printPartOfWall ( to , 16 ) ;
break ;
case - 4 : //upper turret
siegeH - > printPartOfWall ( to , 17 ) ;
break ;
case - 2 : //keep
siegeH - > printPartOfWall ( to , 15 ) ;
break ;
}
2009-09-05 17:10:26 +03:00
}
2011-05-15 20:18:36 +03:00
}
2009-09-04 17:11:42 +03:00
}
2009-08-26 17:09:55 +03:00
}
2009-09-04 17:11:42 +03:00
2011-05-15 20:18:36 +03:00
// Damaged wall below gate have to be drawn earlier than a non-damaged wall below gate.
if ( ( hex = = 112 & & curInt - > cb - > battleGetWallState ( 3 ) = = 3 ) | | ( hex = = 147 & & curInt - > cb - > battleGetWallState ( 3 ) ! = 3 ) )
siegeH - > printPartOfWall ( to , 5 ) ;
// Damaged bottom wall have to be drawn earlier than a non-damaged bottom wall.
if ( ( hex = = 165 & & curInt - > cb - > battleGetWallState ( 4 ) = = 3 ) | | ( hex = = 185 & & curInt - > cb - > battleGetWallState ( 4 ) ! = 3 ) )
siegeH - > printPartOfWall ( to , 4 ) ;
2009-08-26 17:09:55 +03:00
}
2010-12-24 23:44:48 +02:00
void CBattleInterface : : redrawBackgroundWithHexes ( const CStack * activeStack )
2009-01-15 19:01:08 +02:00
{
2011-02-26 19:32:56 +02:00
attackableHexes . clear ( ) ;
2011-07-27 12:35:27 +03:00
if ( activeStack )
occupyableHexes = curInt - > cb - > battleGetAvailableHexes ( activeStack , true , & attackableHexes ) ;
2009-01-15 19:01:08 +02:00
//preparating background graphic with hexes and shaded hexes
blitAt ( background , 0 , 0 , backgroundWithHexes ) ;
2010-02-19 18:02:34 +02:00
if ( curInt - > sysOpts . printCellBorders )
2009-01-15 19:01:08 +02:00
CSDL_Ext : : blit8bppAlphaTo24bpp ( cellBorders , NULL , backgroundWithHexes , NULL ) ;
2010-02-19 18:02:34 +02:00
if ( curInt - > sysOpts . printStackRange )
2009-01-15 19:01:08 +02:00
{
2011-02-26 19:32:56 +02:00
std : : vector < THex > hexesToShade = occupyableHexes ;
hexesToShade . insert ( hexesToShade . end ( ) , attackableHexes . begin ( ) , attackableHexes . end ( ) ) ;
BOOST_FOREACH ( THex hex , hexesToShade )
2009-01-15 19:01:08 +02:00
{
2011-02-26 19:32:56 +02:00
int i = hex . getY ( ) ; //row
int j = hex . getX ( ) - 1 ; //column
2009-01-15 19:01:08 +02:00
int x = 58 + ( i % 2 = = 0 ? 22 : 0 ) + 44 * j ;
int y = 86 + 42 * i ;
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( cellShade - > h , cellShade - > w , x , y ) ;
CSDL_Ext : : blit8bppAlphaTo24bpp ( cellShade , NULL , backgroundWithHexes , & temp_rect ) ;
2009-01-15 19:01:08 +02:00
}
}
}
2011-08-12 22:38:30 +03:00
void CBattleInterface : : printConsoleAttacked ( const CStack * defender , int dmg , int killed , const CStack * attacker , bool multiple )
2009-01-15 19:01:08 +02:00
{
char tabh [ 200 ] ;
2011-08-12 22:38:30 +03:00
int end = 0 ;
if ( attacker ) //ignore if stacks were killed by spell
{
end = sprintf ( tabh , CGI - > generaltexth - > allTexts [ attacker - > count > 1 ? 377 : 376 ] . c_str ( ) ,
( attacker - > count > 1 ? attacker - > getCreature ( ) - > namePl . c_str ( ) : attacker - > getCreature ( ) - > nameSing . c_str ( ) ) , dmg ) ;
}
2009-01-15 19:01:08 +02:00
if ( killed > 0 )
{
if ( killed > 1 )
{
2011-08-12 22:38:30 +03:00
sprintf ( tabh + end , CGI - > generaltexth - > allTexts [ 379 ] . c_str ( ) , killed ,
multiple ? CGI - > generaltexth - > allTexts [ 43 ] . c_str ( ) : defender - > getCreature ( ) - > namePl . c_str ( ) ) ; // creatures perish
2009-01-15 19:01:08 +02:00
}
else //killed == 1
{
2011-08-12 22:38:30 +03:00
sprintf ( tabh + end , CGI - > generaltexth - > allTexts [ 378 ] . c_str ( ) ,
multiple ? CGI - > generaltexth - > allTexts [ 42 ] . c_str ( ) : defender - > getCreature ( ) - > nameSing . c_str ( ) ) ; // creature perishes
2009-01-15 19:01:08 +02:00
}
}
console - > addText ( std : : string ( tabh ) ) ;
}
void CBattleInterface : : projectileShowHelper ( SDL_Surface * to )
{
if ( to = = NULL )
to = screen ;
std : : list < std : : list < SProjectileInfo > : : iterator > toBeDeleted ;
for ( std : : list < SProjectileInfo > : : iterator it = projectiles . begin ( ) ; it ! = projectiles . end ( ) ; + + it )
{
2011-05-26 17:47:45 +03:00
// Creature have to be in a shooting anim and the anim start delay must be over.
// Otherwise abort to start moving the projectile.
if ( it - > animStartDelay > 0 )
2011-05-28 13:05:25 +03:00
{
2011-05-26 17:47:45 +03:00
if ( it - > animStartDelay = = creAnims [ it - > stackID ] - > getAnimationFrame ( ) + 1
& & creAnims [ it - > stackID ] - > getType ( ) > = 14 & & creAnims [ it - > stackID ] - > getType ( ) < = 16 )
it - > animStartDelay = 0 ;
else
continue ;
2011-05-28 13:05:25 +03:00
}
2011-05-26 17:47:45 +03:00
2009-01-15 19:01:08 +02:00
SDL_Rect dst ;
dst . h = idToProjectile [ it - > creID ] - > ourImages [ it - > frameNum ] . bitmap - > h ;
dst . w = idToProjectile [ it - > creID ] - > ourImages [ it - > frameNum ] . bitmap - > w ;
dst . x = it - > x ;
dst . y = it - > y ;
2011-05-30 17:16:34 +03:00
// The equation below calculates the center pos of the canon, but we need the top left pos
// of it for drawing
if ( it - > catapultInfo )
{
2011-07-13 21:39:02 +03:00
dst . x - = 17. ;
dst . y - = 10. ;
2011-05-30 17:16:34 +03:00
}
2009-01-16 19:58:41 +02:00
if ( it - > reverse )
{
SDL_Surface * rev = CSDL_Ext : : rotate01 ( idToProjectile [ it - > creID ] - > ourImages [ it - > frameNum ] . bitmap ) ;
CSDL_Ext : : blit8bppAlphaTo24bpp ( rev , NULL , to , & dst ) ;
SDL_FreeSurface ( rev ) ;
}
else
{
CSDL_Ext : : blit8bppAlphaTo24bpp ( idToProjectile [ it - > creID ] - > ourImages [ it - > frameNum ] . bitmap , NULL , to , & dst ) ;
}
2011-05-26 17:47:45 +03:00
2011-05-30 17:16:34 +03:00
// Update projectile
2009-01-15 19:01:08 +02:00
+ + it - > step ;
if ( it - > step = = it - > lastStep )
{
toBeDeleted . insert ( toBeDeleted . end ( ) , it ) ;
}
else
{
2011-05-30 17:16:34 +03:00
if ( it - > catapultInfo )
{
// Parabolic shot of the trajectory, as follows: f(x) = ax^2 + bx + c
it - > x + = it - > dx ;
2011-06-26 13:22:48 +03:00
it - > y = it - > catapultInfo - > calculateY ( it - > x - this - > pos . x ) + this - > pos . y ;
2011-05-30 17:16:34 +03:00
}
else
{
// Normal projectile, just add the calculated "deltas" to the x and y positions.
it - > x + = it - > dx ;
it - > y + = it - > dy ;
}
2009-01-15 19:01:08 +02:00
if ( it - > spin )
{
+ + ( it - > frameNum ) ;
it - > frameNum % = idToProjectile [ it - > creID ] - > ourImages . size ( ) ;
}
}
}
for ( std : : list < std : : list < SProjectileInfo > : : iterator > : : iterator it = toBeDeleted . begin ( ) ; it ! = toBeDeleted . end ( ) ; + + it )
{
projectiles . erase ( * it ) ;
}
}
2009-09-20 15:47:40 +03:00
void CBattleInterface : : endAction ( const BattleAction * action )
{
//if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //activating interface when move is finished
2009-11-13 23:01:33 +02:00
// {
// activate();
// }
2010-12-04 21:15:20 +02:00
if ( action - > actionType = = BattleAction : : HERO_SPELL )
2009-09-20 15:47:40 +03:00
{
if ( action - > side )
defendingHero - > setPhase ( 0 ) ;
else
attackingHero - > setPhase ( 0 ) ;
}
2010-12-04 21:15:20 +02:00
if ( action - > actionType = = BattleAction : : WALK & & creAnims [ action - > stackNumber ] - > getType ( ) ! = 2 ) //walk or walk & attack
2009-09-20 15:47:40 +03:00
{
2010-12-24 23:44:48 +02:00
const CStack * stack = curInt - > cb - > battleGetStackByID ( action - > stackNumber ) ;
pendingAnims . push_back ( std : : make_pair ( new CBattleMoveEnd ( this , stack , action - > destinationTile ) , false ) ) ;
2009-09-20 15:47:40 +03:00
}
2010-12-04 21:15:20 +02:00
if ( action - > actionType = = BattleAction : : CATAPULT ) //catapult
2009-09-24 16:44:55 +03:00
{
}
2011-01-14 20:08:01 +02:00
//check if we should reverse stacks
2011-02-23 19:10:35 +02:00
//for some strange reason, it's not enough
// std::set<const CStack *> stacks;
// stacks.insert(LOCPLINT->cb->battleGetStackByID(action->stackNumber));
// stacks.insert(LOCPLINT->cb->battleGetStackByPos(action->destinationTile));
2011-05-03 06:14:18 +03:00
TStacks stacks = curInt - > cb - > battleGetStacks ( CBattleCallback : : MINE_AND_ENEMY ) ;
2011-01-14 20:08:01 +02:00
BOOST_FOREACH ( const CStack * s , stacks )
{
if ( s & & creDir [ s - > ID ] ! = bool ( s - > attackerOwned ) & & s - > alive ( ) )
{
addNewAnim ( new CReverseAnim ( this , s , s - > position , false ) ) ;
}
}
2010-02-10 05:21:23 +02:00
queue - > update ( ) ;
2011-02-23 05:57:45 +02:00
if ( tacticsMode ) //we have activated next stack after sending request that has been just realized -> blockmap due to movement has changed
redrawBackgroundWithHexes ( activeStack ) ;
2009-09-20 15:47:40 +03:00
}
void CBattleInterface : : hideQueue ( )
{
2010-02-19 18:02:34 +02:00
curInt - > sysOpts . showQueue = false ;
2009-09-24 16:23:52 +03:00
queue - > deactivate ( ) ;
2009-09-20 15:47:40 +03:00
if ( ! queue - > embedded )
{
moveBy ( Point ( 0 , - queue - > pos . h / 2 ) ) ;
GH . totalRedraw ( ) ;
}
}
void CBattleInterface : : showQueue ( )
{
2010-02-19 18:02:34 +02:00
curInt - > sysOpts . showQueue = true ;
2009-09-24 16:23:52 +03:00
queue - > activate ( ) ;
2009-09-20 15:47:40 +03:00
if ( ! queue - > embedded )
{
moveBy ( Point ( 0 , + queue - > pos . h / 2 ) ) ;
GH . totalRedraw ( ) ;
}
}
2009-09-24 16:23:52 +03:00
void CBattleInterface : : startAction ( const BattleAction * action )
{
2011-02-14 22:31:53 +02:00
if ( action - > actionType = = BattleAction : : END_TACTIC_PHASE )
{
2011-08-25 18:24:37 +03:00
SDL_FreeSurface ( menu ) ;
2011-02-14 22:31:53 +02:00
menu = BitmapHandler : : loadBitmap ( " CBAR.bmp " ) ;
2011-08-25 18:24:37 +03:00
2011-02-14 22:31:53 +02:00
graphics - > blueToPlayersAdv ( menu , curInt - > playerID ) ;
2011-08-25 18:24:37 +03:00
bDefence - > block ( false ) ;
bWait - > block ( false ) ;
2011-02-14 22:31:53 +02:00
if ( active )
{
2011-02-24 15:57:47 +02:00
if ( btactEnd & & btactNext ) //if the other side had tactics, there are no buttons
{
btactEnd - > deactivate ( ) ;
btactNext - > deactivate ( ) ;
bConsoleDown - > activate ( ) ;
bConsoleUp - > activate ( ) ;
}
2011-02-14 22:31:53 +02:00
}
redraw ( ) ;
return ;
}
2010-02-19 18:02:34 +02:00
const CStack * stack = curInt - > cb - > battleGetStackByID ( action - > stackNumber ) ;
2009-09-24 16:23:52 +03:00
if ( stack )
{
queue - > update ( ) ;
}
else
{
2010-12-04 21:15:20 +02:00
assert ( action - > actionType = = BattleAction : : HERO_SPELL ) ; //only cast spell is valid action without acting stack number
2009-09-24 16:23:52 +03:00
}
2010-12-04 21:15:20 +02:00
if ( action - > actionType = = BattleAction : : WALK
| | ( action - > actionType = = BattleAction : : WALK_AND_ATTACK & & action - > destinationTile ! = stack - > position ) )
2009-09-24 16:23:52 +03:00
{
moveStarted = true ;
2011-02-09 15:56:30 +02:00
if ( creAnims [ action - > stackNumber ] - > framesInGroup ( CCreatureAnim : : MOVE_START ) )
2009-09-24 16:23:52 +03:00
{
2010-12-24 23:44:48 +02:00
const CStack * stack = curInt - > cb - > battleGetStackByID ( action - > stackNumber ) ;
pendingAnims . push_back ( std : : make_pair ( new CBattleMoveStart ( this , stack ) , false ) ) ;
2009-09-24 16:23:52 +03:00
}
}
2009-11-13 23:01:33 +02:00
if ( active )
deactivate ( ) ;
2009-09-24 16:23:52 +03:00
char txt [ 400 ] ;
2010-12-04 21:15:20 +02:00
if ( action - > actionType = = BattleAction : : HERO_SPELL ) //when hero casts spell
2009-09-24 16:23:52 +03:00
{
if ( action - > side )
defendingHero - > setPhase ( 4 ) ;
else
attackingHero - > setPhase ( 4 ) ;
return ;
}
if ( ! stack )
{
tlog1 < < " Something wrong with stackNumber in actionStarted. Stack number: " < < action - > stackNumber < < std : : endl ;
return ;
}
int txtid = 0 ;
switch ( action - > actionType )
{
2011-01-18 19:23:31 +02:00
case BattleAction : : WAIT :
2009-09-24 16:23:52 +03:00
txtid = 136 ;
break ;
2011-01-18 19:23:31 +02:00
case BattleAction : : BAD_MORALE :
txtid = - 34 ; //negative -> no separate singular/plural form
2009-09-24 16:23:52 +03:00
displayEffect ( 30 , stack - > position ) ;
break ;
}
2010-05-02 21:20:26 +03:00
if ( txtid > 0 & & stack - > count ! = 1 )
2009-09-24 16:23:52 +03:00
txtid + + ; //move to plural text
else if ( txtid < 0 )
txtid = - txtid ;
if ( txtid )
{
2010-11-20 19:36:02 +02:00
sprintf ( txt , CGI - > generaltexth - > allTexts [ txtid ] . c_str ( ) , ( stack - > count ! = 1 ) ? stack - > getCreature ( ) - > namePl . c_str ( ) : stack - > getCreature ( ) - > nameSing . c_str ( ) , 0 ) ;
2009-09-24 16:23:52 +03:00
console - > addText ( txt ) ;
}
2010-03-07 19:40:33 +02:00
2011-04-25 12:03:13 +03:00
//displaying special abilities
switch ( action - > actionType )
2010-03-07 19:40:33 +02:00
{
2011-04-25 12:03:13 +03:00
case BattleAction : : STACK_HEAL :
2011-05-15 09:37:57 +03:00
displayEffect ( 74 , action - > destinationTile ) ;
CCS - > soundh - > playSound ( soundBase : : REGENER ) ;
2011-04-25 12:03:13 +03:00
break ;
2010-03-07 19:40:33 +02:00
}
2009-09-24 16:23:52 +03:00
}
2011-01-08 21:38:42 +02:00
void CBattleInterface : : waitForAnims ( )
{
LOCPLINT - > pim - > unlock ( ) ;
animsAreDisplayed . waitWhileTrue ( ) ;
LOCPLINT - > pim - > lock ( ) ;
}
2010-05-07 15:29:41 +03:00
2011-02-12 18:12:48 +02:00
void CBattleInterface : : bEndTacticPhase ( )
{
2011-02-23 05:57:45 +02:00
btactEnd - > block ( true ) ;
2011-08-25 18:24:37 +03:00
tacticsMode = false ;
2011-02-12 18:12:48 +02:00
}
2011-02-24 15:57:47 +02:00
static bool immobile ( const CStack * s )
{
return ! s - > Speed ( ) ;
}
2011-02-12 18:12:48 +02:00
void CBattleInterface : : bTacticNextStack ( )
{
2011-05-25 02:17:57 +03:00
TStacks stacksOfMine = tacticianInterface - > cb - > battleGetStacks ( CBattleCallback : : ONLY_MINE ) ;
2011-02-25 19:57:30 +02:00
stacksOfMine . erase ( std : : remove_if ( stacksOfMine . begin ( ) , stacksOfMine . end ( ) , & immobile ) , stacksOfMine . end ( ) ) ;
2011-02-14 22:31:53 +02:00
TStacks : : iterator it = vstd : : find ( stacksOfMine , activeStack ) ;
if ( it ! = stacksOfMine . end ( ) & & + + it ! = stacksOfMine . end ( ) )
stackActivated ( * it ) ;
else
stackActivated ( stacksOfMine . front ( ) ) ;
2011-02-12 18:12:48 +02:00
}
2009-01-15 19:01:08 +02:00
void CBattleHero : : show ( SDL_Surface * to )
{
//animation of flag
if ( flip )
{
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect (
flag - > ourImages [ flagAnim ] . bitmap - > h ,
flag - > ourImages [ flagAnim ] . bitmap - > w ,
pos . x + 61 ,
pos . y + 39 ) ;
2009-01-15 19:01:08 +02:00
CSDL_Ext : : blit8bppAlphaTo24bpp (
flag - > ourImages [ flagAnim ] . bitmap ,
NULL ,
screen ,
2011-06-11 07:54:41 +03:00
& temp_rect ) ;
2009-01-15 19:01:08 +02:00
}
else
{
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect (
flag - > ourImages [ flagAnim ] . bitmap - > h ,
flag - > ourImages [ flagAnim ] . bitmap - > w ,
pos . x + 72 ,
pos . y + 39 ) ;
2009-01-15 19:01:08 +02:00
CSDL_Ext : : blit8bppAlphaTo24bpp (
flag - > ourImages [ flagAnim ] . bitmap ,
NULL ,
screen ,
2011-06-11 07:54:41 +03:00
& temp_rect ) ;
2009-01-15 19:01:08 +02:00
}
+ + flagAnimCount ;
if ( flagAnimCount % 4 = = 0 )
{
+ + flagAnim ;
flagAnim % = flag - > ourImages . size ( ) ;
}
//animation of hero
int tick = - 1 ;
for ( int i = 0 ; i < dh - > ourImages . size ( ) ; + + i )
{
if ( dh - > ourImages [ i ] . groupNumber = = phase )
+ + tick ;
if ( tick = = image )
{
SDL_Rect posb = pos ;
CSDL_Ext : : blit8bppAlphaTo24bpp ( dh - > ourImages [ i ] . bitmap , NULL , to , & posb ) ;
2009-02-28 18:44:56 +02:00
if ( phase ! = 4 | | nextPhase ! = - 1 | | image < 4 )
2009-01-15 19:01:08 +02:00
{
2009-02-28 18:44:56 +02:00
if ( flagAnimCount % 2 = = 0 )
{
+ + image ;
}
2009-02-09 16:50:32 +02:00
if ( dh - > ourImages [ ( i + 1 ) % dh - > ourImages . size ( ) ] . groupNumber ! = phase ) //back to appropriate frame
{
image = 0 ;
}
}
if ( phase = = 4 & & nextPhase ! = - 1 & & image = = 7 )
{
phase = nextPhase ;
2009-02-28 18:44:56 +02:00
nextPhase = - 1 ;
2009-01-15 19:01:08 +02:00
image = 0 ;
}
break ;
}
}
}
void CBattleHero : : activate ( )
{
2009-08-11 19:05:33 +03:00
activateLClick ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleHero : : deactivate ( )
{
2009-08-11 19:05:33 +03:00
deactivateLClick ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleHero : : setPhase ( int newPhase )
{
2009-02-09 16:50:32 +02:00
if ( phase ! = 4 )
{
phase = newPhase ;
image = 0 ;
}
else
{
nextPhase = newPhase ;
}
2009-01-15 19:01:08 +02:00
}
2009-08-11 19:05:33 +03:00
void CBattleHero : : clickLeft ( tribool down , bool previousState )
2009-01-15 19:01:08 +02:00
{
2009-09-19 12:57:37 +03:00
if ( myOwner - > spellDestSelectMode ) //we are casting a spell
return ;
2010-02-19 18:02:34 +02:00
if ( ! down & & myHero & & myOwner - > curInt - > cb - > battleCanCastSpell ( ) ) //check conditions
2009-01-15 19:01:08 +02:00
{
for ( int it = 0 ; it < BFIELD_SIZE ; + + it ) //do nothing when any hex is hovered - hero's animation overlaps battlefield
{
if ( myOwner - > bfield [ it ] . hovered & & myOwner - > bfield [ it ] . strictHovered )
return ;
}
2010-12-19 16:39:56 +02:00
CCS - > curh - > changeGraphic ( 0 , 0 ) ;
2009-01-15 19:01:08 +02:00
2010-02-19 18:02:34 +02:00
CSpellWindow * spellWindow = new CSpellWindow ( genRect ( 595 , 620 , ( conf . cc . resx - 620 ) / 2 , ( conf . cc . resy - 595 ) / 2 ) , myHero , myOwner - > curInt ) ;
2009-08-07 01:36:51 +03:00
GH . pushInt ( spellWindow ) ;
2009-01-15 19:01:08 +02:00
}
}
2009-08-19 08:00:59 +03:00
CBattleHero : : CBattleHero ( const std : : string & defName , int phaseG , int imageG , bool flipG , unsigned char player , const CGHeroInstance * hero , const CBattleInterface * owner ) : flip ( flipG ) , myHero ( hero ) , myOwner ( owner ) , phase ( phaseG ) , nextPhase ( - 1 ) , image ( imageG ) , flagAnim ( 0 ) , flagAnimCount ( 0 )
2009-01-15 19:01:08 +02:00
{
dh = CDefHandler : : giveDef ( defName ) ;
for ( int i = 0 ; i < dh - > ourImages . size ( ) ; + + i ) //transforming images
{
if ( flip )
{
SDL_Surface * hlp = CSDL_Ext : : rotate01 ( dh - > ourImages [ i ] . bitmap ) ;
SDL_FreeSurface ( dh - > ourImages [ i ] . bitmap ) ;
dh - > ourImages [ i ] . bitmap = hlp ;
}
2009-06-07 01:47:23 +03:00
CSDL_Ext : : alphaTransform ( dh - > ourImages [ i ] . bitmap ) ;
2009-01-15 19:01:08 +02:00
}
if ( flip )
flag = CDefHandler : : giveDef ( " CMFLAGR.DEF " ) ;
else
flag = CDefHandler : : giveDef ( " CMFLAGL.DEF " ) ;
//coloring flag and adding transparency
for ( int i = 0 ; i < flag - > ourImages . size ( ) ; + + i )
{
2009-06-07 01:47:23 +03:00
CSDL_Ext : : alphaTransform ( flag - > ourImages [ i ] . bitmap ) ;
2009-01-15 19:01:08 +02:00
graphics - > blueToPlayersAdv ( flag - > ourImages [ i ] . bitmap , player ) ;
}
}
CBattleHero : : ~ CBattleHero ( )
{
delete dh ;
delete flag ;
}
2009-09-21 11:29:41 +03:00
Point CBattleHex : : getXYUnitAnim ( const int & hexNum , const bool & attacker , const CStack * stack , const CBattleInterface * cbi )
2009-01-15 19:01:08 +02:00
{
2009-09-21 11:29:41 +03:00
Point ret ( - 500 , - 500 ) ; //returned value
2011-06-18 07:56:32 +03:00
if ( stack & & stack - > position < 0 ) //creatures in turrets
2009-09-06 12:13:16 +03:00
{
switch ( stack - > position )
{
case - 2 : //keep
2011-05-18 20:51:10 +03:00
ret = graphics - > wallPositions [ cbi - > siegeH - > town - > town - > typeID ] [ 17 ] ;
2009-09-06 12:13:16 +03:00
break ;
case - 3 : //lower turret
2011-05-18 20:51:10 +03:00
ret = graphics - > wallPositions [ cbi - > siegeH - > town - > town - > typeID ] [ 18 ] ;
2009-09-06 12:13:16 +03:00
break ;
case - 4 : //upper turret
2011-05-18 20:51:10 +03:00
ret = graphics - > wallPositions [ cbi - > siegeH - > town - > town - > typeID ] [ 19 ] ;
2009-09-06 12:13:16 +03:00
break ;
}
}
2009-01-15 19:01:08 +02:00
else
{
2009-09-21 11:29:41 +03:00
ret . y = - 139 + 42 * ( hexNum / BFIELD_WIDTH ) ; //counting y
//counting x
2009-01-15 19:01:08 +02:00
if ( attacker )
{
2009-09-21 11:29:41 +03:00
ret . x = - 160 + 22 * ( ( ( hexNum / BFIELD_WIDTH ) + 1 ) % 2 ) + 44 * ( hexNum % BFIELD_WIDTH ) ;
2009-01-15 19:01:08 +02:00
}
else
{
2009-09-21 11:29:41 +03:00
ret . x = - 219 + 22 * ( ( ( hexNum / BFIELD_WIDTH ) + 1 ) % 2 ) + 44 * ( hexNum % BFIELD_WIDTH ) ;
}
//shifting position for double - hex creatures
2010-05-02 21:20:26 +03:00
if ( stack & & stack - > doubleWide ( ) )
2009-09-21 11:29:41 +03:00
{
if ( attacker )
{
2011-05-26 17:47:45 +03:00
ret . x - = 44 ;
2009-09-21 11:29:41 +03:00
}
else
{
2011-05-26 17:47:45 +03:00
ret . x + = 45 ;
2009-09-21 11:29:41 +03:00
}
2009-01-15 19:01:08 +02:00
}
}
//returning
2010-02-19 18:02:34 +02:00
return ret + CPlayerInterface : : battleInt - > pos ;
2009-01-15 19:01:08 +02:00
}
void CBattleHex : : activate ( )
{
2009-08-11 19:05:33 +03:00
activateHover ( ) ;
activateMouseMove ( ) ;
activateLClick ( ) ;
activateRClick ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleHex : : deactivate ( )
{
2009-08-11 19:05:33 +03:00
deactivateHover ( ) ;
deactivateMouseMove ( ) ;
deactivateLClick ( ) ;
deactivateRClick ( ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleHex : : hover ( bool on )
{
hovered = on ;
2009-08-11 19:05:33 +03:00
//Hoverable::hover(on);
2009-01-15 19:01:08 +02:00
if ( ! on & & setAlterText )
{
myInterface - > console - > alterTxt = std : : string ( ) ;
setAlterText = false ;
}
}
2009-10-16 05:09:58 +03:00
CBattleHex : : CBattleHex ( ) : setAlterText ( false ) , myNumber ( - 1 ) , accessible ( true ) , hovered ( false ) , strictHovered ( false ) , myInterface ( NULL )
2009-01-15 19:01:08 +02:00
{
}
void CBattleHex : : mouseMoved ( const SDL_MouseMotionEvent & sEvent )
{
if ( myInterface - > cellShade )
{
if ( CSDL_Ext : : SDL_GetPixel ( myInterface - > cellShade , sEvent . x - pos . x , sEvent . y - pos . y ) = = 0 ) //hovered pixel is outside hex
{
strictHovered = false ;
}
else //hovered pixel is inside hex
{
strictHovered = true ;
}
}
if ( hovered & & strictHovered ) //print attacked creature to console
{
2011-02-09 17:19:53 +02:00
const CStack * attackedStack = myInterface - > curInt - > cb - > battleGetStackByPos ( myNumber ) ;
if ( myInterface - > console - > alterTxt . size ( ) = = 0 & & attackedStack ! = NULL & &
attackedStack - > owner ! = myInterface - > curInt - > playerID & &
attackedStack - > alive ( ) )
2009-01-15 19:01:08 +02:00
{
char tabh [ 160 ] ;
2010-11-20 19:36:02 +02:00
const std : : string & attackedName = attackedStack - > count = = 1 ? attackedStack - > getCreature ( ) - > nameSing : attackedStack - > getCreature ( ) - > namePl ;
2009-01-15 19:01:08 +02:00
sprintf ( tabh , CGI - > generaltexth - > allTexts [ 220 ] . c_str ( ) , attackedName . c_str ( ) ) ;
myInterface - > console - > alterTxt = std : : string ( tabh ) ;
setAlterText = true ;
}
}
else if ( setAlterText )
{
myInterface - > console - > alterTxt = std : : string ( ) ;
setAlterText = false ;
}
}
2009-08-11 19:05:33 +03:00
void CBattleHex : : clickLeft ( tribool down , bool previousState )
2009-01-15 19:01:08 +02:00
{
if ( ! down & & hovered & & strictHovered ) //we've been really clicked!
{
myInterface - > hexLclicked ( myNumber ) ;
}
}
2009-08-11 19:05:33 +03:00
void CBattleHex : : clickRight ( tribool down , bool previousState )
2009-01-15 19:01:08 +02:00
{
2010-12-08 22:17:05 +02:00
const CStack * myst = myInterface - > curInt - > cb - > battleGetStackByPos ( myNumber ) ; //stack info
if ( hovered & & strictHovered & & myst ! = NULL )
2009-01-15 19:01:08 +02:00
{
2010-12-08 22:17:05 +02:00
if ( ! myst - > alive ( ) ) return ;
2009-01-15 19:01:08 +02:00
if ( down )
{
2011-05-25 16:11:03 +03:00
GH . pushInt ( createCreWindow ( myst ) ) ;
2009-01-15 19:01:08 +02:00
}
}
}
2009-01-29 20:07:31 +02:00
CBattleConsole : : CBattleConsole ( ) : lastShown ( - 1 ) , alterTxt ( " " ) , whoSetAlter ( 0 )
2009-01-15 19:01:08 +02:00
{
}
CBattleConsole : : ~ CBattleConsole ( )
{
texts . clear ( ) ;
}
void CBattleConsole : : show ( SDL_Surface * to )
{
2009-04-03 18:55:26 +03:00
if ( ingcAlter . size ( ) )
{
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddleWB ( ingcAlter , pos . x + pos . w / 2 , pos . y + 11 , FONT_SMALL , 80 , zwykly , to ) ;
2009-04-03 18:55:26 +03:00
}
else if ( alterTxt . size ( ) )
2009-01-15 19:01:08 +02:00
{
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddleWB ( alterTxt , pos . x + pos . w / 2 , pos . y + 11 , FONT_SMALL , 80 , zwykly , to ) ;
2009-01-15 19:01:08 +02:00
}
else if ( texts . size ( ) )
{
if ( texts . size ( ) = = 1 )
{
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddleWB ( texts [ 0 ] , pos . x + pos . w / 2 , pos . y + 11 , FONT_SMALL , 80 , zwykly , to ) ;
2009-01-15 19:01:08 +02:00
}
else
{
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddleWB ( texts [ lastShown - 1 ] , pos . x + pos . w / 2 , pos . y + 11 , FONT_SMALL , 80 , zwykly , to ) ;
CSDL_Ext : : printAtMiddleWB ( texts [ lastShown ] , pos . x + pos . w / 2 , pos . y + 27 , FONT_SMALL , 80 , zwykly , to ) ;
2009-01-15 19:01:08 +02:00
}
}
}
bool CBattleConsole : : addText ( const std : : string & text )
{
if ( text . size ( ) > 70 )
return false ; //text too long!
int firstInToken = 0 ;
for ( int i = 0 ; i < text . size ( ) ; + + i ) //tokenize
{
if ( text [ i ] = = 10 )
{
texts . push_back ( text . substr ( firstInToken , i - firstInToken ) ) ;
firstInToken = i + 1 ;
}
}
texts . push_back ( text . substr ( firstInToken , text . size ( ) ) ) ;
lastShown = texts . size ( ) - 1 ;
return true ;
}
void CBattleConsole : : eraseText ( unsigned int pos )
{
if ( pos < texts . size ( ) )
{
texts . erase ( texts . begin ( ) + pos ) ;
if ( lastShown = = texts . size ( ) )
- - lastShown ;
}
}
void CBattleConsole : : changeTextAt ( const std : : string & text , unsigned int pos )
{
if ( pos > = texts . size ( ) ) //no such pos
return ;
texts [ pos ] = text ;
}
void CBattleConsole : : scrollUp ( unsigned int by )
{
if ( lastShown > by )
lastShown - = by ;
}
void CBattleConsole : : scrollDown ( unsigned int by )
{
if ( lastShown + by < texts . size ( ) )
lastShown + = by ;
}
2010-02-19 18:02:34 +02:00
CBattleResultWindow : : CBattleResultWindow ( const BattleResult & br , const SDL_Rect & pos , CBattleInterface * _owner )
: owner ( _owner )
2009-01-15 19:01:08 +02:00
{
this - > pos = pos ;
background = BitmapHandler : : loadBitmap ( " CPRESULT.BMP " , true ) ;
2010-02-19 18:02:34 +02:00
graphics - > blueToPlayersAdv ( background , owner - > curInt - > playerID ) ;
2009-01-15 19:01:08 +02:00
SDL_Surface * pom = SDL_ConvertSurface ( background , screen - > format , screen - > flags ) ;
SDL_FreeSurface ( background ) ;
background = pom ;
2009-06-01 06:36:13 +03:00
exit = new AdventureMapButton ( std : : string ( ) , std : : string ( ) , boost : : bind ( & CBattleResultWindow : : bExitf , this ) , 384 + pos . x , 505 + pos . y , " iok6432.def " , SDLK_RETURN ) ;
2011-04-30 22:52:35 +03:00
exit - > borderColor = Colors : : MetallicGold ;
2011-04-26 16:30:29 +03:00
exit - > borderEnabled = true ;
2009-01-15 19:01:08 +02:00
if ( br . winner = = 0 ) //attacker won
{
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 410 ] , 59 , 124 , FONT_SMALL , zwykly , background ) ;
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 411 ] , 408 , 124 , FONT_SMALL , zwykly , background ) ;
2009-01-15 19:01:08 +02:00
}
else //if(br.winner==1)
{
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 411 ] , 59 , 124 , FONT_SMALL , zwykly , background ) ;
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 410 ] , 412 , 124 , FONT_SMALL , zwykly , background ) ;
2009-01-15 19:01:08 +02:00
}
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 407 ] , 232 , 302 , FONT_BIG , tytulowy , background ) ;
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 408 ] , 232 , 332 , FONT_BIG , zwykly , background ) ;
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 409 ] , 237 , 428 , FONT_BIG , zwykly , background ) ;
2009-01-15 19:01:08 +02:00
std : : string attackerName , defenderName ;
if ( owner - > attackingHeroInstance ) //a hero attacked
{
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( 64 , 58 , 21 , 38 ) ;
SDL_BlitSurface ( graphics - > portraitLarge [ owner - > attackingHeroInstance - > portrait ] , NULL , background , & temp_rect ) ;
2009-01-15 19:01:08 +02:00
//setting attackerName
attackerName = owner - > attackingHeroInstance - > name ;
}
else //a monster attacked
{
int bestMonsterID = - 1 ;
int bestPower = 0 ;
2010-12-06 01:10:02 +02:00
for ( TSlots : : const_iterator it = owner - > army1 - > Slots ( ) . begin ( ) ; it ! = owner - > army1 - > Slots ( ) . end ( ) ; + + it )
2009-01-15 19:01:08 +02:00
{
2010-11-22 02:34:46 +02:00
if ( it - > second - > type - > AIValue > bestPower )
2009-01-15 19:01:08 +02:00
{
2010-11-22 02:34:46 +02:00
bestPower = it - > second - > type - > AIValue ;
bestMonsterID = it - > second - > type - > idNumber ;
2009-01-15 19:01:08 +02:00
}
}
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( 64 , 58 , 21 , 38 ) ;
SDL_BlitSurface ( graphics - > bigImgs [ bestMonsterID ] , NULL , background , & temp_rect ) ;
2009-01-15 19:01:08 +02:00
//setting attackerName
2010-05-02 21:20:26 +03:00
attackerName = CGI - > creh - > creatures [ bestMonsterID ] - > namePl ;
2009-01-15 19:01:08 +02:00
}
if ( owner - > defendingHeroInstance ) //a hero defended
{
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( 64 , 58 , 392 , 38 ) ;
SDL_BlitSurface ( graphics - > portraitLarge [ owner - > defendingHeroInstance - > portrait ] , NULL , background , & temp_rect ) ;
2009-01-15 19:01:08 +02:00
//setting defenderName
defenderName = owner - > defendingHeroInstance - > name ;
}
else //a monster defended
{
int bestMonsterID = - 1 ;
int bestPower = 0 ;
2010-12-06 01:10:02 +02:00
for ( TSlots : : const_iterator it = owner - > army2 - > Slots ( ) . begin ( ) ; it ! = owner - > army2 - > Slots ( ) . end ( ) ; + + it )
2009-01-15 19:01:08 +02:00
{
2010-11-22 02:34:46 +02:00
if ( it - > second - > type - > AIValue > bestPower )
2009-01-15 19:01:08 +02:00
{
2010-11-22 02:34:46 +02:00
bestPower = it - > second - > type - > AIValue ;
bestMonsterID = it - > second - > type - > idNumber ;
2009-01-15 19:01:08 +02:00
}
}
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( 64 , 58 , 392 , 38 ) ;
SDL_BlitSurface ( graphics - > bigImgs [ bestMonsterID ] , NULL , background , & temp_rect ) ;
2009-01-15 19:01:08 +02:00
//setting defenderName
2010-05-02 21:20:26 +03:00
defenderName = CGI - > creh - > creatures [ bestMonsterID ] - > namePl ;
2009-01-15 19:01:08 +02:00
}
//printing attacker and defender's names
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAt ( attackerName , 89 , 37 , FONT_SMALL , zwykly , background ) ;
CSDL_Ext : : printTo ( defenderName , 381 , 53 , FONT_SMALL , zwykly , background ) ;
2009-01-15 19:01:08 +02:00
//printing casualities
for ( int step = 0 ; step < 2 ; + + step )
{
if ( br . casualties [ step ] . size ( ) = = 0 )
{
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 523 ] , 235 , 360 + 97 * step , FONT_SMALL , zwykly , background ) ;
2009-01-15 19:01:08 +02:00
}
else
{
int xPos = 235 - ( br . casualties [ step ] . size ( ) * 32 + ( br . casualties [ step ] . size ( ) - 1 ) * 10 ) / 2 ; //increment by 42 with each picture
int yPos = 344 + step * 97 ;
2009-09-24 16:23:52 +03:00
for ( std : : map < ui32 , si32 > : : const_iterator it = br . casualties [ step ] . begin ( ) ; it ! = br . casualties [ step ] . end ( ) ; + + it )
2009-01-15 19:01:08 +02:00
{
blitAt ( graphics - > smallImgs [ it - > first ] , xPos , yPos , background ) ;
2009-06-17 19:46:16 +03:00
std : : ostringstream amount ;
2009-01-15 19:01:08 +02:00
amount < < it - > second ;
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddle ( amount . str ( ) , xPos + 16 , yPos + 42 , FONT_SMALL , zwykly , background ) ;
2009-01-15 19:01:08 +02:00
xPos + = 42 ;
}
}
}
//printing result description
2010-02-19 18:02:34 +02:00
bool weAreAttacker = ( owner - > curInt - > playerID = = owner - > attackingHeroInstance - > tempOwner ) ;
2010-08-30 02:12:34 +03:00
if ( ( br . winner = = 0 & & weAreAttacker ) | | ( br . winner = = 1 & & ! weAreAttacker ) ) //we've won
2009-01-15 19:01:08 +02:00
{
2011-02-20 11:24:53 +02:00
int text = - 1 ;
2010-08-30 02:12:34 +03:00
switch ( br . result )
2009-01-15 19:01:08 +02:00
{
2010-08-30 02:12:34 +03:00
case 0 : text = 304 ; break ;
case 1 : text = 303 ; break ;
case 2 : text = 302 ; break ;
}
2010-12-19 16:39:56 +02:00
CCS - > musich - > playMusic ( musicBase : : winBattle ) ;
2011-08-08 17:20:22 +03:00
CCS - > videoh - > open ( VIDEO_WIN ) ;
2010-08-30 02:12:34 +03:00
std : : string str = CGI - > generaltexth - > allTexts [ text ] ;
const CGHeroInstance * ourHero = weAreAttacker ? owner - > attackingHeroInstance : owner - > defendingHeroInstance ;
if ( ourHero )
{
str + = CGI - > generaltexth - > allTexts [ 305 ] ;
boost : : algorithm : : replace_first ( str , " %s " , ourHero - > name ) ;
boost : : algorithm : : replace_first ( str , " %d " , boost : : lexical_cast < std : : string > ( br . exp [ weAreAttacker ? 0 : 1 ] ) ) ;
2009-01-15 19:01:08 +02:00
}
2010-08-30 02:12:34 +03:00
CSDL_Ext : : printAtMiddleWB ( str , 235 , 235 , FONT_SMALL , 55 , zwykly , background ) ;
}
else // we lose
{
switch ( br . result )
{
case 0 : //normal victory
2009-01-15 19:01:08 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > musich - > playMusic ( musicBase : : loseCombat ) ;
CCS - > videoh - > open ( VIDEO_LOSE_BATTLE_START ) ;
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 311 ] , 235 , 235 , FONT_SMALL , zwykly , background ) ;
2010-08-30 02:12:34 +03:00
break ;
2009-01-15 19:01:08 +02:00
}
2010-08-30 02:12:34 +03:00
case 1 : //flee
2009-01-15 19:01:08 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > musich - > playMusic ( musicBase : : retreatBattle ) ;
CCS - > videoh - > open ( VIDEO_RETREAT_START ) ;
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 310 ] , 235 , 235 , FONT_SMALL , zwykly , background ) ;
2010-08-30 02:12:34 +03:00
break ;
2009-01-15 19:01:08 +02:00
}
2010-08-30 02:12:34 +03:00
case 2 : //surrender
2009-01-15 19:01:08 +02:00
{
2010-12-19 16:39:56 +02:00
CCS - > musich - > playMusic ( musicBase : : surrenderBattle ) ;
CCS - > videoh - > open ( VIDEO_SURRENDER ) ;
2010-08-30 02:12:34 +03:00
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 309 ] , 235 , 220 , FONT_SMALL , zwykly , background ) ;
break ;
}
2009-01-15 19:01:08 +02:00
}
}
}
2009-06-01 06:36:13 +03:00
CBattleResultWindow : : ~ CBattleResultWindow ( )
2009-01-15 19:01:08 +02:00
{
SDL_FreeSurface ( background ) ;
}
2009-06-01 06:36:13 +03:00
void CBattleResultWindow : : activate ( )
2009-01-15 19:01:08 +02:00
{
2010-02-19 18:02:34 +02:00
owner - > curInt - > showingDialog - > set ( true ) ;
2009-01-15 19:01:08 +02:00
exit - > activate ( ) ;
}
2009-06-01 06:36:13 +03:00
void CBattleResultWindow : : deactivate ( )
2009-01-15 19:01:08 +02:00
{
exit - > deactivate ( ) ;
}
2009-06-01 06:36:13 +03:00
void CBattleResultWindow : : show ( SDL_Surface * to )
2009-01-15 19:01:08 +02:00
{
//evaluating to
if ( ! to )
to = screen ;
2010-12-19 16:39:56 +02:00
CCS - > videoh - > update ( 107 , 70 , background , false , true ) ;
2009-06-28 19:02:39 +03:00
2009-01-15 19:01:08 +02:00
SDL_BlitSurface ( background , NULL , to , & pos ) ;
2011-02-20 11:24:53 +02:00
exit - > showAll ( to ) ;
2009-01-15 19:01:08 +02:00
}
2009-06-01 06:36:13 +03:00
void CBattleResultWindow : : bExitf ( )
2009-01-15 19:01:08 +02:00
{
2011-01-08 21:38:42 +02:00
if ( LOCPLINT - > cb - > getStartInfo ( ) - > mode = = StartInfo : : DUEL )
{
std : : exit ( 0 ) ;
}
2010-02-19 18:19:44 +02:00
CPlayerInterface * intTmp = owner - > curInt ;
2009-08-07 01:36:51 +03:00
GH . popInts ( 2 ) ; //first - we; second - battle interface
2010-02-19 18:19:44 +02:00
intTmp - > showingDialog - > setn ( false ) ;
2010-12-19 16:39:56 +02:00
CCS - > videoh - > close ( ) ;
2009-01-15 19:01:08 +02:00
}
CBattleOptionsWindow : : CBattleOptionsWindow ( const SDL_Rect & position , CBattleInterface * owner ) : myInt ( owner )
{
pos = position ;
2010-02-02 18:24:53 +02:00
SDL_Surface * hhlp = BitmapHandler : : loadBitmap ( " comopbck.bmp " , true ) ;
2010-02-19 18:02:34 +02:00
graphics - > blueToPlayersAdv ( hhlp , owner - > curInt - > playerID ) ;
background = SDL_ConvertSurface ( hhlp , screen - > format , 0 ) ;
SDL_SetColorKey ( background , SDL_SRCCOLORKEY , SDL_MapRGB ( background - > format , 0 , 255 , 255 ) ) ;
2010-02-02 18:24:53 +02:00
SDL_FreeSurface ( hhlp ) ;
2009-01-15 19:01:08 +02:00
viewGrid = new CHighlightableButton ( boost : : bind ( & CBattleInterface : : setPrintCellBorders , owner , true ) , boost : : bind ( & CBattleInterface : : setPrintCellBorders , owner , false ) , boost : : assign : : map_list_of ( 0 , CGI - > generaltexth - > zelp [ 427 ] . first ) ( 3 , CGI - > generaltexth - > zelp [ 427 ] . first ) , CGI - > generaltexth - > zelp [ 427 ] . second , false , " sysopchk.def " , NULL , 185 , 140 , false ) ;
2010-02-19 18:02:34 +02:00
viewGrid - > select ( owner - > curInt - > sysOpts . printCellBorders ) ;
2009-01-15 19:01:08 +02:00
movementShadow = new CHighlightableButton ( boost : : bind ( & CBattleInterface : : setPrintStackRange , owner , true ) , boost : : bind ( & CBattleInterface : : setPrintStackRange , owner , false ) , boost : : assign : : map_list_of ( 0 , CGI - > generaltexth - > zelp [ 428 ] . first ) ( 3 , CGI - > generaltexth - > zelp [ 428 ] . first ) , CGI - > generaltexth - > zelp [ 428 ] . second , false , " sysopchk.def " , NULL , 185 , 173 , false ) ;
2010-02-19 18:02:34 +02:00
movementShadow - > select ( owner - > curInt - > sysOpts . printStackRange ) ;
2009-01-15 19:01:08 +02:00
mouseShadow = new CHighlightableButton ( boost : : bind ( & CBattleInterface : : setPrintMouseShadow , owner , true ) , boost : : bind ( & CBattleInterface : : setPrintMouseShadow , owner , false ) , boost : : assign : : map_list_of ( 0 , CGI - > generaltexth - > zelp [ 429 ] . first ) ( 3 , CGI - > generaltexth - > zelp [ 429 ] . first ) , CGI - > generaltexth - > zelp [ 429 ] . second , false , " sysopchk.def " , NULL , 185 , 207 , false ) ;
2010-02-19 18:02:34 +02:00
mouseShadow - > select ( owner - > curInt - > sysOpts . printMouseShadow ) ;
2009-01-15 19:01:08 +02:00
animSpeeds = new CHighlightableButtonsGroup ( 0 ) ;
animSpeeds - > addButton ( boost : : assign : : map_list_of ( 0 , CGI - > generaltexth - > zelp [ 422 ] . first ) , CGI - > generaltexth - > zelp [ 422 ] . second , " sysopb9.def " , 188 , 309 , 1 ) ;
animSpeeds - > addButton ( boost : : assign : : map_list_of ( 0 , CGI - > generaltexth - > zelp [ 423 ] . first ) , CGI - > generaltexth - > zelp [ 423 ] . second , " sysob10.def " , 252 , 309 , 2 ) ;
animSpeeds - > addButton ( boost : : assign : : map_list_of ( 0 , CGI - > generaltexth - > zelp [ 424 ] . first ) , CGI - > generaltexth - > zelp [ 424 ] . second , " sysob11.def " , 315 , 309 , 4 ) ;
animSpeeds - > select ( owner - > getAnimSpeed ( ) , 1 ) ;
animSpeeds - > onChange = boost : : bind ( & CBattleInterface : : setAnimSpeed , owner , _1 ) ;
2011-05-28 13:05:25 +03:00
setToDefault = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 393 ] , boost : : bind ( & CBattleOptionsWindow : : bDefaultf , this ) , 405 , 443 , " codefaul.def " ) ;
2011-02-20 11:24:53 +02:00
setToDefault - > swappedImages = true ;
setToDefault - > update ( ) ;
2011-05-28 13:05:25 +03:00
exit = new AdventureMapButton ( CGI - > generaltexth - > zelp [ 392 ] , boost : : bind ( & CBattleOptionsWindow : : bExitf , this ) , 516 , 443 , " soretrn.def " , SDLK_RETURN ) ;
2011-02-20 11:24:53 +02:00
exit - > swappedImages = true ;
exit - > update ( ) ;
2009-01-15 19:01:08 +02:00
//printing texts to background
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 392 ] , 242 , 32 , FONT_BIG , tytulowy , background ) ; //window title
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 393 ] , 122 , 214 , FONT_MEDIUM , tytulowy , background ) ; //animation speed
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 394 ] , 122 , 293 , FONT_MEDIUM , tytulowy , background ) ; //music volume
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 395 ] , 122 , 359 , FONT_MEDIUM , tytulowy , background ) ; //effects' volume
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 396 ] , 353 , 66 , FONT_MEDIUM , tytulowy , background ) ; //auto - combat options
CSDL_Ext : : printAtMiddle ( CGI - > generaltexth - > allTexts [ 397 ] , 353 , 265 , FONT_MEDIUM , tytulowy , background ) ; //creature info
2009-01-15 19:01:08 +02:00
//auto - combat options
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 398 ] , 283 , 86 , FONT_MEDIUM , zwykly , background ) ; //creatures
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 399 ] , 283 , 116 , FONT_MEDIUM , zwykly , background ) ; //spells
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 400 ] , 283 , 146 , FONT_MEDIUM , zwykly , background ) ; //catapult
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 151 ] , 283 , 176 , FONT_MEDIUM , zwykly , background ) ; //ballista
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 401 ] , 283 , 206 , FONT_MEDIUM , zwykly , background ) ; //first aid tent
2009-01-15 19:01:08 +02:00
//creature info
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 402 ] , 283 , 285 , FONT_MEDIUM , zwykly , background ) ; //all stats
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 403 ] , 283 , 315 , FONT_MEDIUM , zwykly , background ) ; //spells only
2009-01-15 19:01:08 +02:00
//general options
2010-02-02 18:24:53 +02:00
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 404 ] , 61 , 57 , FONT_MEDIUM , zwykly , background ) ; //hex grid
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 405 ] , 61 , 90 , FONT_MEDIUM , zwykly , background ) ; //movement shadow
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 406 ] , 61 , 124 , FONT_MEDIUM , zwykly , background ) ; //cursor shadow
CSDL_Ext : : printAt ( CGI - > generaltexth - > allTexts [ 577 ] , 61 , 156 , FONT_MEDIUM , zwykly , background ) ; //spellbook animation
2009-01-15 19:01:08 +02:00
//texts printed
}
CBattleOptionsWindow : : ~ CBattleOptionsWindow ( )
{
SDL_FreeSurface ( background ) ;
delete setToDefault ;
delete exit ;
delete viewGrid ;
delete movementShadow ;
delete animSpeeds ;
delete mouseShadow ;
}
void CBattleOptionsWindow : : activate ( )
{
setToDefault - > activate ( ) ;
exit - > activate ( ) ;
viewGrid - > activate ( ) ;
movementShadow - > activate ( ) ;
animSpeeds - > activate ( ) ;
mouseShadow - > activate ( ) ;
}
void CBattleOptionsWindow : : deactivate ( )
{
setToDefault - > deactivate ( ) ;
exit - > deactivate ( ) ;
viewGrid - > deactivate ( ) ;
movementShadow - > deactivate ( ) ;
animSpeeds - > deactivate ( ) ;
mouseShadow - > deactivate ( ) ;
}
void CBattleOptionsWindow : : show ( SDL_Surface * to )
{
if ( ! to ) //"evaluating" to
to = screen ;
SDL_BlitSurface ( background , NULL , to , & pos ) ;
2011-02-20 11:24:53 +02:00
setToDefault - > showAll ( to ) ;
exit - > showAll ( to ) ;
viewGrid - > showAll ( to ) ;
movementShadow - > showAll ( to ) ;
animSpeeds - > showAll ( to ) ;
mouseShadow - > showAll ( to ) ;
2009-01-15 19:01:08 +02:00
}
void CBattleOptionsWindow : : bDefaultf ( )
{
}
void CBattleOptionsWindow : : bExitf ( )
{
2009-08-07 01:36:51 +03:00
GH . popIntTotally ( this ) ;
2009-01-15 19:01:08 +02:00
}
2009-08-24 15:55:05 +03:00
2009-08-28 13:05:45 +03:00
std : : string CBattleInterface : : SiegeHelper : : townTypeInfixes [ F_NUMBER ] = { " CS " , " RM " , " TW " , " IN " , " NC " , " DN " , " ST " , " FR " , " EL " } ;
2009-08-24 15:55:05 +03:00
2009-08-26 17:09:55 +03:00
CBattleInterface : : SiegeHelper : : SiegeHelper ( const CGTownInstance * siegeTown , const CBattleInterface * _owner )
2010-10-31 00:53:41 +03:00
: owner ( _owner ) , town ( siegeTown )
2009-08-26 17:09:55 +03:00
{
for ( int g = 0 ; g < ARRAY_COUNT ( walls ) ; + + g )
{
2009-09-01 16:54:13 +03:00
walls [ g ] = BitmapHandler : : loadBitmap ( getSiegeName ( g ) ) ;
2009-08-26 17:09:55 +03:00
}
}
CBattleInterface : : SiegeHelper : : ~ SiegeHelper ( )
{
for ( int g = 0 ; g < ARRAY_COUNT ( walls ) ; + + g )
{
SDL_FreeSurface ( walls [ g ] ) ;
}
}
std : : string CBattleInterface : : SiegeHelper : : getSiegeName ( ui16 what , ui16 additInfo ) const
{
2009-09-01 16:54:13 +03:00
if ( what = = 2 | | what = = 3 | | what = = 8 )
{
2009-09-05 17:10:26 +03:00
if ( additInfo = = 3 ) additInfo = 2 ;
2009-09-01 16:54:13 +03:00
}
2009-08-26 17:09:55 +03:00
char buf [ 100 ] ;
2009-08-27 02:38:17 +03:00
SDL_itoa ( additInfo , buf , 10 ) ;
2009-08-26 17:09:55 +03:00
std : : string addit ( buf ) ;
switch ( what )
{
case 0 : //background
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " BACK.BMP " ;
case 1 : //background wall
2009-08-28 12:03:58 +03:00
{
switch ( town - > town - > typeID )
{
case 5 : case 4 : case 1 : case 6 :
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " TPW1.BMP " ;
case 0 : case 2 : case 3 : case 7 : case 8 :
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " TPWL.BMP " ;
default :
return " " ;
}
}
2009-08-26 17:09:55 +03:00
case 2 : //keep
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " MAN " + addit + " .BMP " ;
case 3 : //bottom tower
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " TW1 " + addit + " .BMP " ;
case 4 : //bottom wall
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " WA1 " + addit + " .BMP " ;
case 5 : //below gate
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " WA3 " + addit + " .BMP " ;
case 6 : //over gate
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " WA4 " + addit + " .BMP " ;
case 7 : //upper wall
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " WA6 " + addit + " .BMP " ;
case 8 : //upper tower
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " TW2 " + addit + " .BMP " ;
case 9 : //gate
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " DRW " + addit + " .BMP " ;
case 10 : //gate arch
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " ARCH.BMP " ;
case 11 : //bottom static wall
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " WA2.BMP " ;
case 12 : //upper static wall
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " WA5.BMP " ;
2009-09-02 17:10:19 +03:00
case 13 : //moat
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " MOAT.BMP " ;
case 14 : //mlip
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " MLIP.BMP " ;
2009-09-04 17:11:42 +03:00
case 15 : //keep creature cover
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " MANC.BMP " ;
case 16 : //bottom turret creature cover
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " TW1C.BMP " ;
case 17 : //upper turret creature cover
return " SG " + townTypeInfixes [ town - > town - > typeID ] + " TW2C.BMP " ;
2009-08-26 17:09:55 +03:00
default :
return " " ;
}
}
2011-04-30 22:52:35 +03:00
/// What: 1. background wall, 2. keep, 3. bottom tower, 4. bottom wall, 5. wall below gate,
/// 6. wall over gate, 7. upper wall, 8. upper tower, 9. gate, 10. gate arch, 11. bottom static wall, 12. upper static wall, 13. moat, 14. mlip,
/// 15. keep turret cover, 16. lower turret cover, 17. upper turret cover
/// Positions are loaded from the config file: /config/wall_pos.txt
2009-08-26 17:09:55 +03:00
void CBattleInterface : : SiegeHelper : : printPartOfWall ( SDL_Surface * to , int what )
2009-08-24 15:55:05 +03:00
{
2009-08-26 17:09:55 +03:00
Point pos = Point ( - 1 , - 1 ) ;
2011-04-30 22:52:35 +03:00
if ( what > = 1 & & what < = 17 )
2009-08-26 17:09:55 +03:00
{
2011-04-30 22:52:35 +03:00
pos . x = graphics - > wallPositions [ town - > town - > typeID ] [ what - 1 ] . x + owner - > pos . x ;
pos . y = graphics - > wallPositions [ town - > town - > typeID ] [ what - 1 ] . y + owner - > pos . y ;
}
2009-08-26 17:09:55 +03:00
if ( pos . x ! = - 1 )
{
2009-09-01 16:54:13 +03:00
blitAt ( walls [ what ] , pos . x , pos . y , to ) ;
2009-08-26 17:09:55 +03:00
}
2009-08-24 15:55:05 +03:00
}
2009-09-20 15:47:40 +03:00
void CStackQueue : : update ( )
{
stacksSorted . clear ( ) ;
2010-02-19 18:02:34 +02:00
owner - > curInt - > cb - > getStackQueue ( stacksSorted , QUEUE_SIZE ) ;
2009-09-20 15:47:40 +03:00
for ( int i = 0 ; i < QUEUE_SIZE ; i + + )
{
stackBoxes [ i ] - > setStack ( stacksSorted [ i ] ) ;
}
}
2010-02-19 18:02:34 +02:00
CStackQueue : : CStackQueue ( bool Embedded , CBattleInterface * _owner )
: embedded ( Embedded ) , owner ( _owner )
2009-09-20 15:47:40 +03:00
{
OBJ_CONSTRUCTION_CAPTURING_ALL ;
if ( embedded )
{
box = NULL ;
bg = NULL ;
pos . w = QUEUE_SIZE * 37 ;
pos . h = 32 ; //height of small creature img
pos . x = screen - > w / 2 - pos . w / 2 ;
pos . y = ( screen - > h - 600 ) / 2 + 10 ;
}
else
{
box = BitmapHandler : : loadBitmap ( " CHRROP.pcx " ) ;
bg = BitmapHandler : : loadBitmap ( " DIBOXPI.pcx " ) ;
pos . w = 600 ;
pos . h = bg - > h ;
}
stackBoxes . resize ( QUEUE_SIZE ) ;
for ( int i = 0 ; i < QUEUE_SIZE ; i + + )
{
stackBoxes [ i ] = new StackBox ( box ) ;
stackBoxes [ i ] - > pos . x + = 6 + ( embedded ? 37 : 79 ) * i ;
}
}
CStackQueue : : ~ CStackQueue ( )
{
SDL_FreeSurface ( box ) ;
}
void CStackQueue : : showAll ( SDL_Surface * to )
2009-09-21 11:29:41 +03:00
{
blitBg ( to ) ;
CIntObject : : showAll ( to ) ;
}
void CStackQueue : : blitBg ( SDL_Surface * to )
2009-09-20 15:47:40 +03:00
{
if ( bg )
{
for ( int w = 0 ; w < pos . w ; w + = bg - > w )
{
blitAtLoc ( bg , w , 0 , to ) ;
}
}
}
void CStackQueue : : StackBox : : showAll ( SDL_Surface * to )
{
assert ( my ) ;
if ( bg )
{
graphics - > blueToPlayersAdv ( bg , my - > owner ) ;
2009-10-01 23:00:21 +03:00
//SDL_UpdateRect(bg, 0, 0, 0, 0);
2011-06-11 07:54:41 +03:00
SDL_Rect temp_rect = genRect ( bg - > h , bg - > w , pos . x , pos . y ) ;
CSDL_Ext : : blit8bppAlphaTo24bpp ( bg , NULL , to , & temp_rect ) ;
2009-10-01 23:00:21 +03:00
//blitAt(bg, pos, to);
2010-11-20 19:36:02 +02:00
blitAt ( graphics - > bigImgs [ my - > getCreature ( ) - > idNumber ] , pos . x + 9 , pos . y + 1 , to ) ;
2010-05-02 21:20:26 +03:00
printAtMiddleLoc ( makeNumberShort ( my - > count ) , pos . w / 2 , pos . h - 12 , FONT_MEDIUM , zwykly , to ) ;
2009-09-20 15:47:40 +03:00
}
else
{
blitAt ( graphics - > smallImgs [ - 2 ] , pos , to ) ;
2010-11-20 19:36:02 +02:00
blitAt ( graphics - > smallImgs [ my - > getCreature ( ) - > idNumber ] , pos , to ) ;
2009-09-20 15:47:40 +03:00
const SDL_Color & ownerColor = ( my - > owner = = 255 ? * graphics - > neutralColor : graphics - > playerColors [ my - > owner ] ) ;
CSDL_Ext : : drawBorder ( to , pos , int3 ( ownerColor . r , ownerColor . g , ownerColor . b ) ) ;
2010-05-02 21:20:26 +03:00
printAtMiddleLoc ( makeNumberShort ( my - > count ) , pos . w / 2 , pos . h - 8 , FONT_TINY , zwykly , to ) ;
2009-09-20 15:47:40 +03:00
}
}
void CStackQueue : : StackBox : : setStack ( const CStack * nStack )
{
my = nStack ;
}
CStackQueue : : StackBox : : StackBox ( SDL_Surface * BG )
2010-10-31 00:53:41 +03:00
: my ( NULL ) , bg ( BG )
2009-09-20 15:47:40 +03:00
{
if ( bg )
{
pos . w = bg - > w ;
pos . h = bg - > h ;
}
else
{
pos . w = pos . h = 32 ;
}
pos . y + = 2 ;
}
CStackQueue : : StackBox : : ~ StackBox ( )
{
}
void CStackQueue : : StackBox : : hover ( bool on )
{
2009-10-12 08:00:28 +03:00
}
2011-05-30 17:16:34 +03:00
2011-07-13 21:39:02 +03:00
double CatapultProjectileInfo : : calculateY ( double x )
2011-05-30 17:16:34 +03:00
{
return ( facA * pow ( 10. , - 3. ) ) * pow ( x , 2.0 ) + facB * x + facC ;
}