File: CGarrisonInt.h

package info (click to toggle)
vcmi 1.6.5%2Bdfsg-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 32,060 kB
  • sloc: cpp: 238,971; python: 265; sh: 224; xml: 157; ansic: 78; objc: 61; makefile: 49
file content (153 lines) | stat: -rw-r--r-- 5,153 bytes parent folder | download
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
/*
 * CGarrisonInt.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 "../gui/CIntObject.h"

VCMI_LIB_NAMESPACE_BEGIN

class CArmedInstance;
class CStackInstance;

VCMI_LIB_NAMESPACE_END

class CGarrisonInt;
class CButton;
class CAnimImage;
class CLabel;

enum class EGarrisonType
{
	UPPER, /// up garrison (Garrisoned)
	LOWER, /// down garrison (Visiting)
};

/// A single garrison slot which holds one creature of a specific amount
class CGarrisonSlot : public CIntObject
{
	SlotID ID; //for identification
	CGarrisonInt *owner;
	const CStackInstance * myStack; //nullptr if slot is empty
	const CCreature * creature;
	EGarrisonType upg;

	std::shared_ptr<CAnimImage> creatureImage;
	std::shared_ptr<CAnimImage> selectionImage; // image for selection, not always visible
	std::shared_ptr<CLabel> stackCount;

public:
	bool viewInfo();
	bool highlightOrDropArtifact();
	bool split();

	/// If certain creates cannot be moved, the selection should change
	/// Force reselection in these cases
	///     * When attempting to take creatures from ally
	///     * When attempting to swap creatures with an ally
	///     * When attempting to take unremovable units
	/// @return Whether reselection must be done
	bool mustForceReselection() const;

	void setHighlight(bool on);
	std::function<void()> getDismiss() const;

	const CArmedInstance * getObj() const;
	bool our() const;
	SlotID getSlot() const { return ID; }
	EGarrisonType getGarrison() const { return upg; }
	bool ally() const;

	// CIntObject overrides
	void showPopupWindow(const Point & cursorPosition) override;
	void clickPressed(const Point & cursorPosition) override;
	void hover (bool on) override; //call-in
	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;

	void update();
	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg, const CStackInstance * creature_);

	void splitIntoParts(EGarrisonType type, int amount);
	bool handleSplittingShortcuts(); /// Returns true when some shortcut is pressed, false otherwise

	friend class CGarrisonInt;
};

/// Class which manages slots of upper and lower garrison, splitting of units
class CGarrisonInt :public CIntObject
{
	/// Chosen slot. Should be changed only via selectSlot.
	CGarrisonSlot * highlighted;
	bool inSplittingMode;
	std::vector<std::shared_ptr<CGarrisonSlot>> availableSlots;  ///< Slots of upper and lower garrison

	void createSlots();
	bool checkSelected(const CGarrisonSlot * selected, TQuantity min = 0) const;

	std::map<EGarrisonType, const CArmedInstance*> armedObjs;

public:
	enum class ESlotsLayout
	{
		ONE_ROW,
		TWO_ROWS,
		REVERSED_TWO_ROWS
	};

	int interx;  ///< Space between slots
	Point garOffset;  ///< Offset between garrisons (not used if only one hero)
	std::vector<std::shared_ptr<CButton>> splitButtons;  ///< May be empty if no buttons

	bool smallIcons;      ///< true - 32x32 imgs, false - 58x64
	bool removableUnits;  ///< player Can remove units from up

	ESlotsLayout layout;

	void selectSlot(CGarrisonSlot * slot); ///< @param slot null = deselect
	const CGarrisonSlot * getSelection() const;

	void setSplittingMode(bool on);
	bool getSplittingMode();

	bool hasEmptySlot(EGarrisonType type) const;
	SlotID getEmptySlot(EGarrisonType type) const;

	void setArmy(const CArmedInstance * army, EGarrisonType type);
	void addSplitBtn(std::shared_ptr<CButton> button);

	void recreateSlots();

	const CArmedInstance* upperArmy() const;
	const CArmedInstance* lowerArmy() const;
	const CArmedInstance* army(EGarrisonType which) const;
	bool isArmyOwned(EGarrisonType which) const;

	void splitClick();  ///< handles click on split button
	void splitStacks(const CGarrisonSlot * from, const CArmedInstance * armyDest, SlotID slotDest, int amount);  ///< TODO: comment me
	void moveStackToAnotherArmy(const CGarrisonSlot * selected);
	void bulkMoveArmy(const CGarrisonSlot * selected);
	void bulkMergeStacks(const CGarrisonSlot * selected); // Gather all creatures of selected type to the selected slot from other hero/garrison slots
	void bulkSplitStack(const CGarrisonSlot * selected); // Used to separate one-creature troops from main stack
	void bulkSmartSplitStack(const CGarrisonSlot * selected);

	/// Constructor
	/// @param position Relative position to parent element
	/// @param slotInterval Distance between slots;
	/// @param secondGarrisonOffset
	/// @param s1, s2 Top and bottom armies
	/// @param _removableUnits You can take units from top
	/// @param smallImgs Units images size 64x58 or 32x32
	/// @param _layout - when TWO_ROWS - Display slots in 2 rows (1st row = 4 slots, 2nd = 3 slots), REVERSED_TWO_ROWS = 3 slots in 1st row
	CGarrisonInt(const Point & position, int slotInterval,
				 const Point & secondGarrisonOffset,
				 const CArmedInstance * upperArmy, const CArmedInstance * lowerArmy = nullptr,
				 bool _removableUnits = true,
				 bool smallImgs = false,
				 ESlotsLayout _layout = ESlotsLayout::ONE_ROW);
};