Implement tile element paint (#1113)
This commit is contained in:
parent
f4d0d9215c
commit
18422de137
|
@ -8,6 +8,24 @@ namespace OpenLoco::ImageIds
|
|||
{
|
||||
constexpr uint32_t null = 0xFFFFFFFF;
|
||||
|
||||
constexpr uint32_t construction_arrow_north = 428;
|
||||
constexpr uint32_t construction_arrow_east = 429;
|
||||
constexpr uint32_t construction_arrow_south = 430;
|
||||
constexpr uint32_t construction_arrow_west = 431;
|
||||
constexpr uint32_t construction_arrow_north2 = 432;
|
||||
constexpr uint32_t construction_arrow_east2 = 433;
|
||||
constexpr uint32_t construction_arrow_south2 = 434;
|
||||
constexpr uint32_t construction_arrow_west2 = 435;
|
||||
constexpr uint32_t construction_arrow_north3 = 436;
|
||||
constexpr uint32_t construction_arrow_east3 = 437;
|
||||
constexpr uint32_t construction_arrow_south3 = 438;
|
||||
constexpr uint32_t construction_arrow_west3 = 439;
|
||||
constexpr uint32_t construction_arrow_north_east = 440;
|
||||
constexpr uint32_t construction_arrow_south_east = 441;
|
||||
constexpr uint32_t construction_arrow_south_west = 442;
|
||||
constexpr uint32_t construction_arrow_north_west = 443;
|
||||
|
||||
constexpr uint32_t blank_tile = 448;
|
||||
constexpr uint32_t currency_symbol = 1919;
|
||||
|
||||
constexpr uint32_t text_palette = 2169;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "../Ui.h"
|
||||
#include "../Ui/WindowManager.h"
|
||||
#include "PaintEntity.h"
|
||||
#include "PaintTile.h"
|
||||
|
||||
using namespace OpenLoco::Interop;
|
||||
using namespace OpenLoco::Ui::ViewportInteraction;
|
||||
|
@ -20,6 +21,37 @@ namespace OpenLoco::Paint
|
|||
_spritePositionX = pos.x;
|
||||
_spritePositionY = pos.y;
|
||||
}
|
||||
void PaintSession::setMapPosition(const Map::Pos2& pos)
|
||||
{
|
||||
_mapPosition = pos;
|
||||
}
|
||||
void PaintSession::setUnkPosition(const Map::Pos2& pos)
|
||||
{
|
||||
_unkPositionX = pos.x;
|
||||
_unkPositionY = pos.y;
|
||||
}
|
||||
void PaintSession::setVpPosition(const Ui::Point& pos)
|
||||
{
|
||||
_vpPositionX = pos.x;
|
||||
_vpPositionY = pos.y;
|
||||
}
|
||||
|
||||
void PaintSession::resetTileColumn(const Ui::Point& pos)
|
||||
{
|
||||
setVpPosition(pos);
|
||||
_didPassSurface = false;
|
||||
_525CE4[0] = 0xFFFF;
|
||||
_525CF0 = 0;
|
||||
_525CF0 = 0;
|
||||
_525CF8 = 0;
|
||||
_F003F4 = 0;
|
||||
_F003F6 = 0;
|
||||
std::fill(std::begin(_unkSegments), std::end(_unkSegments), 0);
|
||||
std::fill(std::begin(_E400D0), std::end(_E400D0), nullptr);
|
||||
std::fill(std::begin(_E400E4), std::end(_E400E4), nullptr);
|
||||
_112C300 = 0;
|
||||
_112C306 = 0;
|
||||
}
|
||||
|
||||
loco_global<int32_t[4], 0x4FD120> _4FD120;
|
||||
loco_global<int32_t[4], 0x4FD130> _4FD130;
|
||||
|
@ -156,22 +188,38 @@ namespace OpenLoco::Paint
|
|||
});
|
||||
}
|
||||
|
||||
// 0x00461CF8
|
||||
static void paintTileElements(PaintSession& session, const Map::Pos2& loc)
|
||||
const uint16_t segmentOffsets[9] = { Segment::_58, Segment::_5C, Segment::_60, Segment::_64, Segment::_68, Segment::_6C, Segment::_70, Segment::_74, Segment::_78 };
|
||||
|
||||
void PaintSession::setSegmentSupportHeight(const uint16_t segments, const uint16_t height, const uint8_t slope)
|
||||
{
|
||||
registers regs{};
|
||||
regs.eax = loc.x;
|
||||
regs.ecx = loc.y;
|
||||
call(0x00461CF8, regs);
|
||||
for (int32_t s = 0; s < 9; s++)
|
||||
{
|
||||
if (segments & segmentOffsets[s])
|
||||
{
|
||||
_supportSegments[s].height = height;
|
||||
if (height != 0xFFFF)
|
||||
{
|
||||
_supportSegments[s].slope = slope;
|
||||
_supportSegments[s].var_03 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 0x004617C6
|
||||
static void paintTileElements2(PaintSession& session, const Map::Pos2& loc)
|
||||
void PaintSession::setGeneralSupportHeight(const uint16_t height, const uint8_t slope)
|
||||
{
|
||||
registers regs{};
|
||||
regs.eax = loc.x;
|
||||
regs.ecx = loc.y;
|
||||
call(0x004617C6, regs);
|
||||
_support->height = height;
|
||||
_support->slope = slope;
|
||||
_support->var_03 = 0;
|
||||
}
|
||||
|
||||
void PaintSession::resetTunnels()
|
||||
{
|
||||
std::fill(std::begin(_tunnelCounts), std::end(_tunnelCounts), 0);
|
||||
_tunnels0[0].height = 0xFF;
|
||||
_tunnels0[1].height = 0xFF;
|
||||
_tunnels0[2].height = 0xFF;
|
||||
_tunnels0[3].height = 0xFF;
|
||||
}
|
||||
|
||||
struct GenerationParameters
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "../Interop/Interop.hpp"
|
||||
#include "../Map/Map.hpp"
|
||||
#include "../Types.hpp"
|
||||
#include "../Ui/Types.hpp"
|
||||
|
||||
namespace OpenLoco::Map
|
||||
{
|
||||
|
@ -25,6 +26,20 @@ namespace OpenLoco::Gfx
|
|||
|
||||
namespace OpenLoco::Paint
|
||||
{
|
||||
namespace Segment
|
||||
{
|
||||
constexpr uint16_t _58 = (1 << 0); // TBC: 0
|
||||
constexpr uint16_t _5C = (1 << 1); // TBC: 6
|
||||
constexpr uint16_t _60 = (1 << 2); // TBC: 2
|
||||
constexpr uint16_t _64 = (1 << 3); // TBC: 8
|
||||
constexpr uint16_t _68 = (1 << 4); // TBC: 3
|
||||
constexpr uint16_t _6C = (1 << 5); // TBC: 7
|
||||
constexpr uint16_t _70 = (1 << 6); // TBC: 1
|
||||
constexpr uint16_t _74 = (1 << 7); // TBC: 5
|
||||
constexpr uint16_t _78 = (1 << 8); // TBC: 4
|
||||
|
||||
constexpr uint16_t all = _58 | _5C | _60 | _64 | _68 | _6C | _70 | _74 | _78;
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
/* size 0x12 */
|
||||
|
@ -113,6 +128,21 @@ namespace OpenLoco::Paint
|
|||
PaintStringStruct string;
|
||||
};
|
||||
assert_struct_size(PaintEntry, 0x34);
|
||||
|
||||
struct SupportHeight
|
||||
{
|
||||
uint16_t height;
|
||||
uint8_t slope;
|
||||
uint8_t var_03; // Used by general support height only
|
||||
};
|
||||
assert_struct_size(SupportHeight, 4);
|
||||
|
||||
struct TunnelEntry
|
||||
{
|
||||
uint8_t height;
|
||||
uint8_t type;
|
||||
};
|
||||
assert_struct_size(TunnelEntry, 2);
|
||||
#pragma pack(pop)
|
||||
struct GenerationParameters;
|
||||
|
||||
|
@ -127,10 +157,33 @@ namespace OpenLoco::Paint
|
|||
[[nodiscard]] Ui::ViewportInteraction::InteractionArg getTownNameInteractionInfo(const uint32_t flags);
|
||||
Gfx::Context* getContext() { return _context; }
|
||||
uint8_t getRotation() { return currentRotation; }
|
||||
int16_t getMaxHeight() { return _maxHeight; }
|
||||
uint32_t get112C300() { return _112C300; }
|
||||
uint16_t getF003F4() { return _F003F4; }
|
||||
const SupportHeight& getGeneralSupportHeight() { return _support; }
|
||||
uint16_t get525CE4(const uint8_t i) { return _525CE4[i]; }
|
||||
uint16_t get525CF8() { return _525CF8; }
|
||||
Map::Pos2 getUnkPosition()
|
||||
{
|
||||
return Map::Pos2{ _unkPositionX, _unkPositionY };
|
||||
}
|
||||
// TileElement or Entity
|
||||
void setCurrentItem(void* item) { _currentItem = item; }
|
||||
void setItemType(const Ui::ViewportInteraction::InteractionItem type) { _itemType = type; }
|
||||
void setEntityPosition(const Map::Pos2& pos);
|
||||
void setMapPosition(const Map::Pos2& pos);
|
||||
void setUnkPosition(const Map::Pos2& pos);
|
||||
void setVpPosition(const Ui::Point& pos);
|
||||
void setUnkVpY(const uint16_t y) { _unkVpPositionY = y; }
|
||||
void setSegmentSupportHeight(const uint16_t segments, const uint16_t height, const uint8_t slope);
|
||||
void setGeneralSupportHeight(const uint16_t height, const uint8_t slope);
|
||||
void setMaxHeight(const int16_t height) { _maxHeight = height; }
|
||||
void set525CF8(const uint16_t segments) { _525CF8 = segments; }
|
||||
void set525CF0(const uint8_t newValue) { _525CF0 = newValue; }
|
||||
void setF003F6(const uint16_t newValue) { _F003F6 = newValue; }
|
||||
void set525CE4(const uint8_t i, const uint16_t newValue) { _525CE4[i] = newValue; }
|
||||
void resetTileColumn(const Ui::Point& pos);
|
||||
void resetTunnels();
|
||||
|
||||
/*
|
||||
* @param amount @<eax>
|
||||
|
@ -206,42 +259,59 @@ namespace OpenLoco::Paint
|
|||
private:
|
||||
void generateTilesAndEntities(GenerationParameters&& p);
|
||||
|
||||
inline static Interop::loco_global<uint8_t[4], 0x0050C185> _tunnelCounts;
|
||||
inline static Interop::loco_global<TunnelEntry[32], 0x0050C077> _tunnels0;
|
||||
inline static Interop::loco_global<TunnelEntry[32], 0x0050C0BB> _tunnels1;
|
||||
inline static Interop::loco_global<TunnelEntry[32], 0x0050C0FF> _tunnels2;
|
||||
inline static Interop::loco_global<TunnelEntry[32], 0x0050C143> _tunnels3;
|
||||
inline static Interop::loco_global<uint16_t[2], 0x00525CE4> _525CE4;
|
||||
inline static Interop::loco_global<uint8_t, 0x00525CF0> _525CF0;
|
||||
inline static Interop::loco_global<uint16_t, 0x00525CF8> _525CF8;
|
||||
inline static Interop::loco_global<Gfx::Context*, 0x00E0C3E0> _context;
|
||||
inline static Interop::loco_global<PaintEntry[4000], 0x00E0C410> _paintEntries;
|
||||
inline static Interop::loco_global<PaintStruct* [1024], 0x00E3F0C0> _quadrants;
|
||||
inline static Interop::loco_global<uint32_t, 0x00E400C0> _quadrantBackIndex;
|
||||
inline static Interop::loco_global<uint32_t, 0x00E400C4> _quadrantFrontIndex;
|
||||
inline static Interop::loco_global<const void*, 0x00E4F0B4> _currentlyDrawnItem;
|
||||
inline static Interop::loco_global<PaintEntry*, 0x00E0C404> _endOfPaintStructArray;
|
||||
inline static Interop::loco_global<PaintEntry*, 0x00E0C408> _paintHead;
|
||||
inline static Interop::loco_global<PaintEntry*, 0x00E0C40C> _nextFreePaintStruct;
|
||||
inline static Interop::loco_global<PaintEntry[4000], 0x00E0C410> _paintEntries;
|
||||
inline static Interop::loco_global<coord_t, 0x00E3F090> _spritePositionX;
|
||||
inline static Interop::loco_global<coord_t, 0x00E3F092> _unkPositionX;
|
||||
inline static Interop::loco_global<int16_t, 0x00E3F094> _vpPositionX;
|
||||
inline static Interop::loco_global<coord_t, 0x00E3F096> _spritePositionY;
|
||||
inline static Interop::loco_global<PaintStruct*, 0x00E40120> _lastPS;
|
||||
inline static Interop::loco_global<coord_t, 0x00E3F098> _unkPositionY;
|
||||
inline static Interop::loco_global<int16_t, 0x00E3F09A> _vpPositionY;
|
||||
inline static Interop::loco_global<int16_t, 0x00E3F09C> _unkVpPositionY;
|
||||
inline static Interop::loco_global<bool, 0x00E3F09E> _didPassSurface;
|
||||
inline static Interop::loco_global<Ui::ViewportInteraction::InteractionItem, 0x00E3F0AC> _itemType;
|
||||
inline static Interop::loco_global<Map::Pos2, 0x00E3F0B0> _mapPosition;
|
||||
inline static Interop::loco_global<void*, 0x00E3F0B4> _currentItem;
|
||||
inline static Interop::loco_global<PaintStruct* [1024], 0x00E3F0C0> _quadrants;
|
||||
inline static Interop::loco_global<uint32_t, 0x00E400C0> _quadrantBackIndex;
|
||||
inline static Interop::loco_global<uint32_t, 0x00E400C4> _quadrantFrontIndex;
|
||||
inline static Interop::loco_global<PaintEntry* [2], 0x00E400E4> _E400E4;
|
||||
inline static Interop::loco_global<PaintEntry* [5], 0x00E400D0> _E400D0;
|
||||
inline static Interop::loco_global<PaintStringStruct*, 0x00E40118> _paintStringHead;
|
||||
inline static Interop::loco_global<PaintStringStruct*, 0x00E4011C> _lastPaintString;
|
||||
inline static Interop::loco_global<Map::Pos2, 0x00E3F0B0> _mapPosition;
|
||||
inline static Interop::loco_global<PaintStruct*, 0x00E40120> _lastPS;
|
||||
inline static Interop::loco_global<const void*, 0x00E4F0B4> _currentlyDrawnItem;
|
||||
inline static Interop::loco_global<int16_t, 0x00F00152> _maxHeight;
|
||||
inline static Interop::loco_global<uint16_t, 0x00F003F4> _F003F4;
|
||||
inline static Interop::loco_global<uint16_t, 0x00F003F6> _F003F6;
|
||||
inline static Interop::loco_global<uint32_t[9], 0x00F003F8> _unkSegments;
|
||||
inline static Interop::loco_global<SupportHeight[9], 0x00F00458> _supportSegments;
|
||||
inline static Interop::loco_global<SupportHeight, 0x00F0047C> _support;
|
||||
inline static Interop::loco_global<int16_t, 0x00F00480> _waterHeight;
|
||||
inline static Interop::loco_global<uint32_t, 0x0112C300> _112C300;
|
||||
inline static Interop::loco_global<uint16_t, 0x0112C306> _112C306;
|
||||
uint8_t currentRotation; // new field set from 0x00E3F0B8 but split out into this struct as seperate item
|
||||
|
||||
// From OpenRCT2 equivalent fields not found yet or new
|
||||
//uint32_t viewFlags; // new field might not be needed tbc
|
||||
//AttachedPaintStruct* unkF1AD2C; // no equivalent
|
||||
//support_height supportSegments[9];
|
||||
//support_height support;
|
||||
//PaintStruct* woodenSupportsPrependTo;
|
||||
//tunnel_entry leftTunnels[TUNNEL_MAX_COUNT];
|
||||
//uint8_t leftTunnelCount;
|
||||
//tunnel_entry rightTunnels[TUNNEL_MAX_COUNT];
|
||||
//uint8_t rightTunnelCount;
|
||||
//uint8_t verticalTunnelHeight;
|
||||
//const Map::TileElement* surfaceElement;
|
||||
//Map::TileElement* pathElementOnSameHeight;
|
||||
//Map::TileElement* trackElementOnSameHeight;
|
||||
//bool didPassSurface;
|
||||
//uint8_t unk141E9DB;
|
||||
//uint16_t waterHeight;
|
||||
//uint32_t trackColours[4];
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,397 @@
|
|||
#include "PaintTile.h"
|
||||
#include "../Graphics/Colour.h"
|
||||
#include "../Graphics/ImageIds.h"
|
||||
#include "../Input.h"
|
||||
#include "../Map/TileManager.h"
|
||||
#include "../Ui.h"
|
||||
#include "Paint.h"
|
||||
|
||||
using namespace OpenLoco::Interop;
|
||||
using namespace OpenLoco::Ui::ViewportInteraction;
|
||||
|
||||
namespace OpenLoco::Paint
|
||||
{
|
||||
// 0x004621FF
|
||||
static void paintVoid(PaintSession& session, const Map::Pos2& loc)
|
||||
{
|
||||
constexpr Map::Pos2 unkOffsets[4] = {
|
||||
{ 0, 0 },
|
||||
{ 32, 0 },
|
||||
{ 32, 32 },
|
||||
{ 0, 32 },
|
||||
};
|
||||
|
||||
const auto loc2 = loc + unkOffsets[session.getRotation()];
|
||||
const auto vpPos = Map::gameToScreen(Map::Pos3(loc2.x, loc2.y, 16), session.getRotation());
|
||||
if (vpPos.y + 32 <= session.getContext()->y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (vpPos.y - 20 >= session.getContext()->height + session.getContext()->y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
session.setEntityPosition(loc2);
|
||||
session.setItemType(InteractionItem::noInteraction);
|
||||
session.addToPlotListAsParent(ImageIds::blank_tile, { 0, 0, 16 }, { 32, 32, 255 });
|
||||
}
|
||||
|
||||
// 0x00461EA7
|
||||
static void paintConstructionArrow(PaintSession& session, const Map::Pos2& loc)
|
||||
{
|
||||
static loco_global<Map::Pos3, 0x00F24942> _constructionArrowLocation;
|
||||
static loco_global<uint8_t, 0x00F24948> _constructionArrowDirection;
|
||||
if (!Input::hasMapSelectionFlag(Input::MapSelectionFlags::unk_02))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (session.getUnkPosition() != _constructionArrowLocation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
session.setEntityPosition(loc);
|
||||
const auto dirIndex = (_constructionArrowDirection & 0xFC) | (((_constructionArrowDirection & 0x3) + session.getRotation()) & 0x3);
|
||||
constexpr std::array<uint32_t, 16> constructionArrowImages = {
|
||||
ImageIds::construction_arrow_north,
|
||||
ImageIds::construction_arrow_east,
|
||||
ImageIds::construction_arrow_south,
|
||||
ImageIds::construction_arrow_west,
|
||||
ImageIds::construction_arrow_north2,
|
||||
ImageIds::construction_arrow_east2,
|
||||
ImageIds::construction_arrow_south2,
|
||||
ImageIds::construction_arrow_west2,
|
||||
ImageIds::construction_arrow_north3,
|
||||
ImageIds::construction_arrow_east3,
|
||||
ImageIds::construction_arrow_south3,
|
||||
ImageIds::construction_arrow_west3,
|
||||
ImageIds::construction_arrow_north_east,
|
||||
ImageIds::construction_arrow_south_east,
|
||||
ImageIds::construction_arrow_south_west,
|
||||
ImageIds::construction_arrow_north_west,
|
||||
};
|
||||
const auto imageId = Gfx::recolour(constructionArrowImages[dirIndex], Colour::dark_olive_green);
|
||||
session.setItemType(InteractionItem::noInteraction);
|
||||
session.addToPlotListAsParent(imageId, { 0, 0, _constructionArrowLocation->z }, Map::Pos3(0, 0, _constructionArrowLocation->z + 10), { 32, 32, 255 });
|
||||
}
|
||||
|
||||
// 0x004792E7 streetlights?
|
||||
static void sub_4792E7(PaintSession& session)
|
||||
{
|
||||
call(0x004792E7);
|
||||
}
|
||||
|
||||
// 0x0046748F
|
||||
static void sub_46748F(PaintSession& session)
|
||||
{
|
||||
call(0x0046748F);
|
||||
}
|
||||
|
||||
// 0x0045CA67
|
||||
static void sub_45CA67(PaintSession& session)
|
||||
{
|
||||
call(0x0045CA67);
|
||||
}
|
||||
|
||||
// 0x0045CC1B
|
||||
static void sub_45CC1B(PaintSession& session)
|
||||
{
|
||||
call(0x0045CC1B);
|
||||
}
|
||||
|
||||
// 0x0042AC9C
|
||||
static bool sub_42AC9C(PaintSession& session)
|
||||
{
|
||||
registers regs;
|
||||
call(0x0042AC9C, regs);
|
||||
return regs.al != 0;
|
||||
}
|
||||
|
||||
// 0x004656BF
|
||||
static void paintSurface(PaintSession& session, Map::SurfaceElement& elSurface)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elSurface);
|
||||
regs.dx = elSurface.baseZ() * 4;
|
||||
call(0x004656BF, regs);
|
||||
}
|
||||
|
||||
// 0x0049B6BF
|
||||
static void paintTrack(PaintSession& session, Map::TrackElement& elTrack)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elTrack);
|
||||
regs.ecx = (session.getRotation() + elTrack.unkDirection()) & 0x3;
|
||||
regs.dx = elTrack.baseZ() * 4;
|
||||
call(0x0049B6BF, regs);
|
||||
}
|
||||
|
||||
// 0x0048B313
|
||||
static void paintStation(PaintSession& session, Map::StationElement& elStation)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elStation);
|
||||
regs.ecx = (session.getRotation() + elStation.rotation()) & 0x3;
|
||||
regs.dx = elStation.baseZ() * 4;
|
||||
call(0x0048B313, regs);
|
||||
}
|
||||
|
||||
// 0x0048864C
|
||||
static void paintSignal(PaintSession& session, Map::SignalElement& elSignal)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elSignal);
|
||||
regs.ecx = (session.getRotation() + (elSignal.data()[0] & 0x3)) & 0x3;
|
||||
regs.dx = elSignal.baseZ() * 4;
|
||||
call(0x0048864C, regs);
|
||||
}
|
||||
|
||||
// 0x0042C6C4
|
||||
static void paintBuilding(PaintSession& session, Map::BuildingElement& elBuilding)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elBuilding);
|
||||
regs.ecx = (session.getRotation() + (elBuilding.data()[0] & 0x3)) & 0x3;
|
||||
regs.dx = elBuilding.baseZ() * 4;
|
||||
call(0x0042C6C4, regs);
|
||||
}
|
||||
|
||||
// 0x004BAEDA
|
||||
static void paintTree(PaintSession& session, Map::TreeElement& elTree)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elTree);
|
||||
regs.ecx = (session.getRotation() + (elTree.data()[0] & 0x3)) & 0x3;
|
||||
regs.dx = elTree.baseZ() * 4;
|
||||
call(0x004BAEDA, regs);
|
||||
}
|
||||
|
||||
// 0x004C3D7C
|
||||
static void paintWall(PaintSession& session, Map::WallElement& elWall)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elWall);
|
||||
regs.ecx = (session.getRotation() + (elWall.data()[0] & 0x3)) & 0x3;
|
||||
regs.dx = elWall.baseZ() * 4;
|
||||
call(0x004C3D7C, regs);
|
||||
}
|
||||
|
||||
// 0x004759A6
|
||||
static void paintRoad(PaintSession& session, Map::RoadElement& elRoad)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elRoad);
|
||||
regs.ecx = (session.getRotation() + elRoad.unkDirection()) & 0x3;
|
||||
regs.dx = elRoad.baseZ() * 4;
|
||||
call(0x004759A6, regs);
|
||||
}
|
||||
|
||||
// 0x00453C52
|
||||
static void paintIndustry(PaintSession& session, Map::IndustryElement& elIndustry)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = X86Pointer(&elIndustry);
|
||||
regs.ecx = (session.getRotation() + (elIndustry.data()[0] & 0x3)) & 0x3;
|
||||
regs.dx = elIndustry.baseZ() * 4;
|
||||
call(0x00453C52, regs);
|
||||
}
|
||||
|
||||
// 0x00461CF8
|
||||
void paintTileElements(PaintSession& session, const Map::Pos2& loc)
|
||||
{
|
||||
if (loc.x >= 383 * Map::tile_size || loc.y >= 383 * Map::tile_size || loc.x < 32 || loc.y < 32)
|
||||
{
|
||||
paintVoid(session, loc);
|
||||
return;
|
||||
}
|
||||
|
||||
session.setSegmentSupportHeight(Segment::all, std::numeric_limits<uint16_t>::max(), 0);
|
||||
session.setGeneralSupportHeight(std::numeric_limits<uint16_t>::max(), 0);
|
||||
session.resetTunnels();
|
||||
session.setUnkPosition(loc);
|
||||
session.setMapPosition(loc);
|
||||
|
||||
auto tile = Map::TileManager::get(loc);
|
||||
uint8_t maxClearZ = 0;
|
||||
for (const auto& el : tile)
|
||||
{
|
||||
maxClearZ = std::max(maxClearZ, el.clearZ());
|
||||
const auto* surface = el.asSurface();
|
||||
if (!surface)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (surface->water())
|
||||
{
|
||||
maxClearZ = std::max<uint8_t>(maxClearZ, surface->water() * 4);
|
||||
}
|
||||
if (surface->hasHighTypeFlag())
|
||||
{
|
||||
maxClearZ = std::max<uint8_t>(maxClearZ, surface->clearZ() + 24);
|
||||
}
|
||||
}
|
||||
session.setMaxHeight((maxClearZ * 4) + 32);
|
||||
|
||||
constexpr Map::Pos2 unkOffsets[4] = {
|
||||
{ 0, 0 },
|
||||
{ 32, 0 },
|
||||
{ 32, 32 },
|
||||
{ 0, 32 },
|
||||
};
|
||||
|
||||
const auto loc2 = loc + unkOffsets[session.getRotation()];
|
||||
const auto vpPos = Map::gameToScreen(Map::Pos3(loc2.x, loc2.y, 0), session.getRotation());
|
||||
paintConstructionArrow(session, loc2);
|
||||
|
||||
if (vpPos.y + 52 <= session.getContext()->y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (vpPos.y - session.getMaxHeight() > session.getContext()->y + session.getContext()->height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
session.setEntityPosition(loc2);
|
||||
session.resetTileColumn({ vpPos.x, vpPos.y });
|
||||
|
||||
for (auto& el : tile)
|
||||
{
|
||||
// This is not a good idea not all tiles (surface) have a rotation
|
||||
//const uint8_t rotation = (el.rotation() + session.getRotation()) & 0x3;
|
||||
session.setUnkVpY(vpPos.y - el.baseZ() * 4);
|
||||
session.setCurrentItem(&el);
|
||||
switch (el.type())
|
||||
{
|
||||
case Map::ElementType::surface:
|
||||
{
|
||||
auto* elSurface = el.asSurface();
|
||||
if (elSurface != nullptr)
|
||||
{
|
||||
paintSurface(session, *elSurface);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map::ElementType::track:
|
||||
{
|
||||
auto* elTrack = el.asTrack();
|
||||
if (elTrack != nullptr)
|
||||
{
|
||||
paintTrack(session, *elTrack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map::ElementType::station:
|
||||
{
|
||||
auto* elStation = el.asStation();
|
||||
if (elStation != nullptr)
|
||||
{
|
||||
paintStation(session, *elStation);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map::ElementType::signal:
|
||||
{
|
||||
auto* elSignal = el.asSignal();
|
||||
if (elSignal != nullptr)
|
||||
{
|
||||
paintSignal(session, *elSignal);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map::ElementType::building:
|
||||
{
|
||||
auto* elBuilding = el.asBuilding();
|
||||
if (elBuilding != nullptr)
|
||||
{
|
||||
paintBuilding(session, *elBuilding);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map::ElementType::tree:
|
||||
{
|
||||
auto* elTree = el.asTree();
|
||||
if (elTree != nullptr)
|
||||
{
|
||||
paintTree(session, *elTree);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map::ElementType::wall:
|
||||
{
|
||||
auto* elWall = el.asWall();
|
||||
if (elWall != nullptr)
|
||||
{
|
||||
paintWall(session, *elWall);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map::ElementType::road:
|
||||
{
|
||||
auto* elRoad = el.asRoad();
|
||||
if (elRoad != nullptr)
|
||||
{
|
||||
paintRoad(session, *elRoad);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Map::ElementType::industry:
|
||||
{
|
||||
auto* elIndustry = el.asIndustry();
|
||||
if (elIndustry != nullptr)
|
||||
{
|
||||
paintIndustry(session, *elIndustry);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (el.isLast() || el.baseZ() != ((&el) + 1)->baseZ())
|
||||
{
|
||||
if (session.get112C300() != 0)
|
||||
{
|
||||
sub_4792E7(session);
|
||||
}
|
||||
if (session.getF003F4() != 0)
|
||||
{
|
||||
sub_46748F(session);
|
||||
}
|
||||
|
||||
sub_45CA67(session);
|
||||
sub_45CC1B(session);
|
||||
session.setF003F6(0);
|
||||
if (session.get525CE4(0) != 0xFFFF)
|
||||
{
|
||||
if (sub_42AC9C(session))
|
||||
{
|
||||
session.setSegmentSupportHeight(Segment::all, 0xFFFF, 0);
|
||||
}
|
||||
if (session.getGeneralSupportHeight().height >= session.get525CE4(0))
|
||||
{
|
||||
session.setGeneralSupportHeight(session.get525CE4(0), 0x20);
|
||||
}
|
||||
session.set525CE4(0, 0xFFFF);
|
||||
session.set525CF0(0);
|
||||
}
|
||||
|
||||
if (session.get525CF8() != 0)
|
||||
{
|
||||
for (auto bit = Utility::bitScanForward(session.get525CF8()); bit != -1; bit = Utility::bitScanForward(session.get525CF8()))
|
||||
{
|
||||
session.set525CF8(session.get525CF8() & ~(1 << bit));
|
||||
session.setSegmentSupportHeight(1 << bit, 0xFFFF, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 0x004617C6
|
||||
void paintTileElements2(PaintSession& session, const Map::Pos2& loc)
|
||||
{
|
||||
registers regs{};
|
||||
regs.eax = loc.x;
|
||||
regs.ecx = loc.y;
|
||||
call(0x004617C6, regs);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
#include "../Map/Map.hpp"
|
||||
|
||||
namespace OpenLoco::Paint
|
||||
{
|
||||
struct PaintSession;
|
||||
void paintTileElements(PaintSession& session, const Map::Pos2& loc);
|
||||
void paintTileElements2(PaintSession& session, const Map::Pos2& loc);
|
||||
}
|
|
@ -107,6 +107,7 @@
|
|||
<ClCompile Include="Paint\Paint.cpp" />
|
||||
<ClCompile Include="Paint\PaintEntity.cpp" />
|
||||
<ClCompile Include="Paint\PaintMiscEntity.cpp" />
|
||||
<ClCompile Include="Paint\PaintTile.cpp" />
|
||||
<ClCompile Include="Paint\PaintVehicle.cpp" />
|
||||
<ClCompile Include="Platform\Crash.cpp" />
|
||||
<ClCompile Include="Platform\Platform.Posix.cpp" />
|
||||
|
@ -313,6 +314,7 @@
|
|||
<ClInclude Include="Paint\Paint.h" />
|
||||
<ClInclude Include="Paint\PaintEntity.h" />
|
||||
<ClInclude Include="Paint\PaintMiscEntity.h" />
|
||||
<ClInclude Include="Paint\PaintTile.h" />
|
||||
<ClInclude Include="Paint\PaintVehicle.h" />
|
||||
<ClInclude Include="Platform/Crash.h" />
|
||||
<ClInclude Include="Platform\Platform.h" />
|
||||
|
|
Loading…
Reference in New Issue