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 H2TILES_H
23 #define H2TILES_H
24 
25 #include <list>
26 
27 #include "army_troop.h"
28 #include "artifact.h"
29 #include "color.h"
30 #include "direction.h"
31 #include "mp2.h"
32 #include "resource.h"
33 #include "skill.h"
34 
35 class Heroes;
36 class Spell;
37 class Monster;
38 
39 namespace MP2
40 {
41     struct mp2tile_t;
42     struct mp2addon_t;
43 }
44 
45 namespace Interface
46 {
47     class GameArea;
48     bool SkipRedrawTileBottom4Hero( const uint8_t tileset, const uint8_t icnIndex, const int passable );
49 }
50 
51 namespace Maps
52 {
53     struct TilesAddon
54     {
55         enum level_t : uint8_t
56         {
57             GROUND = 0,
58             DOWN = 1,
59             SHADOW = 2,
60             UPPER = 3
61         };
62 
63         TilesAddon();
64         TilesAddon( const uint8_t lv, const uint32_t uid, const uint8_t obj, const uint32_t index_ );
65         TilesAddon( const TilesAddon & ta );
66 
67         ~TilesAddon() = default;
68 
69         TilesAddon & operator=( const TilesAddon & ta ) = delete;
70 
isUniqTilesAddon71         bool isUniq( const uint32_t id ) const
72         {
73             return uniq == id;
74         }
75 
76         bool isRoad() const;
77         bool hasSpriteAnimation() const;
78 
79         std::string String( int level ) const;
80 
81         static bool isShadow( const TilesAddon & );
82 
83         static bool isResource( const TilesAddon & );
84         static bool isArtifact( const TilesAddon & );
85         static bool isFlag32( const TilesAddon & );
86 
87         static bool PredicateSortRules1( const TilesAddon &, const TilesAddon & );
88 
89         uint32_t uniq;
90         uint8_t level;
91         uint8_t object;
92         uint8_t index;
93     };
94 
95     struct Addons : public std::list<TilesAddon>
96     {
97         void Remove( u32 uniq );
98     };
99 
100     class Tiles
101     {
102     public:
103         Tiles();
104 
105         void Init( s32, const MP2::mp2tile_t & );
106 
GetIndex()107         int32_t GetIndex() const
108         {
109             return _index;
110         }
111 
112         fheroes2::Point GetCenter( void ) const;
113         MP2::MapObjectType GetObject( bool ignoreObjectUnderHero = true ) const;
114         uint8_t GetObjectTileset() const;
115 
116         uint8_t GetObjectSpriteIndex() const;
117 
118         u32 GetObjectUID() const;
119 
120         // Get Tile metadata field #1 (used for things like monster count or resource amount)
GetQuantity1()121         uint8_t GetQuantity1() const
122         {
123             return quantity1;
124         }
125 
126         // Get Tile metadata field #2 (used for things like animations or resource type )
GetQuantity2()127         uint8_t GetQuantity2() const
128         {
129             return quantity2;
130         }
131 
132         // Get third field containing Tile metadata (adventure spell ID)
GetQuantity3()133         uint8_t GetQuantity3() const
134         {
135             return quantity3;
136         }
137 
138         int GetPassable() const;
139         int GetGround() const;
140         bool isWater() const;
141 
142         u32 TileSpriteIndex( void ) const;
143         u32 TileSpriteShape( void ) const;
144 
145         const fheroes2::Image & GetTileSurface( void ) const;
146 
147         bool isObject( const MP2::MapObjectType objectType ) const;
148         bool hasSpriteAnimation() const;
149         bool validateWaterRules( bool fromWater ) const;
150         bool isPassable( int direct, bool fromWater, bool skipfog, const int heroColor ) const;
151         bool isRoad() const;
152         bool isStream( void ) const;
153         bool isShadow() const;
154         bool GoodForUltimateArtifact() const;
155 
156         TilesAddon * FindAddonLevel1( u32 uniq1 );
157         TilesAddon * FindAddonLevel2( u32 uniq2 );
158 
159         void SetTile( u32 sprite_index, u32 shape /* 0: none, 1 : vert, 2: horz, 3: both */ );
160         void SetObject( const MP2::MapObjectType objectType );
161 
SetIndex(const uint32_t index)162         void SetIndex( const uint32_t index )
163         {
164             _index = index;
165         }
166 
167         void setBoat( int direction );
168         int getBoatDirection() const;
169         void resetObjectSprite();
170 
171         void FixObject( void );
172 
173         uint32_t GetRegion() const;
174         void UpdateRegion( uint32_t newRegionID );
175 
176         // Set initial passability based on information read from mp2 and addon structures.
177         void setInitialPassability();
178 
179         // Update passability based on neigbhours around.
180         void updatePassability();
181 
182         int getOriginalPassability() const;
183 
184         bool isClearGround() const;
185 
186         bool doesObjectExist( const uint32_t uid ) const;
187 
188         // ICN::FLAGS32 version
189         void CaptureFlags32( const MP2::MapObjectType objectType, int col );
190 
191         // Removes all ICN::FLAGS32 objects from this tile.
192         void removeFlags();
193 
194         void RedrawTile( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, const Interface::GameArea & area ) const;
195         static void RedrawEmptyTile( fheroes2::Image & dst, const fheroes2::Point & mp, const fheroes2::Rect & visibleTileROI, const Interface::GameArea & area );
196         void RedrawBottom( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, bool isPuzzleDraw, const Interface::GameArea & area ) const;
197         void RedrawBottom4Hero( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, const Interface::GameArea & area ) const;
198         void RedrawTop( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, const bool isPuzzleDraw, const Interface::GameArea & area ) const;
199         void RedrawTopFromBottom( fheroes2::Image & dst, const Interface::GameArea & area ) const;
200         void RedrawTop4Hero( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, bool skip_ground, const Interface::GameArea & area ) const;
201         void RedrawObjects( fheroes2::Image & dst, bool isPuzzleDraw, const Interface::GameArea & area ) const;
202         void RedrawBoat( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, const Interface::GameArea & area ) const;
203         void RedrawBoatShadow( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, const Interface::GameArea & area ) const;
204         void RedrawMonster( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, const Interface::GameArea & area ) const;
205         int GetFogDirections( int color ) const;
206         void RedrawFogs( fheroes2::Image & dst, int color, const Interface::GameArea & area ) const;
207         void RedrawAddon( fheroes2::Image & dst, const Addons & addon, const fheroes2::Rect & visibleTileROI, bool isPuzzleDraw, const Interface::GameArea & area ) const;
208         void RedrawPassable( fheroes2::Image & dst, const fheroes2::Rect & visibleTileROI, const Interface::GameArea & area ) const;
209 
210         void AddonsPushLevel1( const MP2::mp2tile_t & );
211         void AddonsPushLevel1( const MP2::mp2addon_t & );
212         void AddonsPushLevel1( const TilesAddon & );
213         void AddonsPushLevel2( const MP2::mp2tile_t & );
214         void AddonsPushLevel2( const MP2::mp2addon_t & );
215 
getLevel1Addons()216         const Addons & getLevel1Addons() const
217         {
218             return addons_level1;
219         }
220 
getLevel2Addons()221         const Addons & getLevel2Addons() const
222         {
223             return addons_level2;
224         }
225 
226         void AddonsSort( void );
227         void Remove( u32 uniqID );
228         void RemoveObjectSprite( void );
229         void UpdateObjectSprite( uint32_t uniqID, uint8_t rawTileset, uint8_t newTileset, int indexChange );
230         void ReplaceObjectSprite( uint32_t uniqID, uint8_t rawTileset, uint8_t newTileset, uint8_t indexToReplace, uint8_t newIndex );
231 
232         std::string String( void ) const;
233 
isFog(const int colors)234         bool isFog( const int colors ) const
235         {
236             // colors may be the union friends
237             return ( fog_colors & colors ) == colors;
238         }
239 
240         bool isFogAllAround( const int color ) const;
241         void ClearFog( int color );
242 
243         /* monster operation */
244         bool MonsterJoinConditionSkip( void ) const;
245         bool MonsterJoinConditionFree( void ) const;
246         int MonsterJoinCondition( void ) const;
247         void MonsterSetJoinCondition( int );
248         void MonsterSetFixedCount( void );
249         bool MonsterFixedCount( void ) const;
250         void MonsterSetCount( u32 count );
251         u32 MonsterCount( void ) const;
252 
253         bool CaptureObjectIsProtection( void ) const;
254 
255         /* object quantity operation */
256         void QuantityUpdate( bool isFirstLoad = true );
257         void QuantityReset( void );
258         bool QuantityIsValid( void ) const;
259         void QuantitySetColor( int );
260         int QuantityVariant( void ) const;
261         int QuantityExt( void ) const;
262         int QuantityColor( void ) const;
263         u32 QuantityGold( void ) const;
264         Spell QuantitySpell( void ) const;
265         Skill::Secondary QuantitySkill( void ) const;
266         Artifact QuantityArtifact( void ) const;
267         ResourceCount QuantityResourceCount( void ) const;
268         Funds QuantityFunds( void ) const;
269         Monster QuantityMonster( void ) const;
270         Troop QuantityTroop( void ) const;
271 
272         void SetObjectPassable( bool );
273 
274         // Set Tile metadata field (used for things like adventure spell ID)
SetQuantity3(const uint8_t value)275         void SetQuantity3( const uint8_t value )
276         {
277             quantity3 = value;
278         }
279 
280         Heroes * GetHeroes( void ) const;
281         void SetHeroes( Heroes * );
282 
283         // If tile is empty (MP2::OBJ_ZERO) then verify whether it is a coast and update the tile if needed.
284         void updateEmpty();
285 
286         // Set tile to coast MP2::OBJ_COAST) if it's near water or to empty (MP2::OBJ_ZERO)
287         void setAsEmpty();
288 
289         uint32_t getObjectIdByICNType( const int icnId ) const;
290 
291         std::vector<uint8_t> getValidTileSets() const;
292 
293         bool containsTileSet( const std::vector<uint8_t> & tileSets ) const;
294 
295         static int ColorFromBarrierSprite( const uint8_t tileset, const uint8_t icnIndex );
296         static int ColorFromTravellerTentSprite( const uint8_t tileset, const uint8_t icnIndex );
297         static MP2::MapObjectType GetLoyaltyObject( const uint8_t tileset, const uint8_t icnIndex );
298         static bool isShadowSprite( const uint8_t tileset, const uint8_t icnIndex );
299         static bool isShadowSprite( const int tileset, const uint8_t icnIndex );
300         static void UpdateAbandoneMineLeftSprite( uint8_t & tileset, uint8_t & index, const int resource );
301         static void UpdateAbandoneMineRightSprite( uint8_t & tileset, uint8_t & index );
302         static std::pair<int, int> ColorRaceFromHeroSprite( const uint32_t heroSpriteIndex );
303         static std::pair<uint32_t, uint32_t> GetMonsterSpriteIndices( const Tiles & tile, const uint32_t monsterIndex );
304         static void PlaceMonsterOnTile( Tiles & tile, const Monster & mons, const uint32_t count );
305         static void UpdateAbandoneMineSprite( Tiles & tile );
306 
307         // Some tiles have incorrect object type. This is due to original Editor issues.
308         static void fixTileObjectType( Tiles & tile );
309 
310         static int32_t getIndexOfMainTile( const Maps::Tiles & tile );
311 
312     private:
313         TilesAddon * FindFlags( void );
314 
315         // correct flags, ICN::FLAGS32 vesion
316         void CorrectFlags32( const int col, const u32 index, const bool up );
317         void RemoveJailSprite( void );
318 
319         void QuantitySetVariant( int );
320         void QuantitySetExt( int );
321         void QuantitySetSkill( int );
322         void QuantitySetSpell( int );
323         void QuantitySetArtifact( int );
324         void QuantitySetResource( int, u32 );
325 
326         bool isTallObject() const;
327 
328         bool isDetachedObject() const;
329 
330         static void UpdateMonsterInfo( Tiles & );
331         static void UpdateDwellingPopulation( Tiles & tile, bool isFirstLoad );
332         static void UpdateMonsterPopulation( Tiles & );
333         static void UpdateRNDArtifactSprite( Tiles & );
334         static void UpdateRNDResourceSprite( Tiles & );
335 
336         static void updateTileById( Maps::Tiles & tile, const uint32_t uid, const uint8_t newIndex );
337 
338         friend StreamBase & operator<<( StreamBase &, const Tiles & );
339         friend StreamBase & operator>>( StreamBase &, Tiles & );
340 
341         friend bool operator<( const Tiles & l, const Tiles & r )
342         {
343             return l.GetIndex() < r.GetIndex();
344         }
345 
346         Addons addons_level1;
347         Addons addons_level2; // 16
348 
349         int32_t _index = 0;
350         uint16_t pack_sprite_index = 0;
351 
352         uint32_t uniq = 0;
353         uint8_t objectTileset = 0;
354         uint8_t objectIndex = 255;
355         uint8_t mp2_object = 0;
356         uint16_t tilePassable = DIRECTION_ALL;
357         uint8_t fog_colors = Color::ALL;
358 
359         uint8_t heroID = 0;
360         uint8_t quantity1 = 0;
361         uint8_t quantity2 = 0;
362         uint8_t quantity3 = 0;
363 
364         bool tileIsRoad = false;
365 
366         // This field does not persist in savegame.
367         uint32_t _region = 0;
368 
369         uint8_t _level = 0;
370     };
371 
372     StreamBase & operator<<( StreamBase &, const TilesAddon & );
373     StreamBase & operator<<( StreamBase &, const Tiles & );
374     StreamBase & operator>>( StreamBase &, TilesAddon & );
375     StreamBase & operator>>( StreamBase &, Tiles & );
376 }
377 
378 #endif
379