Implement RoadElement::update (#1106)
This commit is contained in:
parent
14edc842b6
commit
51789bd329
|
@ -85,7 +85,7 @@ namespace OpenLoco::GameCommands
|
|||
{ GameCommand::vehicleOrderDelete, nullptr, 0x0047057A, false },
|
||||
{ GameCommand::vehicleOrderSkip, Vehicles::orderSkip, 0x0047071A, false },
|
||||
{ GameCommand::gc_unk_38, nullptr, 0x00475FBC, true },
|
||||
{ GameCommand::gc_unk_39, nullptr, 0x004775A5, true },
|
||||
{ GameCommand::removeRoad, nullptr, 0x004775A5, true },
|
||||
{ GameCommand::createRoadMod, nullptr, 0x0047A21E, true },
|
||||
{ GameCommand::removeRoadMod, nullptr, 0x0047A42F, true },
|
||||
{ GameCommand::gc_unk_42, nullptr, 0x0048C708, true },
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace OpenLoco::GameCommands
|
|||
vehicleOrderDelete = 36,
|
||||
vehicleOrderSkip = 37,
|
||||
gc_unk_38 = 38,
|
||||
gc_unk_39 = 39,
|
||||
removeRoad = 39,
|
||||
createRoadMod = 40,
|
||||
removeRoadMod = 41,
|
||||
gc_unk_42 = 42,
|
||||
|
@ -727,6 +727,40 @@ namespace OpenLoco::GameCommands
|
|||
return doCommand(GameCommand::vehicleOrderSkip, regs);
|
||||
}
|
||||
|
||||
struct RoadRemovalArgs
|
||||
{
|
||||
static constexpr auto command = GameCommand::removeRoad;
|
||||
|
||||
RoadRemovalArgs() = default;
|
||||
explicit RoadRemovalArgs(const registers& regs)
|
||||
: pos(regs.ax, regs.cx, regs.di)
|
||||
, unkDirection(regs.bh & 0x3)
|
||||
, roadId(regs.dl & 0xF)
|
||||
, sequenceIndex(regs.dh & 0x3)
|
||||
, objectId(regs.bp & 0xF)
|
||||
{
|
||||
}
|
||||
|
||||
Map::Pos3 pos;
|
||||
uint8_t unkDirection;
|
||||
uint8_t roadId;
|
||||
uint8_t sequenceIndex;
|
||||
uint8_t objectId;
|
||||
|
||||
explicit operator registers() const
|
||||
{
|
||||
registers regs;
|
||||
regs.ax = pos.x;
|
||||
regs.cx = pos.y;
|
||||
regs.di = pos.z;
|
||||
regs.bh = unkDirection;
|
||||
regs.dl = roadId;
|
||||
regs.dh = sequenceIndex;
|
||||
regs.bp = objectId;
|
||||
return regs;
|
||||
}
|
||||
};
|
||||
|
||||
struct RoadModsPlacementArgs
|
||||
{
|
||||
static constexpr auto command = GameCommand::createRoadMod;
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
#include "../CompanyManager.h"
|
||||
#include "../GameCommands/GameCommands.h"
|
||||
#include "../Interop/Interop.hpp"
|
||||
#include "../Objects/RoadObject.h"
|
||||
#include "Tile.h"
|
||||
#include "TileManager.h"
|
||||
|
||||
using namespace OpenLoco::Interop;
|
||||
|
||||
namespace OpenLoco::Map
|
||||
{
|
||||
static loco_global<uint32_t, 0x00525FBC> _525FBC;
|
||||
|
||||
// 0x00477FC2
|
||||
bool RoadElement::update(const Map::Pos2& loc)
|
||||
{
|
||||
if (owner() == CompanyId::neutral || isPlayerCompany(owner()))
|
||||
return true;
|
||||
|
||||
if (!(_525FBC & (1 << roadObjectId())))
|
||||
return true;
|
||||
|
||||
if (sequenceIndex())
|
||||
return true;
|
||||
|
||||
if (hasUnkBit4() || hasLevelCrossing() || mods())
|
||||
return true;
|
||||
|
||||
if (isGhost() || isFlag5())
|
||||
return true;
|
||||
|
||||
if (hasStationElement())
|
||||
return true;
|
||||
|
||||
// Verify there are no other conflicting tile elements on the current tile either.
|
||||
// This probably duplicates the above series of checks as well?
|
||||
auto tile = TileManager::get(loc);
|
||||
for (auto& el : tile)
|
||||
{
|
||||
auto* roadEl = el.asRoad();
|
||||
if (roadEl == nullptr)
|
||||
continue;
|
||||
|
||||
if (roadEl->baseZ() != baseZ())
|
||||
continue;
|
||||
|
||||
if (roadEl->owner() == CompanyId::neutral || isPlayerCompany(roadEl->owner()))
|
||||
continue;
|
||||
|
||||
if (!(_525FBC & (1 << roadEl->roadObjectId())))
|
||||
continue;
|
||||
|
||||
if (roadEl->sequenceIndex())
|
||||
return true;
|
||||
|
||||
if (hasUnkBit4() || hasLevelCrossing() || mods())
|
||||
return true;
|
||||
|
||||
if (roadEl->isGhost() || roadEl->isFlag5())
|
||||
return true;
|
||||
|
||||
if (roadEl->hasStationElement())
|
||||
return true;
|
||||
}
|
||||
|
||||
CompanyId_t backup = CompanyManager::updatingCompanyId();
|
||||
CompanyManager::updatingCompanyId(owner());
|
||||
|
||||
GameCommands::RoadRemovalArgs args;
|
||||
args.pos = Map::Pos3(loc.x, loc.y, baseZ() * 4);
|
||||
args.unkDirection = unkDirection();
|
||||
args.roadId = roadId();
|
||||
args.sequenceIndex = sequenceIndex();
|
||||
args.objectId = roadObjectId();
|
||||
GameCommands::doCommand(args, GameCommands::Flags::apply);
|
||||
|
||||
CompanyManager::updatingCompanyId(backup);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -314,10 +314,13 @@ namespace OpenLoco::Map
|
|||
uint8_t sequenceIndex() const { return _5 & 0x3; } // _5l
|
||||
uint8_t bridge() const { return _6 >> 5; } // _6u
|
||||
bool hasStationElement() const { return (_type & 0x80) != 0; }
|
||||
bool hasUnkBit4() const { return _7 & (1 << 4); }
|
||||
bool hasLevelCrossing() const { return _7 & (1 << 5); }
|
||||
bool hasMod(uint8_t mod) const { return _7 & (1 << (mod + 6)); } // _7u (bits 6 and 7)
|
||||
uint8_t mods() const { return _7 >> 6; } // _7u
|
||||
uint8_t owner() const { return _7 & 0xF; } // _7l
|
||||
void setOwner(uint8_t newOwner) { _7 = (_7 & 0xF0) | (newOwner & 0xF); }
|
||||
bool update(const Map::Pos2& loc);
|
||||
};
|
||||
|
||||
struct IndustryElement : public TileElementBase
|
||||
|
|
|
@ -598,8 +598,14 @@ namespace OpenLoco::Map::TileManager
|
|||
call(0x004BD52B, regs);
|
||||
break;
|
||||
case ElementType::road:
|
||||
call(0x00477FC2, regs);
|
||||
{
|
||||
auto* elRoad = el.asRoad();
|
||||
if (elRoad != nullptr)
|
||||
return elRoad->update(loc);
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ElementType::industry:
|
||||
call(0x00456FF7, regs);
|
||||
break;
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
<ClCompile Include="Map\BuildingTile.cpp" />
|
||||
<ClCompile Include="Map\AnimationManager.cpp" />
|
||||
<ClCompile Include="Map\MapGenerator.cpp" />
|
||||
<ClCompile Include="Map\RoadTile.cpp" />
|
||||
<ClCompile Include="Map\SurfaceTile.cpp" />
|
||||
<ClCompile Include="Map\Tile.cpp" />
|
||||
<ClCompile Include="Map\TileManager.cpp" />
|
||||
|
|
Loading…
Reference in New Issue