OpenRCT2/src/openrct2/ride/Vehicle.h

534 lines
16 KiB
C++

/*****************************************************************************
* Copyright (c) 2014-2020 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
#include "../Identifiers.h"
#include "../audio/audio.h"
#include "../common.h"
#include "../entity/EntityBase.h"
#include "../ride/RideTypes.h"
#include "../world/Location.hpp"
#include "Station.h"
#include "VehicleColour.h"
#include "VehicleEntry.h"
#include "VehicleSubpositionData.h"
#include <array>
#include <cstddef>
#include <vector>
using track_type_t = uint16_t;
struct Ride;
struct rct_ride_entry;
struct rct_ride_entry_vehicle;
class DataSerialiser;
struct paint_session;
struct GForces
{
int32_t VerticalG{};
int32_t LateralG{};
};
// Size: 0x09
struct rct_vehicle_info
{
int16_t x; // 0x00
int16_t y; // 0x02
int16_t z; // 0x04
uint8_t direction; // 0x06
uint8_t Pitch; // 0x07
uint8_t bank_rotation; // 0x08
};
struct SoundIdVolume;
constexpr const uint16_t VehicleTrackDirectionMask = 0b0000000000000011;
constexpr const uint16_t VehicleTrackTypeMask = 0b1111111111111100;
enum class MiniGolfAnimation : uint8_t;
struct Vehicle : EntityBase
{
static constexpr auto cEntityType = EntityType::Vehicle;
enum class Type : uint8_t
{
Head,
Tail,
};
enum class Status : uint8_t
{
MovingToEndOfStation,
WaitingForPassengers,
WaitingToDepart,
Departing,
Travelling,
Arriving,
UnloadingPassengers,
TravellingBoat,
Crashing,
Crashed,
TravellingDodgems,
Swinging,
Rotating,
FerrisWheelRotating,
SimulatorOperating,
ShowingFilm,
SpaceRingsOperating,
TopSpinOperating,
HauntedHouseOperating,
DoingCircusShow,
CrookedHouseOperating,
WaitingForCableLift,
TravellingCableLift,
Stopping,
WaitingForPassengers17,
WaitingToStart,
Starting,
Operating1A,
Stopping1B,
UnloadingPassengers1C,
StoppedByBlockBrakes
};
Type SubType;
uint8_t Pitch;
uint8_t bank_rotation;
int32_t remaining_distance;
int32_t velocity;
int32_t acceleration;
RideId ride;
uint8_t vehicle_type;
rct_vehicle_colour colours;
union
{
uint16_t track_progress;
struct
{
int8_t var_34;
uint8_t var_35;
};
};
uint16_t TrackTypeAndDirection;
CoordsXYZ TrackLocation;
EntityId next_vehicle_on_train;
// The previous vehicle on the same train or the last vehicle on the previous or only train.
EntityId prev_vehicle_on_ride;
// The next vehicle on the same train or the first vehicle on the next or only train
EntityId next_vehicle_on_ride;
uint16_t var_44;
uint16_t mass;
uint16_t update_flags;
uint8_t SwingSprite;
StationIndex current_station;
union
{
int16_t SwingPosition;
int16_t current_time;
struct
{
int8_t ferris_wheel_var_0;
int8_t ferris_wheel_var_1;
};
};
union
{
int16_t SwingSpeed;
int16_t crash_z;
};
Status status;
uint8_t sub_state;
EntityId peep[32];
uint8_t peep_tshirt_colours[32];
uint8_t num_seats;
uint8_t num_peeps;
uint8_t next_free_seat;
uint8_t restraints_position; // 0 == Close, 255 == Open
union
{
int16_t spin_speed;
int16_t crash_x;
};
uint16_t sound2_flags;
uint8_t spin_sprite; // lowest 3 bits not used for sprite selection (divide by 8 to use)
OpenRCT2::Audio::SoundId sound1_id;
uint8_t sound1_volume;
OpenRCT2::Audio::SoundId sound2_id;
uint8_t sound2_volume;
int8_t sound_vector_factor;
union
{
uint16_t var_C0;
int16_t crash_y;
uint16_t time_waiting;
EntityId cable_lift_target;
};
uint8_t speed;
uint8_t powered_acceleration;
union
{
uint8_t DodgemsCollisionDirection;
uint8_t CollisionDetectionTimer;
};
uint8_t animation_frame;
uint8_t pad_C6[0x2];
uint32_t animationState;
OpenRCT2::Audio::SoundId scream_sound_id;
VehicleTrackSubposition TrackSubposition;
union
{
uint8_t NumLaps;
uint8_t NumSwings;
uint8_t NumLaunches;
uint8_t NumRotations;
uint8_t TimeActive;
};
uint8_t brake_speed;
uint16_t lost_time_out;
int8_t vertical_drop_countdown;
uint8_t var_D3;
MiniGolfAnimation mini_golf_current_animation;
uint8_t mini_golf_flags;
ObjectEntryIndex ride_subtype;
uint8_t colours_extended;
uint8_t seat_rotation;
uint8_t target_seat_rotation;
CoordsXY BoatLocation;
bool IsCrashedVehicle;
constexpr bool IsHead() const
{
return SubType == Vehicle::Type::Head;
}
void Update();
Vehicle* GetHead();
const Vehicle* GetHead() const;
Vehicle* GetCar(size_t carIndex) const;
void SetState(Vehicle::Status vehicleStatus, uint8_t subState = 0);
bool IsGhost() const;
void UpdateSoundParams(std::vector<OpenRCT2::Audio::VehicleSoundParams>& vehicleSoundParamsList) const;
std::optional<EntityId> DodgemsCarWouldCollideAt(const CoordsXY& coords) const;
int32_t UpdateTrackMotion(int32_t* outStation);
int32_t CableLiftUpdateTrackMotion();
GForces GetGForces() const;
void SetMapToolbar() const;
int32_t IsUsedInPairs() const;
rct_ride_entry* GetRideEntry() const;
rct_ride_entry_vehicle* Entry() const;
Ride* GetRide() const;
Vehicle* TrainHead() const;
Vehicle* TrainTail() const;
void EnableCollisionsForTrain();
/**
* Instantly moves the specific car forward or backwards along the track.
*/
void MoveRelativeDistance(int32_t distance);
track_type_t GetTrackType() const
{
return TrackTypeAndDirection >> 2;
}
uint8_t GetTrackDirection() const
{
return TrackTypeAndDirection & VehicleTrackDirectionMask;
}
void SetTrackType(track_type_t trackType)
{
// set the upper 14 bits to 0, then set track type
TrackTypeAndDirection &= ~VehicleTrackTypeMask;
TrackTypeAndDirection |= trackType << 2;
}
void SetTrackDirection(uint8_t trackDirection)
{
// set the lower 2 bits only
TrackTypeAndDirection &= ~VehicleTrackDirectionMask;
TrackTypeAndDirection |= trackDirection & VehicleTrackDirectionMask;
}
bool HasUpdateFlag(uint32_t flag) const
{
return (update_flags & flag) != 0;
}
void ClearUpdateFlag(uint32_t flag)
{
update_flags &= ~flag;
}
void SetUpdateFlag(uint32_t flag)
{
update_flags |= flag;
}
void ApplyMass(int16_t appliedMass);
void Serialise(DataSerialiser& stream);
void Paint(paint_session& session, int32_t imageDirection) const;
private:
bool SoundCanPlay() const;
uint16_t GetSoundPriority() const;
const rct_vehicle_info* GetMoveInfo() const;
uint16_t GetTrackProgress() const;
OpenRCT2::Audio::VehicleSoundParams CreateSoundParam(uint16_t priority) const;
void CableLiftUpdate();
bool CableLiftUpdateTrackMotionForwards();
bool CableLiftUpdateTrackMotionBackwards();
void CableLiftUpdateMovingToEndOfStation();
void CableLiftUpdateWaitingToDepart();
void CableLiftUpdateDeparting();
void CableLiftUpdateTravelling();
void CableLiftUpdateArriving();
void Sub6DBF3E();
void UpdateMeasurements();
void UpdateMovingToEndOfStation();
void UpdateWaitingForPassengers();
void UpdateWaitingToDepart();
void UpdateCrash();
void UpdateDodgemsMode();
void UpdateSwinging();
void UpdateSimulatorOperating();
void UpdateTopSpinOperating();
void UpdateFerrisWheelRotating();
void UpdateSpaceRingsOperating();
void UpdateHauntedHouseOperating();
void UpdateCrookedHouseOperating();
void UpdateRotating();
void UpdateDeparting();
void FinishDeparting();
void UpdateTravelling();
void UpdateTravellingCableLift();
void UpdateTravellingBoat();
void UpdateMotionBoatHire();
void TryReconnectBoatToTrack(const CoordsXY& currentBoatLocation, const CoordsXY& trackCoords);
void UpdateDepartingBoatHire();
void UpdateTravellingBoatHireSetup();
void UpdateBoatLocation();
void UpdateArrivingPassThroughStation(
const Ride& curRide, const rct_ride_entry_vehicle& vehicleEntry, bool stationBrakesWork);
void UpdateArriving();
void UpdateUnloadingPassengers();
void UpdateWaitingForCableLift();
void UpdateShowingFilm();
void UpdateDoingCircusShow();
void UpdateCrossings() const;
void UpdateSound();
void GetLiftHillSound(Ride* curRide, SoundIdVolume& curSound);
OpenRCT2::Audio::SoundId UpdateScreamSound();
OpenRCT2::Audio::SoundId ProduceScreamSound(const int32_t totalNumPeeps);
void UpdateCrashSetup();
void UpdateCollisionSetup();
int32_t UpdateMotionDodgems();
void UpdateAnimationAnimalFlying();
void UpdateAdditionalAnimation();
void CheckIfMissing();
bool CurrentTowerElementIsTop();
bool UpdateTrackMotionForwards(rct_ride_entry_vehicle* vehicleEntry, Ride* curRide, rct_ride_entry* rideEntry);
bool UpdateTrackMotionBackwards(rct_ride_entry_vehicle* vehicleEntry, Ride* curRide, rct_ride_entry* rideEntry);
int32_t UpdateTrackMotionPoweredRideAcceleration(
rct_ride_entry_vehicle* vehicleEntry, uint32_t totalMass, const int32_t curAcceleration);
int32_t NumPeepsUntilTrainTail() const;
void InvalidateWindow();
void TestReset();
void UpdateTestFinish();
void PeepEasterEggHereWeAre() const;
bool CanDepartSynchronised() const;
void ReverseReverserCar();
void UpdateReverserCarBogies();
void UpdateHandleWaterSplash() const;
void Claxon() const;
void UpdateTrackMotionUpStopCheck() const;
void ApplyNonStopBlockBrake();
void ApplyStopBlockBrake();
void CheckAndApplyBlockSectionStopSite();
void UpdateVelocity();
void UpdateSpinningCar();
void UpdateSwingingCar();
int32_t GetSwingAmount() const;
bool OpenRestraints();
bool CloseRestraints();
void CrashOnWater();
void CrashOnLand();
void SimulateCrash() const;
void KillAllPassengersInTrain();
void KillPassengers(Ride* curRide);
void TrainReadyToDepart(uint8_t num_peeps_on_train, uint8_t num_used_seats);
int32_t UpdateTrackMotionMiniGolfCalculateAcceleration(const rct_ride_entry_vehicle& vehicleEntry);
int32_t UpdateTrackMotionMiniGolf(int32_t* outStation);
void UpdateTrackMotionMiniGolfVehicle(Ride* curRide, rct_ride_entry* rideEntry, rct_ride_entry_vehicle* vehicleEntry);
bool UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, Ride* curRide, rct_ride_entry* rideEntry);
bool UpdateTrackMotionBackwardsGetNewTrack(uint16_t trackType, Ride* curRide, uint16_t* progress);
bool UpdateMotionCollisionDetection(const CoordsXYZ& loc, EntityId* otherVehicleIndex);
void UpdateGoKartAttemptSwitchLanes();
void UpdateSceneryDoor() const;
void UpdateSceneryDoorBackwards() const;
void UpdateLandscapeDoor() const;
void UpdateLandscapeDoorBackwards() const;
};
static_assert(sizeof(Vehicle) <= 512);
struct train_ref
{
Vehicle* head;
Vehicle* tail;
};
namespace MiniGolfFlag
{
constexpr uint8_t Flag0 = (1 << 0);
constexpr uint8_t Flag1 = (1 << 1);
constexpr uint8_t Flag2 = (1 << 2);
constexpr uint8_t Flag3 = (1 << 3);
constexpr uint8_t Flag4 = (1 << 4);
constexpr uint8_t Flag5 = (1 << 5); // transitioning between hole
} // namespace MiniGolfFlag
enum class MiniGolfState : int16_t
{
Unk0,
Unk1, // Unused
Unk2,
Unk3,
Unk4,
Unk5,
Unk6,
};
enum class MiniGolfAnimation : uint8_t
{
Walk,
PlaceBallDown,
SwingLeft,
PickupBall,
Jump,
PlaceBallUp,
PuttLeft,
Swing,
Putt,
};
enum
{
VEHICLE_ENTRY_ANIMATION_NONE,
VEHICLE_ENTRY_ANIMATION_MINITURE_RAILWAY_LOCOMOTIVE,
VEHICLE_ENTRY_ANIMATION_SWAN,
VEHICLE_ENTRY_ANIMATION_CANOES,
VEHICLE_ENTRY_ANIMATION_ROW_BOATS,
VEHICLE_ENTRY_ANIMATION_WATER_TRICYCLES,
VEHICLE_ENTRY_ANIMATION_OBSERVATION_TOWER,
VEHICLE_ENTRY_ANIMATION_HELICARS,
VEHICLE_ENTRY_ANIMATION_MONORAIL_CYCLES,
VEHICLE_ENTRY_ANIMATION_MULTI_DIM_COASTER,
VEHICLE_ENTRY_ANIMATION_ANIMAL_FLYING // OpenRCT2-specific feature
};
enum : uint32_t
{
VEHICLE_UPDATE_FLAG_ON_LIFT_HILL = (1 << 0),
VEHICLE_UPDATE_FLAG_COLLISION_DISABLED = (1 << 1),
VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT = (1 << 2),
VEHICLE_UPDATE_FLAG_REVERSING_SHUTTLE = (1 << 3), // Shuttle is in reverse
VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART = (1 << 4),
VEHICLE_UPDATE_FLAG_TESTING = (1 << 5),
VEHICLE_UPDATE_FLAG_6 = (1 << 6),
VEHICLE_UPDATE_FLAG_ZERO_VELOCITY = (1 << 7), // Used on rides when safety cutout stops them on a lift
VEHICLE_UPDATE_FLAG_BROKEN_CAR = (1 << 8),
VEHICLE_UPDATE_FLAG_BROKEN_TRAIN = (1 << 9),
VEHICLE_UPDATE_FLAG_ON_BRAKE_FOR_DROP = (1 << 10),
VEHICLE_UPDATE_FLAG_USE_INVERTED_SPRITES = (1 << 11), // Used on rides where trains can run for extended periods of time,
// i.e. the Flying, Lay-down and Multi-dimension RCs.
VEHICLE_UPDATE_FLAG_12 = (1 << 12),
VEHICLE_UPDATE_FLAG_ROTATION_OFF_WILD_MOUSE = (1 << 13), // After passing a rotation toggle track piece this will enable
VEHICLE_UPDATE_FLAG_SINGLE_CAR_POSITION = (1 << 14), // OpenRCT2 Flag: Used to override UpdateMotion to move the position of
// an individual car on a train
};
enum
{
VEHICLE_VISUAL_DEFAULT,
VEHICLE_VISUAL_FLAT_RIDE_OR_CAR_RIDE,
VEHICLE_VISUAL_LAUNCHED_FREEFALL,
VEHICLE_VISUAL_OBSERVATION_TOWER,
VEHICLE_VISUAL_RIVER_RAPIDS,
VEHICLE_VISUAL_MINI_GOLF_PLAYER,
VEHICLE_VISUAL_MINI_GOLF_BALL,
VEHICLE_VISUAL_REVERSER,
VEHICLE_VISUAL_SPLASH_BOATS_OR_WATER_COASTER,
VEHICLE_VISUAL_ROTO_DROP,
VEHICLE_VISUAL_SPLASH1_EFFECT,
VEHICLE_VISUAL_SPLASH2_EFFECT,
VEHICLE_VISUAL_SPLASH3_EFFECT,
VEHICLE_VISUAL_SPLASH4_EFFECT,
VEHICLE_VISUAL_SPLASH5_EFFECT,
VEHICLE_VISUAL_VIRGINIA_REEL,
VEHICLE_VISUAL_SUBMARINE
};
enum : uint32_t
{
VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_AT_STATION = 1 << 0,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_1 = 1 << 1,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_2 = 1 << 2,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_3 = 1 << 3,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_ON_LIFT_HILL = 1 << 4,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_5 = 1 << 5,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_DERAILED = 1 << 6,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_COLLISION = 1 << 7,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_8 = 1 << 8,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_9 = 1 << 9,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_AT_BLOCK_BRAKE = 1 << 10,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_11 = 1 << 11,
VEHICLE_UPDATE_MOTION_TRACK_FLAG_12 = 1 << 12,
};
enum
{
VEHICLE_SOUND2_FLAGS_LIFT_HILL = 1 << 1 // When on a lift hill generate sound
};
enum
{
FRICTION_SOUND_WOOD_SMALL = 1,
FRICTION_SOUND_STEEL = 2,
FRICTION_SOUND_PETROL = 21,
FRICTION_SOUND_TRAIN = 31,
FRICTION_SOUND_WATERSLIDE = 32,
FRICTION_SOUND_WOOD_LARGE = 54,
FRICTION_SOUND_STEEL_SMOOTH = 57,
FRICTION_SOUND_NONE = 255
};
enum
{
SOUND_RANGE_SCREAMS_0 = 0,
SOUND_RANGE_SCREAMS_1_WOODEN_COASTERS = 1,
SOUND_RANGE_SCREAMS_2 = 2,
SOUND_RANGE_WHISTLE = 3,
SOUND_RANGE_BELL = 4,
SOUND_RANGE_NONE = 255
};
#define VEHICLE_SEAT_PAIR_FLAG 0x80
#define VEHICLE_SEAT_NUM_MASK 0x7F
Vehicle* try_get_vehicle(EntityId spriteIndex);
void vehicle_update_all();
void vehicle_sounds_update();
extern Vehicle* gCurrentVehicle;
extern StationIndex _vehicleStationIndex;
extern uint32_t _vehicleMotionTrackFlags;
extern int32_t _vehicleVelocityF64E08;
extern int32_t _vehicleVelocityF64E0C;
extern int32_t _vehicleUnkF64E10;
extern uint8_t _vehicleF64E2C;
extern Vehicle* _vehicleFrontVehicle;
extern CoordsXYZ unk_F64E20;