diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index b764a2faf8..fbf1071cd9 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -939,6 +939,8 @@ declare global { interface MapChangeSizeArgs extends GameActionArgs { targetSizeX: number; targetSizeY: number; + shiftX: number; + shiftY: number; } interface MazePlaceTrackArgs extends GameActionArgs { diff --git a/src/openrct2/actions/MapChangeSizeAction.cpp b/src/openrct2/actions/MapChangeSizeAction.cpp index 04e28ac200..18f4d86c2c 100644 --- a/src/openrct2/actions/MapChangeSizeAction.cpp +++ b/src/openrct2/actions/MapChangeSizeAction.cpp @@ -18,7 +18,13 @@ #include "../world/Park.h" MapChangeSizeAction::MapChangeSizeAction(const TileCoordsXY& targetSize) + : MapChangeSizeAction(targetSize, TileCoordsXY()) +{ +} + +MapChangeSizeAction::MapChangeSizeAction(const TileCoordsXY& targetSize, const TileCoordsXY& shift) : _targetSize(targetSize) + , _shift(shift) { } @@ -31,6 +37,7 @@ void MapChangeSizeAction::Serialise(DataSerialiser& stream) { GameAction::Serialise(stream); stream << DS_TAG(_targetSize); + stream << DS_TAG(_shift); } GameActions::Result MapChangeSizeAction::Query() const @@ -63,6 +70,9 @@ GameActions::Result MapChangeSizeAction::Execute() const MapExtendBoundarySurfaceY(); } + // Shift the map (allows increasing the map at the 0,0 position + ShiftMap(_shift); + // Shrink map if (_targetSize.x < gameState.MapSize.x || _targetSize.y < gameState.MapSize.y) { @@ -84,4 +94,6 @@ void MapChangeSizeAction::AcceptParameters(GameActionParameterVisitor& visitor) { visitor.Visit("targetSizeX", _targetSize.x); visitor.Visit("targetSizeY", _targetSize.y); + visitor.Visit("shiftX", _shift.x); + visitor.Visit("shiftY", _shift.y); } diff --git a/src/openrct2/actions/MapChangeSizeAction.h b/src/openrct2/actions/MapChangeSizeAction.h index 81e8db3e64..e46bae208a 100644 --- a/src/openrct2/actions/MapChangeSizeAction.h +++ b/src/openrct2/actions/MapChangeSizeAction.h @@ -17,6 +17,7 @@ class MapChangeSizeAction final : public GameActionBase(); + for (int32_t y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++) + { + for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) + { + auto srcX = x - amount.x; + auto srcY = y - amount.y; + if (x >= 0 && y >= 0 && x < gMapSize.x && y < gMapSize.y && srcX >= 0 && srcY >= 0 && srcX < gMapSize.x + && srcY < gMapSize.y) + { + auto srcTile = _tileIndex.GetFirstElementAt(TileCoordsXY(srcX, srcY)); + do + { + newElements.push_back(*srcTile); + } while (!(srcTile++)->IsLastForTile()); + } + else if (x == 0 || y == 0 || x == gMapSize.x - 1 || y == gMapSize.y - 1) + { + auto surface = GetDefaultSurfaceElement(); + surface.SetBaseZ(MINIMUM_LAND_HEIGHT_BIG); + surface.SetClearanceZ(MINIMUM_LAND_HEIGHT_BIG); + surface.AsSurface()->SetSlope(0); + surface.AsSurface()->SetWaterHeight(0); + newElements.push_back(surface); + } + else + { + newElements.push_back(GetDefaultSurfaceElement()); + } + } + } + SetTileElements(std::move(newElements)); + MapRemoveOutOfRangeElements(); + + for (auto& spawn : gPeepSpawns) + spawn += amountToMove; + + for (auto& entrance : gParkEntrances) + entrance += amountToMove; + + // Entities + for (auto i = 0; i < EnumValue(EntityType::Count); i++) + { + auto entityType = static_cast(i); + auto& list = GetEntityList(entityType); + for (const auto& entityId : list) + { + auto entity = GetEntity(entityId); + auto location = entity->GetLocation(); + location += amountToMove; + entity->MoveTo(location); + + switch (entityType) + { + case EntityType::Guest: + case EntityType::Staff: + { + auto peep = entity->As(); + peep->NextLoc += amountToMove; + peep->DestinationX += amountToMove.x; + peep->DestinationY += amountToMove.y; + peep->PathfindGoal += amount; + for (auto& h : peep->PathfindHistory) + h += amount; + break; + } + case EntityType::Vehicle: + { + auto vehicle = entity->As(); + vehicle->TrackLocation += amountToMove; + vehicle->BoatLocation += amountToMove; + break; + } + case EntityType::Duck: + { + auto duck = entity->As(); + duck->target_x += amountToMove.x; + duck->target_y += amountToMove.y; + break; + } + } + if (entityType == EntityType::Staff) + { + auto staff = entity->As(); + auto patrol = staff->PatrolInfo; + if (patrol != nullptr) + { + auto positions = patrol->ToVector(); + for (auto& p : positions) + p += amount; + patrol->Clear(); + patrol->Union(positions); + } + } + } + } + + // Rides + for (auto& ride : GetRideManager()) + { + auto& stations = ride.GetStations(); + for (auto& station : stations) + { + station.Start += amountToMove; + station.Entrance += amount; + station.Exit += amount; + } + + ride.overall_view += amountToMove; + ride.boat_hire_return_position += amount; + ride.CurTestTrackLocation += amount; + ride.ChairliftBullwheelLocation[0] += amount; + ride.ChairliftBullwheelLocation[1] += amount; + ride.CableLiftLoc += amountToMove; + } + + // Banners + auto numBanners = GetNumBanners(); + auto id = BannerIndex::FromUnderlying(0); + size_t count = 0; + while (count < numBanners) + { + auto* banner = GetBanner(id); + if (banner != nullptr) + { + banner->position += amount; + count++; + } + } +} diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index ab9ac02c85..f1bc156f22 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -246,3 +246,4 @@ void FixLandOwnershipTiles(std::initializer_list tiles); void FixLandOwnershipTilesWithOwnership( std::initializer_list tiles, uint8_t ownership, bool doNotDowngrade = false); MapRange ClampRangeWithinMap(const MapRange& range); +void ShiftMap(const TileCoordsXY& amount);