mirror of
https://github.com/OpenRCT2/OpenRCT2.git
synced 2025-01-22 18:31:59 -05:00
Merge pull request #20263 from IntelOrca/shift-map
Add functionality to shift the entire map
This commit is contained in:
commit
06e2363b1e
8 changed files with 234 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
0.4.12 (in development)
|
||||
------------------------------------------------------------------------
|
||||
- Feature: [#622] Add option to align the top toolbar buttons horizontally centred (off by default).
|
||||
- Feature: [#20263] Ability to increase the size of the map in the (0, 0) direction.
|
||||
- Feature: [#21714] [Plugin] Costume assignment is now tailored to each staff type.
|
||||
- Feature: [#21853] Enlarged UI mode.
|
||||
- Feature: [#21893] On launch, the game now indicates what system is being initialised.
|
||||
|
|
2
distribution/openrct2.d.ts
vendored
2
distribution/openrct2.d.ts
vendored
|
@ -939,6 +939,8 @@ declare global {
|
|||
interface MapChangeSizeArgs extends GameActionArgs {
|
||||
targetSizeX: number;
|
||||
targetSizeY: number;
|
||||
shiftX: number;
|
||||
shiftY: number;
|
||||
}
|
||||
|
||||
interface MazePlaceTrackArgs extends GameActionArgs {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ class MapChangeSizeAction final : public GameActionBase<GameCommand::ChangeMapSi
|
|||
public:
|
||||
MapChangeSizeAction() = default;
|
||||
MapChangeSizeAction(const TileCoordsXY& targetSize);
|
||||
MapChangeSizeAction(const TileCoordsXY& targetSize, const TileCoordsXY& shift);
|
||||
|
||||
void AcceptParameters(GameActionParameterVisitor& visitor) override;
|
||||
uint16_t GetActionFlags() const override;
|
||||
|
@ -27,4 +28,5 @@ public:
|
|||
|
||||
private:
|
||||
TileCoordsXY _targetSize;
|
||||
TileCoordsXY _shift;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
#include "../actions/WallRemoveAction.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../core/Guard.hpp"
|
||||
#include "../entity/Duck.h"
|
||||
#include "../entity/EntityTweener.h"
|
||||
#include "../entity/Fountain.h"
|
||||
#include "../entity/PatrolArea.h"
|
||||
#include "../entity/Staff.h"
|
||||
#include "../interface/Cursors.h"
|
||||
#include "../interface/Viewport.h"
|
||||
#include "../interface/Window.h"
|
||||
|
@ -45,6 +50,7 @@
|
|||
#include "../world/tile_element/Slope.h"
|
||||
#include "Banner.h"
|
||||
#include "Climate.h"
|
||||
#include "Entrance.h"
|
||||
#include "Footpath.h"
|
||||
#include "MapAnimation.h"
|
||||
#include "Park.h"
|
||||
|
@ -2231,3 +2237,201 @@ MapRange ClampRangeWithinMap(const MapRange& range)
|
|||
MapRange validRange = MapRange{ aX, aY, bX, bY };
|
||||
return validRange;
|
||||
}
|
||||
|
||||
static inline void shiftIfNotNull(TileCoordsXY& coords, const TileCoordsXY& amount)
|
||||
{
|
||||
if (!coords.IsNull())
|
||||
coords += amount;
|
||||
}
|
||||
|
||||
static inline void shiftIfNotNull(CoordsXY& coords, const CoordsXY& amount)
|
||||
{
|
||||
if (!coords.IsNull())
|
||||
coords += amount;
|
||||
}
|
||||
|
||||
void ShiftMap(const TileCoordsXY& amount)
|
||||
{
|
||||
if (amount.x == 0 && amount.y == 0)
|
||||
return;
|
||||
|
||||
auto amountToMove = amount.ToCoordsXY();
|
||||
auto& gameState = GetGameState();
|
||||
|
||||
// Tile elements
|
||||
auto newElements = std::vector<TileElement>();
|
||||
for (int32_t y = 0; y < kMaximumMapSizeTechnical; y++)
|
||||
{
|
||||
for (int32_t x = 0; x < kMaximumMapSizeTechnical; x++)
|
||||
{
|
||||
auto srcX = x - amount.x;
|
||||
auto srcY = y - amount.y;
|
||||
if (x > 0 && y > 0 && x < gameState.MapSize.x - 1 && y < gameState.MapSize.y - 1 && srcX > 0 && srcY > 0
|
||||
&& srcX < gameState.MapSize.x - 1 && srcY < gameState.MapSize.y - 1)
|
||||
{
|
||||
auto srcTile = _tileIndex.GetFirstElementAt(TileCoordsXY(srcX, srcY));
|
||||
do
|
||||
{
|
||||
newElements.push_back(*srcTile);
|
||||
} while (!(srcTile++)->IsLastForTile());
|
||||
}
|
||||
else if (x == 0 || y == 0 || x == gameState.MapSize.x - 1 || y == gameState.MapSize.y - 1)
|
||||
{
|
||||
auto surface = GetDefaultSurfaceElement();
|
||||
surface.SetBaseZ(kMinimumLandZ);
|
||||
surface.SetClearanceZ(kMinimumLandZ);
|
||||
surface.AsSurface()->SetSlope(0);
|
||||
surface.AsSurface()->SetWaterHeight(0);
|
||||
newElements.push_back(surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto copyX = std::clamp(srcX, 1, gameState.MapSize.x - 2);
|
||||
auto copyY = std::clamp(srcY, 1, gameState.MapSize.y - 2);
|
||||
auto srcTile = MapGetSurfaceElementAt(TileCoordsXY(copyX, copyY));
|
||||
if (srcTile != nullptr)
|
||||
{
|
||||
auto tileEl = *srcTile;
|
||||
tileEl.SetOwner(OWNERSHIP_UNOWNED);
|
||||
tileEl.SetParkFences(0);
|
||||
tileEl.SetLastForTile(true);
|
||||
newElements.push_back(*reinterpret_cast<TileElement*>(&tileEl));
|
||||
}
|
||||
else
|
||||
{
|
||||
newElements.push_back(GetDefaultSurfaceElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetTileElements(std::move(newElements));
|
||||
MapRemoveOutOfRangeElements();
|
||||
|
||||
for (auto& spawn : gameState.PeepSpawns)
|
||||
shiftIfNotNull(spawn, amountToMove);
|
||||
|
||||
for (auto& entrance : gameState.Park.Entrances)
|
||||
shiftIfNotNull(entrance, amountToMove);
|
||||
|
||||
// Entities
|
||||
auto& entityTweener = EntityTweener::Get();
|
||||
for (auto i = 0; i < EnumValue(EntityType::Count); i++)
|
||||
{
|
||||
auto entityType = static_cast<EntityType>(i);
|
||||
auto& list = GetEntityList(entityType);
|
||||
for (const auto& entityId : list)
|
||||
{
|
||||
auto entity = GetEntity(entityId);
|
||||
|
||||
// Do not tween the entity
|
||||
entityTweener.RemoveEntity(entity);
|
||||
|
||||
auto location = entity->GetLocation();
|
||||
shiftIfNotNull(location, amountToMove);
|
||||
entity->MoveTo(location);
|
||||
|
||||
switch (entityType)
|
||||
{
|
||||
case EntityType::Guest:
|
||||
case EntityType::Staff:
|
||||
{
|
||||
auto peep = entity->As<Peep>();
|
||||
if (peep != nullptr)
|
||||
{
|
||||
shiftIfNotNull(peep->NextLoc, amountToMove);
|
||||
peep->DestinationX += amountToMove.x;
|
||||
peep->DestinationY += amountToMove.y;
|
||||
shiftIfNotNull(peep->PathfindGoal, amount);
|
||||
for (auto& h : peep->PathfindHistory)
|
||||
shiftIfNotNull(h, amount);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EntityType::Vehicle:
|
||||
{
|
||||
auto vehicle = entity->As<Vehicle>();
|
||||
if (vehicle != nullptr)
|
||||
{
|
||||
shiftIfNotNull(vehicle->TrackLocation, amountToMove);
|
||||
shiftIfNotNull(vehicle->BoatLocation, amountToMove);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EntityType::Duck:
|
||||
{
|
||||
auto duck = entity->As<Duck>();
|
||||
if (duck != nullptr)
|
||||
{
|
||||
duck->target_x += amountToMove.x;
|
||||
duck->target_y += amountToMove.y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EntityType::JumpingFountain:
|
||||
{
|
||||
auto fountain = entity->As<JumpingFountain>();
|
||||
if (fountain != nullptr)
|
||||
{
|
||||
fountain->TargetX += amountToMove.x;
|
||||
fountain->TargetY += amountToMove.y;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (entityType == EntityType::Staff)
|
||||
{
|
||||
auto staff = entity->As<Staff>();
|
||||
if (staff != nullptr)
|
||||
{
|
||||
auto patrol = staff->PatrolInfo;
|
||||
if (patrol != nullptr)
|
||||
{
|
||||
auto positions = patrol->ToVector();
|
||||
for (auto& p : positions)
|
||||
shiftIfNotNull(p, amount);
|
||||
patrol->Clear();
|
||||
patrol->Union(positions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateConsolidatedPatrolAreas();
|
||||
|
||||
// Rides
|
||||
for (auto& ride : GetRideManager())
|
||||
{
|
||||
auto& stations = ride.GetStations();
|
||||
for (auto& station : stations)
|
||||
{
|
||||
shiftIfNotNull(station.Start, amountToMove);
|
||||
shiftIfNotNull(station.Entrance, amount);
|
||||
shiftIfNotNull(station.Exit, amount);
|
||||
}
|
||||
|
||||
shiftIfNotNull(ride.overall_view, amountToMove);
|
||||
shiftIfNotNull(ride.boat_hire_return_position, amount);
|
||||
shiftIfNotNull(ride.CurTestTrackLocation, amount);
|
||||
shiftIfNotNull(ride.ChairliftBullwheelLocation[0], amount);
|
||||
shiftIfNotNull(ride.ChairliftBullwheelLocation[1], amount);
|
||||
shiftIfNotNull(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)
|
||||
{
|
||||
shiftIfNotNull(banner->position, amount);
|
||||
count++;
|
||||
}
|
||||
id = BannerIndex::FromUnderlying(id.ToUnderlying() + 1);
|
||||
}
|
||||
|
||||
ShiftAllMapAnimations(amountToMove);
|
||||
}
|
||||
|
|
|
@ -246,3 +246,4 @@ void FixLandOwnershipTiles(std::initializer_list<TileCoordsXY> tiles);
|
|||
void FixLandOwnershipTilesWithOwnership(
|
||||
std::initializer_list<TileCoordsXY> tiles, uint8_t ownership, bool doNotDowngrade = false);
|
||||
MapRange ClampRangeWithinMap(const MapRange& range);
|
||||
void ShiftMap(const TileCoordsXY& amount);
|
||||
|
|
|
@ -709,3 +709,14 @@ void MapAnimationAutoCreateAtTileElement(TileCoordsXY coords, TileElement* el)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ShiftAllMapAnimations(CoordsXY amount)
|
||||
{
|
||||
if (amount.x == 0 && amount.y == 0)
|
||||
return;
|
||||
|
||||
for (auto& a : _mapAnimations)
|
||||
{
|
||||
a.location += amount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,3 +46,4 @@ void MapAnimationInvalidateAll();
|
|||
const std::vector<MapAnimation>& GetMapAnimations();
|
||||
void MapAnimationAutoCreate();
|
||||
void MapAnimationAutoCreateAtTileElement(TileCoordsXY coords, TileElement* el);
|
||||
void ShiftAllMapAnimations(CoordsXY amount);
|
||||
|
|
Loading…
Reference in a new issue