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:
@@ -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 car’s 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())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user