1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-25 07:44:38 +01:00

steam position modifier and animation speed properties (#11269)

* Add speed and frame properties

* add steam position modifier

* copy code from OpenLoco

* update sin and cos

* add computation function

* finalize locomotion code

* fix formatting

* refine code

* refactor things slightly

* manually fix formatting

* use PascalCase and rename

* fix copyright notice

* fix name again

* rename function, move outt  of namespace

* fix rebase issues

* remove pitch table derived from physics

* rename some stuff

* flip vertical component sign to make sense

* change json structure

* create steam particles based on number of animation frames

* fix formatting

* add slope for spiral lift hill down

* fix formatting again

* parens around bitwise and

* make animations separate functions

* rename MultiDimCoaster to MultiDimension

* use EnumValue method

* rework multidim frame count

* bump network to be safe

* fix formatting

* move array out of function

* make table const

* move struct into RideObject.cpp

* try new method to fix numbers in multidim

* implement ZehMatt modulo

* add documentation to new function

* include Yaw.hpp

* rename src/ride/SteamPosition.hpp to src/math/Trigonometry.hpp

* actually add src/math/Trigonometry.hpp

* move ComputeSteamOffset to Vehicle.cpp

* use static asserts on arrays

* fix changelog grammar

* add more static asserts
This commit is contained in:
spacek531
2023-03-09 05:45:45 -08:00
committed by GitHub
parent 2ac5e070c1
commit fdbc3d29bb
11 changed files with 455 additions and 238 deletions

View File

@@ -43,6 +43,56 @@ static const uint8_t SpriteGroupMultiplier[EnumValue(SpriteGroupType::Count)] =
1, 2, 2, 2, 2, 2, 2, 10, 1, 2, 2, 2, 2, 2, 2, 2, 6, 4, 4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 20, 3, 1,
};
constexpr const uint8_t DefaultSteamSpawnPosition[] = { 11, 22 };
static const EnumMap<CarEntryAnimation> AnimationNameLookup{
{ "none", CarEntryAnimation::None },
{ "simpleVehicle", CarEntryAnimation::SimpleVehicle },
{ "steamLocomotive", CarEntryAnimation::SteamLocomotive },
{ "swanBoat", CarEntryAnimation::SwanBoat },
{ "monorailCycle", CarEntryAnimation::MonorailCycle },
{ "MultiDimension", CarEntryAnimation::MultiDimension },
{ "observationTower", CarEntryAnimation::ObservationTower },
{ "animalFlying", CarEntryAnimation::AnimalFlying },
};
constexpr const auto NumLegacyAnimationTypes = 11;
struct LegacyAnimationParameters
{
uint16_t Speed;
uint8_t NumFrames;
CarEntryAnimation Alias;
};
constexpr const LegacyAnimationParameters VehicleEntryDefaultAnimation[] = {
{ 0, 1, CarEntryAnimation::None }, // None
{ 1 << 12, 4, CarEntryAnimation::SteamLocomotive }, // Miniature Railway Locomotive
{ 1 << 10, 2, CarEntryAnimation::SwanBoat }, // Swan Boat
{ 1 << 11, 6, CarEntryAnimation::SimpleVehicle }, // Canoe
{ 1 << 11, 7, CarEntryAnimation::SimpleVehicle }, // Rowboat
{ 1 << 10, 2, CarEntryAnimation::SimpleVehicle }, // Water Tricycle
{ 0x3333, 8, CarEntryAnimation::ObservationTower }, // Observation Tower
{ 1 << 10, 4, CarEntryAnimation::SimpleVehicle }, // Mini Helicopter
{ 1 << 11, 4, CarEntryAnimation::MonorailCycle }, // Monorail Cycle
{ 0x3333, 8, CarEntryAnimation::MultiDimension }, // Multi Dimension Coaster
{ 24, 4, CarEntryAnimation::AnimalFlying }, // Animal Flying
};
static_assert(std::size(VehicleEntryDefaultAnimation) == NumLegacyAnimationTypes);
static CarEntryAnimation GetAnimationTypeFromString(const std::string& s)
{
auto result = AnimationNameLookup.find(s);
return (result != AnimationNameLookup.end()) ? result->second : CarEntryAnimation::None;
}
static LegacyAnimationParameters GetDefaultAnimationParameters(uint8_t legacyAnimationType)
{
if (legacyAnimationType >= NumLegacyAnimationTypes)
return VehicleEntryDefaultAnimation[0];
return VehicleEntryDefaultAnimation[legacyAnimationType];
}
static constexpr SpritePrecision PrecisionFromNumFrames(uint8_t numRotationFrames)
{
if (numRotationFrames == 0)
@@ -240,7 +290,7 @@ void RideObject::Load()
carEntry.NumCarImages = imageIndex - currentCarImagesOffset;
// Move the offset over this cars images. Including peeps
// Move the offset over this car's images. Including peeps
currentCarImagesOffset = imageIndex + carEntry.no_seating_rows * carEntry.NumCarImages;
// 0x6DEB0D
@@ -350,7 +400,7 @@ void RideObject::ReadLegacyCar([[maybe_unused]] IReadObjectContext* context, ISt
car->sprite_width = stream->ReadValue<uint8_t>();
car->sprite_height_negative = stream->ReadValue<uint8_t>();
car->sprite_height_positive = stream->ReadValue<uint8_t>();
car->animation = stream->ReadValue<uint8_t>();
auto legacyAnimation = stream->ReadValue<uint8_t>();
car->flags = stream->ReadValue<uint32_t>();
car->base_num_frames = stream->ReadValue<uint16_t>();
stream->Seek(15 * 4, STREAM_SEEK_CURRENT);
@@ -368,6 +418,14 @@ void RideObject::ReadLegacyCar([[maybe_unused]] IReadObjectContext* context, ISt
car->draw_order = stream->ReadValue<uint8_t>();
car->num_vertical_frames_override = stream->ReadValue<uint8_t>();
stream->Seek(4, STREAM_SEEK_CURRENT);
// OpenRCT2-specific features below
auto animationProperties = GetDefaultAnimationParameters(legacyAnimation);
car->animation = animationProperties.Alias;
car->AnimationSpeed = animationProperties.Speed;
car->AnimationFrames = animationProperties.NumFrames;
car->SteamEffect.Longitudinal = DefaultSteamSpawnPosition[0];
car->SteamEffect.Vertical = DefaultSteamSpawnPosition[1];
ReadLegacySpriteGroups(car, spriteGroups);
}
@@ -383,8 +441,8 @@ uint8_t RideObject::CalculateNumVerticalFrames(const CarEntry& carEntry)
{
if (!(carEntry.flags & CAR_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES))
{
if (carEntry.flags & CAR_ENTRY_FLAG_VEHICLE_ANIMATION
&& carEntry.animation != CAR_ENTRY_ANIMATION_OBSERVATION_TOWER)
if ((carEntry.flags & CAR_ENTRY_FLAG_VEHICLE_ANIMATION)
&& carEntry.animation != CarEntryAnimation::ObservationTower)
{
if (!(carEntry.flags & CAR_ENTRY_FLAG_DODGEM_INUSE_LIGHTS))
{
@@ -647,7 +705,6 @@ CarEntry RideObject::ReadJsonCar([[maybe_unused]] IReadObjectContext* context, j
car.sprite_width = Json::GetNumber<uint8_t>(jCar["spriteWidth"]);
car.sprite_height_negative = Json::GetNumber<uint8_t>(jCar["spriteHeightNegative"]);
car.sprite_height_positive = Json::GetNumber<uint8_t>(jCar["spriteHeightPositive"]);
car.animation = Json::GetNumber<uint8_t>(jCar["animation"]);
car.base_num_frames = Json::GetNumber<uint16_t>(jCar["baseNumFrames"]);
car.NumCarImages = Json::GetNumber<uint32_t>(jCar["numImages"]);
car.no_seating_rows = Json::GetNumber<uint8_t>(jCar["numSeatRows"]);
@@ -664,6 +721,38 @@ CarEntry RideObject::ReadJsonCar([[maybe_unused]] IReadObjectContext* context, j
car.draw_order = Json::GetNumber<uint8_t>(jCar["drawOrder"]);
car.num_vertical_frames_override = Json::GetNumber<uint8_t>(jCar["numVerticalFramesOverride"]);
auto jAnimation = jCar["animation"];
if (jAnimation.is_object())
{
car.animation = GetAnimationTypeFromString(Json::GetString(jAnimation["animationType"]));
car.AnimationSpeed = Json::GetNumber<uint16_t>(jAnimation["animationSpeed"]);
car.AnimationFrames = Json::GetNumber<uint16_t>(jAnimation["animationFrames"]);
}
else
{
auto animationProperties = GetDefaultAnimationParameters(Json::GetNumber<uint8_t>(jAnimation));
car.animation = animationProperties.Alias;
car.AnimationSpeed = animationProperties.Speed;
car.AnimationFrames = animationProperties.NumFrames;
if (!jCar["animationSpeed"].is_null())
car.AnimationSpeed = Json::GetNumber<uint16_t>(jCar["animationSpeed"]);
if (!jCar["animationFrames"].is_null())
car.AnimationFrames = Json::GetNumber<uint16_t>(jCar["animationFrames"]);
}
auto jSteamTranslation = jCar["steamPosition"];
if (jSteamTranslation.is_object())
{
car.SteamEffect.Longitudinal = Json::GetNumber<int8_t>(jSteamTranslation["longitudinal"], DefaultSteamSpawnPosition[0]);
car.SteamEffect.Vertical = Json::GetNumber<int8_t>(jSteamTranslation["vertical"], DefaultSteamSpawnPosition[1]);
}
else
{
car.SteamEffect.Longitudinal = DefaultSteamSpawnPosition[0];
car.SteamEffect.Vertical = DefaultSteamSpawnPosition[1];
}
auto jLoadingPositions = jCar["loadingPositions"];
if (jLoadingPositions.is_array())
{