Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/objects/rideVehicle.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CAR_ENTRY_FLAG_SPINNING } from "../utilities/game";
import * as Log from "../utilities/logger";
import { isNumber } from "../utilities/type";
import { getRideObject } from "./rideType";
Expand Down Expand Up @@ -112,4 +113,13 @@ export class RideVehicle
const type = this._type();
return !type || isPowered(type);
}
}

/**
* Returns true if this car is considered a "spinning" ride type.
*/
_isSpinning(): boolean
{
const type = this._type();
return !!type && ((type.flags & CAR_ENTRY_FLAG_SPINNING) !== 0);
}
}
4 changes: 2 additions & 2 deletions src/services/spacingEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function getDistanceFromProgress(car: Car, trackProgress: number): number
? new ForwardIterator(trackProgress, currentProgress)
: new BackwardIterator(abs(trackProgress), currentProgress);

let trackPosition = currentTrackLocation;
let trackPosition: CoordsXYZD = currentTrackLocation;
let trackDistances = getTrackDistances(iteratorSegment, subposition, trackPosition.direction);
subpositionIterator._setInitialDistanceFromCarRemainingDistance(car.remainingDistance);

Expand Down Expand Up @@ -371,4 +371,4 @@ class BackwardIterator extends SubpositionIterator
nextTile.z + nextTrack._endZ
);
}
}
}
14 changes: 12 additions & 2 deletions src/services/vehicleEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const execute = register<UpdateVehicleSettingArgs>("rve-update-car", updateVehic
type VehicleUpdateKeys
= "rideObject" | "vehicleObject" | "isReversed" | "trackProgress" | "spacing"
| "numSeats" | "mass" | "poweredAcceleration" | "poweredMaxSpeed" | "x" | "y" | "z"
| "body" | "trim" | "tertiary";
| "spin" | "body" | "trim" | "tertiary";

const
rideTypeKey = "rideObject",
Expand All @@ -27,6 +27,7 @@ const
xPosition = "x",
yPosition = "y",
zPosition = "z",
spinKey = "spin",
primaryColour = "body",
secondaryColour = "trim",
tertiaryColour = "tertiary";
Expand Down Expand Up @@ -153,6 +154,14 @@ export function setPositionZ(vehicles: VehicleSpan[], z: number): void
updateValue(vehicles, zPosition, z);
}

/**
* Sets the z position for this vehicle.
*/
export function setSpin(vehicles: VehicleSpan[], spin: number): void
{
updateValue(vehicles, spinKey, spin);
}


/**
* Arguments for updating a single key in a vehicle object.
Expand Down Expand Up @@ -223,6 +232,7 @@ function updateVehicleSetting(args: UpdateVehicleSettingArgs): void
case massKey:
case poweredAccelerationKey:
case poweredMaxSpeedKey:
case spinKey:
{
callback = (car): void =>
{
Expand Down Expand Up @@ -278,4 +288,4 @@ function updateVehicleSetting(args: UpdateVehicleSettingArgs): void
}

forEachVehicle(targets, callback);
}
}
2 changes: 1 addition & 1 deletion src/services/vehiclePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export function toggleVehiclePicker(isPressed: boolean, onPick: (car: Car) => vo
/**
* Finds a car within a certain range of the selected tile element.
*/
function findCarNearbyTileElement(coords: CoordsXYZ, elementIdx: number): Car | undefined
function findCarNearbyTileElement(coords: CoordsXY, elementIdx: number): Car | undefined
{
const element = getTileElement(coords.x, coords.y, elementIdx);
const entitiesOnTile = map.getAllEntitiesOnTile("car", coords);
Expand Down
14 changes: 12 additions & 2 deletions src/ui/mainWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { RideVehicleVariant, VehicleVisibility } from "../objects/rideVehicleVar
import { invoke, refreshRide } from "../services/events";
import { applyToTargets, CopyFilter, getTargets, getVehicleSettings } from "../services/vehicleCopier";
import { dragToolId, toggleVehicleDragger } from "../services/vehicleDragger";
import { changeSpacing, changeTrackProgress, setMass, setPositionX, setPositionY, setPositionZ, setPoweredAcceleration, setPoweredMaximumSpeed, setPrimaryColour, setReversed, setRideType, setSeatCount, setSecondaryColour, setTertiaryColour, setVariant } from "../services/vehicleEditor";
import { changeSpacing, changeTrackProgress, setMass, setPositionX, setPositionY, setPositionZ, setPoweredAcceleration, setPoweredMaximumSpeed, setPrimaryColour, setReversed, setRideType, setSeatCount, setSecondaryColour, setSpin, setTertiaryColour, setVariant } from "../services/vehicleEditor";
import { locate } from "../services/vehicleLocater";
import { pickerToolId, toggleVehiclePicker } from "../services/vehiclePicker";
import { cancelTools } from "../utilities/tools";
Expand Down Expand Up @@ -37,7 +37,7 @@ model._selectedRide.subscribe(r =>

export const mainWindow = window({
title,
width: { value: 500, min: 465, max: 560 },
width: { value: 515, min: 515, max: 560 },
height: 407,
spacing: 5,
onOpen: () => model._open(),
Expand Down Expand Up @@ -375,6 +375,16 @@ export const mainWindow = window({
value: model._z,
format: model._formatPosition,
onChange: (_, incr) => model._modifyVehicle(setPositionZ, incr)
}),
labelSpinner({
_label: { text: "Seat spin:" },
minimum: 0,
maximum: 255,
disabled: model._isSpinDisabled,
step: model._multiplier,
value: model._spin,
wrapMode: "clampThenWrap",
onChange: value => model._modifyVehicle(setSpin, value)
})
]
}),
Expand Down
3 changes: 3 additions & 0 deletions src/utilities/game.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Game const for vehicle flag to determine spin ability.
// see src/openrct2/ride/CarEntry.h:CAR_ENTRY_FLAG_SPINNING
export const CAR_ENTRY_FLAG_SPINNING = 1 << 18;
3 changes: 3 additions & 0 deletions src/viewmodels/vehicleViewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class VehicleViewModel
readonly _x = store<number>(0);
readonly _y = store<number>(0);
readonly _z = store<number>(0);
readonly _spin = store<number>(0);

readonly _primaryColour = store<Colour>(0);
readonly _secondaryColour = store<Colour>(0);
Expand All @@ -51,6 +52,7 @@ export class VehicleViewModel
readonly _isPicking = store<boolean>(false);
readonly _isDragging = store<boolean>(false);
readonly _isEditDisabled = compute(this._selectedVehicle, v => !v);
readonly _isSpinDisabled = compute(this._selectedVehicle, v => !v || !v[0]._isSpinning());
readonly _isPositionDisabled = compute(this._isMoving, this._isEditDisabled, (m, e) => m || e);
readonly _formatPosition = (pos: number): string => (this._isEditDisabled.get() ? "Not available" : pos.toString());
readonly _multiplierIndex = store<number>(0);
Expand Down Expand Up @@ -277,6 +279,7 @@ export class VehicleViewModel
this._x.set(car.x);
this._y.set(car.y);
this._z.set(car.z);
this._spin.set(car.spin);

const train = this._selectedTrain.get();
if (train)
Expand Down
35 changes: 20 additions & 15 deletions tests/services/spacingEditor.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class TrackPiece
{
return new TrackPiece({ x, y, z, direction }, this.type, this.subpositions);
}

toLocation(): CarTrackLocation
{
return { ...this.position, trackType: this.type };
}
}

const flatTrackPiece = new TrackPiece({ x: 0, y: 0, z: 0, direction: 0 }, 1,
Expand Down Expand Up @@ -326,7 +331,7 @@ const multiTurnTest = test.macro({
exec(t, startTrackPiece: number, startProgress: number, progress: number, expectedResult: number): void
{
const trackPieces = [ rightTurn1TrackPiece, rightTurn2TrackPiece, steepUpTrackPiece, steepTurnTrackPiece ];
const trackLocation: CoordsXYZD = { ...trackPieces[startTrackPiece].position, direction: 0 };
const trackLocation: CarTrackLocation = { ...trackPieces[startTrackPiece].position, direction: 0, trackType: 0 };
setupTrackIterator(trackPieces, startTrackPiece);
const car = Mock.car({ trackProgress: startProgress, trackLocation, remainingDistance: (progress >= 0) ? ForwardRemainingDistance : 0 });

Expand Down Expand Up @@ -405,8 +410,8 @@ test("Flat track: get spacing to preceding vehicle 1 step away", t =>
{
const mapMock = setupTrackIterator([ flatTrackPiece ]);
const train = createTrain(mapMock, [
{ trackProgress: 17, trackLocation: flatTrackPiece.position }, // front car
{ trackProgress: 16, trackLocation: flatTrackPiece.position }
{ trackProgress: 17, trackLocation: flatTrackPiece.toLocation() }, // front car
{ trackProgress: 16, trackLocation: flatTrackPiece.toLocation() }
]);

const spacing = getSpacingToPrecedingVehicle(train, train._at(1)._car(), 1);
Expand All @@ -419,8 +424,8 @@ test("Flat track: get spacing to preceding vehicle 10 step away", t =>
{
const mapMock = setupTrackIterator([ flatTrackPiece ]);
const train = createTrain(mapMock, [
{ trackProgress: 17, trackLocation: flatTrackPiece.position }, // front car
{ trackProgress: 7, trackLocation: flatTrackPiece.position }
{ trackProgress: 17, trackLocation: flatTrackPiece.toLocation() }, // front car
{ trackProgress: 7, trackLocation: flatTrackPiece.toLocation() }
]);

const spacing = getSpacingToPrecedingVehicle(train, train._at(1)._car(), 1);
Expand All @@ -433,8 +438,8 @@ test("Flat track: get spacing to preceding vehicle 31 step away", t =>
{
const mapMock = setupTrackIterator([ flatTrackPiece ]);
const train = createTrain(mapMock, [
{ trackProgress: 31, trackLocation: flatTrackPiece.position }, // front car
{ trackProgress: 0, trackLocation: flatTrackPiece.position } // back car
{ trackProgress: 31, trackLocation: flatTrackPiece.toLocation() }, // front car
{ trackProgress: 0, trackLocation: flatTrackPiece.toLocation() } // back car
]);

const spacing = getSpacingToPrecedingVehicle(train, train._at(1)._car(), 1);
Expand All @@ -447,8 +452,8 @@ test("Flat track: get spacing to preceding vehicle is too far away", t =>
{
const mapMock = setupTrackIterator([ flatTrackPiece ]);
const train = createTrain(mapMock, [
{ trackProgress: 15, trackLocation: { x: 10, y: 10, z: 10, direction: 0 } }, // front car
{ trackProgress: 10, trackLocation: flatTrackPiece.position }
{ trackProgress: 15, trackLocation: { x: 10, y: 10, z: 10, direction: 0, trackType: 0 } }, // front car
{ trackProgress: 10, trackLocation: flatTrackPiece.toLocation()}
]);

const spacing = getSpacingToPrecedingVehicle(train, train._at(1)._car(), 1);
Expand All @@ -462,8 +467,8 @@ test("Two flat tracks: get spacing to next track piece by 1", t =>
const pieces = [ flatTrackPiece.copyTo(32, 64), flatTrackPiece.copyTo(32, 32) ];
const mapMock = setupTrackIterator(pieces);
const train = createTrain(mapMock, [
{ trackProgress: 0, trackLocation: pieces[1].position }, // front car
{ trackProgress: 31, trackLocation: pieces[0].position } // back car
{ trackProgress: 0, trackLocation: pieces[1].toLocation() }, // front car
{ trackProgress: 31, trackLocation: pieces[0].toLocation() } // back car
]);
const car = train._at(1)._car();

Expand All @@ -478,8 +483,8 @@ test("Two flat tracks: get spacing to next track piece by 10", t =>
const pieces = [ flatTrackPiece.copyTo(32, 64), flatTrackPiece.copyTo(32, 32) ];
const mapMock = setupTrackIterator(pieces);
const train = createTrain(mapMock, [
{ trackProgress: 3, trackLocation: pieces[1].position }, // front car
{ trackProgress: 25, trackLocation: pieces[0].position } // back car
{ trackProgress: 3, trackLocation: pieces[1].toLocation() }, // front car
{ trackProgress: 25, trackLocation: pieces[0].toLocation() } // back car
]);
const car = train._at(1)._car();

Expand All @@ -494,8 +499,8 @@ test("Three flat tracks: get spacing to next track piece by 50", t =>
const pieces = [ flatTrackPiece.copyTo(32, 96), flatTrackPiece.copyTo(32, 64), flatTrackPiece.copyTo(32, 32) ];
const mapMock = setupTrackIterator(pieces);
const train = createTrain(mapMock, [
{ trackProgress: 5, trackLocation: pieces[2].position }, // front car
{ trackProgress: 19, trackLocation: pieces[0].position } // back car
{ trackProgress: 5, trackLocation: pieces[2].toLocation() }, // front car
{ trackProgress: 19, trackLocation: pieces[0].toLocation() } // back car
]);
const car = train._at(1)._car();

Expand Down