File: CPlayerInterface.h

package info (click to toggle)
vcmi 0.99%2Bdfsg%2Bgit20190113.f06c8a87-1
  • links: PTS, VCS
  • area: contrib
  • in suites: buster
  • size: 11,096 kB
  • sloc: cpp: 142,605; sh: 315; objc: 248; makefile: 32; ansic: 28; python: 13
file content (277 lines) | stat: -rw-r--r-- 14,504 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
 * CPlayerInterface.h, 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
 *
 */
#pragma once


#include "../lib/FunctionList.h"
#include "../lib/CGameInterface.h"
#include "../lib/NetPacksBase.h"
#include "gui/CIntObject.h"

#ifdef __GNUC__
#define sprintf_s snprintf
#endif

class CButton;
class CToggleGroup;
struct TryMoveHero;
class CGHeroInstance;
class CAdvMapInt;
class CCastleInterface;
class CBattleInterface;
class CStack;
class CComponent;
class CCreature;
struct SDL_Surface;
struct CGPath;
class CCreatureAnimation;
class CSelectableComponent;
class CCreatureSet;
class CGObjectInstance;
class CSlider;
struct UpgradeInfo;
template <typename T> struct CondSh;
class CInGameConsole;
class CInGameConsole;
union SDL_Event;
class CInfoWindow;
class IShowActivatable;
class ClickableL;
class ClickableR;
class Hoverable;
class KeyInterested;
class MotionInterested;
class TimeInterested;
class IShowable;
struct CPathsInfo;

namespace boost
{
	class mutex;
	class recursive_mutex;
}

/// Central class for managing user interface logic
class CPlayerInterface : public CGameInterface, public IUpdateable
{
	const CArmedInstance * currentSelection;
public:
	ObjectInstanceID destinationTeleport; //contain -1 or object id if teleportation
	int3 destinationTeleportPos;

	//minor interfaces
	CondSh<bool> *showingDialog; //indicates if dialog box is displayed

	static boost::recursive_mutex *pim;
	bool makingTurn; //if player is already making his turn
	int firstCall; // -1 - just loaded game; 1 - just started game; 0 otherwise
	int autosaveCount;
	static const int SAVES_COUNT = 5;

	CCastleInterface * castleInt; //nullptr if castle window isn't opened
	static CBattleInterface * battleInt; //nullptr if no battle
	CInGameConsole * cingconsole;

	std::shared_ptr<CCallback> cb; //to communicate with engine
	const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)

	std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)

	std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
	std::vector<const CGTownInstance *> towns; //our towns on the adventure map
	std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
	std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping

	//During battle is quick combat mode is used
	std::shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
	bool isAutoFightOn; //Flag, switch it to stop quick combat. Don't touch if there is no battle interface.

	const CArmedInstance * getSelection();
	void setSelection(const CArmedInstance * obj);

	struct SpellbookLastSetting
	{
		int spellbookLastPageBattle, spellbokLastPageAdvmap; //on which page we left spellbook
		int spellbookLastTabBattle, spellbookLastTabAdvmap; //on which page we left spellbook

		SpellbookLastSetting();
		template <typename Handler> void serialize( Handler &h, const int version )
		{
			h & spellbookLastPageBattle;
			h & spellbokLastPageAdvmap;
			h & spellbookLastTabBattle;
			h & spellbookLastTabAdvmap;
		}
	} spellbookSettings;

	void update() override;
	void initializeHeroTownList();
	int getLastIndex(std::string namePrefix);

	//overridden funcs from CGameInterface
	void garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) override;

	void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) override; //what: 1 - built, 2 - demolished

	void artifactPut(const ArtifactLocation &al) override;
	void artifactRemoved(const ArtifactLocation &al) override;
	void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override;
	void artifactAssembled(const ArtifactLocation &al) override;
	void artifactDisassembled(const ArtifactLocation &al) override;

	void heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) override;
	void heroCreated(const CGHeroInstance* hero) override;
	void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
	void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
	void heroInGarrisonChange(const CGTownInstance *town) override;
	void heroMoved(const TryMoveHero & details) override;
	void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) override;
	void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override;
	void heroManaPointsChanged(const CGHeroInstance * hero) override;
	void heroMovePointsChanged(const CGHeroInstance * hero) override;
	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override;
	void receivedResource() override;
	void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID) override;
	void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
	void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
	void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
	void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
	void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
	void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
	void showPuzzleMap() override;
	void viewWorldMap() override;
	void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override;
	void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override;
	void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
	void showTavernWindow(const CGObjectInstance *townOrTavern) override;
	void showThievesGuildWindow (const CGObjectInstance * obj) override;
	void showQuestLog() override;
	void advmapSpellCast(const CGHeroInstance * caster, int spellID) override; //called when a hero casts a spell
	void tileHidden(const std::unordered_set<int3, ShashInt3> &pos) override; //called when given tiles become hidden under fog of war
	void tileRevealed(const std::unordered_set<int3, ShashInt3> &pos) override; //called when fog of war disappears from given tiles
	void newObject(const CGObjectInstance * obj) override;
	void availableArtifactsChanged(const CGBlackMarket *bm = nullptr) override; //bm may be nullptr, then artifacts are changed in the global pool (used by merchants in towns)
	void yourTurn() override;
	void availableCreaturesChanged(const CGDwelling *town) override;
	void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) override;//if gain hero received bonus, else he lost it
	void playerBonusChanged(const Bonus &bonus, bool gain) override;
	void requestRealized(PackageApplied *pa) override;
	void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override;
	void centerView (int3 pos, int focusTime) override;
	void objectPropertyChanged(const SetObjectProperty * sop) override;
	void objectRemoved(const CGObjectInstance *obj) override;
	void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
	void playerStartsTurn(PlayerColor player) override; //called before yourTurn on active itnerface
	void showComp(const Component &comp, std::string message) override; //display component in the advmapint infobox
	void saveGame(BinarySerializer & h, const int version) override; //saving
	void loadGame(BinaryDeserializer & h, const int version) override; //loading
	void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override;

	//for battles
	void actionFinished(const BattleAction& action) override;//occurs AFTER action taken by active stack or by the hero
	void actionStarted(const BattleAction& action) override;//occurs BEFORE action taken by active stack or by the hero
	BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack
	void battleAttack(const BattleAttack *ba) override; //stack performs attack
	void battleEnd(const BattleResult *br) override; //end of battle
	void battleNewRoundFirst(int round) override; //called at the beginning of each turn before changes are applied; used for HP regen handling
	void battleNewRound(int round) override; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
	void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance) override;
	void battleSpellCast(const BattleSpellCast *sc) override;
	void battleStacksEffectsSet(const SetStackEffect & sse) override; //called when a specific effect is set to stacks
	void battleTriggerEffect(const BattleTriggerEffect & bte) override; //various one-shot effect
	void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, const std::vector<MetaString> & battleLog) override;
	void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) override; //called by engine just before battle starts; side=0 - left, side=1 - right
	void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; //called by engine when battle starts; side=0 - left, side=1 - right
	void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects, const std::vector<MetaString> & battleLog) override;
	void battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles) override;
	void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
	void battleGateStateChanged(const EGateState state) override;
	void yourTacticPhase(int distance) override;

	//-------------//
	void showArtifactAssemblyDialog(ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList<bool()> onYes, CFunctionList<bool()> onNo);
	void garrisonsChanged(std::vector<const CGObjectInstance *> objs);
	void garrisonChanged(const CGObjectInstance * obj);
	void heroKilled(const CGHeroInstance* hero);
	void waitWhileDialog(bool unlockPim = true);
	void waitForAllDialogs(bool unlockPim = true);
	bool shiftPressed() const; //determines if shift key is pressed (left or right or both)
	bool ctrlPressed() const; //determines if ctrl key is pressed (left or right or both)
	bool altPressed() const; //determines if alt key is pressed (left or right or both)
	void redrawHeroWin(const CGHeroInstance * hero);
	void openTownWindow(const CGTownInstance * town); //shows townscreen
	void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
	void updateInfo(const CGObjectInstance * specific);
	void init(std::shared_ptr<CCallback> CB) override;
	int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
	void activateForSpectator(); // TODO: spectator probably need own player interface class

	// show dialogs
	void showInfoDialog(const std::string &text, std::shared_ptr<CComponent> component);
	void showInfoDialog(const std::string &text, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>(), int soundID = 0);
	void showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text);
	void showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>());

	void stopMovement();
	void moveHero(const CGHeroInstance *h, CGPath path);
	void initMovement(const TryMoveHero &details, const CGHeroInstance * ho, const int3 &hp );//initializing objects and performing first step of move
	void movementPxStep( const TryMoveHero &details, int i, const int3 &hp, const CGHeroInstance * ho );//performing step of movement
	void finishMovement( const TryMoveHero &details, const int3 &hp, const CGHeroInstance * ho ); //finish movement
	void eraseCurrentPathOf( const CGHeroInstance * ho, bool checkForExistanceOfPath = true );

	void removeLastNodeFromPath(const CGHeroInstance *ho);
	CGPath *getAndVerifyPath( const CGHeroInstance * h );
	void acceptTurn(); //used during hot seat after your turn message is close
	void tryDiggging(const CGHeroInstance *h);
	void showShipyardDialogOrProblemPopup(const IShipyard *obj); //obj may be town or shipyard;
	void requestReturningToMainMenu(bool won);
	void sendCustomEvent(int code);
	void proposeLoadingGame();

	// Ambient sounds
	void updateAmbientSounds(bool resetAll = false);

	///returns true if all events are processed internally
	bool capturedAllEvents();

	CPlayerInterface(PlayerColor Player);
	~CPlayerInterface();

private:

	template <typename Handler> void serializeTempl(Handler &h, const int version);

private:

	struct IgnoreEvents
	{
		CPlayerInterface & owner;
		IgnoreEvents(CPlayerInterface & Owner):owner(Owner)
		{
			owner.ignoreEvents = true;
		};
		~IgnoreEvents()
		{
			owner.ignoreEvents = false;
		};

	};



	bool duringMovement;
	bool ignoreEvents;

	void doMoveHero(const CGHeroInstance *h, CGPath path);
	void setMovementStatus(bool value);
	void askToAssembleArtifact(const ArtifactLocation &al);
};

extern CPlayerInterface * LOCPLINT;