2017-07-13 10:26:03 +02:00
/*
* NetPacksClient . 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
*
*/
2011-12-14 00:23:17 +03:00
# include "StdInc.h"
2009-03-07 17:55:56 +02:00
# include "../lib/NetPacks.h"
2011-12-14 00:23:17 +03:00
2009-05-20 13:08:56 +03:00
# include "Client.h"
# include "CPlayerInterface.h"
# include "CGameInfo.h"
2023-02-01 20:42:06 +02:00
# include "windows/GUIClasses.h"
# include "adventureMap/mapHandler.h"
# include "adventureMap/CInGameConsole.h"
# include "battle/BattleInterface.h"
# include "gui/CGuiHandler.h"
# include "widgets/MiscWidgets.h"
# include "CMT.h"
# include "CServerHandler.h"
# include "../CCallback.h"
# include "../lib/filesystem/Filesystem.h"
# include "../lib/filesystem/FileInfo.h"
2016-09-10 02:32:40 +02:00
# include "../lib/serializer/Connection.h"
# include "../lib/serializer/BinarySerializer.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CGeneralTextHandler.h"
# include "../lib/CHeroHandler.h"
2009-03-07 17:55:56 +02:00
# include "../lib/VCMI_Lib.h"
2013-04-07 13:48:07 +03:00
# include "../lib/mapping/CMap.h"
2009-10-10 08:47:59 +03:00
# include "../lib/VCMIDirs.h"
2015-02-02 10:25:26 +02:00
# include "../lib/spells/CSpellHandler.h"
2014-06-05 23:51:24 +03:00
# include "../lib/CSoundBase.h"
2014-06-25 17:11:07 +03:00
# include "../lib/StartInfo.h"
2012-09-29 13:59:43 +03:00
# include "../lib/CConfigHandler.h"
2013-04-07 13:48:07 +03:00
# include "../lib/mapping/CCampaignHandler.h"
2010-12-25 21:23:30 +02:00
# include "../lib/CGameState.h"
2017-03-17 17:48:44 +02:00
# include "../lib/CStack.h"
2017-06-24 16:42:05 +02:00
# include "../lib/battle/BattleInfo.h"
2011-12-14 00:23:17 +03:00
# include "../lib/GameConstants.h"
2015-12-02 21:39:53 +02:00
# include "../lib/CPlayerState.h"
2009-03-07 17:55:56 +02:00
2018-02-03 16:44:30 +02:00
// TODO: as Tow suggested these template should all be part of CClient
// This will require rework spectator interface properly though
template < typename T , typename . . . Args , typename . . . Args2 >
bool callOnlyThatInterface ( CClient * cl , PlayerColor player , void ( T : : * ptr ) ( Args . . . ) , Args2 & & . . . args )
{
if ( vstd : : contains ( cl - > playerint , player ) )
{
( ( * cl - > playerint [ player ] ) . * ptr ) ( std : : forward < Args2 > ( args ) . . . ) ;
return true ;
}
return false ;
}
template < typename T , typename . . . Args , typename . . . Args2 >
bool callInterfaceIfPresent ( CClient * cl , PlayerColor player , void ( T : : * ptr ) ( Args . . . ) , Args2 & & . . . args )
{
bool called = callOnlyThatInterface ( cl , player , ptr , std : : forward < Args2 > ( args ) . . . ) ;
return called ;
}
template < typename T , typename . . . Args , typename . . . Args2 >
void callOnlyThatBattleInterface ( CClient * cl , PlayerColor player , void ( T : : * ptr ) ( Args . . . ) , Args2 & & . . . args )
{
if ( vstd : : contains ( cl - > battleints , player ) )
( ( * cl - > battleints [ player ] ) . * ptr ) ( std : : forward < Args2 > ( args ) . . . ) ;
if ( cl - > additionalBattleInts . count ( player ) )
{
for ( auto bInt : cl - > additionalBattleInts [ player ] )
( ( * bInt ) . * ptr ) ( std : : forward < Args2 > ( args ) . . . ) ;
}
}
template < typename T , typename . . . Args , typename . . . Args2 >
void callBattleInterfaceIfPresent ( CClient * cl , PlayerColor player , void ( T : : * ptr ) ( Args . . . ) , Args2 & & . . . args )
{
callOnlyThatInterface ( cl , player , ptr , std : : forward < Args2 > ( args ) . . . ) ;
}
//calls all normal interfaces and privileged ones, playerints may be updated when iterating over it, so we need a copy
template < typename T , typename . . . Args , typename . . . Args2 >
void callAllInterfaces ( CClient * cl , void ( T : : * ptr ) ( Args . . . ) , Args2 & & . . . args )
{
for ( auto pInt : cl - > playerint )
( ( * pInt . second ) . * ptr ) ( std : : forward < Args2 > ( args ) . . . ) ;
}
//calls all normal interfaces and privileged ones, playerints may be updated when iterating over it, so we need a copy
template < typename T , typename . . . Args , typename . . . Args2 >
void callBattleInterfaceIfPresentForBothSides ( CClient * cl , void ( T : : * ptr ) ( Args . . . ) , Args2 & & . . . args )
{
callOnlyThatBattleInterface ( cl , cl - > gameState ( ) - > curB - > sides [ 0 ] . color , ptr , std : : forward < Args2 > ( args ) . . . ) ;
callOnlyThatBattleInterface ( cl , cl - > gameState ( ) - > curB - > sides [ 1 ] . color , ptr , std : : forward < Args2 > ( args ) . . . ) ;
if ( settings [ " session " ] [ " spectate " ] . Bool ( ) & & ! settings [ " session " ] [ " spectate-skip-battle " ] . Bool ( ) & & LOCPLINT - > battleInt )
{
callOnlyThatBattleInterface ( cl , PlayerColor : : SPECTATOR , ptr , std : : forward < Args2 > ( args ) . . . ) ;
}
}
2016-10-28 23:37:20 +02:00
void SetResources : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2016-11-26 14:14:43 +02:00
//todo: inform on actual resource set transfered
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : receivedResource ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void SetPrimSkill : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2011-05-10 01:20:47 +03:00
const CGHeroInstance * h = cl - > getHero ( id ) ;
2009-03-19 16:17:19 +02:00
if ( ! h )
{
2017-08-11 13:38:10 +02:00
logNetwork - > error ( " Cannot find hero with ID %d " , id . getNum ( ) ) ;
2009-03-19 16:17:19 +02:00
return ;
}
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroPrimarySkillChanged , h , which , val ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void SetSecSkill : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2011-05-10 01:20:47 +03:00
const CGHeroInstance * h = cl - > getHero ( id ) ;
2010-07-20 17:08:13 +03:00
if ( ! h )
{
2017-08-11 13:38:10 +02:00
logNetwork - > error ( " Cannot find hero with ID %d " , id . getNum ( ) ) ;
2010-07-20 17:08:13 +03:00
return ;
}
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroSecondarySkillChanged , h , which , val ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void HeroVisitCastle : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2011-05-10 01:20:47 +03:00
const CGHeroInstance * h = cl - > getHero ( hid ) ;
if ( start ( ) )
2009-03-07 17:55:56 +02:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroVisitsTown , h , GS ( cl ) - > getTown ( tid ) ) ;
2009-03-07 17:55:56 +02:00
}
}
2016-10-28 23:37:20 +02:00
void ChangeSpells : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
//TODO: inform interface?
}
2016-10-28 23:37:20 +02:00
void SetMana : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2011-05-10 01:20:47 +03:00
const CGHeroInstance * h = cl - > getHero ( hid ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroManaPointsChanged , h ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void SetMovePoints : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2011-05-10 01:20:47 +03:00
const CGHeroInstance * h = cl - > getHero ( hid ) ;
2014-09-21 16:42:08 +03:00
cl - > invalidatePaths ( ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroMovePointsChanged , h ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void FoWChange : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2013-06-29 16:05:48 +03:00
for ( auto & i : cl - > playerint )
2014-06-21 16:41:05 +03:00
{
if ( cl - > getPlayerRelations ( i . first , player ) = = PlayerRelations : : SAME_PLAYER & & waitForDialogs & & LOCPLINT = = i . second . get ( ) )
{
LOCPLINT - > waitWhileDialog ( ) ;
}
2013-02-04 00:05:44 +03:00
if ( cl - > getPlayerRelations ( i . first , player ) ! = PlayerRelations : : ENEMIES )
2012-02-21 00:01:54 +03:00
{
if ( mode )
i . second - > tileRevealed ( tiles ) ;
else
i . second - > tileHidden ( tiles ) ;
}
2014-06-21 16:41:05 +03:00
}
2011-09-03 05:54:33 +03:00
cl - > invalidatePaths ( ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void SetAvailableHeroes : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
//TODO: inform interface?
}
2018-03-10 23:19:36 +02:00
static void dispatchGarrisonChange ( CClient * cl , ObjectInstanceID army1 , ObjectInstanceID army2 )
2010-11-27 22:17:28 +02:00
{
2018-03-10 23:19:36 +02:00
auto obj1 = cl - > getObj ( army1 ) ;
if ( ! obj1 )
{
logNetwork - > error ( " Cannot find army with ID %d " , army1 . getNum ( ) ) ;
return ;
}
callInterfaceIfPresent ( cl , obj1 - > tempOwner , & IGameEventsReceiver : : garrisonsChanged , army1 , army2 ) ;
if ( army2 ! = ObjectInstanceID ( ) & & army2 ! = army1 )
{
auto obj2 = cl - > getObj ( army2 ) ;
if ( ! obj2 )
{
logNetwork - > error ( " Cannot find army with ID %d " , army2 . getNum ( ) ) ;
return ;
}
if ( obj1 - > tempOwner ! = obj2 - > tempOwner )
callInterfaceIfPresent ( cl , obj2 - > tempOwner , & IGameEventsReceiver : : garrisonsChanged , army1 , army2 ) ;
}
}
void ChangeStackCount : : applyCl ( CClient * cl )
{
dispatchGarrisonChange ( cl , army , ObjectInstanceID ( ) ) ;
2010-11-27 22:17:28 +02:00
}
2018-03-10 23:19:36 +02:00
void SetStackType : : applyCl ( CClient * cl )
2010-11-27 22:17:28 +02:00
{
2018-03-10 23:19:36 +02:00
dispatchGarrisonChange ( cl , army , ObjectInstanceID ( ) ) ;
2010-11-27 22:17:28 +02:00
}
2018-03-10 23:19:36 +02:00
void EraseStack : : applyCl ( CClient * cl )
2010-11-27 22:17:28 +02:00
{
2018-03-10 23:19:36 +02:00
dispatchGarrisonChange ( cl , army , ObjectInstanceID ( ) ) ;
2010-11-27 22:17:28 +02:00
}
2018-03-10 23:19:36 +02:00
void SwapStacks : : applyCl ( CClient * cl )
2010-11-27 22:17:28 +02:00
{
2018-03-10 23:19:36 +02:00
dispatchGarrisonChange ( cl , srcArmy , dstArmy ) ;
2010-11-27 22:17:28 +02:00
}
2018-03-10 23:19:36 +02:00
void InsertNewStack : : applyCl ( CClient * cl )
2010-11-27 22:17:28 +02:00
{
2018-03-10 23:19:36 +02:00
dispatchGarrisonChange ( cl , army , ObjectInstanceID ( ) ) ;
2010-11-27 22:17:28 +02:00
}
2018-03-10 23:19:36 +02:00
void RebalanceStacks : : applyCl ( CClient * cl )
2010-11-27 22:17:28 +02:00
{
2018-03-10 23:19:36 +02:00
dispatchGarrisonChange ( cl , srcArmy , dstArmy ) ;
2010-11-27 22:17:28 +02:00
}
2021-11-28 14:57:38 +02:00
void BulkRebalanceStacks : : applyCl ( CClient * cl )
{
if ( ! moves . empty ( ) )
{
auto destArmy = moves [ 0 ] . srcArmy = = moves [ 0 ] . dstArmy
? ObjectInstanceID ( )
: moves [ 0 ] . dstArmy ;
dispatchGarrisonChange ( cl , moves [ 0 ] . srcArmy , destArmy ) ;
}
}
void BulkSmartRebalanceStacks : : applyCl ( CClient * cl )
{
if ( ! moves . empty ( ) )
{
assert ( moves [ 0 ] . srcArmy = = moves [ 0 ] . dstArmy ) ;
dispatchGarrisonChange ( cl , moves [ 0 ] . srcArmy , ObjectInstanceID ( ) ) ;
}
else if ( ! changes . empty ( ) )
{
dispatchGarrisonChange ( cl , changes [ 0 ] . army , ObjectInstanceID ( ) ) ;
}
}
2016-10-28 23:37:20 +02:00
void PutArtifact : : applyCl ( CClient * cl )
2010-12-26 16:34:11 +02:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , al . owningPlayer ( ) , & IGameEventsReceiver : : artifactPut , al ) ;
2010-12-26 16:34:11 +02:00
}
2016-10-28 23:37:20 +02:00
void EraseArtifact : : applyCl ( CClient * cl )
2010-12-26 16:34:11 +02:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , al . owningPlayer ( ) , & IGameEventsReceiver : : artifactRemoved , al ) ;
2010-12-26 16:34:11 +02:00
}
2023-01-02 16:19:45 +02:00
void MoveArtifact : : applyCl ( CClient * cl )
2010-12-26 16:34:11 +02:00
{
2023-01-02 16:19:45 +02:00
auto moveArtifact = [ this , cl ] ( PlayerColor player ) - > void
2022-11-07 00:36:13 +02:00
{
2023-01-02 16:19:45 +02:00
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : artifactMoved , src , dst ) ;
if ( askAssemble )
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : artifactPossibleAssembling , dst ) ;
} ;
moveArtifact ( src . owningPlayer ( ) ) ;
if ( src . owningPlayer ( ) ! = dst . owningPlayer ( ) )
moveArtifact ( dst . owningPlayer ( ) ) ;
2010-12-26 16:34:11 +02:00
}
2022-11-06 23:54:50 +02:00
void BulkMoveArtifacts : : applyCl ( CClient * cl )
{
2022-11-10 20:48:19 +02:00
auto applyMove = [ this , cl ] ( std : : vector < LinkedSlots > & artsPack ) - > void
2022-11-06 23:54:50 +02:00
{
2022-11-10 20:48:19 +02:00
for ( auto & slotToMove : artsPack )
2022-11-06 23:54:50 +02:00
{
2022-11-07 14:13:36 +02:00
auto srcLoc = ArtifactLocation ( srcArtHolder , slotToMove . srcPos ) ;
auto dstLoc = ArtifactLocation ( dstArtHolder , slotToMove . dstPos ) ;
2022-11-07 00:36:13 +02:00
callInterfaceIfPresent ( cl , srcLoc . owningPlayer ( ) , & IGameEventsReceiver : : artifactMoved , srcLoc , dstLoc ) ;
2022-11-10 18:29:39 +02:00
if ( srcLoc . owningPlayer ( ) ! = dstLoc . owningPlayer ( ) )
2022-11-07 00:36:13 +02:00
callInterfaceIfPresent ( cl , dstLoc . owningPlayer ( ) , & IGameEventsReceiver : : artifactMoved , srcLoc , dstLoc ) ;
2022-11-06 23:54:50 +02:00
}
2022-11-10 20:48:19 +02:00
} ;
applyMove ( artsPack0 ) ;
if ( swap )
applyMove ( artsPack1 ) ;
2022-11-06 23:54:50 +02:00
}
2016-10-28 23:37:20 +02:00
void AssembledArtifact : : applyCl ( CClient * cl )
2011-01-22 05:43:20 +02:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , al . owningPlayer ( ) , & IGameEventsReceiver : : artifactAssembled , al ) ;
2011-01-22 05:43:20 +02:00
}
2016-10-28 23:37:20 +02:00
void DisassembledArtifact : : applyCl ( CClient * cl )
2011-01-22 05:43:20 +02:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , al . owningPlayer ( ) , & IGameEventsReceiver : : artifactDisassembled , al ) ;
2011-01-22 05:43:20 +02:00
}
2018-03-10 21:19:55 +02:00
void HeroVisit : : applyCl ( CClient * cl )
2011-05-10 01:20:47 +03:00
{
2018-03-10 21:19:55 +02:00
auto hero = cl - > getHero ( heroId ) ;
auto obj = cl - > getObj ( objId , false ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : heroVisit , hero , obj , starting ) ;
2011-05-10 01:20:47 +03:00
}
2016-10-28 23:37:20 +02:00
void NewTurn : : applyCl ( CClient * cl )
2011-08-25 18:24:37 +03:00
{
2011-09-03 05:54:33 +03:00
cl - > invalidatePaths ( ) ;
2011-08-25 18:24:37 +03:00
}
2016-10-28 23:37:20 +02:00
void GiveBonus : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2011-09-03 05:54:33 +03:00
cl - > invalidatePaths ( ) ;
2010-02-10 04:56:00 +02:00
switch ( who )
{
case HERO :
{
2013-02-14 02:55:42 +03:00
const CGHeroInstance * h = GS ( cl ) - > getHero ( ObjectInstanceID ( id ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroBonusChanged , h , * h - > getBonusList ( ) . back ( ) , true ) ;
2010-02-10 04:56:00 +02:00
}
break ;
case PLAYER :
{
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
const PlayerState * p = GS ( cl ) - > getPlayerState ( PlayerColor ( id ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , PlayerColor ( id ) , & IGameEventsReceiver : : playerBonusChanged , * p - > getBonusList ( ) . back ( ) , true ) ;
2010-02-10 04:56:00 +02:00
}
break ;
}
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void ChangeObjPos : : applyFirstCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2013-02-14 02:55:42 +03:00
CGObjectInstance * obj = GS ( cl ) - > getObjInstance ( objid ) ;
2017-03-12 09:54:24 +02:00
if ( flags & 1 & & CGI - > mh )
2009-03-07 17:55:56 +02:00
CGI - > mh - > hideObject ( obj ) ;
}
2016-10-28 23:37:20 +02:00
void ChangeObjPos : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2013-02-14 02:55:42 +03:00
CGObjectInstance * obj = GS ( cl ) - > getObjInstance ( objid ) ;
2017-03-12 09:54:24 +02:00
if ( flags & 1 & & CGI - > mh )
2009-03-07 17:55:56 +02:00
CGI - > mh - > printObject ( obj ) ;
2010-03-11 01:16:30 +02:00
2011-09-03 05:54:33 +03:00
cl - > invalidatePaths ( ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void PlayerEndsGame : : applyCl ( CClient * cl )
2010-01-29 22:52:45 +02:00
{
2018-02-03 16:44:30 +02:00
callAllInterfaces ( cl , & IGameEventsReceiver : : gameOver , player , victoryLossCheckResult ) ;
2017-06-04 10:59:26 +02:00
// In auto testing mode we always close client if red player won or lose
if ( ! settings [ " session " ] [ " testmap " ] . isNull ( ) & & player = = PlayerColor ( 0 ) )
handleQuit ( settings [ " session " ] [ " spectate " ] . Bool ( ) ) ; // if spectator is active ask to close client or not
2010-01-29 22:52:45 +02:00
}
2022-09-30 21:08:37 +02:00
void PlayerReinitInterface : : applyCl ( CClient * cl )
{
2022-10-12 22:18:15 +02:00
auto initInterfaces = [ cl ] ( )
{
cl - > initPlayerInterfaces ( ) ;
auto currentPlayer = cl - > gameState ( ) - > currentPlayer ;
callAllInterfaces ( cl , & IGameEventsReceiver : : playerStartsTurn , currentPlayer ) ;
callOnlyThatInterface ( cl , currentPlayer , & CGameInterface : : yourTurn ) ;
} ;
2022-10-04 23:54:31 +02:00
for ( auto player : players )
2022-10-01 16:28:45 +02:00
{
2022-10-04 23:54:31 +02:00
auto & plSettings = CSH - > si - > getIthPlayersSettings ( player ) ;
if ( playerConnectionId = = PlayerSettings : : PLAYER_AI )
{
plSettings . connectedPlayerIDs . clear ( ) ;
cl - > initPlayerEnvironments ( ) ;
2022-10-12 22:18:15 +02:00
initInterfaces ( ) ;
2022-10-04 23:54:31 +02:00
}
else if ( playerConnectionId = = CSH - > c - > connectionID )
{
plSettings . connectedPlayerIDs . insert ( playerConnectionId ) ;
cl - > playerint . clear ( ) ;
2022-10-12 22:18:15 +02:00
initInterfaces ( ) ;
2022-10-04 23:54:31 +02:00
}
2022-10-01 16:28:45 +02:00
}
2022-09-30 21:08:37 +02:00
}
2016-10-28 23:37:20 +02:00
void RemoveBonus : : applyCl ( CClient * cl )
2010-02-10 04:56:00 +02:00
{
2011-09-03 05:54:33 +03:00
cl - > invalidatePaths ( ) ;
2010-02-10 04:56:00 +02:00
switch ( who )
{
case HERO :
{
2013-02-14 02:55:42 +03:00
const CGHeroInstance * h = GS ( cl ) - > getHero ( ObjectInstanceID ( id ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroBonusChanged , h , bonus , false ) ;
2010-02-10 04:56:00 +02:00
}
break ;
case PLAYER :
{
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
//const PlayerState *p = GS(cl)->getPlayerState(id);
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , PlayerColor ( id ) , & IGameEventsReceiver : : playerBonusChanged , bonus , false ) ;
2010-02-10 04:56:00 +02:00
}
break ;
}
}
2016-10-28 23:37:20 +02:00
void RemoveObject : : applyFirstCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2009-08-04 02:53:18 +03:00
const CGObjectInstance * o = cl - > getObj ( id ) ;
2012-07-19 12:10:55 +03:00
2017-03-12 09:54:24 +02:00
if ( CGI - > mh )
CGI - > mh - > hideObject ( o , true ) ;
2009-08-04 02:53:18 +03:00
//notify interfaces about removal
2013-03-03 20:06:03 +03:00
for ( auto i = cl - > playerint . begin ( ) ; i ! = cl - > playerint . end ( ) ; i + + )
2009-03-07 17:55:56 +02:00
{
2018-11-02 17:35:25 +02:00
//below line contains little cheat for AI so it will be aware of deletion of enemy heroes that moved or got re-covered by FoW
//TODO: loose requirements as next AI related crashes appear, for example another player collects object that got re-covered by FoW, unsure if AI code workarounds this
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
if ( GS ( cl ) - > isVisible ( o , i - > first ) | | ( ! cl - > getPlayerState ( i - > first ) - > human & & o - > ID = = Obj : : HERO & & o - > tempOwner ! = i - > first ) )
2009-08-04 02:53:18 +03:00
i - > second - > objectRemoved ( o ) ;
2009-03-07 17:55:56 +02:00
}
}
2016-10-28 23:37:20 +02:00
void RemoveObject : : applyCl ( CClient * cl )
2009-03-07 19:08:40 +02:00
{
2011-09-03 05:54:33 +03:00
cl - > invalidatePaths ( ) ;
2009-03-07 19:08:40 +02:00
}
2016-10-28 23:37:20 +02:00
void TryMoveHero : : applyFirstCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2009-07-19 06:10:24 +03:00
CGHeroInstance * h = GS ( cl ) - > getHero ( id ) ;
2009-12-28 06:08:24 +02:00
//check if playerint will have the knowledge about movement - if not, directly update maphandler
2013-03-03 20:06:03 +03:00
for ( auto i = cl - > playerint . begin ( ) ; i ! = cl - > playerint . end ( ) ; i + + )
2009-12-28 06:08:24 +02:00
{
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
auto ps = GS ( cl ) - > getPlayerState ( i - > first ) ;
2017-06-03 07:25:10 +02:00
if ( ps & & ( GS ( cl ) - > isVisible ( start - int3 ( 1 , 0 , 0 ) , i - > first ) | | GS ( cl ) - > isVisible ( end - int3 ( 1 , 0 , 0 ) , i - > first ) ) )
{
if ( ps - > human )
humanKnows = true ;
}
2009-12-28 06:08:24 +02:00
}
2017-03-12 09:54:24 +02:00
if ( ! CGI - > mh )
return ;
2009-12-28 06:08:24 +02:00
if ( result = = TELEPORTATION | | result = = EMBARK | | result = = DISEMBARK | | ! humanKnows )
2016-11-07 23:19:53 +02:00
CGI - > mh - > hideObject ( h , result = = EMBARK & & humanKnows ) ;
2009-07-19 06:10:24 +03:00
if ( result = = DISEMBARK )
CGI - > mh - > printObject ( h - > boat ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void TryMoveHero : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2009-07-03 22:57:14 +03:00
const CGHeroInstance * h = cl - > getHero ( id ) ;
2011-09-03 05:54:33 +03:00
cl - > invalidatePaths ( ) ;
2009-03-07 17:55:56 +02:00
2017-03-12 09:54:24 +02:00
if ( CGI - > mh )
2011-06-21 19:00:19 +03:00
{
2017-03-12 09:54:24 +02:00
if ( result = = TELEPORTATION | | result = = EMBARK | | result = = DISEMBARK )
CGI - > mh - > printObject ( h , result = = DISEMBARK ) ;
2009-07-19 06:10:24 +03:00
2017-03-12 09:54:24 +02:00
if ( result = = EMBARK )
CGI - > mh - > hideObject ( h - > boat ) ;
}
2009-07-19 06:10:24 +03:00
2013-03-03 20:06:03 +03:00
PlayerColor player = h - > tempOwner ;
2009-03-07 17:55:56 +02:00
2013-06-29 16:05:48 +03:00
for ( auto & i : cl - > playerint )
2013-02-04 00:05:44 +03:00
if ( cl - > getPlayerRelations ( i . first , player ) ! = PlayerRelations : : ENEMIES )
2012-02-21 00:01:54 +03:00
i . second - > tileRevealed ( fowRevealed ) ;
2009-03-07 17:55:56 +02:00
//notify interfaces about move
2022-01-25 13:19:48 +02:00
auto gs = cl - > gameState ( ) ;
2013-03-03 20:06:03 +03:00
for ( auto i = cl - > playerint . begin ( ) ; i ! = cl - > playerint . end ( ) ; i + + )
2009-03-07 17:55:56 +02:00
{
2022-01-25 13:19:48 +02:00
if ( i - > first ! = PlayerColor : : SPECTATOR & & gs - > checkForStandardLoss ( i - > first ) ) // Do not notify vanquished player's interface
continue ;
2017-06-03 07:25:10 +02:00
if ( GS ( cl ) - > isVisible ( start - int3 ( 1 , 0 , 0 ) , i - > first )
| | GS ( cl ) - > isVisible ( end - int3 ( 1 , 0 , 0 ) , i - > first ) )
2009-03-07 17:55:56 +02:00
{
2022-01-25 13:19:48 +02:00
// src and dst of enemy hero move may be not visible => 'verbose' should be false
const bool verbose = cl - > getPlayerRelations ( i - > first , player ) ! = PlayerRelations : : ENEMIES ;
i - > second - > heroMoved ( * this , verbose ) ;
2009-03-07 17:55:56 +02:00
}
}
2009-12-28 06:08:24 +02:00
2017-03-12 09:54:24 +02:00
//maphandler didn't get update from playerint, do it now
//TODO: restructure nicely
if ( ! humanKnows & & CGI - > mh )
2009-12-28 06:08:24 +02:00
CGI - > mh - > printObject ( h ) ;
2009-03-07 17:55:56 +02:00
}
2017-09-16 09:42:27 +02:00
bool TryMoveHero : : stopMovement ( ) const
{
return result ! = SUCCESS & & result ! = EMBARK & & result ! = DISEMBARK & & result ! = TELEPORTATION ;
}
2016-10-28 23:37:20 +02:00
void NewStructures : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
CGTownInstance * town = GS ( cl ) - > getTown ( tid ) ;
2013-06-29 16:05:48 +03:00
for ( const auto & id : bid )
2013-11-17 20:57:04 +03:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , town - > tempOwner , & IGameEventsReceiver : : buildChanged , town , id , 1 ) ;
2009-03-07 17:55:56 +02:00
}
}
2009-09-22 17:27:46 +03:00
void RazeStructures : : applyCl ( CClient * cl )
{
CGTownInstance * town = GS ( cl ) - > getTown ( tid ) ;
2013-06-29 16:05:48 +03:00
for ( const auto & id : bid )
2013-11-17 20:57:04 +03:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , town - > tempOwner , & IGameEventsReceiver : : buildChanged , town , id , 2 ) ;
2009-09-22 17:27:46 +03:00
}
}
2009-03-07 17:55:56 +02:00
2016-10-28 23:37:20 +02:00
void SetAvailableCreatures : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2009-07-26 13:43:22 +03:00
const CGDwelling * dw = static_cast < const CGDwelling * > ( cl - > getObj ( tid ) ) ;
2010-05-15 11:33:32 +03:00
//inform order about the change
2013-03-03 20:06:03 +03:00
PlayerColor p ;
2012-09-23 21:01:04 +03:00
if ( dw - > ID = = Obj : : WAR_MACHINE_FACTORY ) //War Machines Factory is not flaggable, it's "owned" by visitor
2010-05-15 11:33:32 +03:00
p = cl - > getTile ( dw - > visitablePos ( ) ) - > visitableObjects . back ( ) - > tempOwner ;
else
p = dw - > tempOwner ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , p , & IGameEventsReceiver : : availableCreaturesChanged , dw ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void SetHeroesInTown : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
CGTownInstance * t = GS ( cl ) - > getTown ( tid ) ;
2013-02-23 15:22:23 +03:00
CGHeroInstance * hGarr = GS ( cl ) - > getHero ( this - > garrison ) ;
CGHeroInstance * hVisit = GS ( cl ) - > getHero ( this - > visiting ) ;
2016-09-11 12:56:00 +02:00
//inform all players that see this object
for ( auto i = cl - > playerint . cbegin ( ) ; i ! = cl - > playerint . cend ( ) ; + + i )
{
if ( i - > first > = PlayerColor : : PLAYER_LIMIT )
continue ;
2013-02-23 15:22:23 +03:00
2016-09-11 12:56:00 +02:00
if ( GS ( cl ) - > isVisible ( t , i - > first ) | |
( hGarr & & GS ( cl ) - > isVisible ( hGarr , i - > first ) ) | |
( hVisit & & GS ( cl ) - > isVisible ( hVisit , i - > first ) ) )
{
cl - > playerint [ i - > first ] - > heroInGarrisonChange ( t ) ;
}
}
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void HeroRecruited : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2013-05-19 01:30:48 +03:00
CGHeroInstance * h = GS ( cl ) - > map - > heroesOnMap . back ( ) ;
2009-03-07 17:55:56 +02:00
if ( h - > subID ! = hid )
{
2017-08-10 18:39:27 +02:00
logNetwork - > error ( " Something wrong with hero recruited! " ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-02 16:27:01 +02:00
bool needsPrinting = true ;
2018-02-03 16:44:30 +02:00
if ( callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroCreated , h ) )
2009-03-07 17:55:56 +02:00
{
2010-07-09 02:03:27 +03:00
if ( const CGTownInstance * t = GS ( cl ) - > getTown ( tid ) )
2016-10-02 16:27:01 +02:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroInGarrisonChange , t ) ;
2016-10-02 16:27:01 +02:00
needsPrinting = false ;
}
}
2017-03-12 09:54:24 +02:00
if ( needsPrinting & & CGI - > mh )
2016-10-02 16:27:01 +02:00
CGI - > mh - > printObject ( h ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void GiveHero : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
CGHeroInstance * h = GS ( cl ) - > getHero ( id ) ;
2017-03-12 09:54:24 +02:00
if ( CGI - > mh )
CGI - > mh - > printObject ( h ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , h - > tempOwner , & IGameEventsReceiver : : heroCreated , h ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void GiveHero : : applyFirstCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2017-03-12 09:54:24 +02:00
if ( CGI - > mh )
CGI - > mh - > hideObject ( GS ( cl ) - > getHero ( id ) ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void InfoWindow : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2009-07-09 22:15:22 +03:00
std : : string str ;
2013-11-17 20:57:04 +03:00
text . toString ( str ) ;
2018-04-07 13:34:11 +02:00
if ( ! callInterfaceIfPresent ( cl , player , & CGameInterface : : showInfoDialog , str , components , ( soundBase : : soundID ) soundID ) )
2017-08-10 18:39:27 +02:00
logNetwork - > warn ( " We received InfoWindow for not our player... " ) ;
2013-11-17 20:57:04 +03:00
}
2009-03-07 17:55:56 +02:00
2021-03-23 16:47:07 +02:00
void SetObjectProperty : : applyCl ( CClient * cl )
2009-07-30 15:49:45 +03:00
{
//inform all players that see this object
2013-02-14 02:55:42 +03:00
for ( auto it = cl - > playerint . cbegin ( ) ; it ! = cl - > playerint . cend ( ) ; + + it )
2009-07-30 15:49:45 +03:00
{
2013-02-14 02:55:42 +03:00
if ( GS ( cl ) - > isVisible ( GS ( cl ) - > getObjInstance ( id ) , it - > first ) )
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , it - > first , & IGameEventsReceiver : : objectPropertyChanged , this ) ;
2009-07-30 15:49:45 +03:00
}
}
2016-10-28 23:37:20 +02:00
void HeroLevelUp : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2018-03-10 21:19:55 +02:00
const CGHeroInstance * hero = cl - > getHero ( heroId ) ;
assert ( hero ) ;
callOnlyThatInterface ( cl , player , & CGameInterface : : heroGotLevel , hero , primskill , skills , queryID ) ;
2009-03-07 17:55:56 +02:00
}
2012-07-15 18:34:00 +03:00
2016-10-28 23:37:20 +02:00
void CommanderLevelUp : : applyCl ( CClient * cl )
2012-05-16 20:29:05 +03:00
{
2018-03-10 21:19:55 +02:00
const CGHeroInstance * hero = cl - > getHero ( heroId ) ;
assert ( hero ) ;
2013-04-20 14:34:01 +03:00
const CCommanderInstance * commander = hero - > commander ;
2018-02-03 16:44:30 +02:00
assert ( commander ) ;
assert ( commander - > armyObj ) ; //is it possible for Commander to exist beyond armed instance?
2018-03-10 21:19:55 +02:00
callOnlyThatInterface ( cl , player , & CGameInterface : : commanderGotLevel , commander , skills , queryID ) ;
2012-05-16 20:29:05 +03:00
}
2009-03-07 17:55:56 +02:00
2016-10-28 23:37:20 +02:00
void BlockingDialog : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2009-07-09 22:15:22 +03:00
std : : string str ;
2013-11-17 20:57:04 +03:00
text . toString ( str ) ;
2018-02-03 16:44:30 +02:00
if ( ! callOnlyThatInterface ( cl , player , & CGameInterface : : showBlockingDialog , str , components , queryID , ( soundBase : : soundID ) soundID , selection ( ) , cancel ( ) ) )
2017-08-10 18:39:27 +02:00
logNetwork - > warn ( " We received YesNoDialog for not our player... " ) ;
2013-11-17 20:57:04 +03:00
}
2009-03-07 17:55:56 +02:00
2009-04-12 03:58:41 +03:00
void GarrisonDialog : : applyCl ( CClient * cl )
{
const CGHeroInstance * h = cl - > getHero ( hid ) ;
const CArmedInstance * obj = static_cast < const CArmedInstance * > ( cl - > getObj ( objid ) ) ;
2018-02-03 16:44:30 +02:00
callOnlyThatInterface ( cl , h - > getOwner ( ) , & CGameInterface : : showGarrisonDialog , obj , h , removableUnits , queryID ) ;
2013-11-17 20:57:04 +03:00
}
void ExchangeDialog : : applyCl ( CClient * cl )
2013-05-27 13:53:28 +03:00
{
2018-03-10 21:19:55 +02:00
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : heroExchangeStarted , hero1 , hero2 , queryID ) ;
2013-05-27 13:53:28 +03:00
}
2016-10-28 23:37:20 +02:00
void TeleportDialog : : applyCl ( CClient * cl )
2015-03-08 15:37:33 +02:00
{
2018-03-10 21:19:55 +02:00
callOnlyThatInterface ( cl , player , & CGameInterface : : showTeleportDialog , channel , exits , impassable , queryID ) ;
2015-03-08 15:37:33 +02:00
}
2017-06-06 06:53:51 +02:00
void MapObjectSelectDialog : : applyCl ( CClient * cl )
{
2018-02-03 16:44:30 +02:00
callOnlyThatInterface ( cl , player , & CGameInterface : : showMapObjectSelectDialog , queryID , icon , title , description , objects ) ;
2017-06-06 06:53:51 +02:00
}
2016-10-28 23:37:20 +02:00
void BattleStart : : applyFirstCl ( CClient * cl )
2013-09-14 22:09:35 +03:00
{
2018-02-03 16:44:30 +02:00
// Cannot use the usual code because curB is not set yet
callOnlyThatBattleInterface ( cl , info - > sides [ 0 ] . color , & IBattleEventsReceiver : : battleStartBefore , info - > sides [ 0 ] . armyObject , info - > sides [ 1 ] . armyObject ,
2013-09-14 22:09:35 +03:00
info - > tile , info - > sides [ 0 ] . hero , info - > sides [ 1 ] . hero ) ;
2018-02-03 16:44:30 +02:00
callOnlyThatBattleInterface ( cl , info - > sides [ 1 ] . color , & IBattleEventsReceiver : : battleStartBefore , info - > sides [ 0 ] . armyObject , info - > sides [ 1 ] . armyObject ,
2013-09-14 22:09:35 +03:00
info - > tile , info - > sides [ 0 ] . hero , info - > sides [ 1 ] . hero ) ;
2018-02-03 16:44:30 +02:00
callOnlyThatBattleInterface ( cl , PlayerColor : : SPECTATOR , & IBattleEventsReceiver : : battleStartBefore , info - > sides [ 0 ] . armyObject , info - > sides [ 1 ] . armyObject ,
2017-06-03 07:25:10 +02:00
info - > tile , info - > sides [ 0 ] . hero , info - > sides [ 1 ] . hero ) ;
2013-09-14 22:09:35 +03:00
}
2016-10-28 23:37:20 +02:00
void BattleStart : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2010-12-23 02:33:48 +02:00
cl - > battleStarted ( info ) ;
2009-03-07 17:55:56 +02:00
}
2010-05-07 15:29:41 +03:00
void BattleNextRound : : applyFirstCl ( CClient * cl )
{
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleNewRoundFirst , round ) ;
2010-05-07 15:29:41 +03:00
}
2016-10-28 23:37:20 +02:00
void BattleNextRound : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleNewRound , round ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void BattleSetActiveStack : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2012-08-27 15:34:43 +03:00
if ( ! askPlayerInterface )
return ;
2016-10-28 23:37:20 +02:00
const CStack * activated = GS ( cl ) - > curB - > battleGetStackByID ( stack ) ;
2013-03-03 20:06:03 +03:00
PlayerColor playerToCall ; //player that will move activated stack
2016-10-28 23:37:20 +02:00
if ( activated - > hasBonusOfType ( Bonus : : HYPNOTIZED ) )
2009-08-18 14:49:34 +03:00
{
2016-10-28 23:37:20 +02:00
playerToCall = ( GS ( cl ) - > curB - > sides [ 0 ] . color = = activated - > owner
2016-01-26 15:51:38 +02:00
? GS ( cl ) - > curB - > sides [ 1 ] . color
2016-10-28 23:37:20 +02:00
: GS ( cl ) - > curB - > sides [ 0 ] . color ) ;
2009-08-18 14:49:34 +03:00
}
else
{
playerToCall = activated - > owner ;
}
2017-11-16 13:15:43 +02:00
cl - > startPlayerBattleAction ( playerToCall ) ;
2009-03-07 17:55:56 +02:00
}
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
void BattleLogMessage : : applyCl ( CClient * cl )
{
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleLogMessage , lines ) ;
}
2011-10-08 16:02:58 +03:00
void BattleTriggerEffect : : applyCl ( CClient * cl )
{
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleTriggerEffect , * this ) ;
2011-10-08 16:02:58 +03:00
}
2016-02-13 16:40:31 +02:00
void BattleUpdateGateState : : applyFirstCl ( CClient * cl )
2016-02-10 06:10:32 +02:00
{
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleGateStateChanged , state ) ;
2016-02-10 06:10:32 +02:00
}
2016-10-28 23:37:20 +02:00
void BattleResult : : applyFirstCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleEnd , this ) ;
2012-08-26 12:07:48 +03:00
cl - > battleFinished ( ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void BattleStackMoved : : applyFirstCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2012-08-26 12:07:48 +03:00
const CStack * movedStack = GS ( cl ) - > curB - > battleGetStackByID ( stack ) ;
2022-12-18 18:26:43 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleStackMoved , movedStack , tilesToMove , distance , teleporting ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void BattleAttack : : applyFirstCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleAttack , this ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void BattleAttack : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2022-12-09 13:10:35 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleStacksAttacked , bsa , shot ( ) ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void StartAction : : applyFirstCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2017-08-05 15:09:29 +02:00
cl - > curbaction = boost : : make_optional ( ba ) ;
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : actionStarted , ba ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void BattleSpellCast : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleSpellCast , this ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void SetStackEffect : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2009-03-21 18:03:07 +02:00
//informing about effects
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleStacksEffectsSet , * this ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void StacksInjured : : applyCl ( CClient * cl )
2009-04-16 03:28:54 +03:00
{
2022-12-09 13:10:35 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleStacksAttacked , stacks , false ) ;
2009-04-16 03:28:54 +03:00
}
2016-10-28 23:37:20 +02:00
void BattleResultsApplied : : applyCl ( CClient * cl )
2009-08-04 02:53:18 +03:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , player1 , & IGameEventsReceiver : : battleResultsApplied ) ;
callInterfaceIfPresent ( cl , player2 , & IGameEventsReceiver : : battleResultsApplied ) ;
callInterfaceIfPresent ( cl , PlayerColor : : SPECTATOR , & IGameEventsReceiver : : battleResultsApplied ) ;
2009-08-04 02:53:18 +03:00
}
2017-07-20 06:08:49 +02:00
void BattleUnitsChanged : : applyCl ( CClient * cl )
2009-08-05 15:46:08 +03:00
{
2022-12-17 17:35:15 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleUnitsChanged , changedStacks ) ;
2009-08-05 15:46:08 +03:00
}
2017-07-20 06:08:49 +02:00
void BattleObstaclesChanged : : applyCl ( CClient * cl )
2009-08-19 13:59:42 +03:00
{
//inform interfaces about removed obstacles
2017-07-20 06:08:49 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleObstaclesChanged , changes ) ;
2009-08-19 13:59:42 +03:00
}
2016-10-28 23:37:20 +02:00
void CatapultAttack : : applyCl ( CClient * cl )
2009-09-01 16:54:13 +03:00
{
//inform interfaces about catapult attack
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : battleCatapultAttacked , * this ) ;
2009-09-01 16:54:13 +03:00
}
2016-10-28 23:37:20 +02:00
CGameState * CPackForClient : : GS ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
return cl - > gs ;
}
2016-10-28 23:37:20 +02:00
void EndAction : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2018-02-03 16:44:30 +02:00
callBattleInterfaceIfPresentForBothSides ( cl , & IBattleEventsReceiver : : actionFinished , * cl - > curbaction ) ;
2013-05-09 14:09:23 +03:00
cl - > curbaction . reset ( ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void PackageApplied : : applyCl ( CClient * cl )
2009-04-16 03:28:54 +03:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : requestRealized , this ) ;
2017-07-12 16:02:25 +02:00
if ( ! CClient : : waitingRequest . tryRemovingElement ( requestID ) )
2018-01-05 19:21:07 +02:00
logNetwork - > warn ( " Surprising server message! PackageApplied for unknown requestID! " ) ;
2009-04-16 03:28:54 +03:00
}
2016-10-28 23:37:20 +02:00
void SystemMessage : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2009-04-04 22:26:41 +03:00
std : : ostringstream str ;
2009-04-11 04:32:50 +03:00
str < < " System message: " < < text ;
2009-04-04 22:26:41 +03:00
2017-08-11 13:38:10 +02:00
logNetwork - > error ( str . str ( ) ) ; // usually used to receive error messages from server
2016-09-26 15:05:27 +02:00
if ( LOCPLINT & & ! settings [ " session " ] [ " hideSystemMessages " ] . Bool ( ) )
2009-04-04 22:26:41 +03:00
LOCPLINT - > cingconsole - > print ( str . str ( ) ) ;
2009-03-07 17:55:56 +02:00
}
2016-10-28 23:37:20 +02:00
void PlayerBlocked : : applyCl ( CClient * cl )
2009-08-04 02:53:18 +03:00
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : playerBlocked , reason , startOrEnd = = BLOCKADE_STARTED ) ;
2009-08-04 02:53:18 +03:00
}
2016-10-28 23:37:20 +02:00
void YourTurn : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2018-01-05 19:21:07 +02:00
logNetwork - > debug ( " Server gives turn to %s " , player . getStr ( ) ) ;
2018-02-03 16:44:30 +02:00
callAllInterfaces ( cl , & IGameEventsReceiver : : playerStartsTurn , player ) ;
callOnlyThatInterface ( cl , player , & CGameInterface : : yourTurn ) ;
2009-03-07 17:55:56 +02:00
}
2018-01-05 19:21:07 +02:00
void SaveGameClient : : applyCl ( CClient * cl )
2009-03-28 20:46:20 +02:00
{
2016-01-26 15:51:38 +02:00
const auto stem = FileInfo : : GetPathStem ( fname ) ;
2022-10-06 13:54:46 +02:00
if ( ! CResourceHandler : : get ( " local " ) - > createResource ( stem . to_string ( ) + " .vcgm1 " ) )
{
logNetwork - > error ( " Failed to create resource %s " , stem . to_string ( ) + " .vcgm1 " ) ;
return ;
}
2012-08-07 14:28:52 +03:00
2012-06-09 22:58:17 +03:00
try
{
2016-01-26 15:51:38 +02:00
CSaveFile save ( * CResourceHandler : : get ( ) - > getResourceName ( ResourceID ( stem . to_string ( ) , EResType : : CLIENT_SAVEGAME ) ) ) ;
2013-02-19 01:37:22 +03:00
cl - > saveCommonState ( save ) ;
2012-06-09 22:58:17 +03:00
save < < * cl ;
}
catch ( std : : exception & e )
{
2017-08-11 13:38:10 +02:00
logNetwork - > error ( " Failed to save game:%s " , e . what ( ) ) ;
2012-06-09 22:58:17 +03:00
}
2009-03-28 20:46:20 +02:00
}
2009-03-07 17:55:56 +02:00
2018-01-05 19:21:07 +02:00
void PlayerMessageClient : : applyCl ( CClient * cl )
2009-03-07 17:55:56 +02:00
{
2017-08-12 13:36:04 +02:00
logNetwork - > debug ( " Player %s sends a message: %s " , player . getStr ( ) , text ) ;
2009-04-04 22:26:41 +03:00
2015-11-08 21:16:58 +02:00
std : : ostringstream str ;
2017-06-03 07:25:10 +02:00
if ( player . isSpectator ( ) )
str < < " Spectator: " < < text ;
else
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
str < < cl - > getPlayerState ( player ) - > nodeName ( ) < < " : " < < text ;
2009-04-04 22:26:41 +03:00
if ( LOCPLINT )
LOCPLINT - > cingconsole - > print ( str . str ( ) ) ;
2009-03-07 17:55:56 +02:00
}
void ShowInInfobox : : applyCl ( CClient * cl )
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : showComp , c , text . toString ( ) ) ;
2009-05-12 06:35:51 +03:00
}
2009-06-16 14:18:14 +03:00
2010-05-16 16:42:19 +03:00
void AdvmapSpellCast : : applyCl ( CClient * cl )
{
2011-09-03 05:54:33 +03:00
cl - > invalidatePaths ( ) ;
2018-03-10 21:19:55 +02:00
auto caster = cl - > getHero ( casterID ) ;
if ( caster )
//consider notifying other interfaces that see hero?
callInterfaceIfPresent ( cl , caster - > getOwner ( ) , & IGameEventsReceiver : : advmapSpellCast , caster , spellID ) ;
else
logNetwork - > error ( " Invalid hero instance " ) ;
2010-05-16 16:42:19 +03:00
}
2015-02-26 16:15:17 +02:00
void ShowWorldViewEx : : applyCl ( CClient * cl )
{
2018-02-03 16:44:30 +02:00
callOnlyThatInterface ( cl , player , & CGameInterface : : showWorldViewEx , objectPositions ) ;
2015-02-26 16:15:17 +02:00
}
2009-07-06 22:41:27 +03:00
void OpenWindow : : applyCl ( CClient * cl )
2009-06-16 14:18:14 +03:00
{
2009-07-06 22:41:27 +03:00
switch ( window )
{
case RECRUITMENT_FIRST :
2009-07-26 13:43:22 +03:00
case RECRUITMENT_ALL :
2009-07-06 22:41:27 +03:00
{
2013-02-14 02:55:42 +03:00
const CGDwelling * dw = dynamic_cast < const CGDwelling * > ( cl - > getObj ( ObjectInstanceID ( id1 ) ) ) ;
const CArmedInstance * dst = dynamic_cast < const CArmedInstance * > ( cl - > getObj ( ObjectInstanceID ( id2 ) ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , dst - > tempOwner , & IGameEventsReceiver : : showRecruitmentDialog , dw , dst , window = = RECRUITMENT_FIRST ? 0 : - 1 ) ;
2009-07-06 22:41:27 +03:00
}
2009-07-26 06:33:13 +03:00
break ;
case SHIPYARD_WINDOW :
{
2013-02-14 02:55:42 +03:00
const IShipyard * sy = IShipyard : : castFrom ( cl - > getObj ( ObjectInstanceID ( id1 ) ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , sy - > o - > tempOwner , & IGameEventsReceiver : : showShipyardDialog , sy ) ;
2009-07-26 06:33:13 +03:00
}
break ;
2010-02-07 17:06:14 +02:00
case THIEVES_GUILD :
{
//displays Thieves' Guild window (when hero enters Den of Thieves)
2013-02-14 02:55:42 +03:00
const CGObjectInstance * obj = cl - > getObj ( ObjectInstanceID ( id2 ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , PlayerColor ( id1 ) , & IGameEventsReceiver : : showThievesGuildWindow , obj ) ;
2010-02-07 17:06:14 +02:00
}
break ;
2010-07-20 17:08:13 +03:00
case UNIVERSITY_WINDOW :
{
//displays University window (when hero enters University on adventure map)
2013-02-14 02:55:42 +03:00
const IMarket * market = IMarket : : castFrom ( cl - > getObj ( ObjectInstanceID ( id1 ) ) ) ;
const CGHeroInstance * hero = cl - > getHero ( ObjectInstanceID ( id2 ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , hero - > tempOwner , & IGameEventsReceiver : : showUniversityWindow , market , hero ) ;
2010-07-20 17:08:13 +03:00
}
break ;
2010-05-18 10:01:54 +03:00
case MARKET_WINDOW :
{
//displays Thieves' Guild window (when hero enters Den of Thieves)
2013-02-14 02:55:42 +03:00
const CGObjectInstance * obj = cl - > getObj ( ObjectInstanceID ( id1 ) ) ;
const CGHeroInstance * hero = cl - > getHero ( ObjectInstanceID ( id2 ) ) ;
2010-05-18 10:01:54 +03:00
const IMarket * market = IMarket : : castFrom ( obj ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , cl - > getTile ( obj - > visitablePos ( ) ) - > visitableObjects . back ( ) - > tempOwner , & IGameEventsReceiver : : showMarketWindow , market , hero ) ;
2010-05-18 10:01:54 +03:00
}
break ;
2010-07-22 03:32:45 +03:00
case HILL_FORT_WINDOW :
{
//displays Hill fort window
2013-02-14 02:55:42 +03:00
const CGObjectInstance * obj = cl - > getObj ( ObjectInstanceID ( id1 ) ) ;
const CGHeroInstance * hero = cl - > getHero ( ObjectInstanceID ( id2 ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , cl - > getTile ( obj - > visitablePos ( ) ) - > visitableObjects . back ( ) - > tempOwner , & IGameEventsReceiver : : showHillFortWindow , obj , hero ) ;
2010-07-22 03:32:45 +03:00
}
break ;
2010-02-10 04:56:00 +02:00
case PUZZLE_MAP :
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , PlayerColor ( id1 ) , & IGameEventsReceiver : : showPuzzleMap ) ;
2010-02-10 04:56:00 +02:00
}
2010-07-20 17:08:13 +03:00
break ;
2010-07-09 02:03:27 +03:00
case TAVERN_WINDOW :
2013-02-14 02:55:42 +03:00
const CGObjectInstance * obj1 = cl - > getObj ( ObjectInstanceID ( id1 ) ) ,
* obj2 = cl - > getObj ( ObjectInstanceID ( id2 ) ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , obj1 - > tempOwner , & IGameEventsReceiver : : showTavernWindow , obj2 ) ;
2010-02-10 04:56:00 +02:00
break ;
2009-07-06 22:41:27 +03:00
}
2009-06-16 14:18:14 +03:00
}
2009-07-26 06:33:13 +03:00
2009-08-11 10:50:29 +03:00
void CenterView : : applyCl ( CClient * cl )
{
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , player , & IGameEventsReceiver : : centerView , pos , focusTime ) ;
2009-08-11 10:50:29 +03:00
}
2009-07-26 06:33:13 +03:00
void NewObject : : applyCl ( CClient * cl )
{
2014-09-21 16:42:08 +03:00
cl - > invalidatePaths ( ) ;
2010-06-24 15:10:45 +03:00
2009-07-26 06:33:13 +03:00
const CGObjectInstance * obj = cl - > getObj ( id ) ;
2017-03-12 09:54:24 +02:00
if ( CGI - > mh )
CGI - > mh - > printObject ( obj , true ) ;
2011-08-25 23:02:38 +03:00
2013-03-03 20:06:03 +03:00
for ( auto i = cl - > playerint . begin ( ) ; i ! = cl - > playerint . end ( ) ; i + + )
2009-07-26 06:33:13 +03:00
{
2011-09-03 05:54:33 +03:00
if ( GS ( cl ) - > isVisible ( obj , i - > first ) )
2009-07-26 06:33:13 +03:00
i - > second - > newObject ( obj ) ;
}
}
2009-10-03 14:16:42 +03:00
2010-06-27 19:03:01 +03:00
void SetAvailableArtifacts : : applyCl ( CClient * cl )
{
if ( id < 0 ) //artifact merchants globally
{
2018-02-03 16:44:30 +02:00
callAllInterfaces ( cl , & IGameEventsReceiver : : availableArtifactsChanged , nullptr ) ;
2010-06-27 19:03:01 +03:00
}
else
{
2013-02-14 02:55:42 +03:00
const CGBlackMarket * bm = dynamic_cast < const CGBlackMarket * > ( cl - > getObj ( ObjectInstanceID ( id ) ) ) ;
2010-06-27 19:03:01 +03:00
assert ( bm ) ;
2018-02-03 16:44:30 +02:00
callInterfaceIfPresent ( cl , cl - > getTile ( bm - > visitablePos ( ) ) - > visitableObjects . back ( ) - > tempOwner , & IGameEventsReceiver : : availableArtifactsChanged , bm ) ;
2010-06-27 19:03:01 +03:00
}
}
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
void EntitiesChanged : : applyCl ( CClient * cl )
{
cl - > invalidatePaths ( ) ;
}