2011-12-14 00:23:17 +03:00
# include "StdInc.h"
2009-05-20 13:08:56 +03:00
# include "NetPacks.h"
2011-12-14 00:23:17 +03:00
2010-12-20 23:22:53 +02:00
# include "CGeneralTextHandler.h"
2014-06-05 14:19:47 +03:00
# include "mapObjects/CObjectClassesHandler.h"
2010-12-20 23:22:53 +02:00
# include "CArtHandler.h"
# include "CHeroHandler.h"
2014-06-05 14:19:47 +03:00
# include "mapObjects/CObjectHandler.h"
2012-08-24 12:37:52 +03:00
# include "CModHandler.h"
2009-05-20 13:08:56 +03:00
# include "VCMI_Lib.h"
2013-04-07 13:48:07 +03:00
# include "mapping/CMap.h"
2015-03-10 22:14:58 +02:00
# include "spells/CSpellHandler.h"
2010-12-20 23:22:53 +02:00
# include "CCreatureHandler.h"
2010-12-25 21:23:30 +02:00
# include "CGameState.h"
# include "BattleState.h"
2013-09-27 18:20:42 +03:00
# include "CTownHandler.h"
2014-06-25 17:11:07 +03:00
# include "mapping/CMapInfo.h"
# include "StartInfo.h"
2009-03-07 17:55:56 +02:00
2009-04-15 17:03:31 +03:00
/*
* NetPacksLib . 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-05-18 01:52:22 +03:00
# undef min
# undef max
2014-01-16 23:24:06 +03:00
2009-05-18 01:52:22 +03:00
2013-12-08 20:54:13 +03:00
std : : ostream & operator < < ( std : : ostream & out , const CPack * pack )
{
return out < < pack - > toString ( ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetResource : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2013-03-03 20:06:03 +03:00
assert ( player < PlayerColor : : PLAYER_LIMIT ) ;
2011-12-14 00:23:17 +03:00
vstd : : amax ( val , 0 ) ; //new value must be >= 0
2009-03-09 12:37:49 +02:00
gs - > getPlayer ( player ) - > resources [ resid ] = val ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetResources : : applyGs ( CGameState * gs )
2011-07-05 09:14:07 +03:00
{
2013-03-03 20:06:03 +03:00
assert ( player < PlayerColor : : PLAYER_LIMIT ) ;
2011-07-05 09:14:07 +03:00
gs - > getPlayer ( player ) - > resources = res ;
}
2009-03-07 17:55:56 +02:00
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetPrimSkill : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2014-04-10 20:11:09 +03:00
CGHeroInstance * hero = gs - > getHero ( id ) ;
2010-05-02 21:20:26 +03:00
assert ( hero ) ;
2014-04-10 20:11:09 +03:00
hero - > setPrimarySkill ( which , val , abs ) ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetSecSkill : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CGHeroInstance * hero = gs - > getHero ( id ) ;
2013-02-04 22:43:16 +03:00
hero - > setSecSkillLevel ( which , val , abs ) ;
2009-03-07 17:55:56 +02:00
}
2014-06-26 19:41:27 +03:00
DLL_LINKAGE SelectMap : : SelectMap ( const CMapInfo & src )
{
mapInfo = & src ;
free = false ;
}
DLL_LINKAGE SelectMap : : SelectMap ( )
{
mapInfo = nullptr ;
free = true ;
}
2014-06-25 17:11:07 +03:00
DLL_LINKAGE SelectMap : : ~ SelectMap ( )
{
if ( free )
delete mapInfo ;
}
2014-06-26 19:41:27 +03:00
DLL_LINKAGE UpdateStartOptions : : UpdateStartOptions ( StartInfo & src )
{
options = & src ;
free = false ;
}
DLL_LINKAGE UpdateStartOptions : : UpdateStartOptions ( )
{
options = nullptr ;
free = true ;
}
2014-06-25 17:11:07 +03:00
DLL_LINKAGE UpdateStartOptions : : ~ UpdateStartOptions ( )
{
if ( free )
delete options ;
}
2012-05-18 17:02:27 +03:00
DLL_LINKAGE void SetCommanderProperty : : applyGs ( CGameState * gs )
{
CCommanderInstance * commander = gs - > getHero ( heroid ) - > commander ;
assert ( commander ) ;
switch ( which )
{
case BONUS :
commander - > accumulateBonus ( accumulatedBonus ) ;
break ;
2012-05-18 22:44:15 +03:00
case SPECIAL_SKILL :
commander - > accumulateBonus ( accumulatedBonus ) ;
commander - > specialSKills . insert ( additionalInfo ) ;
break ;
2012-05-18 17:02:27 +03:00
case SECONDARY_SKILL :
commander - > secondarySkills [ additionalInfo ] = amount ;
break ;
case ALIVE :
if ( amount )
commander - > setAlive ( true ) ;
else
commander - > setAlive ( false ) ;
break ;
2012-05-18 22:44:15 +03:00
case EXPERIENCE :
commander - > giveStackExp ( amount ) ; //TODO: allow setting exp for stacks via netpacks
break ;
2012-05-18 17:02:27 +03:00
}
}
2012-07-06 22:12:04 +03:00
DLL_LINKAGE void AddQuest : : applyGs ( CGameState * gs )
{
assert ( vstd : : contains ( gs - > players , player ) ) ;
2012-07-08 19:36:20 +03:00
auto vec = & gs - > players [ player ] . quests ;
if ( ! vstd : : contains ( * vec , quest ) )
vec - > push_back ( quest ) ;
else
2013-04-09 17:31:36 +03:00
logNetwork - > warnStream ( ) < < " Warning! Attempt to add duplicated quest " ;
2012-07-06 22:12:04 +03:00
}
2013-02-19 01:37:22 +03:00
DLL_LINKAGE void UpdateArtHandlerLists : : applyGs ( CGameState * gs )
{
VLC - > arth - > minors = minors ;
VLC - > arth - > majors = majors ;
VLC - > arth - > treasures = treasures ;
VLC - > arth - > relics = relics ;
}
DLL_LINKAGE void UpdateMapEvents : : applyGs ( CGameState * gs )
{
gs - > map - > events = events ;
}
DLL_LINKAGE void UpdateCastleEvents : : applyGs ( CGameState * gs )
{
auto t = gs - > getTown ( town ) ;
t - > events = events ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void HeroVisitCastle : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CGHeroInstance * h = gs - > getHero ( hid ) ;
CGTownInstance * t = gs - > getTown ( tid ) ;
2011-02-04 16:58:14 +02:00
2014-06-05 18:19:11 +03:00
assert ( h ) ;
assert ( t ) ;
2014-07-01 08:07:40 +03:00
2009-03-07 17:55:56 +02:00
if ( start ( ) )
2011-02-04 16:58:14 +02:00
t - > setVisitingHero ( h ) ;
2009-03-07 17:55:56 +02:00
else
2013-06-26 14:18:27 +03:00
t - > setVisitingHero ( nullptr ) ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void ChangeSpells : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CGHeroInstance * hero = gs - > getHero ( hid ) ;
if ( learn )
2013-06-29 16:05:48 +03:00
for ( auto sid : spells )
2011-01-22 05:43:20 +02:00
hero - > spells . insert ( sid ) ;
2009-03-07 17:55:56 +02:00
else
2013-06-29 16:05:48 +03:00
for ( auto sid : spells )
2011-01-22 05:43:20 +02:00
hero - > spells . erase ( sid ) ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetMana : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2014-11-26 12:30:55 +02:00
CGHeroInstance * hero = gs - > getHero ( hid ) ;
2015-03-10 22:14:58 +02:00
2014-11-26 12:30:55 +02:00
assert ( hero ) ;
2015-03-10 22:14:58 +02:00
2014-11-26 12:30:55 +02:00
if ( absolute )
2015-03-10 22:14:58 +02:00
hero - > mana = val ;
2014-11-26 12:30:55 +02:00
else
hero - > mana + = val ;
vstd : : amax ( hero - > mana , 0 ) ; //not less than 0
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetMovePoints : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CGHeroInstance * hero = gs - > getHero ( hid ) ;
hero - > movement = val ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void FoWChange : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2010-08-03 15:34:06 +03:00
TeamState * team = gs - > getPlayerTeam ( player ) ;
2013-06-29 16:05:48 +03:00
for ( int3 t : tiles )
2010-08-03 15:34:06 +03:00
team - > fogOfWarMap [ t . x ] [ t . y ] [ t . z ] = mode ;
2010-06-06 09:05:39 +03:00
if ( mode = = 0 ) //do not hide too much
{
2013-06-29 16:05:48 +03:00
std : : unordered_set < int3 , ShashInt3 > tilesRevealed ;
for ( auto & elem : gs - > map - > objects )
2010-06-06 09:05:39 +03:00
{
2013-06-29 16:05:48 +03:00
const CGObjectInstance * o = elem ;
2013-01-12 21:08:33 +03:00
if ( o )
2010-06-06 09:05:39 +03:00
{
2013-01-12 21:08:33 +03:00
switch ( o - > ID )
2010-06-06 09:05:39 +03:00
{
2013-01-12 21:08:33 +03:00
case Obj : : HERO :
case Obj : : MINE :
case Obj : : TOWN :
case Obj : : ABANDONED_MINE :
if ( vstd : : contains ( team - > players , o - > tempOwner ) ) //check owned observators
2014-06-24 14:50:27 +03:00
gs - > getTilesInRange ( tiles , o - > getSightCenter ( ) , o - > getSightRadious ( ) , o - > tempOwner , 1 ) ;
2010-06-06 09:05:39 +03:00
break ;
}
}
}
2013-06-29 16:05:48 +03:00
for ( int3 t : tilesRevealed ) //probably not the most optimal solution ever
2010-08-03 15:34:06 +03:00
team - > fogOfWarMap [ t . x ] [ t . y ] [ t . z ] = 1 ;
2010-06-06 09:05:39 +03:00
}
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetAvailableHeroes : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2010-07-08 08:52:11 +03:00
PlayerState * p = gs - > getPlayer ( player ) ;
p - > availableHeroes . clear ( ) ;
2009-03-07 17:55:56 +02:00
2011-12-14 00:23:17 +03:00
for ( int i = 0 ; i < GameConstants : : AVAILABLE_HEROES_PER_PLAYER ; i + + )
2009-03-07 17:55:56 +02:00
{
2012-09-26 16:13:39 +03:00
CGHeroInstance * h = ( hid [ i ] > = 0 ? gs - > hpool . heroesPool [ hid [ i ] ] . get ( ) : nullptr ) ;
2010-07-08 08:52:11 +03:00
if ( h & & army [ i ] )
2011-01-28 04:11:58 +02:00
h - > setToArmy ( army [ i ] ) ;
2010-07-08 08:52:11 +03:00
p - > availableHeroes . push_back ( h ) ;
2009-03-07 17:55:56 +02:00
}
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void GiveBonus : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2013-06-26 14:18:27 +03:00
CBonusSystemNode * cbsn = nullptr ;
2010-02-10 04:56:00 +02:00
switch ( who )
{
case HERO :
2013-02-14 02:55:42 +03:00
cbsn = gs - > getHero ( ObjectInstanceID ( id ) ) ;
2010-02-10 04:56:00 +02:00
break ;
case PLAYER :
2013-03-03 20:06:03 +03:00
cbsn = gs - > getPlayer ( PlayerColor ( id ) ) ;
2010-02-10 04:56:00 +02:00
break ;
2010-06-07 08:28:12 +03:00
case TOWN :
2013-02-14 02:55:42 +03:00
cbsn = gs - > getTown ( ObjectInstanceID ( id ) ) ;
2010-11-19 00:06:56 +02:00
break ;
2010-02-10 04:56:00 +02:00
}
2009-04-21 01:57:07 +03:00
2010-11-19 00:06:56 +02:00
assert ( cbsn ) ;
2013-06-29 16:05:48 +03:00
auto b = new Bonus ( bonus ) ;
2010-11-19 00:06:56 +02:00
cbsn - > addNewBonus ( b ) ;
std : : string & descr = b - > description ;
2009-04-21 01:57:07 +03:00
2013-01-12 21:08:33 +03:00
if ( ! bdescr . message . size ( )
& & bonus . source = = Bonus : : OBJECT
2014-07-07 08:29:07 +03:00
& & ( bonus . type = = Bonus : : LUCK | | bonus . type = = Bonus : : MORALE ) )
2009-04-21 01:57:07 +03:00
{
descr = VLC - > generaltexth - > arraytxt [ bonus . val > 0 ? 110 : 109 ] ; //+/-%d Temporary until next battle"
}
else
{
2009-07-09 22:15:22 +03:00
bdescr . toString ( descr ) ;
2009-04-21 01:57:07 +03:00
}
2014-04-07 20:32:15 +03:00
// Some of(?) versions of H3 use %s here instead of %d. Try to replace both of them
boost : : replace_first ( descr , " %d " , boost : : lexical_cast < std : : string > ( std : : abs ( bonus . val ) ) ) ;
boost : : replace_first ( descr , " %s " , boost : : lexical_cast < std : : string > ( std : : abs ( bonus . val ) ) ) ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void ChangeObjPos : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2013-02-14 02:55:42 +03:00
CGObjectInstance * obj = gs - > getObjInstance ( objid ) ;
2009-03-07 17:55:56 +02:00
if ( ! obj )
{
2013-04-09 17:31:36 +03:00
logNetwork - > errorStream ( ) < < " Wrong ChangeObjPos: object " < < objid . getNum ( ) < < " doesn't exist! " ;
2009-03-07 17:55:56 +02:00
return ;
}
gs - > map - > removeBlockVisTiles ( obj ) ;
obj - > pos = nPos ;
gs - > map - > addBlockVisTiles ( obj ) ;
}
2014-04-07 20:32:15 +03:00
DLL_LINKAGE void ChangeObjectVisitors : : applyGs ( CGameState * gs )
{
switch ( mode ) {
case VISITOR_ADD :
gs - > getHero ( hero ) - > visitedObjects . insert ( object ) ;
gs - > getPlayer ( gs - > getHero ( hero ) - > tempOwner ) - > visitedObjects . insert ( object ) ;
break ;
case VISITOR_CLEAR :
for ( CGHeroInstance * hero : gs - > map - > allHeroes )
hero - > visitedObjects . erase ( object ) ; // remove visit info from all heroes, including those that are not present on map
break ;
case VISITOR_REMOVE :
gs - > getHero ( hero ) - > visitedObjects . erase ( object ) ;
break ;
}
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void PlayerEndsGame : : applyGs ( CGameState * gs )
2010-01-29 22:52:45 +02:00
{
PlayerState * p = gs - > getPlayer ( player ) ;
2013-11-17 20:57:04 +03:00
if ( victoryLossCheckResult . victory ( ) ) p - > status = EPlayerStatus : : WINNER ;
else p - > status = EPlayerStatus : : LOSER ;
2010-01-29 22:52:45 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void RemoveBonus : : applyGs ( CGameState * gs )
2010-02-10 04:56:00 +02:00
{
2011-07-13 21:39:02 +03:00
CBonusSystemNode * node ;
if ( who = = HERO )
2013-02-14 02:55:42 +03:00
node = gs - > getHero ( ObjectInstanceID ( whoID ) ) ;
2011-07-13 21:39:02 +03:00
else
2013-03-03 20:06:03 +03:00
node = gs - > getPlayer ( PlayerColor ( whoID ) ) ;
2010-02-10 04:56:00 +02:00
2015-04-13 08:04:43 +02:00
BonusList & bonuses = node - > getExportedBonusList ( ) ;
2013-01-12 21:08:33 +03:00
2011-07-13 21:39:02 +03:00
for ( int i = 0 ; i < bonuses . size ( ) ; i + + )
2010-02-10 04:56:00 +02:00
{
2011-07-13 21:39:02 +03:00
Bonus * b = bonuses [ i ] ;
if ( b - > source = = source & & b - > sid = = id )
2010-02-10 04:56:00 +02:00
{
2011-07-13 21:39:02 +03:00
bonus = * b ; //backup bonus (to show to interfaces later)
2015-04-13 08:04:43 +02:00
node - > removeBonus ( b ) ;
2010-02-10 04:56:00 +02:00
break ;
}
}
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void RemoveObject : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2013-04-21 15:11:13 +03:00
2013-02-14 02:55:42 +03:00
CGObjectInstance * obj = gs - > getObjInstance ( id ) ;
2014-06-24 20:39:36 +03:00
logGlobal - > debugStream ( ) < < " removing object id= " < < id < < " ; address= " < < ( intptr_t ) obj < < " ; name= " < < obj - > getObjectName ( ) ;
2010-02-11 17:51:26 +02:00
//unblock tiles
2014-01-03 02:48:38 +03:00
gs - > map - > removeBlockVisTiles ( obj ) ;
2010-02-11 17:51:26 +02:00
2012-09-23 21:01:04 +03:00
if ( obj - > ID = = Obj : : HERO )
2009-03-07 17:55:56 +02:00
{
CGHeroInstance * h = static_cast < CGHeroInstance * > ( obj ) ;
2011-02-12 18:12:48 +02:00
PlayerState * p = gs - > getPlayer ( h - > tempOwner ) ;
2013-05-19 01:30:48 +03:00
gs - > map - > heroesOnMap - = h ;
2011-02-12 18:12:48 +02:00
p - > heroes - = h ;
2011-02-22 11:47:25 +02:00
h - > detachFrom ( h - > whereShouldBeAttached ( gs ) ) ;
2013-03-03 20:06:03 +03:00
h - > tempOwner = PlayerColor : : NEUTRAL ; //no one owns beaten hero
2010-01-29 22:52:45 +02:00
2011-02-22 11:47:25 +02:00
if ( h - > visitedTown )
2009-03-07 17:55:56 +02:00
{
if ( h - > inTownGarrison )
2013-06-26 14:18:27 +03:00
h - > visitedTown - > garrisonHero = nullptr ;
2009-03-07 17:55:56 +02:00
else
2013-06-26 14:18:27 +03:00
h - > visitedTown - > visitingHero = nullptr ;
h - > visitedTown = nullptr ;
2009-03-07 17:55:56 +02:00
}
2010-07-08 08:52:11 +03:00
//return hero to the pool, so he may reappear in tavern
gs - > hpool . heroesPool [ h - > subID ] = h ;
if ( ! vstd : : contains ( gs - > hpool . pavailable , h - > subID ) )
gs - > hpool . pavailable [ h - > subID ] = 0xff ;
2011-01-18 20:56:14 +02:00
2013-06-26 14:18:27 +03:00
gs - > map - > objects [ id . getNum ( ) ] = nullptr ;
2013-01-12 21:08:33 +03:00
2013-09-09 00:50:49 +03:00
//If hero on Boat is removed, the Boat disappears
if ( h - > boat )
{
gs - > map - > objects [ h - > boat - > id . getNum ( ) ] . dellNull ( ) ;
h - > boat = nullptr ;
}
2011-02-11 14:27:38 +02:00
2011-01-18 20:56:14 +02:00
return ;
2009-03-07 17:55:56 +02:00
}
2012-07-19 12:10:55 +03:00
2013-07-23 18:03:01 +03:00
auto quest = dynamic_cast < const IQuestObject * > ( obj ) ;
2012-07-19 12:10:55 +03:00
if ( quest )
{
2013-07-23 18:03:01 +03:00
gs - > map - > quests [ quest - > quest - > qid ] = nullptr ;
2013-06-29 16:05:48 +03:00
for ( auto & player : gs - > players )
2012-07-19 12:10:55 +03:00
{
2013-06-29 16:05:48 +03:00
for ( auto & q : player . second . quests )
2012-07-19 12:10:55 +03:00
{
if ( q . obj = = obj )
{
2013-06-26 14:18:27 +03:00
q . obj = nullptr ;
2012-07-19 12:10:55 +03:00
}
}
}
}
2014-02-09 15:10:02 +03:00
for ( TriggeredEvent & event : gs - > map - > triggeredEvents )
{
2014-08-07 19:40:22 +03:00
auto patcher = [ & ] ( EventCondition cond ) - > EventExpression : : Variant
2014-02-09 15:10:02 +03:00
{
if ( cond . object = = obj )
{
if ( cond . condition = = EventCondition : : DESTROY )
{
cond . condition = EventCondition : : CONST_VALUE ;
cond . value = 1 ; // destroyed object, from now on always fulfilled
}
if ( cond . condition = = EventCondition : : CONTROL )
{
cond . condition = EventCondition : : CONST_VALUE ;
cond . value = 0 ; // destroyed object, from now on can not be fulfilled
}
}
2014-08-07 19:40:22 +03:00
return cond ;
2014-02-09 15:10:02 +03:00
} ;
2014-08-07 19:40:22 +03:00
event . trigger = event . trigger . morph ( patcher ) ;
2014-02-09 15:10:02 +03:00
}
2013-02-14 02:55:42 +03:00
gs - > map - > objects [ id . getNum ( ) ] . dellNull ( ) ;
2014-04-01 14:53:28 +03:00
gs - > map - > calculateGuardingGreaturePositions ( ) ;
2009-03-07 17:55:56 +02:00
}
2009-07-18 06:13:13 +03:00
static int getDir ( int3 src , int3 dst )
{
int ret = - 1 ;
if ( dst . x + 1 = = src . x & & dst . y + 1 = = src . y ) //tl
{
ret = 1 ;
}
else if ( dst . x = = src . x & & dst . y + 1 = = src . y ) //t
{
ret = 2 ;
}
else if ( dst . x - 1 = = src . x & & dst . y + 1 = = src . y ) //tr
{
ret = 3 ;
}
else if ( dst . x - 1 = = src . x & & dst . y = = src . y ) //r
{
ret = 4 ;
}
else if ( dst . x - 1 = = src . x & & dst . y - 1 = = src . y ) //br
{
ret = 5 ;
}
else if ( dst . x = = src . x & & dst . y - 1 = = src . y ) //b
{
ret = 6 ;
}
else if ( dst . x + 1 = = src . x & & dst . y - 1 = = src . y ) //bl
{
ret = 7 ;
}
else if ( dst . x + 1 = = src . x & & dst . y = = src . y ) //l
{
ret = 8 ;
}
return ret ;
}
2009-03-07 17:55:56 +02:00
void TryMoveHero : : applyGs ( CGameState * gs )
{
CGHeroInstance * h = gs - > getHero ( id ) ;
h - > movement = movePoints ;
2009-07-19 04:00:19 +03:00
2014-02-15 12:40:33 +03:00
if ( ( result = = SUCCESS | | result = = BLOCKING_VISIT | | result = = EMBARK | | result = = DISEMBARK ) & & start ! = end )
2013-10-13 23:05:34 +03:00
{
auto dir = getDir ( start , end ) ;
if ( dir > 0 & & dir < = 8 )
h - > moveDir = dir ;
2014-05-21 12:02:20 +03:00
//else don`t change move direction - hero might have traversed the subterranean gate, direction should be kept
2010-05-06 15:13:31 +03:00
}
2009-07-19 06:10:24 +03:00
2014-05-21 12:02:20 +03:00
if ( result = = EMBARK ) //hero enters boat at destination tile
2009-07-19 04:00:19 +03:00
{
const TerrainTile & tt = gs - > map - > getTile ( CGHeroInstance : : convertPosition ( end , false ) ) ;
2014-05-21 12:02:20 +03:00
assert ( tt . visitableObjects . size ( ) > = 1 & & tt . visitableObjects . back ( ) - > ID = = Obj : : BOAT ) ; //the only visitable object at destination is Boat
2011-04-23 01:28:13 +03:00
CGBoat * boat = static_cast < CGBoat * > ( tt . visitableObjects . back ( ) ) ;
2009-07-19 04:00:19 +03:00
gs - > map - > removeBlockVisTiles ( boat ) ; //hero blockvis mask will be used, we don't need to duplicate it with boat
h - > boat = boat ;
boat - > hero = h ;
}
2014-05-21 12:02:20 +03:00
else if ( result = = DISEMBARK ) //hero leaves boat to destination tile
2009-07-19 06:10:24 +03:00
{
2010-07-20 21:34:32 +03:00
CGBoat * b = const_cast < CGBoat * > ( h - > boat ) ;
b - > direction = h - > moveDir ;
b - > pos = start ;
2013-06-26 14:18:27 +03:00
b - > hero = nullptr ;
2010-07-20 21:34:32 +03:00
gs - > map - > addBlockVisTiles ( b ) ;
2013-06-26 14:18:27 +03:00
h - > boat = nullptr ;
2009-07-19 06:10:24 +03:00
}
2009-07-19 04:00:19 +03:00
2009-07-19 06:10:24 +03:00
if ( start ! = end & & ( result = = SUCCESS | | result = = TELEPORTATION | | result = = EMBARK | | result = = DISEMBARK ) )
2009-03-07 17:55:56 +02:00
{
gs - > map - > removeBlockVisTiles ( h ) ;
h - > pos = end ;
2010-07-20 21:34:32 +03:00
if ( CGBoat * b = const_cast < CGBoat * > ( h - > boat ) )
b - > pos = end ;
2009-03-07 17:55:56 +02:00
gs - > map - > addBlockVisTiles ( h ) ;
}
2009-07-18 06:13:13 +03:00
2013-06-29 16:05:48 +03:00
for ( int3 t : fowRevealed )
2010-08-03 15:34:06 +03:00
gs - > getPlayerTeam ( h - > getOwner ( ) ) - > fogOfWarMap [ t . x ] [ t . y ] [ t . z ] = 1 ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void NewStructures : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2009-08-23 18:02:21 +03:00
CGTownInstance * t = gs - > getTown ( tid ) ;
2013-06-29 16:05:48 +03:00
for ( const auto & id : bid )
2009-08-23 18:02:21 +03:00
{
2013-11-12 13:45:42 +03:00
assert ( t - > town - > buildings . at ( id ) ! = nullptr ) ;
2009-03-07 17:55:56 +02:00
t - > builtBuildings . insert ( id ) ;
2009-08-23 18:02:21 +03:00
}
2009-03-07 17:55:56 +02:00
t - > builded = builded ;
2011-02-04 16:58:14 +02:00
t - > recreateBuildingsBonuses ( ) ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void RazeStructures : : applyGs ( CGameState * gs )
2009-09-22 17:27:46 +03:00
{
CGTownInstance * t = gs - > getTown ( tid ) ;
2013-06-29 16:05:48 +03:00
for ( const auto & id : bid )
2009-09-22 17:27:46 +03:00
{
t - > builtBuildings . erase ( id ) ;
}
2009-09-24 20:54:02 +03:00
t - > destroyed = destroyed ; //yeaha
2011-02-04 16:58:14 +02:00
t - > recreateBuildingsBonuses ( ) ;
2009-09-22 17:27:46 +03:00
}
2011-02-04 16:58:14 +02:00
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetAvailableCreatures : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2013-02-14 02:55:42 +03:00
CGDwelling * dw = dynamic_cast < CGDwelling * > ( gs - > getObjInstance ( tid ) ) ;
2009-07-26 13:43:22 +03:00
assert ( dw ) ;
dw - > creatures = creatures ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetHeroesInTown : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CGTownInstance * t = gs - > getTown ( tid ) ;
2013-01-12 21:08:33 +03:00
CGHeroInstance * v = gs - > getHero ( visiting ) ,
2009-03-07 17:55:56 +02:00
* g = gs - > getHero ( garrison ) ;
2011-02-04 16:58:14 +02:00
bool newVisitorComesFromGarrison = v & & v = = t - > garrisonHero ;
bool newGarrisonComesFromVisiting = g & & g = = t - > visitingHero ;
if ( newVisitorComesFromGarrison )
2013-06-26 14:18:27 +03:00
t - > setGarrisonedHero ( nullptr ) ;
2011-02-04 16:58:14 +02:00
if ( newGarrisonComesFromVisiting )
2013-06-26 14:18:27 +03:00
t - > setVisitingHero ( nullptr ) ;
2011-02-04 16:58:14 +02:00
if ( ! newGarrisonComesFromVisiting | | v )
t - > setVisitingHero ( v ) ;
if ( ! newVisitorComesFromGarrison | | g )
t - > setGarrisonedHero ( g ) ;
2009-03-07 17:55:56 +02:00
if ( v )
{
gs - > map - > addBlockVisTiles ( v ) ;
}
if ( g )
{
gs - > map - > removeBlockVisTiles ( g ) ;
}
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void HeroRecruited : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2009-08-05 03:05:37 +03:00
assert ( vstd : : contains ( gs - > hpool . heroesPool , hid ) ) ;
2009-03-07 17:55:56 +02:00
CGHeroInstance * h = gs - > hpool . heroesPool [ hid ] ;
CGTownInstance * t = gs - > getTown ( tid ) ;
2011-02-04 16:58:14 +02:00
PlayerState * p = gs - > getPlayer ( player ) ;
2013-09-09 00:50:49 +03:00
assert ( ! h - > boat ) ;
2009-03-07 17:55:56 +02:00
h - > setOwner ( player ) ;
h - > pos = tile ;
h - > movement = h - > maxMovePoints ( true ) ;
gs - > hpool . heroesPool . erase ( hid ) ;
2013-02-14 02:55:42 +03:00
if ( h - > id = = ObjectInstanceID ( ) )
2009-03-07 17:55:56 +02:00
{
2013-02-14 02:55:42 +03:00
h - > id = ObjectInstanceID ( gs - > map - > objects . size ( ) ) ;
2009-03-07 17:55:56 +02:00
gs - > map - > objects . push_back ( h ) ;
}
else
2013-02-14 02:55:42 +03:00
gs - > map - > objects [ h - > id . getNum ( ) ] = h ;
2009-03-07 17:55:56 +02:00
2013-05-19 01:30:48 +03:00
gs - > map - > heroesOnMap . push_back ( h ) ;
2011-02-04 16:58:14 +02:00
p - > heroes . push_back ( h ) ;
h - > attachTo ( p ) ;
2009-08-01 13:08:16 +03:00
h - > initObj ( ) ;
2009-03-07 17:55:56 +02:00
gs - > map - > addBlockVisTiles ( h ) ;
2010-07-09 02:03:27 +03:00
if ( t )
{
2011-02-04 16:58:14 +02:00
t - > setVisitingHero ( h ) ;
2010-07-09 02:03:27 +03:00
}
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void GiveHero : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CGHeroInstance * h = gs - > getHero ( id ) ;
2012-01-03 04:55:26 +03:00
//bonus system
h - > detachFrom ( & gs - > globalEffects ) ;
h - > attachTo ( gs - > getPlayer ( player ) ) ;
2014-05-16 23:50:02 +03:00
h - > appearance = VLC - > objtypeh - > getHandlerFor ( Obj : : HERO , h - > type - > heroClass - > id ) - > getTemplates ( ) . front ( ) ;
2012-01-03 04:55:26 +03:00
2009-03-07 17:55:56 +02:00
gs - > map - > removeBlockVisTiles ( h , true ) ;
h - > setOwner ( player ) ;
h - > movement = h - > maxMovePoints ( true ) ;
2013-05-19 01:30:48 +03:00
gs - > map - > heroesOnMap . push_back ( h ) ;
2009-03-09 12:37:49 +02:00
gs - > getPlayer ( h - > getOwner ( ) ) - > heroes . push_back ( h ) ;
2009-03-07 17:55:56 +02:00
gs - > map - > addBlockVisTiles ( h ) ;
h - > inTownGarrison = false ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void NewObject : : applyGs ( CGameState * gs )
2009-07-26 06:33:13 +03:00
{
2014-10-01 12:38:03 +03:00
const TerrainTile & t = gs - > map - > getTile ( pos ) ;
ETerrainType terrainType = t . terType ;
2013-01-12 21:08:33 +03:00
2013-06-26 14:18:27 +03:00
CGObjectInstance * o = nullptr ;
2009-07-26 06:33:13 +03:00
switch ( ID )
{
2013-01-12 21:08:33 +03:00
case Obj : : BOAT :
2009-07-26 06:33:13 +03:00
o = new CGBoat ( ) ;
2014-10-01 12:38:03 +03:00
terrainType = ETerrainType : : WATER ; //TODO: either boat should only spawn on water, or all water objects should be handled this way
2009-07-26 06:33:13 +03:00
break ;
2013-01-12 21:08:33 +03:00
case Obj : : MONSTER : //probably more options will be needed
2010-08-22 10:11:46 +03:00
o = new CGCreature ( ) ;
{
2010-11-22 02:34:46 +02:00
//CStackInstance hlp;
2010-08-22 10:11:46 +03:00
CGCreature * cre = static_cast < CGCreature * > ( o ) ;
2010-11-22 02:34:46 +02:00
//cre->slots[0] = hlp;
2010-08-22 10:11:46 +03:00
cre - > notGrowingTeam = cre - > neverFlees = 0 ;
cre - > character = 2 ;
2013-02-07 20:34:50 +03:00
cre - > gainedArtifact = ArtifactID : : NONE ;
2011-05-28 04:02:28 +03:00
cre - > identifier = - 1 ;
2013-02-16 17:03:47 +03:00
cre - > addToSlot ( SlotID ( 0 ) , new CStackInstance ( CreatureID ( subID ) , - 1 ) ) ; //add placeholder stack
2010-08-22 10:11:46 +03:00
}
break ;
2009-07-26 06:33:13 +03:00
default :
o = new CGObjectInstance ( ) ;
break ;
}
o - > ID = ID ;
o - > subID = subID ;
o - > pos = pos ;
2014-10-01 12:38:03 +03:00
o - > appearance = VLC - > objtypeh - > getHandlerFor ( o - > ID , o - > subID ) - > getTemplates ( terrainType ) . front ( ) ;
2013-02-14 02:55:42 +03:00
id = o - > id = ObjectInstanceID ( gs - > map - > objects . size ( ) ) ;
2009-07-26 06:33:13 +03:00
gs - > map - > objects . push_back ( o ) ;
gs - > map - > addBlockVisTiles ( o ) ;
o - > initObj ( ) ;
2014-04-01 14:53:28 +03:00
gs - > map - > calculateGuardingGreaturePositions ( ) ;
2013-08-18 18:46:28 +03:00
2014-06-24 20:39:36 +03:00
logGlobal - > debugStream ( ) < < " added object id= " < < id < < " ; address= " < < ( intptr_t ) o < < " ; name= " < < o - > getObjectName ( ) ;
2009-07-26 06:33:13 +03:00
}
2013-08-18 18:46:28 +03:00
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void NewArtifact : : applyGs ( CGameState * gs )
2010-11-10 02:06:25 +02:00
{
2010-12-26 16:34:11 +02:00
assert ( ! vstd : : contains ( gs - > map - > artInstances , art ) ) ;
2011-01-22 05:43:20 +02:00
gs - > map - > addNewArtifactInstance ( art ) ;
2010-12-26 16:34:11 +02:00
2011-07-13 21:39:02 +03:00
assert ( ! art - > getParentNodes ( ) . size ( ) ) ;
2011-01-18 20:56:14 +02:00
art - > setType ( art - > artType ) ;
2011-06-21 12:31:08 +03:00
if ( CCombinedArtifactInstance * cart = dynamic_cast < CCombinedArtifactInstance * > ( art . get ( ) ) )
cart - > createConstituents ( ) ;
2010-11-10 02:06:25 +02:00
}
2009-07-26 06:33:13 +03:00
2011-12-14 00:23:17 +03:00
DLL_LINKAGE const CStackInstance * StackLocation : : getStack ( )
2010-12-14 23:55:23 +02:00
{
if ( ! army - > hasStackAtSlot ( slot ) )
{
2014-03-20 21:17:40 +03:00
logNetwork - > warnStream ( ) < < " Warning: " < < army - > nodeName ( ) < < " don't have a stack at slot " < < slot ;
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-12-14 23:55:23 +02:00
}
return & army - > getStack ( slot ) ;
}
2012-04-14 05:20:22 +03:00
struct ObjectRetriever : boost : : static_visitor < const CArmedInstance * >
{
const CArmedInstance * operator ( ) ( const ConstTransitivePtr < CGHeroInstance > & h ) const
{
return h ;
}
const CArmedInstance * operator ( ) ( const ConstTransitivePtr < CStackInstance > & s ) const
{
return s - > armyObj ;
}
} ;
template < typename T >
struct GetBase : boost : : static_visitor < T * >
{
template < typename TArg >
T * operator ( ) ( TArg & arg ) const
{
return arg ;
}
} ;
2014-02-09 02:07:33 +03:00
DLL_LINKAGE void ArtifactLocation : : removeArtifact ( )
{
CArtifactInstance * a = getArt ( ) ;
assert ( a ) ;
a - > removeFrom ( * this ) ;
}
2012-04-14 05:20:22 +03:00
DLL_LINKAGE const CArmedInstance * ArtifactLocation : : relatedObj ( ) const
{
return boost : : apply_visitor ( ObjectRetriever ( ) , artHolder ) ;
}
2013-03-03 20:06:03 +03:00
DLL_LINKAGE PlayerColor ArtifactLocation : : owningPlayer ( ) const
2012-04-14 05:20:22 +03:00
{
auto obj = relatedObj ( ) ;
2013-03-03 20:06:03 +03:00
return obj ? obj - > tempOwner : PlayerColor : : NEUTRAL ;
2012-04-14 05:20:22 +03:00
}
DLL_LINKAGE CArtifactSet * ArtifactLocation : : getHolderArtSet ( )
{
return boost : : apply_visitor ( GetBase < CArtifactSet > ( ) , artHolder ) ;
}
DLL_LINKAGE CBonusSystemNode * ArtifactLocation : : getHolderNode ( )
{
return boost : : apply_visitor ( GetBase < CBonusSystemNode > ( ) , artHolder ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE const CArtifactInstance * ArtifactLocation : : getArt ( ) const
2010-12-26 16:34:11 +02:00
{
const ArtSlotInfo * s = getSlot ( ) ;
2010-12-29 23:04:22 +02:00
if ( s & & s - > artifact )
{
if ( ! s - > locked )
return s - > artifact ;
else
{
2013-04-09 17:31:36 +03:00
logNetwork - > warnStream ( ) < < " ArtifactLocation::getArt: That location is locked! " ;
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-12-29 23:04:22 +02:00
}
}
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-12-26 16:34:11 +02:00
}
2012-04-14 05:20:22 +03:00
DLL_LINKAGE const CArtifactSet * ArtifactLocation : : getHolderArtSet ( ) const
{
ArtifactLocation * t = const_cast < ArtifactLocation * > ( this ) ;
return t - > getHolderArtSet ( ) ;
}
DLL_LINKAGE const CBonusSystemNode * ArtifactLocation : : getHolderNode ( ) const
{
ArtifactLocation * t = const_cast < ArtifactLocation * > ( this ) ;
return t - > getHolderNode ( ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE CArtifactInstance * ArtifactLocation : : getArt ( )
2010-12-26 16:34:11 +02:00
{
const ArtifactLocation * t = this ;
return const_cast < CArtifactInstance * > ( t - > getArt ( ) ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE const ArtSlotInfo * ArtifactLocation : : getSlot ( ) const
2010-12-26 16:34:11 +02:00
{
2012-04-14 05:20:22 +03:00
return getHolderArtSet ( ) - > getSlot ( slot ) ;
2010-12-26 16:34:11 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void ChangeStackCount : : applyGs ( CGameState * gs )
2010-11-27 03:46:19 +02:00
{
if ( absoluteValue )
sl . army - > setStackCount ( sl . slot , count ) ;
else
sl . army - > changeStackCount ( sl . slot , count ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetStackType : : applyGs ( CGameState * gs )
2010-11-27 03:46:19 +02:00
{
sl . army - > setStackType ( sl . slot , type ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void EraseStack : : applyGs ( CGameState * gs )
2010-11-27 03:46:19 +02:00
{
sl . army - > eraseStack ( sl . slot ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SwapStacks : : applyGs ( CGameState * gs )
2010-11-27 03:46:19 +02:00
{
2010-11-27 22:17:28 +02:00
CStackInstance * s1 = sl1 . army - > detachStack ( sl1 . slot ) ,
* s2 = sl2 . army - > detachStack ( sl2 . slot ) ;
2010-11-27 03:46:19 +02:00
2010-11-27 22:17:28 +02:00
sl2 . army - > putStack ( sl2 . slot , s1 ) ;
sl1 . army - > putStack ( sl1 . slot , s2 ) ;
2010-11-27 03:46:19 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void InsertNewStack : : applyGs ( CGameState * gs )
2010-11-27 03:46:19 +02:00
{
2013-06-29 16:05:48 +03:00
auto s = new CStackInstance ( stack . type , stack . count ) ;
2010-12-06 01:10:02 +02:00
sl . army - > putStack ( sl . slot , s ) ;
2010-11-27 03:46:19 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void RebalanceStacks : : applyGs ( CGameState * gs )
2010-11-27 03:46:19 +02:00
{
2010-12-06 01:10:02 +02:00
const CCreature * srcType = src . army - > getCreature ( src . slot ) ;
TQuantity srcCount = src . army - > getStackCount ( src . slot ) ;
2012-08-24 12:37:52 +03:00
bool stackExp = VLC - > modh - > modules . STACK_EXP ;
2010-12-06 01:10:02 +02:00
if ( srcCount = = count ) //moving whole stack
{
if ( const CCreature * c = dst . army - > getCreature ( dst . slot ) ) //stack at dest -> merge
{
assert ( c = = srcType ) ;
2013-11-09 16:49:36 +03:00
UNUSED ( c ) ;
2013-03-05 10:34:52 +03:00
auto alHere = ArtifactLocation ( src . getStack ( ) , ArtifactPosition : : CREATURE_SLOT ) ;
auto alDest = ArtifactLocation ( dst . getStack ( ) , ArtifactPosition : : CREATURE_SLOT ) ;
auto artHere = alHere . getArt ( ) ;
auto artDest = alDest . getArt ( ) ;
if ( artHere )
{
if ( alDest . getArt ( ) )
{
auto hero = dynamic_cast < CGHeroInstance * > ( src . army . get ( ) ) ;
if ( hero )
{
artDest - > move ( alDest , ArtifactLocation ( hero , alDest . getArt ( ) - > firstBackpackSlot ( hero ) ) ) ;
}
//else - artifact cna be lost :/
else
{
2013-04-09 17:31:36 +03:00
logNetwork - > warnStream ( ) < < " Artifact is present at destination slot! " ;
2013-03-05 10:34:52 +03:00
}
artHere - > move ( alHere , alDest ) ;
//TODO: choose from dialog
}
else //just move to the other slot before stack gets erased
{
artHere - > move ( alHere , alDest ) ;
}
}
2012-08-24 12:37:52 +03:00
if ( stackExp )
2011-03-27 12:31:14 +03:00
{
ui64 totalExp = srcCount * src . army - > getStackExperience ( src . slot ) + dst . army - > getStackCount ( dst . slot ) * dst . army - > getStackExperience ( dst . slot ) ;
src . army - > eraseStack ( src . slot ) ;
dst . army - > changeStackCount ( dst . slot , count ) ;
dst . army - > setStackExp ( dst . slot , totalExp / ( dst . army - > getStackCount ( dst . slot ) ) ) ; //mean
}
else
{
src . army - > eraseStack ( src . slot ) ;
dst . army - > changeStackCount ( dst . slot , count ) ;
}
2010-12-06 01:10:02 +02:00
}
2011-03-27 12:31:14 +03:00
else //move stack to an empty slot, no exp change needed
2010-12-06 01:10:02 +02:00
{
CStackInstance * stackDetached = src . army - > detachStack ( src . slot ) ;
dst . army - > putStack ( dst . slot , stackDetached ) ;
}
}
else
{
if ( const CCreature * c = dst . army - > getCreature ( dst . slot ) ) //stack at dest -> rebalance
{
assert ( c = = srcType ) ;
2013-11-09 16:49:36 +03:00
UNUSED ( c ) ;
2012-08-24 12:37:52 +03:00
if ( stackExp )
2011-03-27 12:31:14 +03:00
{
ui64 totalExp = srcCount * src . army - > getStackExperience ( src . slot ) + dst . army - > getStackCount ( dst . slot ) * dst . army - > getStackExperience ( dst . slot ) ;
src . army - > changeStackCount ( src . slot , - count ) ;
dst . army - > changeStackCount ( dst . slot , count ) ;
dst . army - > setStackExp ( dst . slot , totalExp / ( src . army - > getStackCount ( src . slot ) + dst . army - > getStackCount ( dst . slot ) ) ) ; //mean
}
else
{
src . army - > changeStackCount ( src . slot , - count ) ;
dst . army - > changeStackCount ( dst . slot , count ) ;
}
2010-12-06 01:10:02 +02:00
}
else //split stack to an empty slot
{
src . army - > changeStackCount ( src . slot , - count ) ;
dst . army - > addToSlot ( dst . slot , srcType - > idNumber , count , false ) ;
2012-08-24 12:37:52 +03:00
if ( stackExp )
2011-03-27 12:31:14 +03:00
dst . army - > setStackExp ( dst . slot , src . army - > getStackExperience ( src . slot ) ) ;
2010-12-06 01:10:02 +02:00
}
}
2012-03-06 19:59:55 +03:00
CBonusSystemNode : : treeHasChanged ( ) ;
2010-11-27 03:46:19 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void PutArtifact : : applyGs ( CGameState * gs )
2010-12-26 16:34:11 +02:00
{
assert ( art - > canBePutAt ( al ) ) ;
2012-04-14 05:20:22 +03:00
art - > putAt ( al ) ;
//al.hero->putArtifact(al.slot, art);
2010-12-26 16:34:11 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void EraseArtifact : : applyGs ( CGameState * gs )
2010-12-26 16:34:11 +02:00
{
2014-02-09 02:07:33 +03:00
al . removeArtifact ( ) ;
2010-12-26 16:34:11 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void MoveArtifact : : applyGs ( CGameState * gs )
2010-12-26 16:34:11 +02:00
{
2011-01-06 22:00:19 +02:00
CArtifactInstance * a = src . getArt ( ) ;
2011-12-14 00:23:17 +03:00
if ( dst . slot < GameConstants : : BACKPACK_START )
2011-01-15 04:17:56 +02:00
assert ( ! dst . getArt ( ) ) ;
2011-01-22 05:43:20 +02:00
2011-01-15 19:58:08 +02:00
a - > move ( src , dst ) ;
2012-02-17 22:30:40 +03:00
2014-03-23 15:59:03 +03:00
//TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game?
2014-12-24 17:49:12 +02:00
if ( a - > artType - > id = = ArtifactID : : TITANS_THUNDER & & dst . slot = = ArtifactPosition : : RIGHT_HAND ) //Titan's Thunder creates new spellbook on equip
2012-04-14 05:20:22 +03:00
{
auto hPtr = boost : : get < ConstTransitivePtr < CGHeroInstance > > ( & dst . artHolder ) ;
if ( hPtr )
{
CGHeroInstance * h = * hPtr ;
if ( h & & ! h - > hasSpellbook ( ) )
2013-02-19 01:37:22 +03:00
gs - > giveHeroArtifact ( h , ArtifactID : : SPELLBOOK ) ;
2012-04-14 05:20:22 +03:00
}
}
2010-12-26 16:34:11 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void AssembledArtifact : : applyGs ( CGameState * gs )
2011-01-22 05:43:20 +02:00
{
2012-04-14 05:20:22 +03:00
CArtifactSet * artSet = al . getHolderArtSet ( ) ;
2011-01-22 05:43:20 +02:00
const CArtifactInstance * transformedArt = al . getArt ( ) ;
assert ( transformedArt ) ;
2012-04-14 05:20:22 +03:00
assert ( vstd : : contains ( transformedArt - > assemblyPossibilities ( artSet ) , builtArt ) ) ;
2013-11-09 16:49:36 +03:00
UNUSED ( transformedArt ) ;
2011-01-22 05:43:20 +02:00
2013-06-29 16:05:48 +03:00
auto combinedArt = new CCombinedArtifactInstance ( builtArt ) ;
2011-01-28 04:11:58 +02:00
gs - > map - > addNewArtifactInstance ( combinedArt ) ;
2011-09-24 04:15:36 +03:00
//retrieve all constituents
2013-06-29 16:05:48 +03:00
for ( const CArtifact * constituent : * builtArt - > constituents )
2011-01-22 05:43:20 +02:00
{
2013-03-02 21:41:25 +03:00
ArtifactPosition pos = artSet - > getArtPos ( constituent - > id ) ;
2011-01-22 05:43:20 +02:00
assert ( pos > = 0 ) ;
2012-04-14 05:20:22 +03:00
CArtifactInstance * constituentInstance = artSet - > getArt ( pos ) ;
2011-01-22 05:43:20 +02:00
//move constituent from hero to be part of new, combined artifact
2012-09-28 23:49:23 +03:00
constituentInstance - > removeFrom ( ArtifactLocation ( al . artHolder , pos ) ) ;
2011-01-22 05:43:20 +02:00
combinedArt - > addAsConstituent ( constituentInstance , pos ) ;
2012-04-14 05:20:22 +03:00
if ( ! vstd : : contains ( combinedArt - > artType - > possibleSlots [ artSet - > bearerType ( ) ] , al . slot ) & & vstd : : contains ( combinedArt - > artType - > possibleSlots [ artSet - > bearerType ( ) ] , pos ) )
2011-01-28 04:11:58 +02:00
al . slot = pos ;
2011-01-22 05:43:20 +02:00
}
//put new combined artifacts
2012-04-14 05:20:22 +03:00
combinedArt - > putAt ( al ) ;
2011-01-22 05:43:20 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void DisassembledArtifact : : applyGs ( CGameState * gs )
2011-01-22 05:43:20 +02:00
{
2011-01-24 01:49:17 +02:00
CCombinedArtifactInstance * disassembled = dynamic_cast < CCombinedArtifactInstance * > ( al . getArt ( ) ) ;
assert ( disassembled ) ;
std : : vector < CCombinedArtifactInstance : : ConstituentInfo > constituents = disassembled - > constituentsInfo ;
2012-04-14 05:20:22 +03:00
disassembled - > removeFrom ( al ) ;
2013-06-29 16:05:48 +03:00
for ( CCombinedArtifactInstance : : ConstituentInfo & ci : constituents )
2011-01-24 01:49:17 +02:00
{
2012-04-14 05:20:22 +03:00
ArtifactLocation constituentLoc = al ;
constituentLoc . slot = ( ci . slot > = 0 ? ci . slot : al . slot ) ; //-1 is slot of main constituent -> it'll replace combined artifact in its pos
2011-01-28 04:11:58 +02:00
disassembled - > detachFrom ( ci . art ) ;
2012-04-14 05:20:22 +03:00
ci . art - > putAt ( constituentLoc ) ;
2011-01-24 01:49:17 +02:00
}
2011-01-28 04:11:58 +02:00
gs - > map - > eraseArtifactInstance ( disassembled ) ;
2011-01-22 05:43:20 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void HeroVisit : : applyGs ( CGameState * gs )
2011-05-10 01:20:47 +03:00
{
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetAvailableArtifacts : : applyGs ( CGameState * gs )
2010-06-26 19:02:10 +03:00
{
if ( id > = 0 )
{
2010-12-19 00:11:28 +02:00
if ( CGBlackMarket * bm = dynamic_cast < CGBlackMarket * > ( gs - > map - > objects [ id ] . get ( ) ) )
2010-06-26 19:02:10 +03:00
{
bm - > artifacts = arts ;
}
else
{
2013-04-09 17:31:36 +03:00
logNetwork - > errorStream ( ) < < " Wrong black market id! " ;
2010-06-26 19:02:10 +03:00
}
}
else
{
CGTownInstance : : merchantArtifacts = arts ;
}
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void NewTurn : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
gs - > day = day ;
2013-06-29 16:05:48 +03:00
for ( NewTurn : : Hero h : heroes ) //give mana/movement point
2009-03-07 17:55:56 +02:00
{
2009-04-04 01:34:31 +03:00
CGHeroInstance * hero = gs - > getHero ( h . id ) ;
hero - > movement = h . move ;
hero - > mana = h . mana ;
2009-03-07 17:55:56 +02:00
}
2013-03-03 20:06:03 +03:00
for ( auto i = res . cbegin ( ) ; i ! = res . cend ( ) ; i + + )
2009-11-28 03:42:08 +02:00
{
2013-03-03 20:06:03 +03:00
assert ( i - > first < PlayerColor : : PLAYER_LIMIT ) ;
2011-07-05 09:14:07 +03:00
gs - > getPlayer ( i - > first ) - > resources = i - > second ;
2009-11-28 03:42:08 +02:00
}
2009-03-07 17:55:56 +02:00
2013-06-29 16:05:48 +03:00
for ( auto creatureSet : cres ) //set available creatures in towns
2013-03-14 23:44:00 +03:00
creatureSet . second . applyGs ( gs ) ;
2009-03-07 17:55:56 +02:00
2011-08-26 23:32:05 +03:00
gs - > globalEffects . popBonuses ( Bonus : : OneDay ) ; //works for children -> all game objs
2013-02-02 11:29:57 +03:00
if ( gs - > getDate ( Date : : DAY_OF_WEEK ) = = 1 ) //new week
2011-08-26 23:32:05 +03:00
gs - > globalEffects . popBonuses ( Bonus : : OneWeek ) ; //works for children -> all game objs
2010-08-24 17:26:57 +03:00
2011-08-26 23:32:05 +03:00
//TODO not really a single root hierarchy, what about bonuses placed elsewhere? [not an issue with H3 mechanics but in the future...]
2010-08-24 17:26:57 +03:00
2013-06-29 16:05:48 +03:00
for ( CGTownInstance * t : gs - > map - > towns )
2011-08-26 23:32:05 +03:00
t - > builded = 0 ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetObjectProperty : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2013-02-14 02:55:42 +03:00
CGObjectInstance * obj = gs - > getObjInstance ( id ) ;
2009-03-07 17:55:56 +02:00
if ( ! obj )
2009-08-22 16:59:15 +03:00
{
2013-04-09 17:31:36 +03:00
logNetwork - > errorStream ( ) < < " Wrong object ID - property cannot be set! " ;
2009-08-22 16:59:15 +03:00
return ;
}
2011-03-08 09:40:14 +02:00
CArmedInstance * cai = dynamic_cast < CArmedInstance * > ( obj ) ;
if ( what = = ObjProperty : : OWNER & & cai )
2009-08-22 16:59:15 +03:00
{
2012-09-23 21:01:04 +03:00
if ( obj - > ID = = Obj : : TOWN )
2011-02-21 06:13:00 +02:00
{
2011-03-08 09:40:14 +02:00
CGTownInstance * t = static_cast < CGTownInstance * > ( obj ) ;
2013-03-03 20:06:03 +03:00
if ( t - > tempOwner < PlayerColor : : PLAYER_LIMIT )
2011-03-08 09:40:14 +02:00
gs - > getPlayer ( t - > tempOwner ) - > towns - = t ;
2013-03-03 20:06:03 +03:00
if ( val < PlayerColor : : PLAYER_LIMIT_I )
gs - > getPlayer ( PlayerColor ( val ) ) - > towns . push_back ( t ) ;
2011-02-21 06:13:00 +02:00
}
2011-03-08 09:40:14 +02:00
CBonusSystemNode * nodeToMove = cai - > whatShouldBeAttached ( ) ;
nodeToMove - > detachFrom ( cai - > whereShouldBeAttached ( gs ) ) ;
obj - > setProperty ( what , val ) ;
nodeToMove - > attachTo ( cai - > whereShouldBeAttached ( gs ) ) ;
2009-08-22 16:59:15 +03:00
}
2011-03-08 09:40:14 +02:00
else //not an armed instance
2011-02-22 11:47:25 +02:00
{
obj - > setProperty ( what , val ) ;
}
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void HeroLevelUp : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2014-04-10 20:11:09 +03:00
CGHeroInstance * h = gs - > getHero ( hero - > id ) ;
h - > levelUp ( skills ) ;
2009-03-07 17:55:56 +02:00
}
2012-05-16 20:29:05 +03:00
DLL_LINKAGE void CommanderLevelUp : : applyGs ( CGameState * gs )
{
2013-04-20 14:34:01 +03:00
CCommanderInstance * commander = gs - > getHero ( hero - > id ) - > commander ;
2012-05-18 17:02:27 +03:00
assert ( commander ) ;
2012-05-16 20:29:05 +03:00
commander - > levelUp ( ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleStart : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
gs - > curB = info ;
2010-12-23 02:33:48 +02:00
gs - > curB - > localInit ( ) ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleNextRound : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2011-10-09 10:20:23 +03:00
for ( int i = 0 ; i < 2 ; + + i )
{
2013-07-22 01:01:29 +03:00
gs - > curB - > sides [ i ] . castSpellsCount = 0 ;
vstd : : amax ( - - gs - > curB - > sides [ i ] . enchanterCounter , 0 ) ;
2011-10-09 10:20:23 +03:00
}
2009-03-07 17:55:56 +02:00
gs - > curB - > round = round ;
2013-06-29 16:05:48 +03:00
for ( CStack * s : gs - > curB - > stacks )
2009-03-07 17:55:56 +02:00
{
2011-12-14 00:23:17 +03:00
s - > state - = EBattleStackState : : DEFENDING ;
s - > state - = EBattleStackState : : WAITING ;
s - > state - = EBattleStackState : : MOVED ;
s - > state - = EBattleStackState : : HAD_MORALE ;
s - > state - = EBattleStackState : : FEAR ;
2012-04-17 17:50:23 +03:00
s - > state - = EBattleStackState : : DRAINED_MANA ;
2010-05-02 21:20:26 +03:00
s - > counterAttacks = 1 + s - > valOfBonuses ( Bonus : : ADDITIONAL_RETALIATION ) ;
2011-04-25 12:03:13 +03:00
// new turn effects
2011-02-21 06:13:00 +02:00
s - > battleTurnPassed ( ) ;
2009-03-07 17:55:56 +02:00
}
2012-05-18 23:50:16 +03:00
2013-06-29 16:05:48 +03:00
for ( auto & obst : gs - > curB - > obstacles )
2012-05-18 23:50:16 +03:00
obst - > battleTurnPassed ( ) ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleSetActiveStack : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
gs - > curB - > activeStack = stack ;
CStack * st = gs - > curB - > getStack ( stack ) ;
2011-01-18 19:23:31 +02:00
//remove bonuses that last until when stack gets new turn
2015-04-13 08:43:46 +02:00
st - > popBonuses ( Bonus : : UntilGetsTurn ) ;
2011-01-18 19:23:31 +02:00
2011-12-14 00:23:17 +03:00
if ( vstd : : contains ( st - > state , EBattleStackState : : MOVED ) ) //if stack is moving second time this turn it must had a high morale bonus
st - > state . insert ( EBattleStackState : : HAD_MORALE ) ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleTriggerEffect : : applyGs ( CGameState * gs )
2011-10-08 16:02:58 +03:00
{
CStack * st = gs - > curB - > getStack ( stackID ) ;
switch ( effect )
{
case Bonus : : HP_REGENERATION :
st - > firstHPleft + = val ;
2011-12-14 00:23:17 +03:00
vstd : : amin ( st - > firstHPleft , ( ui32 ) st - > MaxHealth ( ) ) ;
2011-10-08 16:02:58 +03:00
break ;
case Bonus : : MANA_DRAIN :
{
2013-02-14 02:55:42 +03:00
CGHeroInstance * h = gs - > getHero ( ObjectInstanceID ( additionalInfo ) ) ;
2012-04-17 17:50:23 +03:00
st - > state . insert ( EBattleStackState : : DRAINED_MANA ) ;
2011-10-08 16:02:58 +03:00
h - > mana - = val ;
2011-12-14 00:23:17 +03:00
vstd : : amax ( h - > mana , 0 ) ;
2011-10-08 16:02:58 +03:00
break ;
}
case Bonus : : POISON :
{
2013-07-02 15:08:30 +03:00
Bonus * b = st - > getBonusLocalFirst ( Selector : : source ( Bonus : : SPELL_EFFECT , 71 )
. And ( Selector : : type ( Bonus : : STACK_HEALTH ) ) ) ;
2011-10-08 16:02:58 +03:00
if ( b )
b - > val = val ;
break ;
}
case Bonus : : ENCHANTER :
2011-10-08 20:10:43 +03:00
break ;
2011-10-08 16:02:58 +03:00
case Bonus : : FEAR :
2011-12-14 00:23:17 +03:00
st - > state . insert ( EBattleStackState : : FEAR ) ;
2011-10-08 20:10:43 +03:00
break ;
2011-10-08 16:02:58 +03:00
default :
2013-04-09 17:31:36 +03:00
logNetwork - > warnStream ( ) < < " Unrecognized trigger effect type " < < type ;
2011-10-08 16:02:58 +03:00
}
}
2012-05-05 00:16:39 +03:00
DLL_LINKAGE void BattleObstaclePlaced : : applyGs ( CGameState * gs )
{
gs - > curB - > obstacles . push_back ( obstacle ) ;
}
2009-03-07 19:08:40 +02:00
void BattleResult : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2013-06-29 16:05:48 +03:00
for ( CStack * s : gs - > curB - > stacks )
2011-05-25 23:44:18 +03:00
{
2012-07-17 11:52:27 +03:00
if ( s - > base & & s - > base - > armyObj & & vstd : : contains ( s - > state , EBattleStackState : : SUMMONED ) )
2011-05-25 23:44:18 +03:00
{
2012-07-17 11:52:27 +03:00
//stack with SUMMONED flag but coming from garrison -> most likely resurrected, needs to be removed
2011-05-25 23:44:18 +03:00
assert ( & s - > base - > armyObj - > getStack ( s - > slot ) = = s - > base ) ;
const_cast < CArmedInstance * > ( s - > base - > armyObj ) - > eraseStack ( s - > slot ) ;
}
}
2013-06-29 16:05:48 +03:00
for ( auto & elem : gs - > curB - > stacks )
delete elem ;
2009-03-07 17:55:56 +02:00
2013-07-22 01:01:29 +03:00
for ( int i = 0 ; i < 2 ; + + i )
2012-05-07 15:54:22 +03:00
{
2013-07-22 01:01:29 +03:00
if ( auto h = gs - > curB - > battleGetFightingHero ( i ) )
2012-05-07 15:54:22 +03:00
{
2015-04-11 06:18:40 +02:00
h - > popBonuses ( Bonus : : OneBattle ) ; //remove any "until next battle" bonuses
2012-07-16 19:18:02 +03:00
if ( h - > commander & & h - > commander - > alive )
{
2013-06-29 16:05:48 +03:00
for ( auto art : h - > commander - > artifactsWorn ) //increment bonuses for commander artifacts
2012-07-16 19:18:02 +03:00
{
art . second . artifact - > artType - > levelUpArtifact ( art . second . artifact ) ;
}
}
2012-05-07 15:54:22 +03:00
}
}
2009-03-07 17:55:56 +02:00
2013-07-22 01:01:29 +03:00
if ( VLC - > modh - > modules . STACK_EXP )
2011-02-13 15:11:09 +02:00
{
2013-07-22 01:01:29 +03:00
for ( int i = 0 ; i < 2 ; i + + )
if ( exp [ i ] )
gs - > curB - > battleGetArmyObject ( i ) - > giveStackExp ( exp [ i ] ) ;
2014-02-15 12:40:33 +03:00
2012-03-06 19:59:55 +03:00
CBonusSystemNode : : treeHasChanged ( ) ;
2011-02-13 15:11:09 +02:00
}
2013-07-22 01:01:29 +03:00
for ( int i = 0 ; i < 2 ; i + + )
gs - > curB - > battleGetArmyObject ( i ) - > battle = nullptr ;
2010-12-26 16:34:11 +02:00
gs - > curB . dellNull ( ) ;
2009-03-07 17:55:56 +02:00
}
2009-03-07 19:08:40 +02:00
void BattleStackMoved : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2012-05-05 00:16:39 +03:00
CStack * s = gs - > curB - > getStack ( stack ) ;
2014-11-28 19:39:23 +02:00
assert ( s ) ;
2012-05-05 00:16:39 +03:00
BattleHex dest = tilesToMove . back ( ) ;
//if unit ended movement on quicksands that were created by enemy, that quicksand patch becomes visible for owner
2013-06-29 16:05:48 +03:00
for ( auto & oi : gs - > curB - > obstacles )
2012-05-05 00:16:39 +03:00
{
2012-05-18 23:50:16 +03:00
if ( oi - > obstacleType = = CObstacleInstance : : QUICKSAND
& & vstd : : contains ( oi - > getAffectedTiles ( ) , tilesToMove . back ( ) ) )
2012-05-05 00:16:39 +03:00
{
2012-05-18 23:50:16 +03:00
SpellCreatedObstacle * sands = dynamic_cast < SpellCreatedObstacle * > ( oi . get ( ) ) ;
assert ( sands ) ;
if ( sands - > casterSide ! = ! s - > attackerOwned )
sands - > visibleForAnotherSide = true ;
2012-05-05 00:16:39 +03:00
}
}
s - > position = dest ;
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleStackAttacked : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CStack * at = gs - > curB - > getStack ( stackAttacked ) ;
2012-08-26 12:07:48 +03:00
assert ( at ) ;
2010-05-02 21:20:26 +03:00
at - > count = newAmount ;
2009-03-07 17:55:56 +02:00
at - > firstHPleft = newHP ;
2011-07-08 17:54:20 +03:00
2009-03-07 17:55:56 +02:00
if ( killed ( ) )
2011-07-08 17:54:20 +03:00
{
2011-12-14 00:23:17 +03:00
at - > state - = EBattleStackState : : ALIVE ;
2011-07-08 17:54:20 +03:00
}
2010-05-07 15:29:41 +03:00
//life drain handling
2013-06-29 16:05:48 +03:00
for ( auto & elem : healedStacks )
2010-05-07 15:29:41 +03:00
{
2013-06-29 16:05:48 +03:00
elem . applyGs ( gs ) ;
2010-05-07 15:29:41 +03:00
}
2011-07-08 17:54:20 +03:00
if ( willRebirth ( ) )
{
at - > casts - - ;
2011-12-14 00:23:17 +03:00
at - > state . insert ( EBattleStackState : : ALIVE ) ; //hmm?
2011-07-08 17:54:20 +03:00
}
2012-02-18 20:39:47 +03:00
if ( cloneKilled ( ) )
{
2013-09-08 20:43:10 +03:00
//"hide" killed creatures instead so we keep info about it
at - > state . insert ( EBattleStackState : : DEAD_CLONE ) ;
2012-02-18 20:39:47 +03:00
}
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleAttack : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CStack * attacker = gs - > curB - > getStack ( stackAttacking ) ;
if ( counter ( ) )
attacker - > counterAttacks - - ;
2013-01-12 21:08:33 +03:00
2009-03-07 17:55:56 +02:00
if ( shot ( ) )
2010-05-20 13:54:24 +03:00
{
//don't remove ammo if we have a working ammo cart
bool hasAmmoCart = false ;
2013-06-29 16:05:48 +03:00
for ( const CStack * st : gs - > curB - > stacks )
2010-05-20 13:54:24 +03:00
{
2013-02-07 20:34:50 +03:00
if ( st - > owner = = attacker - > owner & & st - > getCreature ( ) - > idNumber = = CreatureID : : AMMO_CART & & st - > alive ( ) )
2010-05-20 13:54:24 +03:00
{
hasAmmoCart = true ;
break ;
}
}
if ( ! hasAmmoCart )
{
attacker - > shots - - ;
}
}
2013-06-29 16:05:48 +03:00
for ( BattleStackAttacked stackAttacked : bsa )
2009-03-21 14:49:58 +02:00
stackAttacked . applyGs ( gs ) ;
2009-08-07 14:22:17 +03:00
2015-04-13 08:28:00 +02:00
attacker - > popBonuses ( Bonus : : UntilAttack ) ;
2009-08-07 14:22:17 +03:00
2013-06-29 16:05:48 +03:00
for ( auto & elem : bsa )
2009-08-07 14:22:17 +03:00
{
2013-06-29 16:05:48 +03:00
CStack * stack = gs - > curB - > getStack ( elem . stackAttacked , false ) ;
2012-02-18 20:39:47 +03:00
if ( stack ) //cloned stack is already gone
2015-04-13 08:28:00 +02:00
stack - > popBonuses ( Bonus : : UntilBeingAttacked ) ;
2009-08-07 14:22:17 +03:00
}
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void StartAction : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
CStack * st = gs - > curB - > getStack ( ba . stackNumber ) ;
2009-09-10 14:28:34 +03:00
2013-02-04 00:05:44 +03:00
if ( ba . actionType = = Battle : : END_TACTIC_PHASE )
2011-02-12 18:12:48 +02:00
{
gs - > curB - > tacticDistance = 0 ;
return ;
}
2012-03-27 23:08:54 +03:00
if ( gs - > curB - > tacticDistance )
{
// moves in tactics phase do not affect creature status
// (tactics stack queue is managed by client)
return ;
}
2013-02-04 00:05:44 +03:00
if ( ba . actionType ! = Battle : : HERO_SPELL ) //don't check for stack if it's custom action by hero
2011-02-11 21:12:08 +02:00
{
2009-09-10 14:28:34 +03:00
assert ( st ) ;
2011-02-11 21:12:08 +02:00
}
else
{
2013-07-22 01:01:29 +03:00
gs - > curB - > sides [ ba . side ] . usedSpellsHistory . push_back ( SpellID ( ba . additionalInfo ) . toSpell ( ) ) ;
2011-02-11 21:12:08 +02:00
}
2009-09-10 14:28:34 +03:00
2009-03-07 17:55:56 +02:00
switch ( ba . actionType )
{
2013-02-04 00:05:44 +03:00
case Battle : : DEFEND :
2011-12-14 00:23:17 +03:00
st - > state . insert ( EBattleStackState : : DEFENDING ) ;
2009-03-07 17:55:56 +02:00
break ;
2013-02-04 00:05:44 +03:00
case Battle : : WAIT :
2011-12-14 00:23:17 +03:00
st - > state . insert ( EBattleStackState : : WAITING ) ;
2009-11-21 00:35:18 +02:00
return ;
2013-02-04 00:05:44 +03:00
case Battle : : HERO_SPELL : //no change in current stack state
2011-10-01 22:56:54 +03:00
return ;
default : //any active stack action - attack, catapult, heal, spell...
2011-12-14 00:23:17 +03:00
st - > state . insert ( EBattleStackState : : MOVED ) ;
2009-03-07 17:55:56 +02:00
break ;
}
2009-11-21 00:35:18 +02:00
2009-11-28 03:42:08 +02:00
if ( st )
2011-12-14 00:23:17 +03:00
st - > state - = EBattleStackState : : WAITING ; //if stack was waiting it has made move, so it won't be "waiting" anymore (if the action was WAIT, then we have returned)
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleSpellCast : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2010-05-02 21:20:26 +03:00
assert ( gs - > curB ) ;
2012-09-14 02:41:03 +03:00
2014-11-25 22:59:21 +02:00
const CSpell * spell = SpellID ( id ) . toSpell ( ) ;
2015-03-10 22:14:58 +02:00
2015-01-30 17:40:15 +02:00
spell - > applyBattle ( gs - > curB , this ) ;
2009-03-07 17:55:56 +02:00
}
2011-04-23 12:57:51 +03:00
void actualizeEffect ( CStack * s , const Bonus & ef )
{
2013-06-29 16:05:48 +03:00
for ( Bonus * stackBonus : s - > getBonusList ( ) ) //TODO: optimize
2011-04-23 12:57:51 +03:00
{
if ( stackBonus - > source = = Bonus : : SPELL_EFFECT & & stackBonus - > type = = ef . type & & stackBonus - > subtype = = ef . subtype )
{
stackBonus - > turnsRemain = std : : max ( stackBonus - > turnsRemain , ef . turnsRemain ) ;
}
}
2015-04-13 07:51:23 +02:00
CBonusSystemNode : : treeHasChanged ( ) ;
}
void actualizeEffect ( CStack * s , const std : : vector < Bonus > & ef )
{
//actualizing features vector
for ( const Bonus & fromEffect : ef )
{
actualizeEffect ( s , fromEffect ) ;
}
2009-05-17 18:24:50 +03:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void SetStackEffect : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
2014-03-07 16:21:09 +03:00
if ( effect . empty ( ) )
{
logGlobal - > errorStream ( ) < < " Trying to apply SetStackEffect with no effects " ;
return ;
}
2011-04-25 12:03:13 +03:00
int spellid = effect . begin ( ) - > sid ; //effects' source ID
2011-04-23 12:57:51 +03:00
2013-06-29 16:05:48 +03:00
for ( ui32 id : stacks )
2009-03-21 14:49:58 +02:00
{
CStack * s = gs - > curB - > getStack ( id ) ;
if ( s )
2009-04-17 17:01:22 +03:00
{
2013-02-11 02:24:57 +03:00
if ( spellid = = SpellID : : DISRUPTING_RAY | | spellid = = SpellID : : ACID_BREATH_DEFENSE | | ! s - > hasBonus ( Selector : : source ( Bonus : : SPELL_EFFECT , spellid ) ) ) //disrupting ray or acid breath or not on the list - just add
2009-05-16 17:49:06 +03:00
{
2013-06-29 16:05:48 +03:00
for ( Bonus & fromEffect : effect )
2009-05-16 17:49:06 +03:00
{
2013-05-19 22:53:03 +03:00
logBonus - > traceStream ( ) < < s - > nodeName ( ) < < " receives a new bonus: " < < fromEffect . Description ( ) ;
2011-01-20 21:57:12 +02:00
s - > addNewBonus ( new Bonus ( fromEffect ) ) ;
2009-05-16 17:49:06 +03:00
}
2009-05-17 18:24:50 +03:00
}
else //just actualize
{
actualizeEffect ( s , effect ) ;
2009-05-16 17:49:06 +03:00
}
2009-04-17 17:01:22 +03:00
}
2009-03-21 14:49:58 +02:00
else
2013-04-09 17:31:36 +03:00
logNetwork - > errorStream ( ) < < " Cannot find stack " < < id ;
2009-03-21 14:49:58 +02:00
}
2011-04-23 12:57:51 +03:00
typedef std : : pair < ui32 , Bonus > p ;
2013-06-29 16:05:48 +03:00
for ( p para : uniqueBonuses )
2011-04-23 12:57:51 +03:00
{
CStack * s = gs - > curB - > getStack ( para . first ) ;
if ( s )
{
2013-07-02 15:08:30 +03:00
if ( ! s - > hasBonus ( Selector : : source ( Bonus : : SPELL_EFFECT , spellid ) . And ( Selector : : typeSubtype ( para . second . type , para . second . subtype ) ) ) )
2011-04-23 12:57:51 +03:00
s - > addNewBonus ( new Bonus ( para . second ) ) ;
else
actualizeEffect ( s , effect ) ;
}
else
2013-04-09 17:31:36 +03:00
logNetwork - > errorStream ( ) < < " Cannot find stack " < < para . first ;
2011-04-23 12:57:51 +03:00
}
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void StacksInjured : : applyGs ( CGameState * gs )
2009-04-16 03:28:54 +03:00
{
2013-06-29 16:05:48 +03:00
for ( BattleStackAttacked stackAttacked : stacks )
2009-04-16 03:28:54 +03:00
stackAttacked . applyGs ( gs ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void StacksHealedOrResurrected : : applyGs ( CGameState * gs )
2009-08-04 20:05:49 +03:00
{
2013-06-29 16:05:48 +03:00
for ( auto & elem : healedStacks )
2009-08-04 20:05:49 +03:00
{
2013-06-29 16:05:48 +03:00
CStack * changedStack = gs - > curB - > getStack ( elem . stackID , false ) ;
2009-08-17 14:22:29 +03:00
//checking if we resurrect a stack that is under a living stack
2012-08-26 12:07:48 +03:00
auto accessibility = gs - > curB - > getAccesibility ( ) ;
2013-01-12 21:08:33 +03:00
2012-08-26 12:07:48 +03:00
if ( ! changedStack - > alive ( ) & & ! accessibility . accessible ( changedStack - > position , changedStack ) )
{
2013-04-09 17:31:36 +03:00
logNetwork - > errorStream ( ) < < " Cannot resurrect " < < changedStack - > nodeName ( ) < < " because hex " < < changedStack - > position < < " is occupied! " ;
2009-08-17 14:22:29 +03:00
return ; //position is already occupied
2012-08-26 12:07:48 +03:00
}
2009-08-17 14:22:29 +03:00
//applying changes
2009-10-17 17:32:42 +03:00
bool resurrected = ! changedStack - > alive ( ) ; //indicates if stack is resurrected or just healed
2010-05-07 15:29:41 +03:00
if ( resurrected )
2009-08-05 15:46:08 +03:00
{
2011-12-14 00:23:17 +03:00
changedStack - > state . insert ( EBattleStackState : : ALIVE ) ;
2009-08-05 15:46:08 +03:00
}
2010-11-09 13:27:58 +02:00
//int missingHPfirst = changedStack->MaxHealth() - changedStack->firstHPleft;
2013-06-29 16:05:48 +03:00
int res = std : : min ( elem . healedHP / changedStack - > MaxHealth ( ) , changedStack - > baseAmount - changedStack - > count ) ;
2010-05-02 21:20:26 +03:00
changedStack - > count + = res ;
2013-07-27 22:01:31 +03:00
if ( elem . lowLevelResurrection )
changedStack - > resurrected + = res ;
2013-06-29 16:05:48 +03:00
changedStack - > firstHPleft + = elem . healedHP - res * changedStack - > MaxHealth ( ) ;
2009-08-05 15:46:08 +03:00
if ( changedStack - > firstHPleft > changedStack - > MaxHealth ( ) )
{
changedStack - > firstHPleft - = changedStack - > MaxHealth ( ) ;
2010-05-02 21:20:26 +03:00
if ( changedStack - > baseAmount > changedStack - > count )
2009-10-17 17:32:42 +03:00
{
2010-05-02 21:20:26 +03:00
changedStack - > count + = 1 ;
2009-10-17 17:32:42 +03:00
}
2009-08-05 15:46:08 +03:00
}
2011-12-14 00:23:17 +03:00
vstd : : amin ( changedStack - > firstHPleft , changedStack - > MaxHealth ( ) ) ;
2009-08-04 20:05:49 +03:00
//removal of negative effects
2009-10-17 17:32:42 +03:00
if ( resurrected )
2009-08-04 20:05:49 +03:00
{
//removing all features from negative spells
2011-07-13 21:39:02 +03:00
const BonusList tmpFeatures = changedStack - > getBonusList ( ) ;
2011-05-25 17:48:49 +03:00
//changedStack->bonuses.clear();
2010-05-02 21:20:26 +03:00
2013-06-29 16:05:48 +03:00
for ( Bonus * b : tmpFeatures )
2009-08-04 20:05:49 +03:00
{
2010-11-19 00:06:56 +02:00
const CSpell * s = b - > sourceSpell ( ) ;
2012-02-17 00:19:07 +03:00
if ( s & & s - > isNegative ( ) )
2009-08-04 20:05:49 +03:00
{
2011-05-25 17:48:49 +03:00
changedStack - > removeBonus ( b ) ;
2009-08-04 20:05:49 +03:00
}
}
}
}
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void ObstaclesRemoved : : applyGs ( CGameState * gs )
2009-08-19 13:59:42 +03:00
{
if ( gs - > curB ) //if there is a battle
{
2013-06-29 16:05:48 +03:00
for ( const si32 rem_obst : obstacles )
2009-08-19 13:59:42 +03:00
{
for ( int i = 0 ; i < gs - > curB - > obstacles . size ( ) ; + + i )
{
2013-01-12 21:08:33 +03:00
if ( gs - > curB - > obstacles [ i ] - > uniqueID = = rem_obst ) //remove this obstacle
2009-08-19 13:59:42 +03:00
{
gs - > curB - > obstacles . erase ( gs - > curB - > obstacles . begin ( ) + i ) ;
break ;
}
}
}
}
}
2014-06-24 17:17:25 +03:00
DLL_LINKAGE CatapultAttack : : CatapultAttack ( )
{
type = 3015 ;
}
DLL_LINKAGE CatapultAttack : : ~ CatapultAttack ( )
{
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void CatapultAttack : : applyGs ( CGameState * gs )
2009-09-01 16:54:13 +03:00
{
2014-06-25 17:11:07 +03:00
if ( gs - > curB & & gs - > curB - > town & & gs - > curB - > town - > fortLevel ( ) ! = CGTownInstance : : NONE ) //if there is a battle and it's a siege
2009-09-01 16:54:13 +03:00
{
2013-06-29 16:05:48 +03:00
for ( const auto & it : attackedParts )
2009-09-07 15:30:10 +03:00
{
2013-08-06 14:20:28 +03:00
gs - > curB - > si . wallState [ it . attackedPart ] =
SiegeInfo : : applyDamage ( EWallState : : EWallState ( gs - > curB - > si . wallState [ it . attackedPart ] ) , it . damageDealt ) ;
2009-09-07 15:30:10 +03:00
}
2009-09-01 16:54:13 +03:00
}
}
2013-12-08 20:54:13 +03:00
DLL_LINKAGE std : : string CatapultAttack : : AttackInfo : : toString ( ) const
{
return boost : : str ( boost : : format ( " {AttackInfo: destinationTile '%d', attackedPart '%d', damageDealt '%d'} " )
% destinationTile % static_cast < int > ( attackedPart ) % static_cast < int > ( damageDealt ) ) ;
}
DLL_LINKAGE std : : ostream & operator < < ( std : : ostream & out , const CatapultAttack : : AttackInfo & attackInfo )
{
return out < < attackInfo . toString ( ) ;
}
DLL_LINKAGE std : : string CatapultAttack : : toString ( ) const
{
return boost : : str ( boost : : format ( " {CatapultAttack: attackedParts '%s', attacker '%d'} " ) % attackedParts % attacker ) ;
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleStacksRemoved : : applyGs ( CGameState * gs )
2009-09-05 17:10:26 +03:00
{
if ( ! gs - > curB )
return ;
2013-06-29 16:05:48 +03:00
for ( ui32 rem_stack : stackIDs )
2009-09-05 17:10:26 +03:00
{
for ( int b = 0 ; b < gs - > curB - > stacks . size ( ) ; + + b ) //find it in vector of stacks
{
2013-01-12 21:08:33 +03:00
if ( gs - > curB - > stacks [ b ] - > ID = = rem_stack ) //if found
2009-09-05 17:10:26 +03:00
{
2012-02-18 23:50:06 +03:00
CStack * toRemove = gs - > curB - > stacks [ b ] ;
2009-09-05 17:10:26 +03:00
gs - > curB - > stacks . erase ( gs - > curB - > stacks . begin ( ) + b ) ; //remove
2012-02-18 23:50:06 +03:00
toRemove - > detachFromAll ( ) ;
delete toRemove ;
2009-09-05 17:10:26 +03:00
break ;
}
}
}
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleStackAdded : : applyGs ( CGameState * gs )
2011-10-01 22:56:54 +03:00
{
2014-11-25 11:26:32 +02:00
newStackID = 0 ;
2011-12-22 16:05:19 +03:00
if ( ! BattleHex ( pos ) . isValid ( ) )
2011-10-01 22:56:54 +03:00
{
2013-04-09 17:31:36 +03:00
logNetwork - > warnStream ( ) < < " No place found for new stack! " ;
2011-10-01 22:56:54 +03:00
return ;
}
2012-02-29 04:31:48 +03:00
CStackBasicDescriptor csbd ( creID , amount ) ;
2013-02-16 17:03:47 +03:00
CStack * addedStack = gs - > curB - > generateNewStack ( csbd , attacker , SlotID ( 255 ) , pos ) ; //TODO: netpacks?
2011-10-01 22:56:54 +03:00
if ( summoned )
2012-02-29 04:31:48 +03:00
addedStack - > state . insert ( EBattleStackState : : SUMMONED ) ;
gs - > curB - > localInitStack ( addedStack ) ;
gs - > curB - > stacks . push_back ( addedStack ) ; //the stack is not "SUMMONED", it is permanent
2015-03-10 22:14:58 +02:00
2014-11-25 11:26:32 +02:00
newStackID = addedStack - > ID ;
2011-10-01 22:56:54 +03:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void BattleSetStackProperty : : applyGs ( CGameState * gs )
2011-10-02 16:59:12 +03:00
{
2011-10-08 12:11:36 +03:00
CStack * stack = gs - > curB - > getStack ( stackID ) ;
2011-10-02 16:59:12 +03:00
switch ( which )
{
case CASTS :
{
if ( absolute )
2011-10-08 12:11:36 +03:00
stack - > casts = val ;
2011-10-02 16:59:12 +03:00
else
2011-10-08 12:11:36 +03:00
stack - > casts + = val ;
2011-12-14 00:23:17 +03:00
vstd : : amax ( stack - > casts , 0 ) ;
2011-10-02 16:59:12 +03:00
break ;
}
2011-10-09 10:20:23 +03:00
case ENCHANTER_COUNTER :
{
2013-07-22 01:01:29 +03:00
auto & counter = gs - > curB - > sides [ gs - > curB - > whatSide ( stack - > owner ) ] . enchanterCounter ;
2011-10-09 10:20:23 +03:00
if ( absolute )
2013-07-22 01:01:29 +03:00
counter = val ;
2011-10-09 10:20:23 +03:00
else
2013-07-22 01:01:29 +03:00
counter + = val ;
vstd : : amax ( counter , 0 ) ;
2011-10-09 10:20:23 +03:00
break ;
}
2011-10-17 11:24:51 +03:00
case UNBIND :
{
stack - > popBonuses ( Selector : : type ( Bonus : : BIND_EFFECT ) ) ;
break ;
}
2012-02-10 16:13:24 +03:00
case CLONED :
{
stack - > state . insert ( EBattleStackState : : CLONED ) ;
break ;
}
2011-10-02 16:59:12 +03:00
}
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE void YourTurn : : applyGs ( CGameState * gs )
2009-03-07 17:55:56 +02:00
{
gs - > currentPlayer = player ;
2013-12-06 22:44:11 +03:00
//count days without town
auto & playerState = gs - > players [ player ] ;
if ( playerState . towns . empty ( ) )
{
2013-12-29 14:27:38 +03:00
if ( playerState . daysWithoutCastle )
+ + ( * playerState . daysWithoutCastle ) ;
2013-12-06 22:44:11 +03:00
else playerState . daysWithoutCastle = 0 ;
}
else
{
playerState . daysWithoutCastle = boost : : none ;
}
2009-03-07 17:55:56 +02:00
}
2011-12-14 00:23:17 +03:00
DLL_LINKAGE Component : : Component ( const CStackBasicDescriptor & stack )
2012-07-19 12:10:55 +03:00
: id ( CREATURE ) , subtype ( stack . type - > idNumber ) , val ( stack . count ) , when ( 0 )
2010-04-02 05:07:40 +03:00
{
2012-07-19 12:10:55 +03:00
type = 2002 ;
2011-09-24 04:15:36 +03:00
}