2008-06-30 03:06:41 +03:00
# define VCMI_DLL
# include <algorithm>
# include <queue>
# include <fstream>
2008-02-25 01:06:27 +02:00
# include "CGameState.h"
2008-06-30 03:06:41 +03:00
# include <boost/random/linear_congruential.hpp>
# include "hch/CDefObjInfoHandler.h"
# include "hch/CArtHandler.h"
2008-12-27 03:01:59 +02:00
# include "hch/CGeneralTextHandler.h"
2008-06-30 03:06:41 +03:00
# include "hch/CTownHandler.h"
2008-08-20 09:57:53 +03:00
# include "hch/CSpellHandler.h"
2008-06-30 03:06:41 +03:00
# include "hch/CHeroHandler.h"
# include "hch/CObjectHandler.h"
# include "hch/CCreatureHandler.h"
# include "lib/VCMI_Lib.h"
# include "map.h"
# include "StartInfo.h"
2008-07-26 16:57:32 +03:00
# include "lib/NetPacks.h"
# include <boost/foreach.hpp>
2008-07-27 20:07:37 +03:00
# include <boost/thread.hpp>
# include <boost/thread/shared_mutex.hpp>
2008-06-30 03:06:41 +03:00
boost : : rand48 ran ;
2008-02-25 01:06:27 +02:00
2008-08-20 09:57:53 +03:00
2008-09-07 06:38:37 +03:00
# ifdef min
# undef min
# endif
# ifdef max
# undef max
# endif
2008-08-20 09:57:53 +03:00
2008-12-27 03:01:59 +02:00
std : : string DLL_EXPORT toString ( MetaString & ms )
{
std : : string ret ;
for ( size_t i = 0 ; i < ms . message . size ( ) ; + + i )
{
if ( ms . message [ i ] > 0 )
{
ret + = ms . strings [ ms . message [ i ] - 1 ] ;
}
else
{
std : : vector < std : : string > * vec ;
int type = ms . texts [ - ms . message [ i ] - 1 ] . first ,
ser = ms . texts [ - ms . message [ i ] - 1 ] . second ;
if ( type = = 5 )
{
ret + = VLC - > arth - > artifacts [ ser ] . Name ( ) ;
continue ;
}
else if ( type = = 7 )
{
ret + = VLC - > creh - > creatures [ ser ] . namePl ;
continue ;
}
else if ( type = = 9 )
{
2009-01-06 20:42:20 +02:00
ret + = VLC - > generaltexth - > mines [ ser ] . first ;
2008-12-27 03:01:59 +02:00
continue ;
}
else if ( type = = 10 )
{
2009-01-06 20:42:20 +02:00
ret + = VLC - > generaltexth - > mines [ ser ] . second ;
2008-12-27 03:01:59 +02:00
continue ;
}
else
{
switch ( type )
{
case 1 :
vec = & VLC - > generaltexth - > allTexts ;
break ;
case 2 :
2009-01-06 20:42:20 +02:00
vec = & VLC - > generaltexth - > xtrainfo ;
2008-12-27 03:01:59 +02:00
break ;
case 3 :
2009-01-06 20:42:20 +02:00
vec = & VLC - > generaltexth - > names ;
2008-12-27 03:01:59 +02:00
break ;
case 4 :
2009-01-06 20:42:20 +02:00
vec = & VLC - > generaltexth - > restypes ;
2008-12-27 03:01:59 +02:00
break ;
case 6 :
vec = & VLC - > generaltexth - > arraytxt ;
break ;
case 8 :
2009-01-06 20:42:20 +02:00
vec = & VLC - > generaltexth - > creGens ;
2008-12-27 03:01:59 +02:00
break ;
case 11 :
2009-01-06 20:42:20 +02:00
vec = & VLC - > generaltexth - > advobtxt ;
2008-12-27 03:01:59 +02:00
break ;
case 12 :
vec = & VLC - > generaltexth - > artifEvents ;
break ;
}
ret + = ( * vec ) [ ser ] ;
}
}
}
for ( size_t i = 0 ; i < ms . replacements . size ( ) ; + + i )
{
ret . replace ( ret . find ( " %s " ) , 2 , ms . replacements [ i ] ) ;
}
return ret ;
}
2008-10-26 22:58:34 +02:00
2008-07-27 20:07:37 +03:00
CGObjectInstance * createObject ( int id , int subid , int3 pos , int owner )
{
CGObjectInstance * nobj ;
switch ( id )
{
2009-02-06 16:15:45 +02:00
case HEROI_TYPE : //hero
2008-07-27 20:07:37 +03:00
{
2008-10-26 22:58:34 +02:00
CGHeroInstance * nobj = new CGHeroInstance ( ) ;
2008-07-27 20:07:37 +03:00
nobj - > pos = pos ;
nobj - > tempOwner = owner ;
nobj - > subID = subid ;
2008-10-26 22:58:34 +02:00
//nobj->initHero(ran);
2008-07-27 20:07:37 +03:00
return nobj ;
}
2009-02-06 16:15:45 +02:00
case TOWNI_TYPE : //town
2008-07-27 20:07:37 +03:00
nobj = new CGTownInstance ;
break ;
default : //rest of objects
nobj = new CGObjectInstance ;
nobj - > defInfo = VLC - > dobjinfo - > gobjs [ id ] [ subid ] ;
break ;
}
nobj - > ID = id ;
nobj - > subID = subid ;
if ( ! nobj - > defInfo )
2008-09-19 15:09:15 +03:00
tlog3 < < " No def declaration for " < < id < < " " < < subid < < std : : endl ;
2008-07-27 20:07:37 +03:00
nobj - > pos = pos ;
//nobj->state = NULL;//new CLuaObjectScript();
nobj - > tempOwner = owner ;
nobj - > info = NULL ;
nobj - > defInfo - > id = id ;
nobj - > defInfo - > subid = subid ;
//assigning defhandler
2009-02-06 16:15:45 +02:00
if ( nobj - > ID = = HEROI_TYPE | | nobj - > ID = = TOWNI_TYPE )
2008-07-27 20:07:37 +03:00
return nobj ;
nobj - > defInfo = VLC - > dobjinfo - > gobjs [ id ] [ subid ] ;
return nobj ;
}
2008-08-05 02:04:15 +03:00
CStack * BattleInfo : : getStack ( int stackID )
{
for ( int g = 0 ; g < stacks . size ( ) ; + + g )
{
if ( stacks [ g ] - > ID = = stackID )
return stacks [ g ] ;
}
return NULL ;
}
CStack * BattleInfo : : getStackT ( int tileID )
{
for ( int g = 0 ; g < stacks . size ( ) ; + + g )
{
if ( stacks [ g ] - > position = = tileID
| | ( stacks [ g ] - > creature - > isDoubleWide ( ) & & stacks [ g ] - > attackerOwned & & stacks [ g ] - > position - 1 = = tileID )
| | ( stacks [ g ] - > creature - > isDoubleWide ( ) & & ! stacks [ g ] - > attackerOwned & & stacks [ g ] - > position + 1 = = tileID ) )
{
2008-09-12 11:51:46 +03:00
if ( stacks [ g ] - > alive ( ) )
2008-08-05 02:04:15 +03:00
{
return stacks [ g ] ;
}
}
}
return NULL ;
}
2008-08-06 20:49:47 +03:00
void BattleInfo : : getAccessibilityMap ( bool * accessibility , int stackToOmmit )
2008-08-05 02:04:15 +03:00
{
2008-11-10 21:06:04 +02:00
memset ( accessibility , 1 , BFIELD_SIZE ) ; //initialize array with trues
2008-08-05 02:04:15 +03:00
for ( int g = 0 ; g < stacks . size ( ) ; + + g )
{
2008-09-12 11:51:46 +03:00
if ( ! stacks [ g ] - > alive ( ) | | stacks [ g ] - > ID = = stackToOmmit ) //we don't want to lock position of this stack
2008-08-05 02:04:15 +03:00
continue ;
accessibility [ stacks [ g ] - > position ] = false ;
if ( stacks [ g ] - > creature - > isDoubleWide ( ) ) //if it's a double hex creature
{
if ( stacks [ g ] - > attackerOwned )
accessibility [ stacks [ g ] - > position - 1 ] = false ;
else
accessibility [ stacks [ g ] - > position + 1 ] = false ;
}
}
2009-02-09 16:50:32 +02:00
//obstacles
for ( int b = 0 ; b < obstacles . size ( ) ; + + b )
{
std : : vector < int > blocked = VLC - > heroh - > obstacles [ obstacles [ b ] . ID ] . getBlocked ( obstacles [ b ] . pos ) ;
for ( int c = 0 ; c < blocked . size ( ) ; + + c )
{
accessibility [ blocked [ c ] ] = false ;
}
}
2008-08-05 02:04:15 +03:00
}
2009-02-05 16:44:27 +02:00
void BattleInfo : : getAccessibilityMapForTwoHex ( bool * accessibility , bool atackerSide , int stackToOmmit , bool addOccupiable ) //send pointer to at least 187 allocated bytes
2008-08-05 02:04:15 +03:00
{
2008-11-10 21:06:04 +02:00
bool mac [ BFIELD_SIZE ] ;
2008-08-06 20:49:47 +03:00
getAccessibilityMap ( mac , stackToOmmit ) ;
2008-11-10 21:06:04 +02:00
memcpy ( accessibility , mac , BFIELD_SIZE ) ;
2008-08-05 02:04:15 +03:00
2009-02-05 16:44:27 +02:00
if ( ! addOccupiable )
2008-08-05 02:04:15 +03:00
{
2009-02-05 16:44:27 +02:00
for ( int b = 0 ; b < BFIELD_SIZE ; + + b )
2008-08-05 02:04:15 +03:00
{
2009-02-05 16:44:27 +02:00
if ( mac [ b ] & & ! ( atackerSide ? mac [ b - 1 ] : mac [ b + 1 ] ) )
{
accessibility [ b ] = false ;
}
2008-08-05 02:04:15 +03:00
}
2008-08-06 02:33:08 +03:00
2009-02-05 16:44:27 +02:00
//removing accessibility for side hexes
for ( int v = 0 ; v < BFIELD_SIZE ; + + v )
if ( atackerSide ? ( v % BFIELD_WIDTH ) = = 1 : ( v % BFIELD_WIDTH ) = = ( BFIELD_WIDTH - 2 ) )
accessibility [ v ] = false ;
}
2008-08-05 02:04:15 +03:00
}
2008-08-06 02:33:08 +03:00
void BattleInfo : : makeBFS ( int start , bool * accessibility , int * predecessor , int * dists ) //both pointers must point to the at least 187-elements int arrays
{
//inits
2008-11-10 21:06:04 +02:00
for ( int b = 0 ; b < BFIELD_SIZE ; + + b )
2008-08-05 02:04:15 +03:00
predecessor [ b ] = - 1 ;
2008-11-10 21:06:04 +02:00
for ( int g = 0 ; g < BFIELD_SIZE ; + + g )
2008-08-06 02:33:08 +03:00
dists [ g ] = 100000000 ;
2008-08-05 02:04:15 +03:00
std : : queue < int > hexq ; //bfs queue
hexq . push ( start ) ;
dists [ hexq . front ( ) ] = 0 ;
int curNext = - 1 ; //for bfs loop only (helper var)
while ( ! hexq . empty ( ) ) //bfs loop
{
int curHex = hexq . front ( ) ;
2008-08-06 20:49:47 +03:00
std : : vector < int > neighbours = neighbouringTiles ( curHex ) ;
2008-08-05 02:04:15 +03:00
hexq . pop ( ) ;
2008-08-06 20:49:47 +03:00
for ( int nr = 0 ; nr < neighbours . size ( ) ; nr + + )
2008-08-05 02:04:15 +03:00
{
2008-08-06 20:49:47 +03:00
curNext = neighbours [ nr ] ;
if ( ! accessibility [ curNext ] | | ( dists [ curHex ] + 1 ) > = dists [ curNext ] )
continue ;
2008-08-05 02:04:15 +03:00
hexq . push ( curNext ) ;
dists [ curNext ] = dists [ curHex ] + 1 ;
predecessor [ curNext ] = curHex ;
}
}
2008-08-06 02:33:08 +03:00
} ;
2009-02-05 16:44:27 +02:00
std : : vector < int > BattleInfo : : getAccessibility ( int stackID , bool addOccupiable )
2008-08-06 02:33:08 +03:00
{
std : : vector < int > ret ;
2008-11-10 21:06:04 +02:00
bool ac [ BFIELD_SIZE ] ;
2008-08-06 02:33:08 +03:00
CStack * s = getStack ( stackID ) ;
if ( s - > creature - > isDoubleWide ( ) )
2009-02-05 16:44:27 +02:00
getAccessibilityMapForTwoHex ( ac , s - > attackerOwned , stackID , addOccupiable ) ;
2008-08-06 02:33:08 +03:00
else
2008-08-06 20:49:47 +03:00
getAccessibilityMap ( ac , stackID ) ;
2008-08-06 02:33:08 +03:00
2008-11-10 21:06:04 +02:00
int pr [ BFIELD_SIZE ] , dist [ BFIELD_SIZE ] ;
2008-08-06 02:33:08 +03:00
makeBFS ( s - > position , ac , pr , dist ) ;
2008-11-10 21:06:04 +02:00
for ( int i = 0 ; i < BFIELD_SIZE ; i + + )
if ( dist [ i ] < = s - > speed ( ) )
2008-08-06 02:33:08 +03:00
ret . push_back ( i ) ;
return ret ;
}
2008-10-11 16:14:52 +03:00
bool BattleInfo : : isStackBlocked ( int ID )
{
CStack * our = getStack ( ID ) ;
for ( int i = 0 ; i < stacks . size ( ) ; i + + )
{
if ( ! stacks [ i ] - > alive ( )
| | stacks [ i ] - > owner = = our - > owner
)
2008-12-08 00:38:04 +02:00
continue ; //we omit dead and allied stacks
2008-11-14 20:18:13 +02:00
if ( stacks [ i ] - > creature - > isDoubleWide ( ) )
{
2008-12-08 00:38:04 +02:00
if ( mutualPosition ( stacks [ i ] - > position , our - > position ) > = 0
| | mutualPosition ( stacks [ i ] - > position + ( stacks [ i ] - > attackerOwned ? - 1 : 1 ) , our - > position ) > = 0 )
2008-11-14 20:18:13 +02:00
return true ;
}
else
{
if ( mutualPosition ( stacks [ i ] - > position , our - > position ) > = 0 )
return true ;
}
2008-10-11 16:14:52 +03:00
}
return false ;
}
2008-08-06 20:49:47 +03:00
signed char BattleInfo : : mutualPosition ( int hex1 , int hex2 )
{
if ( hex2 = = hex1 - ( ( hex1 / 17 ) % 2 ? 18 : 17 ) ) //top left
return 0 ;
if ( hex2 = = hex1 - ( ( hex1 / 17 ) % 2 ? 17 : 16 ) ) //top right
return 1 ;
if ( hex2 = = hex1 - 1 & & hex1 % 17 ! = 0 ) //left
return 5 ;
if ( hex2 = = hex1 + 1 & & hex1 % 17 ! = 16 ) //right
return 2 ;
if ( hex2 = = hex1 + ( ( hex1 / 17 ) % 2 ? 16 : 17 ) ) //bottom left
return 4 ;
if ( hex2 = = hex1 + ( ( hex1 / 17 ) % 2 ? 17 : 18 ) ) //bottom right
return 3 ;
return - 1 ;
}
std : : vector < int > BattleInfo : : neighbouringTiles ( int hex )
{
2008-11-11 17:17:58 +02:00
# define CHECK_AND_PUSH(tile) {int hlp = (tile); if(hlp>=0 && hlp<BFIELD_SIZE && (hlp%BFIELD_WIDTH!=16) && hlp%BFIELD_WIDTH) ret.push_back(hlp);}
2008-08-06 20:49:47 +03:00
std : : vector < int > ret ;
CHECK_AND_PUSH ( hex - ( ( hex / 17 ) % 2 ? 18 : 17 ) ) ;
CHECK_AND_PUSH ( hex - ( ( hex / 17 ) % 2 ? 17 : 16 ) ) ;
CHECK_AND_PUSH ( hex - 1 ) ;
CHECK_AND_PUSH ( hex + 1 ) ;
CHECK_AND_PUSH ( hex + ( ( hex / 17 ) % 2 ? 16 : 17 ) ) ;
CHECK_AND_PUSH ( hex + ( ( hex / 17 ) % 2 ? 17 : 18 ) ) ;
# undef CHECK_AND_PUSH
return ret ;
}
2008-08-06 02:33:08 +03:00
std : : vector < int > BattleInfo : : getPath ( int start , int dest , bool * accessibility )
{
2008-11-10 21:06:04 +02:00
int predecessor [ BFIELD_SIZE ] ; //for getting the Path
int dist [ BFIELD_SIZE ] ; //calculated distances
2008-08-05 02:04:15 +03:00
2008-08-06 02:33:08 +03:00
makeBFS ( start , accessibility , predecessor , dist ) ;
//making the Path
2008-08-05 02:04:15 +03:00
std : : vector < int > path ;
int curElem = dest ;
while ( curElem ! = start )
{
path . push_back ( curElem ) ;
curElem = predecessor [ curElem ] ;
}
return path ;
}
2008-09-09 10:05:02 +03:00
CStack : : CStack ( CCreature * C , int A , int O , int I , bool AO , int S )
2008-12-08 00:38:04 +02:00
: creature ( C ) , amount ( A ) , baseAmount ( A ) , owner ( O ) , position ( - 1 ) , ID ( I ) , attackerOwned ( AO ) , firstHPleft ( C - > hitPoints ) ,
shots ( C - > shots ) , slot ( S ) , counterAttacks ( 1 ) , effects ( ) , state ( )
2008-06-30 03:06:41 +03:00
{
2008-09-14 10:11:07 +03:00
abilities = C - > abilities ;
2008-09-12 11:51:46 +03:00
state . insert ( ALIVE ) ;
2008-06-30 03:06:41 +03:00
}
2008-11-01 00:41:22 +02:00
2008-11-10 21:06:04 +02:00
ui32 CStack : : speed ( ) const
2008-11-09 00:29:19 +02:00
{
int premy = 0 ;
2008-11-10 21:06:04 +02:00
const StackEffect * effect = 0 ;
2008-11-09 00:29:19 +02:00
//haste effect check
effect = getEffect ( 53 ) ;
if ( effect )
premy + = VLC - > spellh - > spells [ effect - > id ] . powers [ effect - > level ] ;
//slow effect check
effect = getEffect ( 54 ) ;
if ( effect )
2009-01-16 19:58:41 +02:00
premy - = ( creature - > speed * VLC - > spellh - > spells [ effect - > id ] . powers [ effect - > level ] ) / 100 ;
2008-11-09 00:29:19 +02:00
//prayer effect check
effect = getEffect ( 48 ) ;
if ( effect )
2008-12-06 18:45:54 +02:00
premy + = VLC - > spellh - > spells [ effect - > id ] . powers [ effect - > level ] ;
2008-11-09 00:29:19 +02:00
//bind effect check
effect = getEffect ( 72 ) ;
if ( effect )
premy = - creature - > speed ;
return creature - > speed + premy ;
}
2008-11-10 21:06:04 +02:00
const CStack : : StackEffect * CStack : : getEffect ( ui16 id ) const
2008-11-09 00:29:19 +02:00
{
for ( int i = 0 ; i < effects . size ( ) ; i + + )
if ( effects [ i ] . id = = id )
return & effects [ i ] ;
return NULL ;
}
2009-02-05 11:49:45 +02:00
si8 CStack : : Morale ( ) const
{
si8 ret = morale ;
2009-02-06 13:50:48 +02:00
if ( getEffect ( 49 ) ) //mirth
{
ret + = VLC - > spellh - > spells [ 49 ] . powers [ getEffect ( 49 ) - > level ] ;
}
if ( getEffect ( 50 ) ) //sorrow
{
ret - = VLC - > spellh - > spells [ 50 ] . powers [ getEffect ( 50 ) - > level ] ;
}
if ( ret > 3 ) ret = 3 ;
if ( ret < - 3 ) ret = - 3 ;
2009-02-05 11:49:45 +02:00
return ret ;
}
si8 CStack : : Luck ( ) const
{
si8 ret = luck ;
2009-02-06 13:50:48 +02:00
if ( getEffect ( 51 ) ) //fortune
{
ret + = VLC - > spellh - > spells [ 51 ] . powers [ getEffect ( 51 ) - > level ] ;
}
if ( getEffect ( 52 ) ) //misfortune
{
ret - = VLC - > spellh - > spells [ 52 ] . powers [ getEffect ( 52 ) - > level ] ;
}
if ( ret > 3 ) ret = 3 ;
if ( ret < - 3 ) ret = - 3 ;
2009-02-05 11:49:45 +02:00
return ret ;
}
2008-11-01 00:41:22 +02:00
CGHeroInstance * CGameState : : HeroesPool : : pickHeroFor ( bool native , int player , const CTown * town , int notThatOne )
{
if ( player < 0 | | player > = PLAYER_LIMIT )
{
2008-12-22 19:48:41 +02:00
tlog1 < < " Cannot pick hero for " < < town - > Name ( ) < < " . Wrong owner! \n " ;
2008-11-01 00:41:22 +02:00
return NULL ;
}
std : : vector < CGHeroInstance * > pool ;
int sum = 0 , r ;
if ( native )
{
for ( std : : map < ui32 , CGHeroInstance * > : : iterator i = heroesPool . begin ( ) ; i ! = heroesPool . end ( ) ; i + + )
{
if ( pavailable [ i - > first ] & 1 < < player
& & i - > second - > type - > heroType / 2 = = town - > typeID
& & i - > second - > subID ! = notThatOne
)
{
pool . push_back ( i - > second ) ;
}
}
if ( ! pool . size ( ) )
return pickHeroFor ( false , player , town , notThatOne ) ;
else
return pool [ rand ( ) % pool . size ( ) ] ;
}
else
{
for ( std : : map < ui32 , CGHeroInstance * > : : iterator i = heroesPool . begin ( ) ; i ! = heroesPool . end ( ) ; i + + )
{
if ( pavailable [ i - > first ] & 1 < < player
& & i - > second - > subID ! = notThatOne
)
{
pool . push_back ( i - > second ) ;
sum + = i - > second - > type - > heroClass - > selectionProbability [ town - > typeID ] ;
}
}
if ( ! pool . size ( ) )
{
tlog1 < < " There are no heroes available for player " < < player < < " ! \n " ;
return NULL ;
}
r = rand ( ) % sum ;
for ( int i = 0 ; i < pool . size ( ) ; i + + )
{
r - = pool [ i ] - > type - > heroClass - > selectionProbability [ town - > typeID ] ;
if ( r < 0 )
return pool [ i ] ;
}
return pool [ pool . size ( ) - 1 ] ;
}
}
2008-08-10 07:46:16 +03:00
void CGameState : : applyNL ( IPack * pack )
2008-07-26 16:57:32 +03:00
{
switch ( pack - > getType ( ) )
{
case 101 : //NewTurn
{
NewTurn * n = static_cast < NewTurn * > ( pack ) ;
day = n - > day ;
BOOST_FOREACH ( NewTurn : : Hero h , n - > heroes ) //give mana/movement point
{
static_cast < CGHeroInstance * > ( map - > objects [ h . id ] ) - > movement = h . move ;
static_cast < CGHeroInstance * > ( map - > objects [ h . id ] ) - > mana = h . mana ;
}
2008-08-10 07:46:16 +03:00
BOOST_FOREACH ( SetResources h , n - > res ) //give resources
applyNL ( & h ) ;
BOOST_FOREACH ( SetAvailableCreatures h , n - > cres ) //set available creatures in towns
applyNL ( & h ) ;
2008-07-26 16:57:32 +03:00
if ( n - > resetBuilded ) //reset amount of structures set in this turn in towns
BOOST_FOREACH ( CGTownInstance * t , map - > towns )
t - > builded = 0 ;
2009-02-06 13:15:39 +02:00
BOOST_FOREACH ( CGHeroInstance * h , map - > heroes )
h - > bonuses . remove_if ( HeroBonus : : OneDay ) ;
if ( getDate ( 1 ) = = 7 ) //new week
BOOST_FOREACH ( CGHeroInstance * h , map - > heroes )
2009-02-07 15:28:23 +02:00
h - > bonuses . remove_if ( HeroBonus : : OneWeek ) ;
2008-07-28 15:44:08 +03:00
break ;
}
2008-07-31 13:35:22 +03:00
case 102 : //set resource amount
{
SetResource * sr = static_cast < SetResource * > ( pack ) ;
players [ sr - > player ] . resources [ sr - > resid ] = sr - > val ;
break ;
}
2008-08-01 14:21:15 +03:00
case 104 :
{
SetResources * sr = static_cast < SetResources * > ( pack ) ;
2008-08-01 21:13:33 +03:00
for ( int i = 0 ; i < sr - > res . size ( ) ; i + + )
2008-08-01 14:21:15 +03:00
players [ sr - > player ] . resources [ i ] = sr - > res [ i ] ;
break ;
}
2008-08-04 18:56:36 +03:00
case 105 :
{
SetPrimSkill * sr = static_cast < SetPrimSkill * > ( pack ) ;
CGHeroInstance * hero = getHero ( sr - > id ) ;
if ( sr - > which < 4 )
{
if ( sr - > abs )
hero - > primSkills [ sr - > which ] = sr - > val ;
else
hero - > primSkills [ sr - > which ] + = sr - > val ;
}
else if ( sr - > which = = 4 ) //XP
{
if ( sr - > abs )
hero - > exp = sr - > val ;
else
hero - > exp + = sr - > val ;
}
break ;
}
2008-08-13 03:44:31 +03:00
case 106 :
{
SetSecSkill * sr = static_cast < SetSecSkill * > ( pack ) ;
CGHeroInstance * hero = getHero ( sr - > id ) ;
2008-09-28 16:29:37 +03:00
if ( hero - > getSecSkillLevel ( sr - > which ) = = 0 )
2008-08-13 03:44:31 +03:00
{
2008-09-28 16:29:37 +03:00
hero - > secSkills . push_back ( std : : pair < int , int > ( sr - > which , sr - > val ) ) ;
2008-08-13 03:44:31 +03:00
}
else
{
for ( unsigned i = 0 ; i < hero - > secSkills . size ( ) ; i + + )
{
if ( hero - > secSkills [ i ] . first = = sr - > which )
{
if ( sr - > abs )
hero - > secSkills [ i ] . second = sr - > val ;
else
hero - > secSkills [ i ] . second + = sr - > val ;
}
}
}
break ;
}
2008-08-13 12:28:06 +03:00
case 108 :
{
HeroVisitCastle * vc = static_cast < HeroVisitCastle * > ( pack ) ;
CGHeroInstance * h = getHero ( vc - > hid ) ;
CGTownInstance * t = getTown ( vc - > tid ) ;
if ( vc - > start ( ) )
{
if ( vc - > garrison ( ) )
{
t - > garrisonHero = h ;
h - > visitedTown = t ;
h - > inTownGarrison = true ;
}
else
{
t - > visitingHero = h ;
h - > visitedTown = t ;
h - > inTownGarrison = false ;
}
}
else
{
if ( vc - > garrison ( ) )
{
t - > garrisonHero = NULL ;
h - > visitedTown = NULL ;
h - > inTownGarrison = false ;
}
else
{
t - > visitingHero = NULL ;
h - > visitedTown = NULL ;
h - > inTownGarrison = false ;
}
}
break ;
}
2008-09-12 11:51:46 +03:00
case 109 :
{
ChangeSpells * rh = static_cast < ChangeSpells * > ( pack ) ;
CGHeroInstance * hero = getHero ( rh - > hid ) ;
if ( rh - > learn )
BOOST_FOREACH ( ui32 sid , rh - > spells )
hero - > spells . insert ( sid ) ;
else
BOOST_FOREACH ( ui32 sid , rh - > spells )
hero - > spells . erase ( sid ) ;
break ;
}
2008-10-19 02:20:48 +03:00
case 110 :
{
SetMana * rh = static_cast < SetMana * > ( pack ) ;
CGHeroInstance * hero = getHero ( rh - > hid ) ;
hero - > mana = rh - > val ;
break ;
}
case 111 :
{
SetMovePoints * rh = static_cast < SetMovePoints * > ( pack ) ;
CGHeroInstance * hero = getHero ( rh - > hid ) ;
hero - > movement = rh - > val ;
break ;
}
case 112 :
{
FoWChange * rh = static_cast < FoWChange * > ( pack ) ;
BOOST_FOREACH ( int3 t , rh - > tiles )
players [ rh - > player ] . fogOfWarMap [ t . x ] [ t . y ] [ t . z ] = rh - > mode ;
break ;
}
2008-10-26 22:58:34 +02:00
case 113 :
{
SetAvailableHeroes * rh = static_cast < SetAvailableHeroes * > ( pack ) ;
players [ rh - > player ] . availableHeroes . clear ( ) ;
2009-02-09 18:18:48 +02:00
CGHeroInstance * h = ( rh - > hid1 > = 0 ? hpool . heroesPool [ rh - > hid1 ] : NULL ) ;
players [ rh - > player ] . availableHeroes . push_back ( h ) ;
if ( h & & rh - > flags & 1 )
2008-11-01 00:41:22 +02:00
{
2009-02-09 18:18:48 +02:00
h - > army . slots . clear ( ) ;
h - > army . slots [ 0 ] = std : : pair < ui32 , si32 > ( VLC - > creh - > nameToID [ h - > type - > refTypeStack [ 0 ] ] , 1 ) ;
2008-11-01 00:41:22 +02:00
}
2009-02-09 18:18:48 +02:00
h = ( rh - > hid2 > = 0 ? hpool . heroesPool [ rh - > hid2 ] : NULL ) ;
players [ rh - > player ] . availableHeroes . push_back ( h ) ;
2008-11-01 00:41:22 +02:00
if ( rh - > flags & 2 )
{
2009-02-09 18:18:48 +02:00
h - > army . slots . clear ( ) ;
h - > army . slots [ 0 ] = std : : pair < ui32 , si32 > ( VLC - > creh - > nameToID [ h - > type - > refTypeStack [ 0 ] ] , 1 ) ;
2008-11-01 00:41:22 +02:00
}
2008-10-26 22:58:34 +02:00
break ;
}
2009-02-03 07:28:05 +02:00
case 115 :
{
GiveBonus * rh = static_cast < GiveBonus * > ( pack ) ;
CGHeroInstance * h = getHero ( rh - > hid ) ;
2009-02-04 15:40:54 +02:00
h - > bonuses . push_back ( rh - > bonus ) ;
h - > bonuses . back ( ) . description = toString ( rh - > bdescr ) ;
2009-02-03 07:28:05 +02:00
break ;
}
2008-08-02 00:41:38 +03:00
case 500 :
{
2008-08-13 07:41:11 +03:00
RemoveObject * rh = static_cast < RemoveObject * > ( pack ) ;
CGObjectInstance * obj = map - > objects [ rh - > id ] ;
2009-02-06 16:15:45 +02:00
if ( obj - > ID = = HEROI_TYPE )
2008-08-13 07:41:11 +03:00
{
CGHeroInstance * h = static_cast < CGHeroInstance * > ( obj ) ;
std : : vector < CGHeroInstance * > : : iterator nitr = std : : find ( map - > heroes . begin ( ) , map - > heroes . end ( ) , h ) ;
map - > heroes . erase ( nitr ) ;
int player = h - > tempOwner ;
nitr = std : : find ( players [ player ] . heroes . begin ( ) , players [ player ] . heroes . end ( ) , h ) ;
players [ player ] . heroes . erase ( nitr ) ;
2008-08-17 12:11:16 +03:00
if ( h - > visitedTown )
{
if ( h - > inTownGarrison )
h - > visitedTown - > garrisonHero = NULL ;
else
h - > visitedTown - > visitingHero = NULL ;
h - > visitedTown = NULL ;
}
2008-08-13 07:41:11 +03:00
}
map - > objects [ rh - > id ] = NULL ;
//unblock tiles
if ( obj - > defInfo )
{
map - > removeBlockVisTiles ( obj ) ;
}
2008-08-02 00:41:38 +03:00
break ;
}
2008-07-28 15:44:08 +03:00
case 501 : //hero try-move
{
TryMoveHero * n = static_cast < TryMoveHero * > ( pack ) ;
CGHeroInstance * h = static_cast < CGHeroInstance * > ( map - > objects [ n - > id ] ) ;
h - > movement = n - > movePoints ;
2008-08-13 07:41:11 +03:00
if ( n - > start ! = n - > end & & n - > result )
{
map - > removeBlockVisTiles ( h ) ;
2008-07-28 15:44:08 +03:00
h - > pos = n - > end ;
2008-08-13 07:41:11 +03:00
map - > addBlockVisTiles ( h ) ;
}
2008-07-28 15:44:08 +03:00
BOOST_FOREACH ( int3 t , n - > fowRevealed )
players [ h - > getOwner ( ) ] . fogOfWarMap [ t . x ] [ t . y ] [ t . z ] = 1 ;
break ;
2008-07-26 16:57:32 +03:00
}
2008-07-31 16:21:42 +03:00
case 502 :
{
SetGarrisons * n = static_cast < SetGarrisons * > ( pack ) ;
for ( std : : map < ui32 , CCreatureSet > : : iterator i = n - > garrs . begin ( ) ; i ! = n - > garrs . end ( ) ; i + + )
2008-08-25 13:25:16 +03:00
{
CArmedInstance * ai = static_cast < CArmedInstance * > ( map - > objects [ i - > first ] ) ;
ai - > army = i - > second ;
2009-02-06 16:15:45 +02:00
if ( ai - > ID = = TOWNI_TYPE & & ( static_cast < CGTownInstance * > ( ai ) ) - > garrisonHero ) //if there is a hero in garrison then we must update also his army
2008-08-25 13:25:16 +03:00
const_cast < CGHeroInstance * > ( ( static_cast < CGTownInstance * > ( ai ) ) - > garrisonHero ) - > army = i - > second ;
2009-02-06 16:15:45 +02:00
else if ( ai - > ID = = HEROI_TYPE )
2008-08-25 13:25:16 +03:00
{
CGHeroInstance * h = static_cast < CGHeroInstance * > ( ai ) ;
if ( h - > visitedTown & & h - > inTownGarrison )
h - > visitedTown - > army = i - > second ;
}
}
2008-07-31 16:21:42 +03:00
break ;
}
2008-08-01 14:21:15 +03:00
case 503 :
{
2008-08-10 07:46:16 +03:00
//SetStrInfo *ssi = static_cast<SetStrInfo*>(pack);
//static_cast<CGTownInstance*>(map->objects[ssi->tid])->strInfo.creatures = ssi->cres;
2008-08-01 14:21:15 +03:00
break ;
}
case 504 :
{
NewStructures * ns = static_cast < NewStructures * > ( pack ) ;
CGTownInstance * t = static_cast < CGTownInstance * > ( map - > objects [ ns - > tid ] ) ;
BOOST_FOREACH ( si32 bid , ns - > bid )
t - > builtBuildings . insert ( bid ) ;
t - > builded = ns - > builded ;
break ;
}
2008-08-10 07:46:16 +03:00
case 506 :
{
SetAvailableCreatures * sac = static_cast < SetAvailableCreatures * > ( pack ) ;
static_cast < CGTownInstance * > ( map - > objects [ sac - > tid ] ) - > strInfo . creatures = sac - > creatures ;
break ;
}
2008-08-16 11:47:41 +03:00
case 508 :
{
SetHeroesInTown * sac = static_cast < SetHeroesInTown * > ( pack ) ;
CGTownInstance * t = getTown ( sac - > tid ) ;
CGHeroInstance * v = getHero ( sac - > visiting ) , * g = getHero ( sac - > garrison ) ;
t - > visitingHero = v ;
t - > garrisonHero = g ;
if ( v )
{
v - > visitedTown = t ;
v - > inTownGarrison = false ;
map - > addBlockVisTiles ( v ) ;
}
if ( g )
{
g - > visitedTown = t ;
g - > inTownGarrison = true ;
map - > removeBlockVisTiles ( g ) ;
}
break ;
}
2008-08-20 22:02:48 +03:00
case 509 :
{
SetHeroArtifacts * sha = static_cast < SetHeroArtifacts * > ( pack ) ;
CGHeroInstance * h = getHero ( sha - > hid ) ;
h - > artifacts = sha - > artifacts ;
h - > artifWorn = sha - > artifWorn ;
break ;
}
2008-12-27 03:01:59 +02:00
case 514 :
{
SetSelection * ss = static_cast < SetSelection * > ( pack ) ;
players [ ss - > player ] . currentSelection = ss - > id ;
break ;
}
2008-10-26 22:58:34 +02:00
case 515 :
{
HeroRecruited * sha = static_cast < HeroRecruited * > ( pack ) ;
CGHeroInstance * h = hpool . heroesPool [ sha - > hid ] ;
CGTownInstance * t = getTown ( sha - > tid ) ;
h - > setOwner ( sha - > player ) ;
h - > pos = sha - > tile ;
h - > movement = h - > maxMovePoints ( true ) ;
hpool . heroesPool . erase ( sha - > hid ) ;
if ( h - > id < 0 )
{
h - > id = map - > objects . size ( ) ;
map - > objects . push_back ( h ) ;
}
else
map - > objects [ h - > id ] = h ;
2009-02-01 16:11:41 +02:00
h - > initHeroDefInfo ( ) ;
2008-10-26 22:58:34 +02:00
map - > heroes . push_back ( h ) ;
players [ h - > tempOwner ] . heroes . push_back ( h ) ;
map - > addBlockVisTiles ( h ) ;
t - > visitingHero = h ;
h - > visitedTown = t ;
h - > inTownGarrison = false ;
break ;
}
2008-07-30 20:51:19 +03:00
case 1001 : //set object property
{
SetObjectProperty * p = static_cast < SetObjectProperty * > ( pack ) ;
2008-12-27 03:01:59 +02:00
setObjProperty ( p ) ;
break ;
}
case 1002 :
{
SetHoverName * shn = static_cast < SetHoverName * > ( pack ) ;
map - > objects [ shn - > id ] - > hoverName = toString ( shn - > name ) ;
2008-07-30 20:51:19 +03:00
break ;
}
2008-08-13 03:44:31 +03:00
case 2000 :
{
HeroLevelUp * bs = static_cast < HeroLevelUp * > ( pack ) ;
getHero ( bs - > heroid ) - > level = bs - > level ;
break ;
}
2008-08-04 18:56:36 +03:00
case 3000 :
{
BattleStart * bs = static_cast < BattleStart * > ( pack ) ;
curB = bs - > info ;
break ;
}
case 3001 :
{
BattleNextRound * ns = static_cast < BattleNextRound * > ( pack ) ;
curB - > round = ns - > round ;
2008-09-12 11:51:46 +03:00
for ( int i = 0 ; i < curB - > stacks . size ( ) ; i + + )
2008-11-15 17:26:08 +02:00
{
curB - > stacks [ i ] - > state - = DEFENDING ;
curB - > stacks [ i ] - > state - = WAITING ;
curB - > stacks [ i ] - > state - = MOVED ;
curB - > stacks [ i ] - > state - = HAD_MORALE ;
2008-09-23 13:58:54 +03:00
curB - > stacks [ i ] - > counterAttacks = 1 ;
2008-11-15 17:26:08 +02:00
}
2008-08-04 18:56:36 +03:00
break ;
}
case 3002 :
{
BattleSetActiveStack * ns = static_cast < BattleSetActiveStack * > ( pack ) ;
curB - > activeStack = ns - > stack ;
2009-02-05 11:49:45 +02:00
CStack * st = curB - > getStack ( ns - > stack ) ;
if ( vstd : : contains ( st - > state , MOVED ) )
st - > state . insert ( HAD_MORALE ) ;
2008-08-04 18:56:36 +03:00
break ;
}
case 3003 :
{
BattleResult * br = static_cast < BattleResult * > ( pack ) ;
for ( unsigned i = 0 ; i < curB - > stacks . size ( ) ; i + + )
delete curB - > stacks [ i ] ;
delete curB ;
curB = NULL ;
2008-08-05 02:04:15 +03:00
break ;
}
case 3004 :
{
BattleStackMoved * br = static_cast < BattleStackMoved * > ( pack ) ;
curB - > getStack ( br - > stack ) - > position = br - > tile ;
break ;
2008-08-04 18:56:36 +03:00
}
2008-08-09 02:02:32 +03:00
case 3005 :
{
BattleStackAttacked * br = static_cast < BattleStackAttacked * > ( pack ) ;
CStack * at = curB - > getStack ( br - > stackAttacked ) ;
at - > amount = br - > newAmount ;
at - > firstHPleft = br - > newHP ;
2008-09-12 11:51:46 +03:00
if ( br - > killed ( ) )
at - > state - = ALIVE ;
2008-08-09 02:02:32 +03:00
break ;
}
case 3006 :
{
BattleAttack * br = static_cast < BattleAttack * > ( pack ) ;
2008-11-01 00:41:22 +02:00
CStack * attacker = curB - > getStack ( br - > stackAttacking ) ;
2008-09-12 11:51:46 +03:00
if ( br - > counter ( ) )
2008-11-01 00:41:22 +02:00
attacker - > counterAttacks - - ;
if ( br - > shot ( ) )
attacker - > shots - - ;
2008-08-10 07:46:16 +03:00
applyNL ( & br - > bsa ) ;
2008-08-09 02:02:32 +03:00
break ;
}
2008-11-15 17:26:08 +02:00
case 3007 :
{
StartAction * br = static_cast < StartAction * > ( pack ) ;
CStack * st = curB - > getStack ( br - > ba . stackNumber ) ;
switch ( br - > ba . actionType )
{
case 3 :
st - > state . insert ( DEFENDING ) ;
break ;
case 8 :
st - > state . insert ( WAITING ) ;
break ;
2009-02-05 11:49:45 +02:00
case 2 : case 6 : case 7 : case 9 : case 10 : case 11 :
2008-11-15 17:26:08 +02:00
st - > state . insert ( MOVED ) ;
break ;
}
break ;
}
2008-10-18 14:41:24 +03:00
case 3009 :
{
SpellCasted * sc = static_cast < SpellCasted * > ( pack ) ;
CGHeroInstance * h = ( sc - > side ) ? getHero ( curB - > hero2 ) : getHero ( curB - > hero1 ) ;
if ( h )
h - > mana - = VLC - > spellh - > spells [ sc - > id ] . costs [ sc - > skill ] ;
//TODO: counter
break ;
}
2008-11-09 00:29:19 +02:00
case 3010 :
{
SetStackEffect * sc = static_cast < SetStackEffect * > ( pack ) ;
CStack * stack = curB - > getStack ( sc - > stack ) ;
stack - > effects . push_back ( sc - > effect ) ;
break ;
}
2008-07-26 16:57:32 +03:00
}
2008-08-10 07:46:16 +03:00
}
void CGameState : : apply ( IPack * pack )
{
2008-08-26 00:14:00 +03:00
while ( ! mx - > try_lock ( ) )
boost : : this_thread : : sleep ( boost : : posix_time : : milliseconds ( 50 ) ) ; //give other threads time to finish
2008-08-10 07:46:16 +03:00
applyNL ( pack ) ;
2008-07-27 20:07:37 +03:00
mx - > unlock ( ) ;
2008-07-26 16:57:32 +03:00
}
2008-06-30 03:06:41 +03:00
int CGameState : : pickHero ( int owner )
{
int h = - 1 ;
2008-08-30 00:41:32 +03:00
if ( ! map - > getHero ( h = scenarioOps - > getIthPlayersSettings ( owner ) . hero , 0 ) & & h > = 0 ) //we haven't used selected hero
2008-06-30 03:06:41 +03:00
return h ;
int f = scenarioOps - > getIthPlayersSettings ( owner ) . castle ;
int i = 0 ;
do //try to find free hero of our faction
{
i + + ;
h = scenarioOps - > getIthPlayersSettings ( owner ) . castle * HEROES_PER_TYPE * 2 + ( ran ( ) % ( HEROES_PER_TYPE * 2 ) ) ; //->scenarioOps->playerInfos[pru].hero = VLC->
} while ( map - > getHero ( h ) & & i < 175 ) ;
if ( i > 174 ) //probably no free heroes - there's no point in further search, we'll take first free
{
2008-09-19 15:09:15 +03:00
tlog3 < < " Warning: cannot find free hero - trying to get first available... " < < std : : endl ;
2008-06-30 03:06:41 +03:00
for ( int j = 0 ; j < HEROES_PER_TYPE * 2 * F_NUMBER ; j + + )
if ( ! map - > getHero ( j ) )
h = j ;
}
return h ;
}
2008-08-04 18:56:36 +03:00
CGHeroInstance * CGameState : : getHero ( int objid )
{
if ( objid < 0 | | objid > = map - > objects . size ( ) )
return NULL ;
return static_cast < CGHeroInstance * > ( map - > objects [ objid ] ) ;
}
2008-08-13 12:28:06 +03:00
CGTownInstance * CGameState : : getTown ( int objid )
{
if ( objid < 0 | | objid > = map - > objects . size ( ) )
return NULL ;
return static_cast < CGTownInstance * > ( map - > objects [ objid ] ) ;
}
2008-06-30 03:06:41 +03:00
std : : pair < int , int > CGameState : : pickObject ( CGObjectInstance * obj )
2008-02-25 01:06:27 +02:00
{
2008-06-30 03:06:41 +03:00
switch ( obj - > ID )
{
case 65 : //random artifact
return std : : pair < int , int > ( 5 , ( ran ( ) % 136 ) + 7 ) ; //tylko sensowny zakres - na poczatku sa katapulty itp, na koncu specjalne i blanki
case 66 : //random treasure artifact
return std : : pair < int , int > ( 5 , VLC - > arth - > treasures [ ran ( ) % VLC - > arth - > treasures . size ( ) ] - > id ) ;
case 67 : //random minor artifact
return std : : pair < int , int > ( 5 , VLC - > arth - > minors [ ran ( ) % VLC - > arth - > minors . size ( ) ] - > id ) ;
case 68 : //random major artifact
return std : : pair < int , int > ( 5 , VLC - > arth - > majors [ ran ( ) % VLC - > arth - > majors . size ( ) ] - > id ) ;
case 69 : //random relic artifact
return std : : pair < int , int > ( 5 , VLC - > arth - > relics [ ran ( ) % VLC - > arth - > relics . size ( ) ] - > id ) ;
case 70 : //random hero
{
2009-02-06 16:15:45 +02:00
return std : : pair < int , int > ( HEROI_TYPE , pickHero ( obj - > tempOwner ) ) ;
2008-06-30 03:06:41 +03:00
}
case 71 : //random monster
2008-08-30 00:41:32 +03:00
{
int r ;
do
{
r = ran ( ) % 197 ;
} while ( vstd : : contains ( VLC - > creh - > notUsedMonsters , r ) ) ;
return std : : pair < int , int > ( 54 , r ) ;
}
2008-06-30 03:06:41 +03:00
case 72 : //random monster lvl1
return std : : pair < int , int > ( 54 , VLC - > creh - > levelCreatures [ 1 ] [ ran ( ) % VLC - > creh - > levelCreatures [ 1 ] . size ( ) ] - > idNumber ) ;
case 73 : //random monster lvl2
return std : : pair < int , int > ( 54 , VLC - > creh - > levelCreatures [ 2 ] [ ran ( ) % VLC - > creh - > levelCreatures [ 2 ] . size ( ) ] - > idNumber ) ;
case 74 : //random monster lvl3
return std : : pair < int , int > ( 54 , VLC - > creh - > levelCreatures [ 3 ] [ ran ( ) % VLC - > creh - > levelCreatures [ 3 ] . size ( ) ] - > idNumber ) ;
case 75 : //random monster lvl4
return std : : pair < int , int > ( 54 , VLC - > creh - > levelCreatures [ 4 ] [ ran ( ) % VLC - > creh - > levelCreatures [ 4 ] . size ( ) ] - > idNumber ) ;
case 76 : //random resource
return std : : pair < int , int > ( 79 , ran ( ) % 7 ) ; //now it's OH3 style, use %8 for mithril
case 77 : //random town
{
int align = ( ( CGTownInstance * ) obj ) - > alignment ,
f ;
if ( align > PLAYER_LIMIT - 1 ) //same as owner / random
{
if ( obj - > tempOwner > PLAYER_LIMIT - 1 )
f = - 1 ; //random
else
f = scenarioOps - > getIthPlayersSettings ( obj - > tempOwner ) . castle ;
}
else
{
f = scenarioOps - > getIthPlayersSettings ( align ) . castle ;
}
if ( f < 0 ) f = ran ( ) % VLC - > townh - > towns . size ( ) ;
2009-02-06 16:15:45 +02:00
return std : : pair < int , int > ( TOWNI_TYPE , f ) ;
2008-06-30 03:06:41 +03:00
}
case 162 : //random monster lvl5
return std : : pair < int , int > ( 54 , VLC - > creh - > levelCreatures [ 5 ] [ ran ( ) % VLC - > creh - > levelCreatures [ 5 ] . size ( ) ] - > idNumber ) ;
case 163 : //random monster lvl6
return std : : pair < int , int > ( 54 , VLC - > creh - > levelCreatures [ 6 ] [ ran ( ) % VLC - > creh - > levelCreatures [ 6 ] . size ( ) ] - > idNumber ) ;
case 164 : //random monster lvl7
return std : : pair < int , int > ( 54 , VLC - > creh - > levelCreatures [ 7 ] [ ran ( ) % VLC - > creh - > levelCreatures [ 7 ] . size ( ) ] - > idNumber ) ;
case 216 : //random dwelling
{
int faction = ran ( ) % F_NUMBER ;
CCreGen2ObjInfo * info = ( CCreGen2ObjInfo * ) obj - > info ;
if ( info - > asCastle )
{
for ( int i = 0 ; i < map - > objects . size ( ) ; i + + )
{
if ( map - > objects [ i ] - > ID = = 77 & & dynamic_cast < CGTownInstance * > ( map - > objects [ i ] ) - > identifier = = info - > identifier )
{
randomizeObject ( map - > objects [ i ] ) ; //we have to randomize the castle first
faction = map - > objects [ i ] - > subID ;
break ;
}
2009-02-06 16:15:45 +02:00
else if ( map - > objects [ i ] - > ID = = TOWNI_TYPE & & dynamic_cast < CGTownInstance * > ( map - > objects [ i ] ) - > identifier = = info - > identifier )
2008-06-30 03:06:41 +03:00
{
faction = map - > objects [ i ] - > subID ;
break ;
}
}
}
else
{
while ( ( ! ( info - > castles [ 0 ] & ( 1 < < faction ) ) ) )
{
if ( ( faction > 7 ) & & ( info - > castles [ 1 ] & ( 1 < < ( faction - 8 ) ) ) )
break ;
faction = ran ( ) % F_NUMBER ;
}
}
int level = ( ( info - > maxLevel - info - > minLevel ) ? ( ran ( ) % ( info - > maxLevel - info - > minLevel ) + info - > minLevel ) : ( info - > minLevel ) ) ;
int cid = VLC - > townh - > towns [ faction ] . basicCreatures [ level ] ;
for ( int i = 0 ; i < VLC - > objh - > cregens . size ( ) ; i + + )
if ( VLC - > objh - > cregens [ i ] = = cid )
return std : : pair < int , int > ( 17 , i ) ;
2008-09-19 15:09:15 +03:00
tlog3 < < " Cannot find a dwelling for creature " < < cid < < std : : endl ;
2008-06-30 03:06:41 +03:00
return std : : pair < int , int > ( 17 , 0 ) ;
}
case 217 :
{
int faction = ran ( ) % F_NUMBER ;
CCreGenObjInfo * info = ( CCreGenObjInfo * ) obj - > info ;
if ( info - > asCastle )
{
for ( int i = 0 ; i < map - > objects . size ( ) ; i + + )
{
if ( map - > objects [ i ] - > ID = = 77 & & dynamic_cast < CGTownInstance * > ( map - > objects [ i ] ) - > identifier = = info - > identifier )
{
randomizeObject ( map - > objects [ i ] ) ; //we have to randomize the castle first
faction = map - > objects [ i ] - > subID ;
break ;
}
2009-02-06 16:15:45 +02:00
else if ( map - > objects [ i ] - > ID = = TOWNI_TYPE & & dynamic_cast < CGTownInstance * > ( map - > objects [ i ] ) - > identifier = = info - > identifier )
2008-06-30 03:06:41 +03:00
{
faction = map - > objects [ i ] - > subID ;
break ;
}
}
}
else
{
while ( ( ! ( info - > castles [ 0 ] & ( 1 < < faction ) ) ) )
{
if ( ( faction > 7 ) & & ( info - > castles [ 1 ] & ( 1 < < ( faction - 8 ) ) ) )
break ;
faction = ran ( ) % F_NUMBER ;
}
}
int cid = VLC - > townh - > towns [ faction ] . basicCreatures [ obj - > subID ] ;
for ( int i = 0 ; i < VLC - > objh - > cregens . size ( ) ; i + + )
if ( VLC - > objh - > cregens [ i ] = = cid )
return std : : pair < int , int > ( 17 , i ) ;
2008-09-19 15:09:15 +03:00
tlog3 < < " Cannot find a dwelling for creature " < < cid < < std : : endl ;
2008-06-30 03:06:41 +03:00
return std : : pair < int , int > ( 17 , 0 ) ;
}
case 218 :
{
CCreGen3ObjInfo * info = ( CCreGen3ObjInfo * ) obj - > info ;
int level = ( ( info - > maxLevel - info - > minLevel ) ? ( ran ( ) % ( info - > maxLevel - info - > minLevel ) + info - > minLevel ) : ( info - > minLevel ) ) ;
int cid = VLC - > townh - > towns [ obj - > subID ] . basicCreatures [ level ] ;
for ( int i = 0 ; i < VLC - > objh - > cregens . size ( ) ; i + + )
if ( VLC - > objh - > cregens [ i ] = = cid )
return std : : pair < int , int > ( 17 , i ) ;
2008-09-19 15:09:15 +03:00
tlog3 < < " Cannot find a dwelling for creature " < < cid < < std : : endl ;
2008-06-30 03:06:41 +03:00
return std : : pair < int , int > ( 17 , 0 ) ;
}
}
return std : : pair < int , int > ( - 1 , - 1 ) ;
}
void CGameState : : randomizeObject ( CGObjectInstance * cur )
{
std : : pair < int , int > ran = pickObject ( cur ) ;
if ( ran . first < 0 | | ran . second < 0 ) //this is not a random object, or we couldn't find anything
{
2009-02-06 16:15:45 +02:00
if ( cur - > ID = = TOWNI_TYPE ) //town - set def
2008-06-30 03:06:41 +03:00
{
CGTownInstance * t = dynamic_cast < CGTownInstance * > ( cur ) ;
if ( t - > hasCapitol ( ) )
t - > defInfo = capitols [ t - > subID ] ;
else if ( t - > hasFort ( ) )
t - > defInfo = forts [ t - > subID ] ;
else
t - > defInfo = villages [ t - > subID ] ;
}
return ;
}
2009-02-06 16:15:45 +02:00
else if ( ran . first = = HEROI_TYPE ) //special code for hero
2008-06-30 03:06:41 +03:00
{
CGHeroInstance * h = dynamic_cast < CGHeroInstance * > ( cur ) ;
2008-09-19 15:09:15 +03:00
if ( ! h ) { tlog2 < < " Wrong random hero at " < < cur - > pos < < std : : endl ; return ; }
2008-06-30 03:06:41 +03:00
cur - > ID = ran . first ;
2008-08-06 01:11:32 +03:00
h - > portrait = cur - > subID = ran . second ;
2008-06-30 03:06:41 +03:00
h - > type = VLC - > heroh - > heroes [ ran . second ] ;
map - > heroes . push_back ( h ) ;
return ; //TODO: maybe we should do something with definfo?
}
2009-02-06 16:15:45 +02:00
else if ( ran . first = = TOWNI_TYPE ) //special code for town
2008-06-30 03:06:41 +03:00
{
CGTownInstance * t = dynamic_cast < CGTownInstance * > ( cur ) ;
2008-09-19 15:09:15 +03:00
if ( ! t ) { tlog2 < < " Wrong random town at " < < cur - > pos < < std : : endl ; return ; }
2008-06-30 03:06:41 +03:00
cur - > ID = ran . first ;
cur - > subID = ran . second ;
t - > town = & VLC - > townh - > towns [ ran . second ] ;
if ( t - > hasCapitol ( ) )
t - > defInfo = capitols [ t - > subID ] ;
else if ( t - > hasFort ( ) )
t - > defInfo = forts [ t - > subID ] ;
else
t - > defInfo = villages [ t - > subID ] ;
map - > towns . push_back ( t ) ;
return ;
}
//we have to replace normal random object
cur - > ID = ran . first ;
cur - > subID = ran . second ;
2009-01-06 20:42:20 +02:00
map - > defy . push_back ( cur - > defInfo = VLC - > dobjinfo - > gobjs [ ran . first ] [ ran . second ] ) ;
2008-08-06 01:11:32 +03:00
if ( ! cur - > defInfo )
{
2008-09-19 15:09:15 +03:00
tlog1 < < " *BIG* WARNING: Missing def declaration for " < < cur - > ID < < " " < < cur - > subID < < std : : endl ;
2008-08-06 01:11:32 +03:00
return ;
}
2008-06-30 03:06:41 +03:00
}
2008-07-25 20:28:28 +03:00
int CGameState : : getDate ( int mode ) const
{
int temp ;
switch ( mode )
{
case 0 :
return day ;
break ;
case 1 :
temp = ( day ) % 7 ;
if ( temp )
return temp ;
else return 7 ;
break ;
case 2 :
temp = ( ( day - 1 ) / 7 ) + 1 ;
if ( ! ( temp % 4 ) )
return 4 ;
else
return ( temp % 4 ) ;
break ;
case 3 :
return ( ( day - 1 ) / 28 ) + 1 ;
break ;
}
return 0 ;
}
2008-07-27 20:07:37 +03:00
CGameState : : CGameState ( )
{
mx = new boost : : shared_mutex ( ) ;
2009-01-11 00:08:18 +02:00
map = NULL ;
curB = NULL ;
scenarioOps = NULL ;
2008-07-27 20:07:37 +03:00
}
CGameState : : ~ CGameState ( )
{
delete mx ;
2009-01-11 00:08:18 +02:00
delete map ;
delete curB ;
delete scenarioOps ;
2008-07-27 20:07:37 +03:00
}
2008-07-25 20:28:28 +03:00
void CGameState : : init ( StartInfo * si , Mapa * map , int Seed )
2008-06-30 03:06:41 +03:00
{
2008-07-26 16:57:32 +03:00
day = 0 ;
2008-07-25 20:28:28 +03:00
seed = Seed ;
2008-08-04 18:56:36 +03:00
ran . seed ( ( boost : : int32_t ) seed ) ;
2008-06-30 03:06:41 +03:00
scenarioOps = si ;
this - > map = map ;
2008-11-28 03:36:34 +02:00
loadTownDInfos ( ) ;
2008-06-30 03:06:41 +03:00
//picking random factions for players
for ( int i = 0 ; i < scenarioOps - > playerInfos . size ( ) ; i + + )
{
if ( scenarioOps - > playerInfos [ i ] . castle = = - 1 )
{
int f ;
do
{
f = ran ( ) % F_NUMBER ;
} while ( ! ( map - > players [ scenarioOps - > playerInfos [ i ] . color ] . allowedFactions & 1 < < f ) ) ;
scenarioOps - > playerInfos [ i ] . castle = f ;
}
}
//randomizing objects
for ( int no = 0 ; no < map - > objects . size ( ) ; + + no )
{
randomizeObject ( map - > objects [ no ] ) ;
if ( map - > objects [ no ] - > ID = = 26 )
2008-09-20 21:30:37 +03:00
{
2008-06-30 03:06:41 +03:00
map - > objects [ no ] - > defInfo - > handler = NULL ;
2008-09-20 21:30:37 +03:00
map - > removeBlockVisTiles ( map - > objects [ no ] ) ;
map - > objects [ no ] - > defInfo - > blockMap [ 5 ] = 255 ;
map - > addBlockVisTiles ( map - > objects [ no ] ) ;
}
2009-01-06 20:42:20 +02:00
map - > objects [ no ] - > hoverName = VLC - > generaltexth - > names [ map - > objects [ no ] - > ID ] ;
2008-06-30 03:06:41 +03:00
}
//std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
2008-08-27 13:19:18 +03:00
/*********give starting hero****************************************/
2008-07-27 20:07:37 +03:00
for ( int i = 0 ; i < PLAYER_LIMIT ; i + + )
{
if ( ( map - > players [ i ] . generateHeroAtMainTown & & map - > players [ i ] . hasMainTown ) | | ( map - > players [ i ] . hasMainTown & & map - > version = = RoE ) )
{
int3 hpos = map - > players [ i ] . posOfMainTown ;
hpos . x + = 1 ; // hpos.y+=1;
int j ;
for ( j = 0 ; j < scenarioOps - > playerInfos . size ( ) ; j + + )
if ( scenarioOps - > playerInfos [ j ] . color = = i )
break ;
if ( j = = scenarioOps - > playerInfos . size ( ) )
continue ;
int h = pickHero ( i ) ;
2009-02-06 16:15:45 +02:00
CGHeroInstance * nnn = static_cast < CGHeroInstance * > ( createObject ( HEROI_TYPE , h , hpos , i ) ) ;
2008-07-27 20:07:37 +03:00
nnn - > id = map - > objects . size ( ) ;
2008-08-13 12:28:06 +03:00
hpos = map - > players [ i ] . posOfMainTown ; hpos . x + = 2 ;
for ( int o = 0 ; o < map - > towns . size ( ) ; o + + ) //find main town
{
if ( map - > towns [ o ] - > pos = = hpos )
{
map - > towns [ o ] - > visitingHero = nnn ;
nnn - > visitedTown = map - > towns [ o ] ;
nnn - > inTownGarrison = false ;
break ;
}
}
2008-10-26 22:58:34 +02:00
nnn - > initHero ( ) ;
2008-07-27 20:07:37 +03:00
map - > heroes . push_back ( nnn ) ;
map - > objects . push_back ( nnn ) ;
2008-09-17 13:18:22 +03:00
map - > addBlockVisTiles ( nnn ) ;
2008-07-27 20:07:37 +03:00
}
}
2008-06-30 03:06:41 +03:00
/*********creating players entries in gs****************************************/
for ( int i = 0 ; i < scenarioOps - > playerInfos . size ( ) ; i + + )
{
std : : pair < int , PlayerState > ins ( scenarioOps - > playerInfos [ i ] . color , PlayerState ( ) ) ;
ins . second . color = ins . first ;
ins . second . serial = i ;
players . insert ( ins ) ;
}
/******************RESOURCES****************************************************/
2008-08-27 13:19:18 +03:00
//TODO: computer player should receive other amount of resource than computer (depending on difficulty)
2008-06-30 03:06:41 +03:00
std : : vector < int > startres ;
std : : ifstream tis ( " config/startres.txt " ) ;
int k ;
for ( int j = 0 ; j < scenarioOps - > difficulty ; j + + )
{
tis > > k ;
for ( int z = 0 ; z < RESOURCE_QUANTITY ; z + + )
tis > > k ;
}
tis > > k ;
for ( int i = 0 ; i < RESOURCE_QUANTITY ; i + + )
{
tis > > k ;
startres . push_back ( k ) ;
}
tis . close ( ) ;
2008-09-07 06:38:37 +03:00
tis . clear ( ) ;
2008-07-25 20:28:28 +03:00
for ( std : : map < ui8 , PlayerState > : : iterator i = players . begin ( ) ; i ! = players . end ( ) ; i + + )
2008-06-30 03:06:41 +03:00
{
( * i ) . second . resources . resize ( RESOURCE_QUANTITY ) ;
for ( int x = 0 ; x < RESOURCE_QUANTITY ; x + + )
( * i ) . second . resources [ x ] = startres [ x ] ;
}
2008-09-07 06:38:37 +03:00
tis . open ( " config/resources.txt " ) ;
tis > > k ;
int pom ;
for ( int i = 0 ; i < k ; i + + )
{
tis > > pom ;
resVals . push_back ( pom ) ;
}
2008-06-30 03:06:41 +03:00
/*************************HEROES************************************************/
2008-10-26 22:58:34 +02:00
std : : set < int > hids ;
for ( int i = 0 ; i < map - > allowedHeroes . size ( ) ; i + + ) //add to hids all allowed heroes
if ( map - > allowedHeroes [ i ] )
hids . insert ( i ) ;
2009-01-06 20:42:20 +02:00
for ( int i = 0 ; i < map - > heroes . size ( ) ; i + + ) //heroes instances initialization
2008-06-30 03:06:41 +03:00
{
if ( map - > heroes [ i ] - > getOwner ( ) < 0 )
{
2008-10-26 22:58:34 +02:00
tlog2 < < " Warning - hero with uninitialized owner! \n " ;
continue ;
2008-06-30 03:06:41 +03:00
}
2008-10-26 22:58:34 +02:00
CGHeroInstance * vhi = ( map - > heroes [ i ] ) ;
vhi - > initHero ( ) ;
2008-12-22 19:48:41 +02:00
players . find ( vhi - > getOwner ( ) ) - > second . heroes . push_back ( vhi ) ;
2008-10-26 22:58:34 +02:00
hids . erase ( vhi - > subID ) ;
}
for ( int i = 0 ; i < map - > predefinedHeroes . size ( ) ; i + + )
{
if ( ! vstd : : contains ( hids , map - > predefinedHeroes [ i ] - > subID ) )
continue ;
map - > predefinedHeroes [ i ] - > initHero ( ) ;
hpool . heroesPool [ map - > predefinedHeroes [ i ] - > subID ] = map - > predefinedHeroes [ i ] ;
hpool . pavailable [ map - > predefinedHeroes [ i ] - > subID ] = 0xff ;
hids . erase ( map - > predefinedHeroes [ i ] - > subID ) ;
}
BOOST_FOREACH ( int hid , hids ) //all not used allowed heroes go into the pool
{
CGHeroInstance * vhi = new CGHeroInstance ( ) ;
vhi - > initHero ( hid ) ;
hpool . heroesPool [ hid ] = vhi ;
hpool . pavailable [ hid ] = 0xff ;
}
for ( int i = 0 ; i < map - > disposedHeroes . size ( ) ; i + + )
{
hpool . pavailable [ map - > disposedHeroes [ i ] . ID ] = map - > disposedHeroes [ i ] . players ;
2008-06-30 03:06:41 +03:00
}
/*************************FOG**OF**WAR******************************************/
2008-07-25 20:28:28 +03:00
for ( std : : map < ui8 , PlayerState > : : iterator k = players . begin ( ) ; k ! = players . end ( ) ; + + k )
2008-06-30 03:06:41 +03:00
{
k - > second . fogOfWarMap . resize ( map - > width ) ;
for ( int g = 0 ; g < map - > width ; + + g )
k - > second . fogOfWarMap [ g ] . resize ( map - > height ) ;
for ( int g = - 0 ; g < map - > width ; + + g )
for ( int h = 0 ; h < map - > height ; + + h )
k - > second . fogOfWarMap [ g ] [ h ] . resize ( map - > twoLevel + 1 , 0 ) ;
for ( int g = 0 ; g < map - > width ; + + g )
for ( int h = 0 ; h < map - > height ; + + h )
for ( int v = 0 ; v < map - > twoLevel + 1 ; + + v )
k - > second . fogOfWarMap [ g ] [ h ] [ v ] = 0 ;
for ( int xd = 0 ; xd < map - > width ; + + xd ) //revealing part of map around heroes
{
for ( int yd = 0 ; yd < map - > height ; + + yd )
{
for ( int ch = 0 ; ch < k - > second . heroes . size ( ) ; + + ch )
{
int deltaX = ( k - > second . heroes [ ch ] - > getPosition ( false ) . x - xd ) * ( k - > second . heroes [ ch ] - > getPosition ( false ) . x - xd ) ;
int deltaY = ( k - > second . heroes [ ch ] - > getPosition ( false ) . y - yd ) * ( k - > second . heroes [ ch ] - > getPosition ( false ) . y - yd ) ;
if ( deltaX + deltaY < k - > second . heroes [ ch ] - > getSightDistance ( ) * k - > second . heroes [ ch ] - > getSightDistance ( ) )
k - > second . fogOfWarMap [ xd ] [ yd ] [ k - > second . heroes [ ch ] - > getPosition ( false ) . z ] = 1 ;
}
}
}
2008-08-26 00:14:00 +03:00
//starting bonus
if ( si - > playerInfos [ k - > second . serial ] . bonus = = brandom )
si - > playerInfos [ k - > second . serial ] . bonus = ran ( ) % 3 ;
switch ( si - > playerInfos [ k - > second . serial ] . bonus )
{
case bgold :
k - > second . resources [ 6 ] + = 500 + ( ran ( ) % 6 ) * 100 ;
break ;
case bresource :
{
int res = VLC - > townh - > towns [ si - > playerInfos [ k - > second . serial ] . castle ] . primaryRes ;
if ( res = = 127 )
{
k - > second . resources [ 0 ] + = 5 + ran ( ) % 6 ;
k - > second . resources [ 2 ] + = 5 + ran ( ) % 6 ;
}
else
{
k - > second . resources [ res ] + = 3 + ran ( ) % 4 ;
}
break ;
}
case bartifact :
{
2008-08-27 13:19:18 +03:00
if ( ! k - > second . heroes . size ( ) )
2008-08-26 00:14:00 +03:00
{
2008-09-19 15:09:15 +03:00
tlog5 < < " Cannot give starting artifact - no heroes! " < < std : : endl ;
2008-08-26 00:14:00 +03:00
break ;
}
CArtifact * toGive ;
do
{
2008-08-27 13:19:18 +03:00
toGive = VLC - > arth - > treasures [ ran ( ) % VLC - > arth - > treasures . size ( ) ] ;
2008-08-26 00:14:00 +03:00
} while ( ! map - > allowedArtifact [ toGive - > id ] ) ;
CGHeroInstance * hero = k - > second . heroes [ 0 ] ;
std : : vector < ui16 > : : iterator slot = vstd : : findFirstNot ( hero - > artifWorn , toGive - > possibleSlots ) ;
if ( slot ! = toGive - > possibleSlots . end ( ) )
hero - > artifWorn [ * slot ] = toGive - > id ;
else
hero - > artifacts . push_back ( toGive - > id ) ;
}
}
2008-06-30 03:06:41 +03:00
}
/****************************TOWNS************************************************/
for ( int i = 0 ; i < map - > towns . size ( ) ; i + + )
{
CGTownInstance * vti = ( map - > towns [ i ] ) ;
if ( ! vti - > town )
vti - > town = & VLC - > townh - > towns [ vti - > subID ] ;
if ( vti - > name . length ( ) = = 0 ) // if town hasn't name we draw it
2008-12-22 19:48:41 +02:00
vti - > name = vti - > town - > Names ( ) [ ran ( ) % vti - > town - > Names ( ) . size ( ) ] ;
2008-08-20 09:57:53 +03:00
//init buildings
2008-06-30 03:06:41 +03:00
if ( vti - > builtBuildings . find ( - 50 ) ! = vti - > builtBuildings . end ( ) ) //give standard set of buildings
{
vti - > builtBuildings . erase ( - 50 ) ;
vti - > builtBuildings . insert ( 10 ) ;
vti - > builtBuildings . insert ( 5 ) ;
vti - > builtBuildings . insert ( 30 ) ;
if ( ran ( ) % 2 )
vti - > builtBuildings . insert ( 31 ) ;
}
2008-08-20 09:57:53 +03:00
//init spells
vti - > spells . resize ( SPELL_LEVELS ) ;
CSpell * s ;
for ( int z = 0 ; z < vti - > obligatorySpells . size ( ) ; z + + )
{
s = & VLC - > spellh - > spells [ vti - > obligatorySpells [ z ] ] ;
vti - > spells [ s - > level - 1 ] . push_back ( s - > id ) ;
vti - > possibleSpells - = s - > id ;
}
while ( vti - > possibleSpells . size ( ) )
{
ui32 total = 0 , sel = - 1 ;
for ( int ps = 0 ; ps < vti - > possibleSpells . size ( ) ; ps + + )
total + = VLC - > spellh - > spells [ vti - > possibleSpells [ ps ] ] . probabilities [ vti - > subID ] ;
int r = ( total ) ? ran ( ) % total : - 1 ;
for ( int ps = 0 ; ps < vti - > possibleSpells . size ( ) ; ps + + )
{
r - = VLC - > spellh - > spells [ vti - > possibleSpells [ ps ] ] . probabilities [ vti - > subID ] ;
if ( r < 0 )
{
sel = ps ;
break ;
}
}
if ( sel < 0 )
sel = 0 ;
CSpell * s = & VLC - > spellh - > spells [ vti - > possibleSpells [ sel ] ] ;
vti - > spells [ s - > level - 1 ] . push_back ( s - > id ) ;
vti - > possibleSpells - = s - > id ;
}
2008-09-01 03:25:36 +03:00
//init garrisons
for ( std : : map < si32 , std : : pair < ui32 , si32 > > : : iterator j = vti - > army . slots . begin ( ) ; j ! = vti - > army . slots . end ( ) ; j + + )
{
if ( j - > second . first > 196 & & j - > second . first < 211 )
{
if ( j - > second . first % 2 )
j - > second . first = vti - > town - > basicCreatures [ ( j - > second . first - 197 ) / 2 ] ;
else
j - > second . first = vti - > town - > upgradedCreatures [ ( j - > second . first - 197 ) / 2 ] ;
}
}
2008-06-30 03:06:41 +03:00
players [ vti - > getOwner ( ) ] . towns . push_back ( vti ) ;
}
2008-07-25 20:28:28 +03:00
for ( std : : map < ui8 , PlayerState > : : iterator k = players . begin ( ) ; k ! = players . end ( ) ; + + k )
2008-06-30 03:06:41 +03:00
{
if ( k - > first = = - 1 | | k - > first = = 255 )
continue ;
for ( int xd = 0 ; xd < map - > width ; + + xd ) //revealing part of map around towns
{
for ( int yd = 0 ; yd < map - > height ; + + yd )
{
for ( int ch = 0 ; ch < k - > second . towns . size ( ) ; + + ch )
{
int deltaX = ( k - > second . towns [ ch ] - > pos . x - xd ) * ( k - > second . towns [ ch ] - > pos . x - xd ) ;
int deltaY = ( k - > second . towns [ ch ] - > pos . y - yd ) * ( k - > second . towns [ ch ] - > pos . y - yd ) ;
if ( deltaX + deltaY < k - > second . towns [ ch ] - > getSightDistance ( ) * k - > second . towns [ ch ] - > getSightDistance ( ) )
k - > second . fogOfWarMap [ xd ] [ yd ] [ k - > second . towns [ ch ] - > pos . z ] = 1 ;
}
}
}
2008-08-20 09:57:53 +03:00
//init visiting and garrisoned heroes
2008-06-30 03:06:41 +03:00
for ( int l = 0 ; l < k - > second . heroes . size ( ) ; l + + )
{
for ( int m = 0 ; m < k - > second . towns . size ( ) ; m + + )
{
int3 vistile = k - > second . towns [ m ] - > pos ; vistile . x - - ; //tile next to the entrance
2008-08-25 13:25:16 +03:00
if ( vistile = = k - > second . heroes [ l ] - > pos | | k - > second . heroes [ l ] - > pos = = k - > second . towns [ m ] - > pos )
2008-06-30 03:06:41 +03:00
{
k - > second . towns [ m ] - > visitingHero = k - > second . heroes [ l ] ;
2008-08-20 09:57:53 +03:00
k - > second . heroes [ l ] - > visitedTown = k - > second . towns [ m ] ;
k - > second . heroes [ l ] - > inTownGarrison = false ;
2008-08-25 13:25:16 +03:00
if ( k - > second . heroes [ l ] - > pos = = k - > second . towns [ m ] - > pos )
k - > second . heroes [ l ] - > pos . x - = 1 ;
break ;
2008-06-30 03:06:41 +03:00
}
}
}
}
2008-12-27 03:01:59 +02:00
2009-01-06 20:42:20 +02:00
for ( int i = 0 ; i < map - > defy . size ( ) ; i + + )
{
map - > defy [ i ] - > serial = i ;
}
2008-12-27 03:01:59 +02:00
for ( int i = 0 ; i < map - > objects . size ( ) ; i + + )
map - > objects [ i ] - > initObj ( ) ;
2008-06-30 03:06:41 +03:00
}
2008-05-27 16:16:35 +03:00
2008-08-02 18:08:03 +03:00
bool CGameState : : battleShootCreatureStack ( int ID , int dest )
2008-08-09 02:02:32 +03:00
{
2008-08-02 18:08:03 +03:00
return true ;
}
int CGameState : : battleGetStack ( int pos )
{
2008-09-05 19:08:25 +03:00
if ( ! curB )
return - 1 ;
2008-08-02 18:08:03 +03:00
for ( int g = 0 ; g < curB - > stacks . size ( ) ; + + g )
{
2008-11-30 02:15:38 +02:00
if ( ( curB - > stacks [ g ] - > position = = pos
| | ( curB - > stacks [ g ] - > creature - > isDoubleWide ( )
& & ( ( curB - > stacks [ g ] - > attackerOwned & & curB - > stacks [ g ] - > position - 1 = = pos )
| | ( ! curB - > stacks [ g ] - > attackerOwned & & curB - > stacks [ g ] - > position + 1 = = pos ) )
) )
& & curB - > stacks [ g ] - > alive ( )
)
2008-08-02 18:08:03 +03:00
return curB - > stacks [ g ] - > ID ;
}
return - 1 ;
}
2009-02-09 16:50:32 +02:00
int CGameState : : battleGetBattlefieldType ( int3 tile )
{
2009-02-10 16:21:51 +02:00
if ( tile = = int3 ( ) & & curB )
tile = curB - > tile ;
else if ( tile = = int3 ( ) & & ! curB )
2009-02-09 16:50:32 +02:00
return - 1 ;
2009-02-10 16:21:51 +02:00
switch ( map - > terrain [ tile . x ] [ tile . y ] [ tile . z ] . tertype )
{
case dirt :
return rand ( ) % 3 + 3 ;
case sand :
return 2 ; //TODO: coast support
case grass :
return rand ( ) % 2 + 6 ;
case snow :
return rand ( ) % 2 + 10 ;
case swamp :
return 13 ;
case rough :
return 23 ;
case subterranean :
return 12 ;
case lava :
return 8 ;
case water :
return 25 ;
case rock :
return 15 ;
default :
return - 1 ;
}
2009-02-09 16:50:32 +02:00
}
2008-08-15 15:11:42 +03:00
UpgradeInfo CGameState : : getUpgradeInfo ( CArmedInstance * obj , int stackPos )
{
UpgradeInfo ret ;
CCreature * base = & VLC - > creh - > creatures [ obj - > army . slots [ stackPos ] . first ] ;
2009-02-06 16:15:45 +02:00
if ( ( obj - > ID = = TOWNI_TYPE ) | | ( ( obj - > ID = = HEROI_TYPE ) & & static_cast < const CGHeroInstance * > ( obj ) - > visitedTown ) )
2008-08-15 15:11:42 +03:00
{
CGTownInstance * t ;
2009-02-06 16:15:45 +02:00
if ( obj - > ID = = TOWNI_TYPE )
2008-08-15 15:11:42 +03:00
t = static_cast < CGTownInstance * > ( const_cast < CArmedInstance * > ( obj ) ) ;
else
t = static_cast < const CGHeroInstance * > ( obj ) - > visitedTown ;
for ( std : : set < si32 > : : iterator i = t - > builtBuildings . begin ( ) ; i ! = t - > builtBuildings . end ( ) ; i + + )
{
if ( ( * i ) > = 37 & & ( * i ) < 44 ) //upgraded creature dwelling
{
int nid = t - > town - > upgradedCreatures [ ( * i ) - 37 ] ; //upgrade offered by that building
if ( base - > upgrades . find ( nid ) ! = base - > upgrades . end ( ) ) //possible upgrade
{
ret . newID . push_back ( nid ) ;
ret . cost . push_back ( std : : set < std : : pair < int , int > > ( ) ) ;
for ( int j = 0 ; j < RESOURCE_QUANTITY ; j + + )
{
int dif = VLC - > creh - > creatures [ nid ] . cost [ j ] - base - > cost [ j ] ;
if ( dif )
ret . cost [ ret . cost . size ( ) - 1 ] . insert ( std : : make_pair ( j , dif ) ) ;
}
}
}
} //end for
}
//TODO: check if hero ability makes some upgrades possible
if ( ret . newID . size ( ) )
ret . oldID = base - > idNumber ;
return ret ;
}
2008-09-07 06:38:37 +03:00
float CGameState : : getMarketEfficiency ( int player , int mode /*=0*/ )
{
boost : : shared_lock < boost : : shared_mutex > lock ( * mx ) ;
if ( mode ) return - 1 ; //todo - support other modes
int mcount = 0 ;
for ( int i = 0 ; i < players [ player ] . towns . size ( ) ; i + + )
if ( vstd : : contains ( players [ player ] . towns [ i ] - > builtBuildings , 14 ) )
mcount + + ;
float ret = std : : min ( ( ( float ) mcount + 1.0f ) / 20.0f , 0.5f ) ;
return ret ;
}
2008-09-23 13:58:54 +03:00
2008-12-22 19:48:41 +02:00
std : : set < int3 > CGameState : : tilesToReveal ( int3 pos , int radious , int player ) const
2008-09-23 13:58:54 +03:00
{
std : : set < int3 > ret ;
int xbeg = pos . x - radious - 2 ;
if ( xbeg < 0 )
xbeg = 0 ;
int xend = pos . x + radious + 2 ;
if ( xend > = map - > width )
xend = map - > width ;
int ybeg = pos . y - radious - 2 ;
if ( ybeg < 0 )
ybeg = 0 ;
int yend = pos . y + radious + 2 ;
if ( yend > = map - > height )
yend = map - > height ;
for ( int xd = xbeg ; xd < xend ; + + xd ) //revealing part of map around heroes
{
for ( int yd = ybeg ; yd < yend ; + + yd )
{
int deltaX = ( pos . x - xd ) * ( pos . x - xd ) ;
int deltaY = ( pos . y - yd ) * ( pos . y - yd ) ;
if ( deltaX + deltaY < radious * radious )
{
2008-12-22 19:48:41 +02:00
if ( player < 0 | | players . find ( player ) - > second . fogOfWarMap [ xd ] [ yd ] [ pos . z ] = = 0 )
2008-09-23 13:58:54 +03:00
{
ret . insert ( int3 ( xd , yd , pos . z ) ) ;
}
}
}
}
return ret ;
}
2008-11-28 03:36:34 +02:00
void CGameState : : loadTownDInfos ( )
{
for ( int i = 0 ; i < F_NUMBER ; i + + )
{
villages [ i ] = new CGDefInfo ( * VLC - > dobjinfo - > castles [ i ] ) ;
forts [ i ] = VLC - > dobjinfo - > castles [ i ] ;
capitols [ i ] = new CGDefInfo ( * VLC - > dobjinfo - > castles [ i ] ) ;
}
}
2008-12-27 03:01:59 +02:00
void CGameState : : setObjProperty ( SetObjectProperty * p )
{
CGObjectInstance * obj = map - > objects [ p - > id ] ;
switch ( p - > what )
{
case 1 :
obj - > tempOwner = p - > val ;
break ;
case 2 :
obj - > blockVisit = p - > val ;
break ;
case 3 :
static_cast < CArmedInstance * > ( obj ) - > army . slots [ 0 ] . second = p - > val ;
break ;
case 4 :
static_cast < CGVisitableOPH * > ( obj ) - > visitors . insert ( p - > val ) ;
break ;
case 5 :
static_cast < CGVisitableOPW * > ( obj ) - > visited = p - > val ;
break ;
}
}
2008-09-29 14:03:30 +03:00
int BattleInfo : : calculateDmg ( const CStack * attacker , const CStack * defender , const CGHeroInstance * attackerHero , const CGHeroInstance * defendingHero , bool shooting )
2008-08-02 18:08:03 +03:00
{
2008-12-20 19:08:51 +02:00
int attackerAttackBonus = attacker - > creature - > attack + ( attackerHero ? attackerHero - > getPrimSkillLevel ( 0 ) : 0 ) ;
if ( attacker - > getEffect ( 56 ) ) //frenzy for attacker
{
attackerAttackBonus + = ( VLC - > spellh - > spells [ attacker - > getEffect ( 56 ) - > id ] . powers [ attacker - > getEffect ( 56 ) - > level ] / 100.0 ) * ( attacker - > creature - > defence + ( attackerHero ? attackerHero - > getPrimSkillLevel ( 1 ) : 0 ) ) ;
}
int defenderDefenseBonus = defender - > creature - > defence + ( defendingHero ? defendingHero - > getPrimSkillLevel ( 1 ) : 0 ) ;
if ( defender - > getEffect ( 56 ) ) //frenzy for defender
{
defenderDefenseBonus = 0 ;
}
int attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus ;
2008-12-06 18:45:54 +02:00
if ( defender - > getEffect ( 48 ) ) //defender's prayer handling
{
2008-12-20 19:08:51 +02:00
attackDefenseBonus - = VLC - > spellh - > spells [ defender - > getEffect ( 48 ) - > id ] . powers [ defender - > getEffect ( 48 ) - > level ] ;
2008-12-06 18:45:54 +02:00
}
if ( attacker - > getEffect ( 48 ) ) //attacker's prayer handling
{
2008-12-20 19:08:51 +02:00
attackDefenseBonus + = VLC - > spellh - > spells [ attacker - > getEffect ( 48 ) - > id ] . powers [ attacker - > getEffect ( 48 ) - > level ] ;
2008-12-06 18:45:54 +02:00
}
if ( defender - > getEffect ( 46 ) ) //stone skin handling
{
2008-12-20 19:08:51 +02:00
attackDefenseBonus - = VLC - > spellh - > spells [ defender - > getEffect ( 46 ) - > id ] . powers [ defender - > getEffect ( 46 ) - > level ] ;
2008-12-06 18:45:54 +02:00
}
if ( attacker - > getEffect ( 45 ) ) //weakness handling
{
2008-12-20 19:08:51 +02:00
attackDefenseBonus - = VLC - > spellh - > spells [ attacker - > getEffect ( 45 ) - > id ] . powers [ attacker - > getEffect ( 45 ) - > level ] ;
2008-12-06 18:45:54 +02:00
}
if ( ! shooting & & attacker - > getEffect ( 43 ) ) //bloodlust handling
{
2008-12-20 19:08:51 +02:00
attackDefenseBonus + = VLC - > spellh - > spells [ attacker - > getEffect ( 43 ) - > id ] . powers [ attacker - > getEffect ( 43 ) - > level ] ;
2008-12-06 18:45:54 +02:00
}
2008-08-02 18:08:03 +03:00
int damageBase = 0 ;
2008-12-06 18:45:54 +02:00
if ( attacker - > getEffect ( 42 ) ) //curse handling (partial, the rest is below)
{
damageBase = attacker - > creature - > damageMin ;
2008-12-20 19:08:51 +02:00
damageBase - = VLC - > spellh - > spells [ attacker - > getEffect ( 42 ) - > id ] . powers [ attacker - > getEffect ( 42 ) - > level ] ;
2008-12-06 18:45:54 +02:00
}
else if ( attacker - > getEffect ( 41 ) ) //bless handling
{
damageBase = attacker - > creature - > damageMax ;
2008-12-20 19:08:51 +02:00
damageBase + = VLC - > spellh - > spells [ attacker - > getEffect ( 41 ) - > id ] . powers [ attacker - > getEffect ( 41 ) - > level ] ;
2008-12-06 18:45:54 +02:00
}
else if ( attacker - > creature - > damageMax = = attacker - > creature - > damageMin ) //constant damage
2008-08-02 18:08:03 +03:00
{
damageBase = attacker - > creature - > damageMin ;
}
else
{
damageBase = rand ( ) % ( attacker - > creature - > damageMax - attacker - > creature - > damageMin ) + attacker - > creature - > damageMin + 1 ;
}
2008-09-29 14:03:30 +03:00
float dmgBonusMultiplier = 1.0f ;
2008-08-02 18:08:03 +03:00
if ( attackDefenseBonus < 0 ) //decreasing dmg
{
if ( 0.02f * ( - attackDefenseBonus ) > 0.3f )
{
dmgBonusMultiplier + = - 0.3f ;
}
else
{
dmgBonusMultiplier + = 0.02f * attackDefenseBonus ;
}
}
else //increasing dmg
{
if ( 0.05f * attackDefenseBonus > 4.0f )
{
dmgBonusMultiplier + = 4.0f ;
}
else
{
dmgBonusMultiplier + = 0.05f * attackDefenseBonus ;
}
}
2008-09-29 14:03:30 +03:00
//handling secondary abilities
if ( attackerHero )
{
if ( shooting )
{
switch ( attackerHero - > getSecSkillLevel ( 1 ) ) //archery
{
case 1 : //basic
dmgBonusMultiplier * = 1.1f ;
break ;
case 2 : //advanced
dmgBonusMultiplier * = 1.25f ;
break ;
case 3 : //expert
dmgBonusMultiplier * = 1.5f ;
break ;
}
}
else
{
switch ( attackerHero - > getSecSkillLevel ( 22 ) ) //offence
{
case 1 : //basic
dmgBonusMultiplier * = 1.1f ;
break ;
case 2 : //advanced
dmgBonusMultiplier * = 1.2f ;
break ;
case 3 : //expert
dmgBonusMultiplier * = 1.3f ;
break ;
}
}
}
if ( defendingHero )
{
switch ( defendingHero - > getSecSkillLevel ( 23 ) ) //armourer
{
case 1 : //basic
dmgBonusMultiplier * = 0.95f ;
break ;
case 2 : //advanced
dmgBonusMultiplier * = 0.9f ;
break ;
case 3 : //expert
dmgBonusMultiplier * = 0.85f ;
break ;
}
}
2008-12-06 18:45:54 +02:00
//handling spell effects
if ( ! shooting & & defender - > getEffect ( 27 ) ) //shield
{
if ( defender - > getEffect ( 27 ) - > level < = 1 ) //none or basic
dmgBonusMultiplier * = 0.85f ;
else //adv or expert
dmgBonusMultiplier * = 0.7f ;
}
if ( shooting & & defender - > getEffect ( 28 ) ) //air shield
{
if ( defender - > getEffect ( 28 ) - > level < = 1 ) //none or basic
dmgBonusMultiplier * = 0.75f ;
else //adv or expert
dmgBonusMultiplier * = 0.5f ;
}
if ( attacker - > getEffect ( 42 ) ) //curse, second part of handling
{
if ( attacker - > getEffect ( 42 ) - > level > = 2 ) //adv or expert
dmgBonusMultiplier * = 0.8f ;
}
2008-08-02 18:08:03 +03:00
return ( float ) damageBase * ( float ) attacker - > amount * dmgBonusMultiplier ;
2008-08-17 22:15:31 +03:00
}
2008-09-09 10:05:02 +03:00
void BattleInfo : : calculateCasualties ( std : : set < std : : pair < ui32 , si32 > > * casualties )
{
for ( int i = 0 ; i < stacks . size ( ) ; i + + ) //setting casualties
{
2008-09-12 11:51:46 +03:00
if ( ! stacks [ i ] - > alive ( ) )
2008-09-09 10:05:02 +03:00
{
casualties [ ! stacks [ i ] - > attackerOwned ] . insert ( std : : pair < ui32 , si32 > ( stacks [ i ] - > creature - > idNumber , stacks [ i ] - > baseAmount ) ) ;
}
else if ( stacks [ i ] - > amount ! = stacks [ i ] - > baseAmount )
{
casualties [ ! stacks [ i ] - > attackerOwned ] . insert ( std : : pair < ui32 , si32 > ( stacks [ i ] - > creature - > idNumber , stacks [ i ] - > baseAmount - stacks [ i ] - > amount ) ) ;
}
}
2008-11-15 17:26:08 +02:00
}
CStack * BattleInfo : : getNextStack ( )
{
CStack * current = getStack ( activeStack ) ;
for ( int i = 0 ; i < stacks . size ( ) ; i + + ) //find fastest not moved/waited stack (stacks vector is sorted by speed)
{
if ( vstd : : contains ( stacks [ i ] - > state , DEFENDING )
| | vstd : : contains ( stacks [ i ] - > state , WAITING )
| | vstd : : contains ( stacks [ i ] - > state , MOVED )
| | ! stacks [ i ] - > alive ( )
)
continue ;
return stacks [ i ] ;
}
for ( int i = stacks . size ( ) - 1 ; i > = 0 ; i - - ) //find slowest waiting stack
{
if ( vstd : : contains ( stacks [ i ] - > state , DEFENDING )
| | vstd : : contains ( stacks [ i ] - > state , MOVED )
| | ! stacks [ i ] - > alive ( )
)
continue ;
return stacks [ i ] ;
}
return NULL ; //all stacks moved or defending!
2008-12-20 19:08:51 +02:00
}
std : : vector < CStack > BattleInfo : : getStackQueue ( )
{
std : : vector < CStack > ret ;
std : : vector < int > taken ; //if non-zero value, corresponding stack has been placed in ret
taken . resize ( stacks . size ( ) ) ;
for ( int g = 0 ; g < taken . size ( ) ; + + g )
{
taken [ g ] = 0 ;
}
for ( int moved = 0 ; moved < 2 ; + + moved ) //in first cycle we add stacks that can act in current turn, in second one the rest of them
{
for ( int gc = 0 ; gc < stacks . size ( ) ; + + gc )
{
int id = - 1 , speed = - 1 ;
for ( int i = 0 ; i < stacks . size ( ) ; + + i ) //find not waited stacks only
{
if ( ( moved = = 1 | | ! vstd : : contains ( stacks [ i ] - > state , DEFENDING ) )
& & stacks [ i ] - > alive ( )
& & ( moved = = 1 | | ! vstd : : contains ( stacks [ i ] - > state , MOVED ) )
& & ! vstd : : contains ( stacks [ i ] - > state , WAITING )
& & taken [ i ] = = 0 )
{
if ( speed = = - 1 | | stacks [ i ] - > speed ( ) > speed )
{
id = i ;
speed = stacks [ i ] - > speed ( ) ;
}
}
}
if ( id ! = - 1 )
{
ret . push_back ( * stacks [ id ] ) ;
taken [ id ] = 1 ;
}
else //choose something from not moved stacks
{
int id = - 1 , speed = 10000 ; //infinite speed
for ( int i = 0 ; i < stacks . size ( ) ; + + i ) //find waited stacks only
{
if ( ( moved = = 1 | | ! vstd : : contains ( stacks [ i ] - > state , DEFENDING ) )
& & stacks [ i ] - > alive ( )
& & ( moved = = 1 | | ! vstd : : contains ( stacks [ i ] - > state , MOVED ) )
& & vstd : : contains ( stacks [ i ] - > state , WAITING )
& & taken [ i ] = = 0 )
{
if ( stacks [ i ] - > speed ( ) < speed ) //slowest one
{
id = i ;
speed = stacks [ i ] - > speed ( ) ;
}
}
}
if ( id ! = - 1 )
{
ret . push_back ( * stacks [ id ] ) ;
taken [ id ] = 1 ;
}
else
{
break ; //no stacks have been found, so none of them will be found in next iterations
}
}
}
}
return ret ;
}