Reduce the use of rct_sprite (#12530)

* Reduce the use of rct_sprite

* Pass the correct types in S4 importer

* Add additional nullptr checks

* Simplify the viewport interaction

* Apply review comments

* Small cleanup of GetEntity

* Fix test paint
This commit is contained in:
Duncan 2020-08-01 11:29:54 +01:00 committed by GitHub
parent 2c350fa416
commit 6d11825e1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 224 additions and 195 deletions

View File

@ -53,10 +53,6 @@ static Peep* viewport_interaction_get_closest_peep(ScreenCoordsXY screenCoords,
*/
int32_t viewport_interaction_get_item_left(const ScreenCoordsXY& screenCoords, viewport_interaction_info* info)
{
TileElement* tileElement;
rct_sprite* sprite;
Vehicle* vehicle;
// No click input for scenario editor or track manager
if (gScreenFlags & (SCREEN_FLAGS_SCENARIO_EDITOR | SCREEN_FLAGS_TRACK_MANAGER))
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
@ -71,13 +67,13 @@ int32_t viewport_interaction_get_item_left(const ScreenCoordsXY& screenCoords, v
mapCoord, &info->type, &info->tileElement, nullptr);
info->x = mapCoord.x;
info->y = mapCoord.y;
tileElement = info->tileElement;
sprite = info->sprite;
auto tileElement = info->tileElement;
auto sprite = info->sprite;
// Allows only balloons to be popped and ducks to be quacked in title screen
if (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO)
{
if (info->type == VIEWPORT_INTERACTION_ITEM_SPRITE && (sprite->generic.Is<Balloon>() || sprite->generic.Is<Duck>()))
if (info->type == VIEWPORT_INTERACTION_ITEM_SPRITE && (sprite->Is<Balloon>() || sprite->Is<Duck>()))
return info->type;
else
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
@ -86,18 +82,30 @@ int32_t viewport_interaction_get_item_left(const ScreenCoordsXY& screenCoords, v
switch (info->type)
{
case VIEWPORT_INTERACTION_ITEM_SPRITE:
switch (sprite->generic.sprite_identifier)
switch (sprite->sprite_identifier)
{
case SPRITE_IDENTIFIER_VEHICLE:
vehicle = &(sprite->vehicle);
if (vehicle->ride_subtype != RIDE_ENTRY_INDEX_NULL)
{
auto vehicle = sprite->As<Vehicle>();
if (vehicle != nullptr && vehicle->ride_subtype != RIDE_ENTRY_INDEX_NULL)
vehicle->SetMapToolbar();
else
info->type = VIEWPORT_INTERACTION_ITEM_NONE;
break;
}
break;
case SPRITE_IDENTIFIER_PEEP:
peep_set_map_tooltip(&sprite->peep);
break;
{
auto peep = sprite->As<Peep>();
if (peep != nullptr)
{
peep_set_map_tooltip(peep);
}
else
{
info->type = VIEWPORT_INTERACTION_ITEM_NONE;
}
}
break;
}
break;
case VIEWPORT_INTERACTION_ITEM_RIDE:
@ -121,14 +129,15 @@ int32_t viewport_interaction_get_item_left(const ScreenCoordsXY& screenCoords, v
// If nothing is under cursor, find a close by peep
if (info->type == VIEWPORT_INTERACTION_ITEM_NONE)
{
info->peep = viewport_interaction_get_closest_peep(screenCoords, 32);
if (info->peep == nullptr)
auto peep = viewport_interaction_get_closest_peep(screenCoords, 32);
if (peep == nullptr)
return VIEWPORT_INTERACTION_ITEM_NONE;
info->sprite = peep;
info->type = VIEWPORT_INTERACTION_ITEM_SPRITE;
info->x = info->peep->x;
info->y = info->peep->y;
peep_set_map_tooltip(info->peep);
info->x = peep->x;
info->y = peep->y;
peep_set_map_tooltip(peep);
}
return info->type;
@ -156,36 +165,42 @@ int32_t viewport_interaction_left_click(const ScreenCoordsXY& screenCoords)
switch (viewport_interaction_get_item_left(screenCoords, &info))
{
case VIEWPORT_INTERACTION_ITEM_SPRITE:
switch (info.sprite->generic.sprite_identifier)
switch (info.sprite->sprite_identifier)
{
case SPRITE_IDENTIFIER_VEHICLE:
{
auto intent = Intent(WD_VEHICLE);
intent.putExtra(INTENT_EXTRA_VEHICLE, info.vehicle);
intent.putExtra(INTENT_EXTRA_VEHICLE, info.sprite);
context_open_intent(&intent);
break;
}
case SPRITE_IDENTIFIER_PEEP:
{
auto intent = Intent(WC_PEEP);
intent.putExtra(INTENT_EXTRA_PEEP, info.peep);
intent.putExtra(INTENT_EXTRA_PEEP, info.sprite);
context_open_intent(&intent);
break;
}
case SPRITE_IDENTIFIER_MISC:
if (game_is_not_paused())
{
switch (info.sprite->generic.type)
switch (info.sprite->type)
{
case SPRITE_MISC_BALLOON:
{
auto balloonPress = BalloonPressAction(info.sprite->generic.sprite_index);
auto balloonPress = BalloonPressAction(info.sprite->sprite_index);
GameActions::Execute(&balloonPress);
}
break;
case SPRITE_MISC_DUCK:
duck_press(&info.sprite->duck);
break;
{
auto duck = info.sprite->As<Duck>();
if (duck != nullptr)
{
duck_press(duck);
}
}
break;
}
}
break;
@ -232,15 +247,21 @@ int32_t viewport_interaction_get_item_right(const ScreenCoordsXY& screenCoords,
info->x = mapCoord.x;
info->y = mapCoord.y;
tileElement = info->tileElement;
rct_sprite* sprite = info->sprite;
auto sprite = info->sprite;
switch (info->type)
{
case VIEWPORT_INTERACTION_ITEM_SPRITE:
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || sprite->generic.sprite_identifier != SPRITE_IDENTIFIER_VEHICLE)
{
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) || sprite->sprite_identifier != SPRITE_IDENTIFIER_VEHICLE)
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
ride = get_ride(sprite->vehicle.ride);
auto vehicle = sprite->As<Vehicle>();
if (vehicle == nullptr)
{
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
}
ride = get_ride(vehicle->ride);
if (ride != nullptr && ride->status == RIDE_STATUS_CLOSED)
{
auto ft = Formatter::MapTooltip();
@ -248,7 +269,7 @@ int32_t viewport_interaction_get_item_right(const ScreenCoordsXY& screenCoords,
ride->FormatNameTo(ft);
}
return info->type;
}
case VIEWPORT_INTERACTION_ITEM_RIDE:
{
if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR)
@ -465,9 +486,14 @@ int32_t viewport_interaction_right_click(const ScreenCoordsXY& screenCoords)
return 0;
case VIEWPORT_INTERACTION_ITEM_SPRITE:
if (info.sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_VEHICLE)
if (info.sprite->sprite_identifier == SPRITE_IDENTIFIER_VEHICLE)
{
auto ride = get_ride(info.sprite->vehicle.ride);
auto vehicle = info.sprite->As<Vehicle>();
if (vehicle == nullptr)
{
break;
}
auto ride = get_ride(vehicle->ride);
if (ride != nullptr)
{
ride_construct(ride);

View File

@ -613,62 +613,55 @@ static void window_title_command_editor_tool_down(
if (info.type == VIEWPORT_INTERACTION_ITEM_SPRITE)
{
uint16_t spriteIndex = info.sprite->generic.sprite_index;
uint16_t spriteIdentifier = info.sprite->generic.sprite_identifier;
bool validSprite = false;
if (info.sprite->generic.Is<Peep>())
auto peep = info.sprite->As<Peep>();
auto vehicle = info.sprite->As<Vehicle>();
auto litter = info.sprite->As<Litter>();
auto duck = info.sprite->As<Duck>();
auto balloon = info.sprite->As<Balloon>();
if (peep != nullptr)
{
validSprite = true;
auto peep = GetEntity<Peep>(spriteIndex);
if (peep != nullptr)
uint8_t formatArgs[32]{};
Formatter ft(formatArgs);
peep->FormatNameTo(ft);
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_STRINGID, &peep->Id);
}
else if (vehicle != nullptr)
{
validSprite = true;
auto ride = vehicle->GetRide();
if (ride != nullptr)
{
uint8_t formatArgs[32]{};
Formatter ft(formatArgs);
peep->FormatNameTo(ft);
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_STRINGID, &peep->Id);
ride->FormatNameTo(ft);
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_STRINGID, formatArgs);
}
}
else if (spriteIdentifier == SPRITE_IDENTIFIER_VEHICLE)
else if (litter != nullptr)
{
validSprite = true;
auto vehicle = GetEntity<Vehicle>(spriteIndex);
if (vehicle != nullptr)
{
auto ride = vehicle->GetRide();
if (ride != nullptr)
{
uint8_t formatArgs[32]{};
Formatter ft(formatArgs);
ride->FormatNameTo(ft);
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_STRINGID, formatArgs);
}
}
}
else if (spriteIdentifier == SPRITE_IDENTIFIER_LITTER)
{
Litter* litter = GetEntity<Litter>(spriteIndex);
if (litter != nullptr && litter->type < std::size(litterNames))
if (litter->type < std::size(litterNames))
{
validSprite = true;
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, litterNames[litter->type], nullptr);
}
}
else if (spriteIdentifier == SPRITE_IDENTIFIER_MISC)
else if (balloon != nullptr)
{
if (info.sprite->generic.Is<Balloon>())
{
validSprite = true;
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_SHOP_ITEM_SINGULAR_BALLOON, nullptr);
}
else if (info.sprite->generic.Is<Duck>())
{
validSprite = true;
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_DUCK, nullptr);
}
validSprite = true;
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_SHOP_ITEM_SINGULAR_BALLOON, nullptr);
}
else if (duck != nullptr)
{
validSprite = true;
format_string(command.SpriteName, USER_STRING_MAX_LENGTH, STR_DUCK, nullptr);
}
if (validSprite)
{
command.SpriteIndex = spriteIndex;
command.SpriteIndex = info.sprite->sprite_index;
window_follow_sprite(w, static_cast<size_t>(command.SpriteIndex));
tool_cancel();
w->Invalidate();

View File

@ -21,10 +21,9 @@ struct paint_struct;
struct rct_drawpixelinfo;
struct Peep;
struct TileElement;
struct Vehicle;
struct rct_window;
union paint_entry;
union rct_sprite;
struct SpriteBase;
enum
{
@ -92,9 +91,7 @@ struct viewport_interaction_info
union
{
TileElement* tileElement;
rct_sprite* sprite;
Peep* peep;
Vehicle* vehicle;
SpriteBase* sprite;
};
};

View File

@ -29,16 +29,19 @@ const uint32_t vehicle_particle_base_sprites[] = {
/**
* rct2: 0x00672AC9
*/
void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDirection)
void misc_paint(paint_session* session, const SpriteBase* misc, int32_t imageDirection)
{
rct_drawpixelinfo* dpi = &session->DPI;
switch (misc->generic.type)
switch (misc->type)
{
case SPRITE_MISC_STEAM_PARTICLE: // 0
{
uint32_t imageId = 22637 + (misc->steam_particle.frame / 256);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, misc->generic.z);
auto particle = misc->As<SteamParticle>();
if (particle == nullptr)
return;
uint32_t imageId = 22637 + (particle->frame / 256);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, particle->z);
break;
}
@ -48,8 +51,9 @@ void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDir
{
return;
}
const MoneyEffect* moneyEffect = &misc->money_effect;
auto moneyEffect = misc->As<MoneyEffect>();
if (moneyEffect == nullptr)
return;
auto [stringId, value] = moneyEffect->GetStringId();
paint_floating_money_effect(
session, value, stringId, moneyEffect->y, moneyEffect->z,
@ -63,35 +67,44 @@ void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDir
{
return;
}
VehicleCrashParticle particle = misc->crashed_vehicle_particle;
uint32_t imageId = vehicle_particle_base_sprites[particle.crashed_sprite_base] + particle.frame / 256;
imageId = imageId | (particle.colour[0] << 19) | (particle.colour[1] << 24) | IMAGE_TYPE_REMAP
auto particle = misc->As<VehicleCrashParticle>();
if (particle == nullptr)
return;
uint32_t imageId = vehicle_particle_base_sprites[particle->crashed_sprite_base] + particle->frame / 256;
imageId = imageId | (particle->colour[0] << 19) | (particle->colour[1] << 24) | IMAGE_TYPE_REMAP
| IMAGE_TYPE_REMAP_2_PLUS;
sub_98196C(session, imageId, 0, 0, 1, 1, 0, misc->generic.z);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, particle->z);
break;
}
case SPRITE_MISC_EXPLOSION_CLOUD: // 3
{
uint32_t imageId = 22878 + (misc->generic.frame / 256);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, misc->generic.z);
auto particle = misc->As<ExplosionCloud>();
if (particle == nullptr)
return;
uint32_t imageId = 22878 + (particle->frame / 256);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, particle->z);
break;
}
case SPRITE_MISC_CRASH_SPLASH: // 4
{
CrashSplashParticle crashSplash = misc->crash_splash;
uint32_t imageId = 22927 + (crashSplash.frame / 256);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, crashSplash.z);
auto crashSplash = misc->As<CrashSplashParticle>();
if (crashSplash == nullptr)
return;
uint32_t imageId = 22927 + (crashSplash->frame / 256);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, crashSplash->z);
break;
}
case SPRITE_MISC_EXPLOSION_FLARE: // 5
{
// Like a flare
uint32_t imageId = 22896 + (misc->generic.frame / 256);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, misc->generic.z);
auto flare = misc->As<ExplosionFlare>();
if (flare == nullptr)
return;
uint32_t imageId = 22896 + (flare->frame / 256);
sub_98196C(session, imageId, 0, 0, 1, 1, 0, flare->z);
break;
}
@ -103,15 +116,16 @@ void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDir
return;
}
JumpingFountain jumpingFountain = misc->jumping_fountain;
uint16_t height = jumpingFountain.z + 6;
auto jumpingFountain = misc->As<JumpingFountain>();
if (jumpingFountain == nullptr)
return;
uint16_t height = jumpingFountain->z + 6;
int32_t ebx = imageDirection / 8;
// Fountain is firing anti clockwise
bool reversed = (jumpingFountain.FountainFlags & FOUNTAIN_FLAG::DIRECTION);
bool reversed = (jumpingFountain->FountainFlags & FOUNTAIN_FLAG::DIRECTION);
// Fountain rotation
bool rotated = (jumpingFountain.sprite_direction / 16) & 1;
bool rotated = (jumpingFountain->sprite_direction / 16) & 1;
bool isAntiClockwise = (ebx / 2) & 1; // Clockwise or Anti-clockwise
// These cancel each other out
@ -120,8 +134,8 @@ void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDir
isAntiClockwise = !isAntiClockwise;
}
uint32_t baseImageId = (jumpingFountain.type == SPRITE_MISC_JUMPING_FOUNTAIN_SNOW) ? 23037 : 22973;
uint32_t imageId = baseImageId + ebx * 16 + jumpingFountain.frame;
uint32_t baseImageId = (jumpingFountain->type == SPRITE_MISC_JUMPING_FOUNTAIN_SNOW) ? 23037 : 22973;
uint32_t imageId = baseImageId + ebx * 16 + jumpingFountain->frame;
constexpr std::array<CoordsXY, 2> antiClockWiseBoundingBoxes = { CoordsXY{ -COORDS_XY_STEP, -3 },
CoordsXY{ 0, -3 } };
constexpr std::array<CoordsXY, 2> clockWiseBoundingBoxes = { CoordsXY{ -COORDS_XY_STEP, 3 }, CoordsXY{ 0, 3 } };
@ -134,24 +148,27 @@ void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDir
case SPRITE_MISC_BALLOON: // 7
{
Balloon balloon = misc->balloon;
uint32_t imageId = 22651 + (balloon.frame & 7);
if (balloon.popped != 0)
auto balloon = misc->As<Balloon>();
if (balloon == nullptr)
return;
uint32_t imageId = 22651 + (balloon->frame & 7);
if (balloon->popped != 0)
{
imageId += 8;
}
imageId = imageId | (balloon.colour << 19) | IMAGE_TYPE_REMAP;
sub_98196C(session, imageId, 0, 0, 1, 1, 0, balloon.z);
imageId = imageId | (balloon->colour << 19) | IMAGE_TYPE_REMAP;
sub_98196C(session, imageId, 0, 0, 1, 1, 0, balloon->z);
break;
}
case SPRITE_MISC_DUCK:
if (dpi->zoom_level <= 1)
{
const Duck* duck = &misc->duck;
uint32_t imageId = duck_get_frame_image(&misc->duck, imageDirection);
const Duck* duck = misc->As<Duck>();
if (duck == nullptr)
return;
uint32_t imageId = duck->GetFrameImage(imageDirection);
if (imageId != 0)
{
sub_98196C(session, imageId, 0, 0, 1, 1, 0, duck->z);

View File

@ -115,7 +115,7 @@ void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t
break;
case SPRITE_IDENTIFIER_MISC:
// TODO: Update misc_paint to take a specific sprite type
misc_paint(session, reinterpret_cast<const rct_sprite*>(spr), image_direction);
misc_paint(session, spr, image_direction);
break;
case SPRITE_IDENTIFIER_LITTER:
litter_paint(session, spr->As<Litter>(), image_direction);

View File

@ -17,7 +17,7 @@ struct paint_session;
void sprite_paint_setup(paint_session* session, const uint16_t x, const uint16_t y);
void misc_paint(paint_session* session, const rct_sprite* misc, int32_t imageDirection);
void misc_paint(paint_session* session, const SpriteBase* misc, int32_t imageDirection);
void litter_paint(paint_session* session, const Litter* litter, int32_t imageDirection);
void peep_paint(paint_session* session, const Peep* peep, int32_t imageDirection);

View File

@ -1672,10 +1672,10 @@ private:
switch (src->type)
{
case SPRITE_MISC_STEAM_PARTICLE:
ImportSteamParticle(reinterpret_cast<SteamParticle*>(dst), reinterpret_cast<SteamParticle*>(src));
ImportSteamParticle(dst->As<SteamParticle>(), reinterpret_cast<RCT12SpriteSteamParticle*>(src));
break;
case SPRITE_MISC_MONEY_EFFECT:
ImportMoneyEffect(reinterpret_cast<MoneyEffect*>(dst), reinterpret_cast<MoneyEffect*>(src));
ImportMoneyEffect(dst->As<MoneyEffect>(), reinterpret_cast<RCT12SpriteMoneyEffect*>(src));
break;
case SPRITE_MISC_CRASHED_VEHICLE_PARTICLE:
break;
@ -1687,13 +1687,13 @@ private:
break;
case SPRITE_MISC_JUMPING_FOUNTAIN_WATER:
ImportJumpingFountainWater(
reinterpret_cast<JumpingFountain*>(dst), reinterpret_cast<JumpingFountain*>(src));
dst->As<JumpingFountain>(), reinterpret_cast<RCT12SpriteJumpingFountain*>(src));
break;
case SPRITE_MISC_BALLOON:
ImportBalloon(reinterpret_cast<Balloon*>(dst), reinterpret_cast<Balloon*>(src));
ImportBalloon(dst->As<Balloon>(), reinterpret_cast<RCT12SpriteBalloon*>(src));
break;
case SPRITE_MISC_DUCK:
ImportDuck(reinterpret_cast<Duck*>(dst), reinterpret_cast<Duck*>(src));
ImportDuck(dst->As<Duck>(), reinterpret_cast<RCT12SpriteDuck*>(src));
break;
}
@ -1703,30 +1703,38 @@ private:
}
}
void ImportMoneyEffect(MoneyEffect* dst, MoneyEffect* src)
void ImportMoneyEffect(MoneyEffect* dst, RCT12SpriteMoneyEffect* src)
{
dst->MoveDelay = src->MoveDelay;
dst->NumMovements = src->NumMovements;
dst->Value = src->Value;
dst->OffsetX = src->OffsetX;
dst->Wiggle = src->Wiggle;
if (dst == nullptr)
return;
dst->MoveDelay = src->move_delay;
dst->NumMovements = src->num_movements;
dst->Value = src->value;
dst->OffsetX = src->offset_x;
dst->Wiggle = src->wiggle;
}
void ImportSteamParticle(SteamParticle* dst, SteamParticle* src)
void ImportSteamParticle(SteamParticle* dst, RCT12SpriteSteamParticle* src)
{
if (dst == nullptr)
return;
dst->frame = src->frame;
}
void ImportJumpingFountainWater(JumpingFountain* dst, JumpingFountain* src)
void ImportJumpingFountainWater(JumpingFountain* dst, RCT12SpriteJumpingFountain* src)
{
dst->FountainFlags = src->FountainFlags;
dst->Iteration = src->Iteration;
dst->NumTicksAlive = src->NumTicksAlive;
if (dst == nullptr)
return;
dst->FountainFlags = src->fountain_flags;
dst->Iteration = src->iteration;
dst->NumTicksAlive = src->num_ticks_alive;
dst->frame = src->frame;
}
void ImportBalloon(Balloon* dst, Balloon* src)
void ImportBalloon(Balloon* dst, RCT12SpriteBalloon* src)
{
if (dst == nullptr)
return;
// Balloons were always blue in RCT1 without AA/LL
if (_gameVersion == FILE_VERSION_RCT1)
{
@ -1738,8 +1746,10 @@ private:
}
}
void ImportDuck(Duck* dst, Duck* src)
void ImportDuck(Duck* dst, RCT12SpriteDuck* src)
{
if (dst == nullptr)
return;
dst->frame = src->frame;
dst->state = src->state;
}

View File

@ -46,11 +46,11 @@ static void paint_crooked_house_structure(
if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)
{
if (ride->vehicles[0] != SPRITE_INDEX_NULL)
auto vehicle = GetEntity<Vehicle>(ride->vehicles[0]);
if (vehicle != nullptr)
{
auto sprite = GetEntity(ride->vehicles[0]);
session->InteractionType = VIEWPORT_INTERACTION_ITEM_SPRITE;
session->CurrentlyDrawnItem = sprite;
session->CurrentlyDrawnItem = vehicle;
}
}

View File

@ -92,7 +92,7 @@ namespace OpenRCT2::Scripting
auto sprite = GetEntity(spriteId);
if (sprite != nullptr && sprite->sprite_identifier != SPRITE_IDENTIFIER_NULL)
{
return GetEntityAsDukValue(reinterpret_cast<rct_sprite*>(sprite));
return GetEntityAsDukValue(sprite);
}
}
duk_push_null(_context);
@ -138,7 +138,7 @@ namespace OpenRCT2::Scripting
{
if (targetList == EntityListId::Peep)
{
if (sprite->As<Staff>())
if (sprite->Is<Staff>())
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScStaff>(sprite->sprite_index)));
else
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScGuest>(sprite->sprite_index)));
@ -174,18 +174,20 @@ namespace OpenRCT2::Scripting
}
private:
DukValue GetEntityAsDukValue(const rct_sprite* sprite) const
DukValue GetEntityAsDukValue(const SpriteBase* sprite) const
{
auto spriteId = sprite->generic.sprite_index;
switch (sprite->generic.sprite_identifier)
auto spriteId = sprite->sprite_index;
switch (sprite->sprite_identifier)
{
case SPRITE_IDENTIFIER_VEHICLE:
return GetObjectAsDukValue(_context, std::make_shared<ScVehicle>(spriteId));
case SPRITE_IDENTIFIER_PEEP:
if (sprite->peep.AssignedPeepType == PeepType::Staff)
{
if (sprite->Is<Staff>())
return GetObjectAsDukValue(_context, std::make_shared<ScStaff>(spriteId));
else
return GetObjectAsDukValue(_context, std::make_shared<ScGuest>(spriteId));
}
default:
return GetObjectAsDukValue(_context, std::make_shared<ScEntity>(spriteId));
}

View File

@ -82,19 +82,22 @@ void Balloon::Pop()
void create_balloon(const CoordsXYZ& balloonPos, int32_t colour, bool isPopped)
{
rct_sprite* sprite = create_sprite(SPRITE_IDENTIFIER_MISC);
if (sprite != nullptr)
{
sprite->balloon.sprite_width = 13;
sprite->balloon.sprite_height_negative = 22;
sprite->balloon.sprite_height_positive = 11;
sprite->balloon.sprite_identifier = SPRITE_IDENTIFIER_MISC;
sprite->balloon.MoveTo(balloonPos);
sprite->balloon.type = SPRITE_MISC_BALLOON;
sprite->balloon.time_to_move = 0;
sprite->balloon.frame = 0;
sprite->balloon.colour = colour;
sprite->balloon.popped = (isPopped ? 1 : 0);
}
if (sprite == nullptr)
return;
sprite->generic.sprite_identifier = SPRITE_IDENTIFIER_MISC;
sprite->generic.type = SPRITE_MISC_BALLOON;
auto balloon = sprite->generic.As<Balloon>();
if (balloon == nullptr)
return; // can never happen
balloon->sprite_width = 13;
balloon->sprite_height_negative = 22;
balloon->sprite_height_positive = 11;
balloon->MoveTo(balloonPos);
balloon->time_to_move = 0;
balloon->frame = 0;
balloon->colour = colour;
balloon->popped = (isPopped ? 1 : 0);
}
void balloon_update(Balloon* balloon)

View File

@ -305,13 +305,16 @@ void create_duck(const CoordsXY& pos)
targetPos.x += offsetXY;
targetPos.y += offsetXY;
sprite->duck.sprite_identifier = SPRITE_IDENTIFIER_MISC;
sprite->duck.type = SPRITE_MISC_DUCK;
sprite->duck.sprite_width = 9;
sprite->duck.sprite_height_negative = 12;
sprite->duck.sprite_height_positive = 9;
sprite->duck.target_x = targetPos.x;
sprite->duck.target_y = targetPos.y;
sprite->generic.sprite_identifier = SPRITE_IDENTIFIER_MISC;
sprite->generic.type = SPRITE_MISC_DUCK;
auto duck = sprite->generic.As<Duck>();
if (duck == nullptr)
return; // can never happen
duck->sprite_width = 9;
duck->sprite_height_negative = 12;
duck->sprite_height_positive = 9;
duck->target_x = targetPos.x;
duck->target_y = targetPos.y;
uint8_t direction = scenario_rand() & 3;
switch (direction)
{
@ -328,10 +331,10 @@ void create_duck(const CoordsXY& pos)
targetPos.y = 8191 - (scenario_rand() & 0x3F);
break;
}
sprite->duck.sprite_direction = direction << 3;
sprite->duck.MoveTo({ targetPos.x, targetPos.y, 496 });
sprite->duck.state = DUCK_STATE::FLY_TO_WATER;
sprite->duck.frame = 0;
duck->sprite_direction = direction << 3;
duck->MoveTo({ targetPos.x, targetPos.y, 496 });
duck->state = DUCK_STATE::FLY_TO_WATER;
duck->frame = 0;
}
void Duck::Update()
@ -368,8 +371,3 @@ void duck_remove_all()
duck->Remove();
}
}
uint32_t duck_get_frame_image(const Duck* duck, int32_t direction)
{
return duck->GetFrameImage(direction);
}

View File

@ -98,28 +98,19 @@ std::string rct_sprite_checksum::ToString() const
return result;
}
rct_sprite* try_get_sprite(size_t spriteIndex)
SpriteBase* try_get_sprite(size_t spriteIndex)
{
rct_sprite* sprite = nullptr;
if (spriteIndex < MAX_SPRITES)
{
sprite = &_spriteList[spriteIndex];
}
return sprite;
return spriteIndex >= MAX_SPRITES ? nullptr : &_spriteList[spriteIndex].generic;
}
rct_sprite* get_sprite(size_t sprite_idx)
SpriteBase* get_sprite(size_t spriteIndex)
{
if (sprite_idx == SPRITE_INDEX_NULL)
if (spriteIndex == SPRITE_INDEX_NULL)
{
return nullptr;
}
openrct2_assert(sprite_idx < MAX_SPRITES, "Tried getting sprite %u", sprite_idx);
if (sprite_idx >= MAX_SPRITES)
{
return nullptr;
}
return &_spriteList[sprite_idx];
openrct2_assert(spriteIndex < MAX_SPRITES, "Tried getting sprite %u", spriteIndex);
return try_get_sprite(spriteIndex);
}
uint16_t sprite_get_first_in_quadrant(const CoordsXY& spritePos)
@ -782,14 +773,7 @@ void sprite_remove(SpriteBase* sprite)
sprite->sprite_identifier = SPRITE_IDENTIFIER_NULL;
_spriteFlashingList[sprite->sprite_index] = false;
size_t quadrantIndex = GetSpatialIndexOffset(sprite->x, sprite->y);
uint16_t* spriteIndex = &gSpriteSpatialIndex[quadrantIndex];
SpriteBase* quadrantSprite;
while (*spriteIndex != SPRITE_INDEX_NULL && (quadrantSprite = GetEntity(*spriteIndex)) != sprite)
{
spriteIndex = &quadrantSprite->next_in_quadrant;
}
*spriteIndex = sprite->next_in_quadrant;
SpriteSpatialRemove(sprite);
}
static bool litter_can_be_at(const CoordsXYZ& mapPos)

View File

@ -201,17 +201,17 @@ enum
LITTER_TYPE_EMPTY_BOWL_BLUE,
};
rct_sprite* try_get_sprite(size_t spriteIndex);
rct_sprite* get_sprite(size_t sprite_idx);
SpriteBase* try_get_sprite(size_t spriteIndex);
SpriteBase* get_sprite(size_t sprite_idx);
template<typename T = SpriteBase> T* GetEntity(size_t sprite_idx)
{
auto spr = reinterpret_cast<SpriteBase*>(get_sprite(sprite_idx));
auto spr = get_sprite(sprite_idx);
return spr != nullptr ? spr->As<T>() : nullptr;
}
template<typename T = SpriteBase> T* TryGetEntity(size_t sprite_idx)
{
auto spr = reinterpret_cast<SpriteBase*>(try_get_sprite(sprite_idx));
auto spr = try_get_sprite(sprite_idx);
return spr != nullptr ? spr->As<T>() : nullptr;
}
@ -258,7 +258,6 @@ void create_duck(const CoordsXY& pos);
void duck_update(Duck* duck);
void duck_press(Duck* duck);
void duck_remove_all();
uint32_t duck_get_frame_image(const Duck* duck, int32_t direction);
///////////////////////////////////////////////////////////////
// Crash particles

View File

@ -167,10 +167,10 @@ template<> bool SpriteBase::Is<Vehicle>() const
return sprite_identifier == SPRITE_IDENTIFIER_VEHICLE;
}
rct_sprite* get_sprite(size_t sprite_idx)
SpriteBase* get_sprite(size_t sprite_idx)
{
assert(sprite_idx < MAX_SPRITES);
return &sprite_list[sprite_idx];
return reinterpret_cast<SpriteBase*>(&sprite_list[sprite_idx]);
}
bool TileElementBase::IsLastForTile() const