mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
310 lines
8.7 KiB
C++
310 lines
8.7 KiB
C++
#ifndef __UOXMAP_CLASSES_H__
|
|
#define __UOXMAP_CLASSES_H__
|
|
|
|
#include <cstdint>
|
|
#include <sstream>
|
|
#include <array>
|
|
#include <bitset>
|
|
#include <algorithm>
|
|
|
|
#include "power.h"
|
|
#include "MultiMul.hpp"
|
|
#include "osunique.hpp"
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
enum TileFlags
|
|
{
|
|
// Flag: Also known as:
|
|
TF_FLOORLEVEL = 0, // "Background"
|
|
TF_HOLDABLE, // "Weapon"
|
|
TF_TRANSPARENT, // "SignGuildBanner"
|
|
TF_TRANSLUCENT, // "WebDirtBlood"
|
|
TF_WALL, // "WallVertTile"
|
|
TF_DAMAGING,
|
|
TF_BLOCKING, // "Impassable"
|
|
TF_WET, // "LiquidWet"
|
|
TF_UNKNOWN1, // "Ignored"
|
|
TF_SURFACE, // "Standable"
|
|
TF_CLIMBABLE, // "Bridge"
|
|
TF_STACKABLE, // "Generic"
|
|
TF_WINDOW, // "WindowArchDoor"
|
|
TF_NOSHOOT, // "CannotShootThru"
|
|
TF_DISPLAYA, // "Prefix A"
|
|
TF_DISPLAYAN, // "Prefix An"
|
|
TF_DESCRIPTION, // "Internal"
|
|
TF_FOLIAGE, // "FadeWithTrans"
|
|
TF_PARTIALHUE,
|
|
TF_UNKNOWN2,
|
|
TF_MAP,
|
|
TF_CONTAINER,
|
|
TF_WEARABLE, // "Equipable"
|
|
TF_LIGHT, // "LightSource"
|
|
TF_ANIMATED,
|
|
TF_NODIAGONAL, // "HoverOver" in SA clients and later, to determine if tiles can be moved on by flying gargoyles
|
|
TF_UNKNOWN3, // "NoDiagonal" in SA clients and later?
|
|
TF_ARMOR, // "WholeBodyItem"
|
|
TF_ROOF, // "WallRoofWeap"
|
|
TF_DOOR,
|
|
TF_STAIRBACK, // "ClimbableBit1"
|
|
TF_STAIRRIGHT, // "ClimbableBit2"
|
|
|
|
// Following flags were added in HS expansion? Purpose unknown
|
|
TF_ALPHABLEND,
|
|
TF_USENEWART,
|
|
TF_ARTUSED,
|
|
TF_NOSHADOW,
|
|
TF_PIXELBLEED,
|
|
TF_PLAYANIMONCE,
|
|
TF_MULTIMOVABLE,
|
|
TF_COUNT
|
|
};
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
// Pre declare tileinfo so we can make it a friend of CBaseTile, CTile, and CLand
|
|
class TileInfo;
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
// Frankly, these chould/should have been structures, There really isn't a reason to make the
|
|
// data private, and then expose everything with accessors. Just adds a lot of verbage,
|
|
// that can clutter when maintaining. Oh well, we stay compatable for now.
|
|
class CBaseTile
|
|
{
|
|
friend TileInfo;
|
|
protected:
|
|
std::bitset<64> flags; // We are going to use a 64 bit value here, so specify 64 bit.
|
|
// This one day may be changed to a vector of bools, but for now
|
|
std::string name;
|
|
|
|
public:
|
|
CBaseTile()
|
|
{
|
|
flags.reset();
|
|
}
|
|
virtual ~CBaseTile() = default;
|
|
// This doesnt seem to be used, but I wonder about DFN overloads?
|
|
//
|
|
/*
|
|
auto Flag( UI08 part ) const -> std::uint8_t
|
|
{
|
|
auto mFlags = static_cast<std::uint32_t>( flags.to_ulong() );
|
|
auto retVal = std::uint8_t( 0 );
|
|
switch( part )
|
|
{
|
|
case 0: retVal = static_cast<std::uint8_t>( mFlags >> 24 ); break;
|
|
case 1: retVal = static_cast<std::uint8_t>( mFlags >> 16 ); break;
|
|
case 2: retVal = static_cast<std::uint8_t>( mFlags >> 8 ); break;
|
|
case 3: retVal = static_cast<std::uint8_t>( mFlags % 256 ); break;
|
|
}
|
|
return retVal;
|
|
}
|
|
*/
|
|
auto Name() const -> const std::string& { return name; }
|
|
auto Name( const std::string &value ) -> void { name = value; }
|
|
|
|
auto FlagsNum() const -> std::uint32_t { return static_cast<std::uint32_t>( flags.to_ulong() ); }
|
|
auto Flags() const -> std::bitset<64> { return flags; }
|
|
void Flags( std::bitset<64> newVal ) { flags = newVal; }
|
|
|
|
bool CheckFlag( TileFlags toCheck ) const
|
|
{
|
|
if( toCheck >= TF_COUNT )
|
|
{
|
|
return false;
|
|
}
|
|
return flags.test( toCheck );
|
|
}
|
|
void SetFlag( TileFlags toSet, bool newVal )
|
|
{
|
|
if( toSet >= TF_COUNT )
|
|
{
|
|
return;
|
|
}
|
|
flags.set( toSet, newVal );
|
|
}
|
|
};
|
|
//o------------------------------------------------------------------------------------------------o
|
|
class CTile : public CBaseTile
|
|
{
|
|
private:
|
|
friend TileInfo;
|
|
std::uint8_t weight;
|
|
std::int8_t layer;
|
|
std::uint16_t unknown1;
|
|
std::uint8_t unknown2;
|
|
std::uint8_t quantity;
|
|
std::uint16_t animation;
|
|
std::uint8_t unknown3;
|
|
std::uint8_t hue;
|
|
std::uint8_t unknown4;
|
|
std::uint8_t unknown5;
|
|
std::int8_t height;
|
|
public:
|
|
CTile() :CBaseTile(), weight( 0 ), layer( 0 ), unknown1( 0 ), unknown2( 0 ), quantity( 0 ), animation( 0 ), unknown3( 0 ), hue( 0 ), unknown4( 0 ), unknown5( 0 ), height( 0 )
|
|
{
|
|
}
|
|
~CTile() = default;
|
|
auto Unknown1() const -> std::uint16_t { return unknown1; }
|
|
auto Unknown2() const -> std::uint8_t { return unknown2; }
|
|
auto Unknown3() const -> std::uint8_t { return unknown3; }
|
|
auto Unknown4() const -> std::uint8_t { return unknown4; }
|
|
auto Unknown5() const -> std::uint8_t { return unknown5; }
|
|
auto Hue() const -> std::uint8_t { return hue; }
|
|
auto Quantity() const -> std::uint8_t { return quantity; }
|
|
auto Animation() const -> std::uint16_t { return animation; }
|
|
auto Weight() const -> std::uint8_t { return weight; }
|
|
auto Layer() const -> std::int8_t { return layer; }
|
|
auto Height() const -> std::int8_t { return height; }
|
|
auto ClimbHeight() const -> std::int8_t
|
|
{
|
|
if( CheckFlag( TF_CLIMBABLE ))
|
|
{
|
|
return height / 2;
|
|
}
|
|
return height;
|
|
}
|
|
void Unknown1( std::uint16_t newVal ) { unknown1 = newVal; }
|
|
void Unknown2( std::uint8_t newVal ) { unknown2 = newVal; }
|
|
void Unknown3( std::uint8_t newVal ) { unknown3 = newVal; }
|
|
void Unknown4( std::uint8_t newVal ) { unknown4 = newVal; }
|
|
void Unknown5( std::uint8_t newVal ) { unknown5 = newVal; }
|
|
void Animation( std::uint16_t newVal ) { animation = newVal; }
|
|
void Weight( std::uint8_t newVal ) { weight = newVal; }
|
|
void Layer( std::int8_t newVal ) { layer = newVal; }
|
|
void Height( std::int8_t newVal ) { height = newVal; }
|
|
void Hue( std::uint8_t newVal ) { hue = newVal; }
|
|
void Quantity( std::uint8_t newVal ) { quantity = newVal; }
|
|
};
|
|
//o------------------------------------------------------------------------------------------------o
|
|
class CLand : public CBaseTile
|
|
{
|
|
friend TileInfo;
|
|
private:
|
|
std::uint16_t textureId;
|
|
// List of road tiles, or road-related tiles, on which houses cannot be placed
|
|
constexpr static
|
|
std::array<std::uint16_t, 18> roadIds
|
|
{
|
|
0x0009, 0x0015, // furrows
|
|
0x0071, 0x0078, // dirt
|
|
0x00E8, 0x00EB, // dirt
|
|
0x0150, 0x015C, // furrows
|
|
0x0442, 0x0479, // sand stone
|
|
0x0501, 0x0510, // sand stone
|
|
0x07AE, 0x07B1, // dirt
|
|
0x3FF4, 0x3FF4, // dirt
|
|
0x3FF8, 0x3FFB // dirt
|
|
};
|
|
|
|
public:
|
|
CLand() :CBaseTile(), textureId( 0 )
|
|
{
|
|
}
|
|
~CLand() = default;
|
|
auto TextureId() const -> std::uint16_t { return textureId; }
|
|
auto TextureId( std::uint16_t newVal ) -> void { textureId = newVal; }
|
|
auto IsRoadId() const -> bool
|
|
{
|
|
auto rValue = false;
|
|
for( size_t j = 0; j < roadIds.size(); j += 2 )
|
|
{
|
|
if( textureId >= roadIds[j] && textureId <= roadIds[j + 1] )
|
|
{
|
|
rValue = true;
|
|
break;
|
|
}
|
|
}
|
|
return rValue;
|
|
}
|
|
};
|
|
|
|
|
|
enum TileType_t { terrain, art, dyn };
|
|
|
|
// A structure that holds tile information. Type, id, information, altitude (if in a map), hue (if a static tile)
|
|
|
|
struct Tile_st
|
|
{
|
|
TileType_t type;
|
|
std::uint16_t tileId; // for instance, this should be a tileid_t , that would make sense!
|
|
std::int8_t altitude;
|
|
std::uint16_t staticHue;
|
|
union
|
|
{
|
|
const CTile *artInfo;
|
|
const CLand *terrainInfo;
|
|
};
|
|
constexpr static std::array<std::uint16_t, 11> terrainVoids
|
|
{
|
|
430, 431, 432,
|
|
433, 434, 475,
|
|
580, 610, 611,
|
|
612, 613
|
|
};
|
|
auto CheckFlag( TileFlags toCheck ) const -> bool
|
|
{
|
|
if( type != TileType_t::terrain )
|
|
{
|
|
return artInfo->CheckFlag( toCheck );
|
|
}
|
|
return terrainInfo->CheckFlag( toCheck );
|
|
}
|
|
Tile_st( TileType_t type = TileType_t::terrain ) :type( type ), tileId( 0 ), altitude( 0 ), staticHue( 0 ), artInfo( nullptr ) {}
|
|
auto isVoid() const -> bool
|
|
{
|
|
auto rValue = false;
|
|
if( type == TileType_t::terrain )
|
|
{
|
|
auto iter = std::find_if( terrainVoids.begin(), terrainVoids.end(), [this]( const std::uint16_t &value )
|
|
{
|
|
return tileId == value;
|
|
});
|
|
rValue = iter != terrainVoids.end();
|
|
}
|
|
return rValue;
|
|
}
|
|
auto IsMountain() const -> bool
|
|
{
|
|
auto rValue = false;
|
|
if( type != TileType_t::terrain )
|
|
{
|
|
rValue = (( tileId >= 431 ) && ( tileId <= 432 )) || (( tileId >= 467 ) && ( tileId <= 474 )) ||
|
|
(( tileId >= 543 ) && ( tileId <= 560 )) || (( tileId >= 1754 ) && ( tileId <= 1757 )) ||
|
|
(( tileId >= 1787 ) && ( tileId <= 1789 )) || (( tileId >= 1821 ) && ( tileId <= 1824 )) ||
|
|
(( tileId >= 1851 ) && ( tileId <= 1854 )) || (( tileId >= 1881 ) && ( tileId <= 1884 ));
|
|
}
|
|
return rValue;
|
|
}
|
|
auto top() -> std::int16_t
|
|
{
|
|
auto value = static_cast<int16_t>( altitude );
|
|
if( type != TileType_t::terrain )
|
|
{
|
|
auto temp = artInfo->Height();
|
|
temp = ( temp & 0x8 ? ( temp & 0xF ) >> 1 : temp & 0xF );
|
|
|
|
value += temp;
|
|
}
|
|
return value;
|
|
}
|
|
auto height() -> std::uint8_t
|
|
{
|
|
if( type != TileType_t::terrain )
|
|
{
|
|
return artInfo->Height();
|
|
}
|
|
return 0;
|
|
}
|
|
auto name() const -> std::string
|
|
{
|
|
if( type != TileType_t::terrain )
|
|
{
|
|
return artInfo->Name();
|
|
}
|
|
return terrainInfo->Name();
|
|
}
|
|
};
|
|
#endif
|
|
|