1 /***************************************************************************
2  *   Copyright (C) 2009 by Andrey Afletdinov <fheroes2@gmail.com>          *
3  *                                                                         *
4  *   Part of the Free Heroes2 Engine:                                      *
5  *   http://sourceforge.net/projects/fheroes2                              *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 #ifndef H2CASTLE_H
23 #define H2CASTLE_H
24 
25 #include <algorithm>
26 #include <map>
27 #include <string>
28 #include <vector>
29 
30 #include "army.h"
31 #include "bitmodes.h"
32 #include "captain.h"
33 #include "castle_heroes.h"
34 #include "mageguild.h"
35 #include "position.h"
36 #include "ui_button.h"
37 
38 namespace fheroes2
39 {
40     class RandomMonsterAnimation;
41 }
42 
43 class Heroes;
44 
45 enum building_t : uint32_t
46 {
47     BUILD_NOTHING = 0x00000000,
48     BUILD_THIEVESGUILD = 0x00000001,
49     BUILD_TAVERN = 0x00000002,
50     BUILD_SHIPYARD = 0x00000004,
51     BUILD_WELL = 0x00000008,
52     BUILD_STATUE = 0x00000010,
53     BUILD_LEFTTURRET = 0x00000020,
54     BUILD_RIGHTTURRET = 0x00000040,
55     BUILD_MARKETPLACE = 0x00000080,
56     BUILD_WEL2 = 0x00000100, // Farm, Garbage He, Crystal Gar, Waterfall, Orchard, Skull Pile
57     BUILD_MOAT = 0x00000200,
58     BUILD_SPEC = 0x00000400, // Fortification, Coliseum, Rainbow, Dungeon, Library, Storm
59     BUILD_CASTLE = 0x00000800,
60     BUILD_CAPTAIN = 0x00001000,
61     BUILD_SHRINE = 0x00002000,
62     BUILD_MAGEGUILD1 = 0x00004000,
63     BUILD_MAGEGUILD2 = 0x00008000,
64     BUILD_MAGEGUILD3 = 0x00010000,
65     BUILD_MAGEGUILD4 = 0x00020000,
66     BUILD_MAGEGUILD5 = 0x00040000,
67     BUILD_MAGEGUILD = BUILD_MAGEGUILD1 | BUILD_MAGEGUILD2 | BUILD_MAGEGUILD3 | BUILD_MAGEGUILD4 | BUILD_MAGEGUILD5,
68     BUILD_TENT = 0x00080000, // deprecated
69     DWELLING_MONSTER1 = 0x00100000,
70     DWELLING_MONSTER2 = 0x00200000,
71     DWELLING_MONSTER3 = 0x00400000,
72     DWELLING_MONSTER4 = 0x00800000,
73     DWELLING_MONSTER5 = 0x01000000,
74     DWELLING_MONSTER6 = 0x02000000,
75     DWELLING_MONSTERS = DWELLING_MONSTER1 | DWELLING_MONSTER2 | DWELLING_MONSTER3 | DWELLING_MONSTER4 | DWELLING_MONSTER5 | DWELLING_MONSTER6,
76     DWELLING_UPGRADE2 = 0x04000000,
77     DWELLING_UPGRADE3 = 0x08000000,
78     DWELLING_UPGRADE4 = 0x10000000,
79     DWELLING_UPGRADE5 = 0x20000000,
80     DWELLING_UPGRADE6 = 0x40000000,
81     DWELLING_UPGRADE7 = 0x80000000, // black dragon
82     DWELLING_UPGRADES = DWELLING_UPGRADE2 | DWELLING_UPGRADE3 | DWELLING_UPGRADE4 | DWELLING_UPGRADE5 | DWELLING_UPGRADE6 | DWELLING_UPGRADE7
83 };
84 
85 enum buildcond_t
86 {
87     NOT_TODAY = -1,
88     ALREADY_BUILT = -2,
89     NEED_CASTLE = -3,
90     BUILD_DISABLE = -4,
91     UNKNOWN_UPGRADE = -5,
92     REQUIRES_BUILD = -6,
93     LACK_RESOURCES = -7,
94     UNKNOWN_COND = 0,
95     ALLOW_BUILD = 1
96 };
97 
98 class Castle : public MapPosition, public BitModes, public ColorBase, public Control
99 {
100 public:
101     enum flags_t
102     {
103         ALLOWCASTLE = 0x0002,
104         CUSTOMARMY = 0x0004,
105         ALLOWBUILD = 0x0008,
106         // UNUSED = 0x0010,
107         CAPITAL = 0x0020
108     };
109 
110     enum class CastleDialogReturnValue : int
111     {
112         DoNothing,
113         Close, // Close the dialog.
114         NextCastle, // Open main dialog of the next castle.
115         PreviousCastle, // Open main dialog of the previous castle.
116         NextCostructionWindow, // Open construction dialog of the next castle.
117         PreviousCostructionWindow // Open construction dialog of the previous castle.
118     };
119 
120     Castle();
121     Castle( s32, s32, int rs );
122     ~Castle() override = default;
123 
124     void LoadFromMP2( std::vector<uint8_t> & data );
125 
126     Captain & GetCaptain( void );
127     const Captain & GetCaptain( void ) const;
128 
129     bool isCastle( void ) const;
130     bool isCapital( void ) const;
131     bool HaveNearlySea( void ) const;
132     bool PresentBoat( void ) const;
133     bool AllowBuyHero( const Heroes &, std::string * = nullptr ) const;
134     bool isPosition( const fheroes2::Point & ) const;
135     bool isNecromancyShrineBuild( void ) const;
136 
137     u32 CountBuildings( void ) const;
138 
139     Heroes * RecruitHero( Heroes * );
140     CastleHeroes GetHeroes( void ) const;
141 
142     int GetRace( void ) const;
143 
144     const std::string & GetName() const;
145 
146     // This method must be called only at the time of map loading and only for castles with empty names.
147     void setName( const std::set<std::string> & usedNames );
148 
149     int GetControl( void ) const override;
150 
151     int GetLevelMageGuild( void ) const;
152     const MageGuild & GetMageGuild( void ) const;
153     bool HaveLibraryCapability( void ) const;
154     bool isLibraryBuild( void ) const;
155     void MageGuildEducateHero( HeroBase & ) const;
156 
157     bool isFortificationBuild() const;
158 
159     const Army & GetArmy( void ) const;
160     Army & GetArmy( void );
161     const Army & GetActualArmy( void ) const;
162     Army & GetActualArmy( void );
163     double GetGarrisonStrength( const Heroes * attackingHero ) const;
164     u32 getMonstersInDwelling( u32 ) const;
165     u32 GetActualDwelling( u32 ) const;
166 
167     bool RecruitMonsterFromDwelling( uint32_t dw, uint32_t count, bool force = false );
168     bool RecruitMonster( const Troop & troop, bool showDialog = true );
169     void recruitBestAvailable( Funds budget );
170     uint32_t getRecruitLimit( const Monster & monster, const Funds & budget ) const;
171 
172     int getBuildingValue() const;
173 
174     // Used only for AI.
175     double getVisitValue( const Heroes & hero ) const;
176 
177     void ChangeColor( int );
178 
179     void ActionNewDay( void );
180     void ActionNewWeek( void );
181     void ActionNewMonth( void );
182     void ActionPreBattle( void );
183     void ActionAfterBattle( bool attacker_wins );
184 
185     void DrawImageCastle( const fheroes2::Point & pt ) const;
186 
187     CastleDialogReturnValue OpenDialog( const bool readOnly, const bool openConstructionWindow );
188 
189     int GetAttackModificator( const std::string * ) const;
190     int GetDefenseModificator( const std::string * ) const;
191     int GetPowerModificator( std::string * ) const;
192     int GetKnowledgeModificator( const std::string * ) const;
193     int GetMoraleModificator( std::string * ) const;
194     int GetLuckModificator( std::string * ) const;
195 
196     bool AllowBuyBuilding( u32 ) const;
197     bool isBuild( u32 bd ) const;
198     bool BuyBuilding( u32 );
199     bool AllowBuyBoat( void ) const;
200     bool BuyBoat( void ) const;
201     u32 GetBuildingRequirement( u32 ) const;
202 
203     int CheckBuyBuilding( u32 ) const;
204     static int GetAllBuildingStatus( const Castle & );
205 
206     void Scoute( void ) const;
207 
208     std::string GetStringBuilding( u32 ) const;
209     std::string GetDescriptionBuilding( u32 ) const;
210 
211     static const char * GetStringBuilding( u32, int race );
212     static const char * GetDescriptionBuilding( u32, int race );
213 
214     static int GetICNBuilding( u32, int race );
215     static int GetICNBoat( int race );
216     u32 GetUpgradeBuilding( u32 ) const;
217 
218     static bool PredicateIsCastle( const Castle * );
219     static bool PredicateIsTown( const Castle * );
220     static bool PredicateIsBuildBuilding( const Castle * castle, const uint32_t building );
221 
222     static u32 GetGrownWell( void );
223     static u32 GetGrownWel2( void );
224     static u32 GetGrownWeekOf();
225     static u32 GetGrownMonthOf( void );
226 
227     std::string String( void ) const;
228 
229     int DialogBuyHero( const Heroes * ) const;
230     int DialogBuyCastle( bool fixed = true ) const;
231 
232     void SwapCastleHeroes( CastleHeroes & );
233 
234 private:
235     enum class ConstructionDialogResult : int
236     {
237         DoNothing,
238         NextConstructionWindow, // Open construction dialog for the next castle.
239         PrevConstructionWindow, // Open construction dialog for the previous castle.
240         Build, // Build something.
241         RecruitHero // Recruit a hero.
242     };
243 
244     u32 * GetDwelling( u32 dw );
245     void EducateHeroes( void );
246 
247     ConstructionDialogResult openConstructionDialog( uint32_t & dwellingTobuild );
248 
249     void OpenTavern( void ) const;
250     void OpenWell( void );
251     void OpenMageGuild( const CastleHeroes & heroes ) const;
252     void WellRedrawInfoArea( const fheroes2::Point & cur_pt, const std::vector<fheroes2::RandomMonsterAnimation> & monsterAnimInfo ) const;
253     void JoinRNDArmy( void );
254     void PostLoad( void );
255 
256     friend StreamBase & operator<<( StreamBase &, const Castle & );
257     friend StreamBase & operator>>( StreamBase &, Castle & );
258 
259     int race;
260     u32 building;
261     Captain captain;
262 
263     std::string name;
264 
265     MageGuild mageguild;
266     u32 dwelling[CASTLEMAXMONSTER];
267     Army army;
268 };
269 
270 namespace CastleDialog
271 {
272     // Class used for fading animation
273     class FadeBuilding
274     {
275     public:
FadeBuilding()276         FadeBuilding()
277             : _alpha( 255 )
278             , _build( BUILD_NOTHING )
279         {}
280 
281         void StartFadeBuilding( const uint32_t build );
282 
283         bool UpdateFadeBuilding();
284 
IsFadeDone()285         bool IsFadeDone() const
286         {
287             return _alpha == 255;
288         }
289 
290         void StopFadeBuilding();
291 
GetAlpha()292         uint8_t GetAlpha() const
293         {
294             return _alpha;
295         }
296 
GetBuild()297         uint32_t GetBuild() const
298         {
299             return _build;
300         }
301 
302     private:
303         uint8_t _alpha;
304         uint32_t _build;
305     };
306 
307     struct builds_t
308     {
builds_tbuilds_t309         builds_t( building_t b, const fheroes2::Rect & r )
310             : id( b )
311             , coord( r )
312         {}
313 
314         bool operator==( u32 b ) const
315         {
316             return b == static_cast<uint32_t>( id );
317         }
318 
319         building_t id;
320         fheroes2::Rect coord;
321     };
322 
323     struct CacheBuildings : std::vector<builds_t>
324     {
325         CacheBuildings( const Castle &, const fheroes2::Point & );
326     };
327 
328     void RedrawAllBuilding( const Castle & castle, const fheroes2::Point & dst_pt, const CacheBuildings & orders, const CastleDialog::FadeBuilding & alphaBuilding,
329                             const uint32_t animationIndex );
330     void RedrawBuildingSpriteToArea( const fheroes2::Sprite &, s32, s32, const fheroes2::Rect &, uint8_t alpha = 255 );
331 
332     void CastleRedrawBuilding( const Castle &, const fheroes2::Point &, u32 build, u32 frame, uint8_t alpha = 255 );
333     void CastleRedrawBuildingExtended( const Castle &, const fheroes2::Point &, u32 build, u32 frame, uint8_t alpha = 255 );
334 }
335 
336 struct VecCastles : public std::vector<Castle *>
337 {
338     Castle * GetFirstCastle( void ) const;
339 
340     void ChangeColors( int, int );
341     void SortByBuildingValue();
342 };
343 
344 class AllCastles
345 {
346 public:
347     AllCastles();
348     AllCastles( AllCastles & ) = delete;
349 
350     ~AllCastles();
351 
352     AllCastles & operator=( const AllCastles & ) = delete;
353 
354     void Init( void );
355     void Clear( void );
356 
357     void AddCastle( Castle * castle );
358 
359     Castle * Get( const fheroes2::Point & position ) const;
360 
361     void Scoute( int ) const;
362 
NewDay()363     void NewDay()
364     {
365         std::for_each( _castles.begin(), _castles.end(), []( Castle * castle ) { castle->ActionNewDay(); } );
366     }
367 
NewWeek()368     void NewWeek()
369     {
370         std::for_each( _castles.begin(), _castles.end(), []( Castle * castle ) { castle->ActionNewWeek(); } );
371     }
372 
NewMonth()373     void NewMonth()
374     {
375         std::for_each( _castles.begin(), _castles.end(), []( Castle * castle ) { castle->ActionNewMonth(); } );
376     }
377 
378     // begin/end methods so we can iterate through the elements
begin()379     std::vector<Castle *>::const_iterator begin() const
380     {
381         return _castles.begin();
382     }
383 
end()384     std::vector<Castle *>::const_iterator end() const
385     {
386         return _castles.end();
387     }
388 
Size()389     size_t Size() const
390     {
391         return _castles.size();
392     }
393 
394 private:
395     std::vector<Castle *> _castles;
396     std::map<fheroes2::Point, size_t> _castleTiles;
397 };
398 
399 StreamBase & operator<<( StreamBase &, const VecCastles & );
400 StreamBase & operator>>( StreamBase &, VecCastles & );
401 
402 StreamBase & operator<<( StreamBase &, const AllCastles & );
403 StreamBase & operator>>( StreamBase &, AllCastles & );
404 
405 StreamBase & operator<<( StreamBase &, const Castle & );
406 StreamBase & operator>>( StreamBase &, Castle & );
407 
408 #endif
409