OpenLoco/src/openloco/map/tile.cpp

205 lines
4.0 KiB
C++

#include "tile.h"
#include "../IndustryManager.h"
#include "../interop/interop.hpp"
#include "../objects/objectmgr.h"
#include "../ui/WindowManager.h"
#include <cassert>
using namespace openloco;
using namespace openloco::interop;
using namespace openloco::ui::WindowManager;
const uint8_t* tile_element_base::data() const
{
return (uint8_t*)this;
}
element_type tile_element_base::type() const
{
return (element_type)((_type & 0x3C) >> 2);
}
bool tile_element_base::isLast() const
{
return (_flags & element_flags::last) != 0;
}
building_object* building_element::object() const
{
return objectmgr::get<building_object>(objectId());
}
tile::tile(tile_coord_t x, tile_coord_t y, tile_element* data)
: _data(data)
, x(x)
, y(y)
{
}
bool tile::isNull() const
{
return _data == nullptr;
}
tile_element* tile::begin()
{
return _data;
}
tile_element* tile::begin() const
{
return const_cast<tile&>(*this).begin();
}
tile_element* tile::end()
{
auto el = _data;
do
{
el++;
} while (!(el - 1)->isLast());
return el;
}
tile_element* tile::end() const
{
return const_cast<tile&>(*this).end();
}
size_t tile::size()
{
return end() - begin();
}
tile_element* tile::operator[](size_t i)
{
#if DEBUG
assert(i < size());
#endif
return &_data[i];
}
size_t tile::indexOf(const tile_element_base* element) const
{
size_t i = 0;
for (const auto& tile : *this)
{
if (&tile == element)
{
return i;
}
i++;
}
return npos;
}
surface_element* tile::surface()
{
surface_element* result = nullptr;
for (auto& tile : *this)
{
result = tile.asSurface();
if (result != nullptr)
{
break;
}
}
return result;
}
openloco::industry* industry_element::industry()
{
return industrymgr::get(_industryId);
}
namespace openloco::map
{
/**
* Return the absolute height of an element, given its (x, y) coordinates
* remember to & with 0xFFFF if you don't want water affecting results
*
* @param x @<ax>
* @param y @<cx>
* @return height @<edx>
*
* 0x00467297
*/
tileHeight tileElementHeight(int16_t x, int16_t y)
{
registers regs;
regs.ax = x;
regs.cx = y;
call(0x00467297, regs);
tileHeight tileZ;
tileZ.landHeight = regs.dx;
tileZ.waterHeight = regs.edx >> 16;
return tileZ;
}
/**
*
* @param x @<ax>
* @param y
* @param z
* @param rotation
* @return
*/
ui::viewport_pos coordinate3dTo2d(int16_t x, int16_t y, int16_t z, int rotation)
{
ui::viewport_pos coordinate_2d;
switch (rotation)
{
default:
case 0:
coordinate_2d.x = y - x;
coordinate_2d.y = ((y + x) >> 1) - z;
break;
case 1:
coordinate_2d.x = -y - x;
coordinate_2d.y = ((y - x) >> 1) - z;
break;
case 2:
coordinate_2d.x = -y + x;
coordinate_2d.y = ((-y - x) >> 1) - z;
break;
case 3:
coordinate_2d.x = y + x;
coordinate_2d.y = ((-y + x) >> 1) - z;
break;
}
return coordinate_2d;
}
map_pos rotate2dCoordinate(map_pos pos, uint8_t rotation)
{
map_pos coordinate2D;
switch (rotation)
{
default:
case 0:
coordinate2D = pos;
break;
case 1:
coordinate2D.x = pos.y;
coordinate2D.y = -pos.x;
break;
case 2:
coordinate2D.x = -pos.x;
coordinate2D.y = -pos.y;
break;
case 3:
coordinate2D.x = -pos.y;
coordinate2D.y = pos.x;
break;
}
return coordinate2D;
}
}