#ifndef __MAPSTUFF_H__ #define __MAPSTUFF_H__ #include "mapclasses.h" #include #include "uox3.h" #include "MultiMul.hpp" constexpr auto MAX_Z_STEP = std::uint8_t( 9 ); constexpr auto MAX_Z_FALL = std::uint8_t( 20 ); //=============================================================================================== // TileInfo //=============================================================================================== class TileInfo { constexpr static auto hsSize = 3188736; std::vector terrainData; std::vector artData; auto ProcessTerrain( std::istream &input ) -> void; auto ProcessArt( std::istream &input ) -> void; bool isHsFormat; public: TileInfo( const std::string &filename = "" ); auto LoadTiles( const std::string &filename ) -> bool; auto TerrainInfo( std::uint16_t tileId ) const -> const CLand&; auto TerrainInfo( std::uint16_t tileId ) -> CLand&; auto ArtInfo( std::uint16_t tileId ) -> CTile&; auto ArtInfo( std::uint16_t tileId ) const -> const CTile&; auto SizeTerrain() const -> size_t; auto SizeArt() const -> size_t; auto CollectionTerrain() const -> const std::vector&; auto CollectionTerrain() -> std::vector&; auto CollectionArt() const -> const std::vector&; auto CollectionArt() -> std::vector&; auto TotalMemory() const -> size_t; }; //================================================================================================== // Blocks and maps would normally be in separate files, but since we dont want to impact windows // project files, we will use the existing files to include them class TerrainBlock { std::array, 8> _tiles; public: TerrainBlock( std::uint8_t *data = nullptr, const TileInfo *info = nullptr ); auto LoadBlock( std::uint8_t *data, const TileInfo *info = nullptr ) -> void; auto TerrainTileAt( int x, int y ) -> Tile_st&; auto TerrainTileAt( int x, int y ) const -> const Tile_st&; }; //========================================================= class ArtBlock { std::array, 8>, 8> _tiles; public: ArtBlock( int length = 0, std::uint8_t *data = nullptr, const TileInfo *info = nullptr ); auto LoadArtBlock( int length, std::uint8_t *data, const TileInfo *info = nullptr ) -> void; auto LoadArtBlock( int length, std::istream &input, const TileInfo *info = nullptr ) -> void; auto ArtTileAt( int x, int y ) -> std::vector&; auto ArtTileAt( int x, int y ) const -> const std::vector&; auto Clear() -> void; }; //========================================================= class UltimaMap : public UopFile { std::vector _terrain; std::vector _art; const TileInfo *tileInfo; static constexpr int _totalMaps = 6; static constexpr std::array, _totalMaps> _mapSizes {{ {7168, 4096}, {7168, 4096}, {2304, 1600}, {2560, 2048}, {1448, 1448}, {1280, 4096} }}; int _mapNum; int _width; int _height; bool isUop; int _diffCount; int _diffTerrain; auto virtual ProcessEntry( std::size_t entry, std::size_t index, std::vector &data ) -> bool final; auto CalcBlock (int x, int y ) const -> int; auto CalcXYOffset( int block ) const -> std::pair; auto LoadTerrainBlock( int blockNum, std::uint8_t *data ) -> void; public: UltimaMap(); UltimaMap( int mapNum, int width = 0, int height = 0, const TileInfo *info = nullptr ); auto Width() const -> int; auto Height() const -> int; auto DiffArt() const -> int; auto DiffTerrain() const -> int; auto SetSize( int width, int height ) -> void; auto Size() const -> std::pair; auto LoadUOPTerrainFile( const std::string &fileName) -> bool; auto LoadMulTerrainFile( const std::string &fileName) -> bool; auto LoadArt( const std::string &mulFile, const std::string &idxFile ) -> bool; auto ApplyDiff( const std::string &difflPath, const std::string &diffiPath, const std::string &diffPath ) -> int; auto ApplyTerrainDiff( const std::string &difflPath, const std::string &diffPath ) -> int; auto BlockAndIndexFor( int x, int y ) const -> std::tuple; auto Uop() const -> bool { return isUop; } auto TerrainAt( int x, int y ) const -> const Tile_st&; auto TerrainAt( int x, int y ) -> Tile_st&; auto ArtAt( int x, int y ) const -> const std::vector&; auto ArtAt( int x, int y ) -> std::vector&; }; //==================================================================================================== struct MapDfnData_st { int width; int height; std::filesystem::path mapFile; std::filesystem::path mapUop; std::filesystem::path staMul; std::filesystem::path staIdx; std::filesystem::path mapDiff; std::filesystem::path mapDiffl; std::filesystem::path staDiff; std::filesystem::path staDiffi; std::filesystem::path staDiffl; MapDfnData_st() : width( 0 ), height( 0 ) {} }; //========================================================================================== // until we can replace //========================================================================================== class CMulHandler { private: // uo eq5q TileInfo tileInfo; MultiCollection multiData; std::unordered_map uoWorlds; auto LoadMapsDFN( const std::string &uoDir ) -> std::map; auto LoadDFNOverrides() -> void; auto LoadTileData( const std::string &uoDir ) -> void; auto LoadMultis( const std::string &uoDir ) -> void; auto LoadMapAndStatics( const std::map &info ) -> void; public: CMulHandler() = default; auto Load() -> void; auto ArtAt( std::int16_t x, std::int16_t y, std::uint8_t world ) -> std::vector&; auto ArtAt( std::int16_t x, std::int16_t y, std::uint8_t world ) const -> const std::vector&; auto SizeOfMap( std::uint8_t worldNumber ) const -> std::pair; auto DiffCountForMap( std::uint8_t worldNumber ) const -> std::pair; auto MultiHeight( CItem *i, std::int16_t x, std::int16_t y, std::int8_t oldZ, std::int8_t maxZ, bool checkHeight = false ) -> std::int8_t; auto MultiTile( CItem *i, std::int16_t x, std::int16_t y, std::int8_t oldZ, bool checkVisible = true ) -> std::uint16_t; auto DoesStaticBlock( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, bool checkWater = false ) -> bool; auto DoesDynamicBlock( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::uint16_t instanceId, bool checkWater, bool waterWalk, bool checkOnlyMultis, bool checkOnlyNonMultis ) -> bool; auto DoesCharacterBlock( UI16 x, UI16 y, SI08 z, UI08 worldNumber, UI16 instanceId ) -> bool; auto DynTile( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::uint16_t instanceId, bool checkOnlyMultis, bool checkOnlyNonMultis ) -> CItem *; auto DoesMapBlock( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, bool checkWater, bool waterWalk, bool checkMultiPlacement, bool checkForRoad ) -> bool; auto CheckStaticFlag( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, TileFlags toCheck, UI16 &foundTileId, bool checkSpawnSurface = false ) -> bool; auto CheckDynamicFlag( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::uint16_t instanceId, TileFlags toCheck, UI16 &foundTileId ) -> bool; auto CheckTileFlag( std::uint16_t itemId, TileFlags flagToCheck) -> bool; // height functions auto StaticTop( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::int8_t maxZ ) -> std::int8_t; auto DynamicElevation( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::uint16_t instanceId, std::int8_t maxZ ) -> std::int8_t; auto MapElevation( std::int16_t x, std::int16_t y, std::uint8_t worldNumber, bool ignoreVoid = false ) -> std::int8_t; auto TileHeight( std::uint16_t tileNum ) -> std::int8_t; auto Height( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::uint16_t instanceId ) -> std::int8_t; auto InBuilding( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::uint16_t instanceId ) -> bool; auto IsIgnored( std::uint16_t landNum ) -> bool { if( landNum == 2 || landNum == 0x1DB || ( landNum >= 0x1AE && landNum <= 0x1B5 )) { return true; } else { return false; } } // look at tile functions auto MultiArea( CMultiObj *i, std::int16_t &x1, std::int16_t &y1, std::int16_t &x2, std::int16_t &y2 ) -> void; auto MultiExists( std::uint16_t multiNum ) const -> bool; auto SeekMulti( std::uint16_t multiNum ) const -> const CollectionItem_st &; auto IsValidTile( std::uint16_t tileNum ) const -> bool; auto SeekTile( std::uint16_t tileNum ) ->CTile&; auto SeekTile( std::uint16_t tileNum ) const -> const CTile&; auto SeekLand( std::uint16_t landNum ) -> CLand&; auto SeekLand( std::uint16_t landNum ) const -> const CLand&; auto SeekMap( std::int16_t x, std::int16_t y, std::uint8_t worldNumber ) -> Tile_st&; auto SeekMap( std::int16_t x, std::int16_t y, std::uint8_t worldNumber ) const -> const Tile_st&; // misc functions auto ValidSpawnLocation( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::uint16_t instanceId, bool checkWater = true ) -> bool; auto ValidMultiLocation( std::int16_t x, std::int16_t y, std::int8_t z, std::uint8_t worldNumber, std::uint16_t instanceId, bool checkWater, bool checkOnlyOtherMultis, bool checkOnlyNonMultis, bool checkForRoads ) -> std::uint8_t; auto MapExists( std::uint8_t worldNumber ) const -> bool; auto InsideValidWorld( std::int16_t x, std::int16_t y, std::uint8_t worldNumber = 0xFF ) const -> bool; auto MapCount() const -> std::uint8_t; }; extern CMulHandler *Map; #endif