mirror of https://github.com/OpenRCT2/OpenRCT2.git
Implement track iterator
This commit is contained in:
parent
76601ef6fc
commit
4eef86dc50
|
@ -224,6 +224,10 @@ declare global {
|
|||
getAllObjects(type: ObjectType): LoadedObject[];
|
||||
getAllObjects(type: "ride"): RideObject[];
|
||||
|
||||
/**
|
||||
* Gets the {@link TrackSegment} for the given type.
|
||||
* @param type The track segment type.
|
||||
*/
|
||||
getTrackSegment(type: number): TrackSegment | undefined;
|
||||
|
||||
/**
|
||||
|
@ -631,6 +635,14 @@ declare global {
|
|||
getAllEntitiesOnTile(type: "car", tilePos: CoordsXY): Car[];
|
||||
getAllEntitiesOnTile(type: "litter", tilePos: CoordsXY): Litter[];
|
||||
createEntity(type: EntityType, initializer: object): Entity;
|
||||
|
||||
/**
|
||||
* Gets a {@link TrackIterator} for the given track element. This can be used to
|
||||
* iterate through a ride's circuit, segment by segment.
|
||||
* @param location The tile coordinates.
|
||||
* @param elementIndex The index of the track element on the tile.
|
||||
*/
|
||||
getTrackIterator(location: CoordsXY, elementIndex: number): TrackIterator | undefined;
|
||||
}
|
||||
|
||||
type TileElementType =
|
||||
|
@ -711,6 +723,7 @@ declare global {
|
|||
hasChainLift: boolean;
|
||||
isInverted: boolean;
|
||||
hasCableLift: boolean;
|
||||
isHighlighted: boolean;
|
||||
}
|
||||
|
||||
interface SmallSceneryElement extends BaseTileElement {
|
||||
|
@ -1144,13 +1157,34 @@ declare global {
|
|||
/**
|
||||
* Gets a list of the elements that make up the track segment.
|
||||
*/
|
||||
readonly elements: TrackSegmentElement;
|
||||
readonly elements: TrackSegmentElement[];
|
||||
}
|
||||
|
||||
interface TrackSegmentElement {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
interface TrackSegmentElement implements CoordsXYZ {
|
||||
}
|
||||
|
||||
interface TrackIterator {
|
||||
/**
|
||||
* The position and direction of the current track segment, from the first element.
|
||||
*/
|
||||
readonly position: CoordsXYZD;
|
||||
|
||||
/**
|
||||
* The current track segment or undefined if at the beginning or end of a disconnected circuit.
|
||||
*/
|
||||
readonly segment: TrackSegment | undefined;
|
||||
|
||||
/**
|
||||
* Moves the iterator to the previous track segment.
|
||||
* @returns true if there is a previous segment, otherwise false.
|
||||
*/
|
||||
previous(): boolean;
|
||||
|
||||
/**
|
||||
* Moves the iterator to the next track segment.
|
||||
* @returns true if there is a next segment, otherwise false.
|
||||
*/
|
||||
next(): boolean;
|
||||
}
|
||||
|
||||
type EntityType =
|
||||
|
|
|
@ -468,6 +468,7 @@
|
|||
<ClInclude Include="scripting\bindings\network\ScPlayer.hpp" />
|
||||
<ClInclude Include="scripting\bindings\network\ScPlayerGroup.hpp" />
|
||||
<ClInclude Include="scripting\bindings\ride\ScRideStation.hpp" />
|
||||
<ClInclude Include="scripting\bindings\ride\ScTrackIterator.h" />
|
||||
<ClInclude Include="scripting\bindings\ride\ScTrackSegment.h" />
|
||||
<ClInclude Include="scripting\bindings\world\ScParkMessage.hpp" />
|
||||
<ClInclude Include="scripting\bindings\world\ScTileElement.hpp" />
|
||||
|
@ -926,6 +927,7 @@
|
|||
<ClCompile Include="scripting\bindings\network\ScPlayerGroup.cpp" />
|
||||
<ClCompile Include="scripting\bindings\ride\ScRide.cpp" />
|
||||
<ClCompile Include="scripting\bindings\ride\ScRideStation.cpp" />
|
||||
<ClCompile Include="scripting\bindings\ride\ScTrackIterator.cpp" />
|
||||
<ClCompile Include="scripting\bindings\ride\ScTrackSegment.cpp" />
|
||||
<ClCompile Include="scripting\bindings\world\ScMap.cpp" />
|
||||
<ClCompile Include="scripting\bindings\world\ScPark.cpp" />
|
||||
|
|
|
@ -664,6 +664,25 @@ bool TrackTypeHasSpeedSetting(track_type_t trackType)
|
|||
return trackType == TrackElemType::Brakes || trackType == TrackElemType::Booster;
|
||||
}
|
||||
|
||||
std::optional<CoordsXYZD> GetTrackSegmentOrigin(const CoordsXYE& posEl)
|
||||
{
|
||||
auto trackEl = posEl.element->AsTrack();
|
||||
if (trackEl == nullptr)
|
||||
return {};
|
||||
|
||||
const auto& ted = GetTrackElementDescriptor(trackEl->GetTrackType());
|
||||
auto direction = trackEl->GetDirection();
|
||||
auto coords = CoordsXYZ(posEl.x, posEl.y, trackEl->GetBaseZ());
|
||||
|
||||
// Subtract the current sequence's offset
|
||||
const auto* trackBlock = &ted.Block[trackEl->GetSequenceIndex()];
|
||||
CoordsXY trackBlockOffset = { trackBlock->x, trackBlock->y };
|
||||
coords += trackBlockOffset.Rotate(direction_reverse(direction));
|
||||
coords.z -= trackBlock->z;
|
||||
|
||||
return CoordsXYZD(coords, direction);
|
||||
}
|
||||
|
||||
uint8_t TrackElement::GetSeatRotation() const
|
||||
{
|
||||
const auto* ride = get_ride(GetRideIndex());
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "../world/Map.h"
|
||||
#include "../world/TileElement.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
constexpr const uint32_t RideConstructionSpecialPieceSelected = 0x10000;
|
||||
|
||||
constexpr const int32_t BLOCK_BRAKE_BASE_SPEED = 0x20364;
|
||||
|
@ -581,3 +583,4 @@ bool track_remove_station_element(const CoordsXYZD& loc, RideId rideIndex, int32
|
|||
money32 maze_set_track(const CoordsXYZD& coords, uint8_t flags, bool initialPlacement, RideId rideIndex, uint8_t mode);
|
||||
|
||||
bool TrackTypeHasSpeedSetting(track_type_t trackType);
|
||||
std::optional<CoordsXYZD> GetTrackSegmentOrigin(const CoordsXYE& posEl);
|
||||
|
|
|
@ -413,6 +413,7 @@ void ScriptEngine::Initialise()
|
|||
ScRideObjectVehicle::Register(ctx);
|
||||
ScTile::Register(ctx);
|
||||
ScTileElement::Register(ctx);
|
||||
ScTrackIterator::Register(ctx);
|
||||
ScTrackSegment::Register(ctx);
|
||||
ScEntity::Register(ctx);
|
||||
ScLitter::Register(ctx);
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2022 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
||||
# include "ScTrackIterator.h"
|
||||
|
||||
# include "../../../Context.h"
|
||||
# include "../../../ride/Ride.h"
|
||||
# include "../../../ride/TrackData.h"
|
||||
# include "../../ScriptEngine.h"
|
||||
# include "ScTrackSegment.h"
|
||||
|
||||
using namespace OpenRCT2::Scripting;
|
||||
using namespace OpenRCT2::TrackMetaData;
|
||||
|
||||
std::shared_ptr<ScTrackIterator> ScTrackIterator::FromElement(const CoordsXY& position, int32_t elementIndex)
|
||||
{
|
||||
auto el = map_get_nth_element_at(position, elementIndex);
|
||||
auto origin = GetTrackSegmentOrigin(CoordsXYE(position, el));
|
||||
if (!origin)
|
||||
return nullptr;
|
||||
|
||||
auto trackEl = el->AsTrack();
|
||||
return std::make_shared<ScTrackIterator>(*origin, trackEl->GetTrackType(), trackEl->GetRideIndex());
|
||||
}
|
||||
|
||||
ScTrackIterator::ScTrackIterator(const CoordsXYZD& position, track_type_t type, RideId ride)
|
||||
: _position(position)
|
||||
, _type(type)
|
||||
, _ride(ride)
|
||||
{
|
||||
}
|
||||
|
||||
void ScTrackIterator::Register(duk_context* ctx)
|
||||
{
|
||||
dukglue_register_property(ctx, &ScTrackIterator::position_get, nullptr, "position");
|
||||
dukglue_register_property(ctx, &ScTrackIterator::segment_get, nullptr, "segment");
|
||||
dukglue_register_method(ctx, &ScTrackIterator::previous, "previous");
|
||||
dukglue_register_method(ctx, &ScTrackIterator::next, "next");
|
||||
}
|
||||
|
||||
DukValue ScTrackIterator::position_get() const
|
||||
{
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
auto ctx = scriptEngine.GetContext();
|
||||
return ToDuk(ctx, _position);
|
||||
}
|
||||
|
||||
DukValue ScTrackIterator::segment_get() const
|
||||
{
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
auto ctx = scriptEngine.GetContext();
|
||||
|
||||
if (_type >= TrackElemType::Count)
|
||||
return ToDuk(ctx, undefined);
|
||||
|
||||
return GetObjectAsDukValue(ctx, std::make_shared<ScTrackSegment>(_type));
|
||||
}
|
||||
|
||||
bool ScTrackIterator::previous()
|
||||
{
|
||||
auto& ted = GetTrackElementDescriptor(_type);
|
||||
auto& seq0 = ted.Block;
|
||||
auto pos = _position + CoordsXYZ(seq0->x, seq0->y, seq0->z);
|
||||
|
||||
auto el = map_get_track_element_at(pos);
|
||||
if (el == nullptr)
|
||||
return false;
|
||||
|
||||
auto posEl = CoordsXYE(pos.x, pos.y, reinterpret_cast<TileElement*>(el));
|
||||
track_begin_end tbe{};
|
||||
auto value = track_block_get_previous(posEl, &tbe);
|
||||
if (tbe.begin_element != nullptr)
|
||||
{
|
||||
auto prev = CoordsXYE(tbe.begin_x, tbe.begin_y, tbe.begin_element);
|
||||
auto origin = GetTrackSegmentOrigin(prev);
|
||||
if (origin)
|
||||
{
|
||||
_position = *origin;
|
||||
_type = prev.element->AsTrack()->GetTrackType();
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScTrackIterator::next()
|
||||
{
|
||||
auto& ted = GetTrackElementDescriptor(_type);
|
||||
auto& seq0 = ted.Block;
|
||||
auto pos = _position + CoordsXYZ(seq0->x, seq0->y, seq0->z);
|
||||
|
||||
auto el = map_get_track_element_at(pos);
|
||||
if (el == nullptr)
|
||||
return false;
|
||||
|
||||
auto posEl = CoordsXYE(_position.x, _position.y, reinterpret_cast<TileElement*>(el));
|
||||
CoordsXYE next;
|
||||
int32_t z{};
|
||||
int32_t direction = -1;
|
||||
auto value = track_block_get_next(&posEl, &next, &z, &direction);
|
||||
if (next.element != nullptr)
|
||||
{
|
||||
auto origin = GetTrackSegmentOrigin(next);
|
||||
if (origin)
|
||||
{
|
||||
_position = *origin;
|
||||
_type = next.element->AsTrack()->GetTrackType();
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2022 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
|
||||
# include "../../../Identifiers.h"
|
||||
# include "../../../world/TileElement.h"
|
||||
# include "../../Duktape.hpp"
|
||||
|
||||
# include <cstdint>
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
{
|
||||
class ScTrackIterator
|
||||
{
|
||||
private:
|
||||
CoordsXYZD _position;
|
||||
track_type_t _type;
|
||||
RideId _ride;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<ScTrackIterator> FromElement(const CoordsXY& position, int32_t elementIndex);
|
||||
static void Register(duk_context* ctx);
|
||||
|
||||
ScTrackIterator(const CoordsXYZD& position, track_type_t type, RideId ride);
|
||||
|
||||
private:
|
||||
DukValue position_get() const;
|
||||
DukValue segment_get() const;
|
||||
bool previous();
|
||||
bool next();
|
||||
};
|
||||
|
||||
} // namespace OpenRCT2::Scripting
|
||||
|
||||
#endif
|
|
@ -31,6 +31,7 @@
|
|||
# include "../entity/ScStaff.hpp"
|
||||
# include "../entity/ScVehicle.hpp"
|
||||
# include "../ride/ScRide.hpp"
|
||||
# include "../ride/ScTrackIterator.h"
|
||||
# include "../world/ScTile.hpp"
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
|
@ -303,6 +304,16 @@ namespace OpenRCT2::Scripting
|
|||
return res;
|
||||
}
|
||||
|
||||
DukValue ScMap::getTrackIterator(const DukValue& dukPosition, int32_t elementIndex) const
|
||||
{
|
||||
auto position = FromDuk<CoordsXY>(dukPosition);
|
||||
auto trackIterator = ScTrackIterator::FromElement(position, elementIndex);
|
||||
if (trackIterator == nullptr)
|
||||
return ToDuk(_context, undefined);
|
||||
|
||||
return GetObjectAsDukValue(_context, trackIterator);
|
||||
}
|
||||
|
||||
void ScMap::Register(duk_context* ctx)
|
||||
{
|
||||
dukglue_register_property(ctx, &ScMap::size_get, nullptr, "size");
|
||||
|
@ -315,6 +326,7 @@ namespace OpenRCT2::Scripting
|
|||
dukglue_register_method(ctx, &ScMap::getAllEntities, "getAllEntities");
|
||||
dukglue_register_method(ctx, &ScMap::getAllEntitiesOnTile, "getAllEntitiesOnTile");
|
||||
dukglue_register_method(ctx, &ScMap::createEntity, "createEntity");
|
||||
dukglue_register_method(ctx, &ScMap::getTrackIterator, "getTrackIterator");
|
||||
}
|
||||
|
||||
DukValue ScMap::GetEntityAsDukValue(const EntityBase* sprite) const
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# include "../../../common.h"
|
||||
# include "../../Duktape.hpp"
|
||||
# include "../ride/ScRide.hpp"
|
||||
# include "../ride/ScTrackIterator.h"
|
||||
# include "../world/ScTile.hpp"
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
|
@ -46,6 +47,8 @@ namespace OpenRCT2::Scripting
|
|||
|
||||
DukValue createEntity(const std::string& type, const DukValue& initializer);
|
||||
|
||||
DukValue getTrackIterator(const DukValue& position, int32_t elementIndex) const;
|
||||
|
||||
static void Register(duk_context* ctx);
|
||||
|
||||
private:
|
||||
|
|
|
@ -1075,6 +1075,27 @@ namespace OpenRCT2::Scripting
|
|||
Invalidate();
|
||||
}
|
||||
|
||||
DukValue ScTileElement::isHighlighted_get() const
|
||||
{
|
||||
auto ctx = GetContext()->GetScriptEngine().GetContext();
|
||||
auto el = _element->AsTrack();
|
||||
if (el != nullptr)
|
||||
duk_push_boolean(ctx, el->IsHighlighted());
|
||||
else
|
||||
duk_push_null(ctx);
|
||||
return DukValue::take_from_stack(ctx);
|
||||
}
|
||||
void ScTileElement::isHighlighted_set(bool value)
|
||||
{
|
||||
ThrowIfGameStateNotMutable();
|
||||
auto el = _element->AsTrack();
|
||||
if (el != nullptr)
|
||||
{
|
||||
el->SetHighlight(value);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
DukValue ScTileElement::object_get() const
|
||||
{
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
|
@ -2045,6 +2066,7 @@ namespace OpenRCT2::Scripting
|
|||
dukglue_register_property(ctx, &ScTileElement::hasChainLift_get, &ScTileElement::hasChainLift_set, "hasChainLift");
|
||||
dukglue_register_property(ctx, &ScTileElement::isInverted_get, &ScTileElement::isInverted_set, "isInverted");
|
||||
dukglue_register_property(ctx, &ScTileElement::hasCableLift_get, &ScTileElement::hasCableLift_set, "hasCableLift");
|
||||
dukglue_register_property(ctx, &ScTileElement::isHighlighted_get, &ScTileElement::isHighlighted_set, "isHighlighted");
|
||||
|
||||
// Small Scenery only
|
||||
dukglue_register_property(ctx, &ScTileElement::age_get, &ScTileElement::age_set, "age");
|
||||
|
|
|
@ -114,6 +114,9 @@ namespace OpenRCT2::Scripting
|
|||
DukValue hasCableLift_get() const;
|
||||
void hasCableLift_set(bool value);
|
||||
|
||||
DukValue isHighlighted_get() const;
|
||||
void isHighlighted_set(bool value);
|
||||
|
||||
DukValue object_get() const;
|
||||
void object_set(const DukValue& value);
|
||||
|
||||
|
|
Loading…
Reference in New Issue