mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-19 04:53:12 +01:00
Merge remote-tracking branch 'upstream/develop' into new-save-format
This commit is contained in:
@@ -50,9 +50,9 @@ set(OBJECTS_VERSION "1.2.1")
|
||||
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip")
|
||||
set(OBJECTS_SHA1 "540e004abc683b3fe22211f5234e3d78ab023c5f")
|
||||
|
||||
set(REPLAYS_VERSION "0.0.43")
|
||||
set(REPLAYS_VERSION "0.0.44")
|
||||
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip")
|
||||
set(REPLAYS_SHA1 "269E4FC432A73AE9A5D601EC2A1C882F3D9BDF3C")
|
||||
set(REPLAYS_SHA1 "586F3930DE8D2C3880AAFD30ABC4D81ABC0B64A4")
|
||||
|
||||
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
|
||||
option(WITH_TESTS "Build tests")
|
||||
|
||||
@@ -3689,6 +3689,20 @@ STR_6436 :Näkymättömyys päälle/pois
|
||||
STR_6437 :Näkymätön
|
||||
STR_6438 :N
|
||||
STR_6439 :Ruututyökalu: Näkymättömyys päälle/pois
|
||||
STR_6440 :Läpinäkyvä vesi
|
||||
STR_6441 :Ainakin yhden polunpinnan tulee olla valittu.
|
||||
STR_6442 :Ainakin yhden jonotusaluepinnan tulee olla valittu.
|
||||
STR_6443 :Ainakin yhden polunkaiteen tulee olla valittu.
|
||||
STR_6444 :Polun pinnat
|
||||
STR_6445 :Polun kaiteet
|
||||
STR_6446 :{WINDOW_COLOUR_2}Pinnan nimi: {BLACK}{STRINGID}
|
||||
STR_6447 :{WINDOW_COLOUR_2}Kaiteen nimi: {BLACK}{STRINGID}
|
||||
STR_6448 :Esineen muotoa ei tueta
|
||||
STR_6449 :{WINDOW_COLOUR_2}Raidat:
|
||||
STR_6450 :{BLACK}”{STRING}”
|
||||
STR_6451 :{BLACK}”{STRING}” - {STRING}
|
||||
STR_6452 :{WINDOW_COLOUR_2}Myy: {BLACK}{STRING}
|
||||
STR_6453 :Kopioi versiotiedot
|
||||
|
||||
#############
|
||||
# Scenarios #
|
||||
|
||||
@@ -2408,7 +2408,7 @@ STR_3308 :{WINDOW_COLOUR_2}흥미도:
|
||||
STR_3309 :{WINDOW_COLOUR_2}{COMMA16}
|
||||
STR_3310 :{WINDOW_COLOUR_2}{LENGTH}
|
||||
STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32}
|
||||
STR_3312 :{WINDOW_COLOUR_2}파괴할 수 없는 놀이기구/시설:
|
||||
STR_3312 :{WINDOW_COLOUR_2}수정·파괴할 수 없는 놀이기구/시설:
|
||||
STR_3313 :시나리오 이름
|
||||
STR_3314 :시나리오 이름을 입력하세요:
|
||||
STR_3315 :공원/시나리오 상세 설명
|
||||
|
||||
@@ -253,7 +253,10 @@ struct GameStateSnapshots final : public IGameStateSnapshots
|
||||
COMPARE_FIELD(Peep, InteractionRideIndex);
|
||||
COMPARE_FIELD(Peep, Id);
|
||||
COMPARE_FIELD(Peep, PathCheckOptimisation);
|
||||
COMPARE_FIELD(Peep, PathfindGoal);
|
||||
COMPARE_FIELD(Peep, PathfindGoal.x);
|
||||
COMPARE_FIELD(Peep, PathfindGoal.y);
|
||||
COMPARE_FIELD(Peep, PathfindGoal.z);
|
||||
COMPARE_FIELD(Peep, PathfindGoal.direction);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
COMPARE_FIELD(Peep, PathfindHistory[i].x);
|
||||
|
||||
@@ -59,7 +59,8 @@ GameActions::Result::Ptr PlaceParkEntranceAction::Query() const
|
||||
|
||||
if (!CheckMapCapacity(3))
|
||||
{
|
||||
return std::make_unique<GameActions::Result>(GameActions::Status::NoFreeElements, STR_CANT_BUILD_THIS_HERE, STR_NONE);
|
||||
return std::make_unique<GameActions::Result>(
|
||||
GameActions::Status::NoFreeElements, STR_CANT_BUILD_THIS_HERE, STR_ERR_LANDSCAPE_DATA_AREA_FULL);
|
||||
}
|
||||
|
||||
if (gParkEntrances.size() >= MAX_PARK_ENTRANCES)
|
||||
|
||||
@@ -870,3 +870,32 @@ template<> struct DataSerializerTraits_t<rct_peep_thought>
|
||||
stream->Write(msg, strlen(msg));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct DataSerializerTraits_t<TileCoordsXYZD>
|
||||
{
|
||||
static void encode(OpenRCT2::IStream* stream, const TileCoordsXYZD& coord)
|
||||
{
|
||||
stream->WriteValue(ByteSwapBE(coord.x));
|
||||
stream->WriteValue(ByteSwapBE(coord.y));
|
||||
stream->WriteValue(ByteSwapBE(coord.z));
|
||||
stream->WriteValue(ByteSwapBE(coord.direction));
|
||||
}
|
||||
|
||||
static void decode(OpenRCT2::IStream* stream, TileCoordsXYZD& coord)
|
||||
{
|
||||
auto x = ByteSwapBE(stream->ReadValue<int32_t>());
|
||||
auto y = ByteSwapBE(stream->ReadValue<int32_t>());
|
||||
auto z = ByteSwapBE(stream->ReadValue<int32_t>());
|
||||
auto d = ByteSwapBE(stream->ReadValue<Direction>());
|
||||
coord = TileCoordsXYZD{ x, y, z, d };
|
||||
}
|
||||
|
||||
static void log(OpenRCT2::IStream* stream, const TileCoordsXYZD& coord)
|
||||
{
|
||||
char msg[128] = {};
|
||||
snprintf(
|
||||
msg, sizeof(msg), "TileCoordsXYZD(x = %d, y = %d, z = %d, direction = %d)", coord.x, coord.y, coord.z,
|
||||
coord.direction);
|
||||
stream->Write(msg, strlen(msg));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -700,8 +700,7 @@ static void peep_pathfind_heuristic_search(
|
||||
/* If this is where the search started this is a search loop and the
|
||||
* current search path ends here.
|
||||
* Return without updating the parameters (best result so far). */
|
||||
if ((_peepPathFindHistory[0].location.x == static_cast<uint8_t>(loc.x))
|
||||
&& (_peepPathFindHistory[0].location.y == static_cast<uint8_t>(loc.y)) && (_peepPathFindHistory[0].location.z == loc.z))
|
||||
if (_peepPathFindHistory[0].location == loc)
|
||||
{
|
||||
#if defined(DEBUG_LEVEL_2) && DEBUG_LEVEL_2
|
||||
if (gPathFindDebug)
|
||||
@@ -1076,7 +1075,7 @@ static void peep_pathfind_heuristic_search(
|
||||
* already been visited by the peep while heading for this goal. */
|
||||
for (auto& pathfindHistory : peep->PathfindHistory)
|
||||
{
|
||||
if (pathfindHistory.x == loc.x && pathfindHistory.y == loc.y && pathfindHistory.z == loc.z)
|
||||
if (pathfindHistory == loc)
|
||||
{
|
||||
if (pathfindHistory.direction == 0)
|
||||
{
|
||||
@@ -1103,9 +1102,7 @@ static void peep_pathfind_heuristic_search(
|
||||
for (int32_t junctionNum = _peepPathFindNumJunctions + 1; junctionNum <= _peepPathFindMaxJunctions;
|
||||
junctionNum++)
|
||||
{
|
||||
if ((_peepPathFindHistory[junctionNum].location.x == static_cast<uint8_t>(loc.x))
|
||||
&& (_peepPathFindHistory[junctionNum].location.y == static_cast<uint8_t>(loc.y))
|
||||
&& (_peepPathFindHistory[junctionNum].location.z == loc.z))
|
||||
if (_peepPathFindHistory[junctionNum].location == loc)
|
||||
{
|
||||
pathLoop = true;
|
||||
break;
|
||||
@@ -1144,9 +1141,7 @@ static void peep_pathfind_heuristic_search(
|
||||
for (uint8_t junctInd = 0; junctInd < *endJunctions; junctInd++)
|
||||
{
|
||||
uint8_t histIdx = _peepPathFindMaxJunctions - junctInd;
|
||||
junctionList[junctInd].x = _peepPathFindHistory[histIdx].location.x;
|
||||
junctionList[junctInd].y = _peepPathFindHistory[histIdx].location.y;
|
||||
junctionList[junctInd].z = _peepPathFindHistory[histIdx].location.z;
|
||||
junctionList[junctInd] = _peepPathFindHistory[histIdx].location;
|
||||
directionList[junctInd] = _peepPathFindHistory[histIdx].direction;
|
||||
}
|
||||
}
|
||||
@@ -1163,9 +1158,7 @@ static void peep_pathfind_heuristic_search(
|
||||
|
||||
/* This junction was NOT previously visited in the current
|
||||
* search path, so add the junction to the history. */
|
||||
_peepPathFindHistory[_peepPathFindNumJunctions].location.x = static_cast<uint8_t>(loc.x);
|
||||
_peepPathFindHistory[_peepPathFindNumJunctions].location.y = static_cast<uint8_t>(loc.y);
|
||||
_peepPathFindHistory[_peepPathFindNumJunctions].location.z = loc.z;
|
||||
_peepPathFindHistory[_peepPathFindNumJunctions].location = loc;
|
||||
// .direction take is added below.
|
||||
|
||||
_peepPathFindNumJunctions--;
|
||||
@@ -1334,7 +1327,7 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
||||
|
||||
permitted_edges &= 0xF;
|
||||
uint8_t edges = permitted_edges;
|
||||
if (isThin && peep->PathfindGoal.x == goal.x && peep->PathfindGoal.y == goal.y && peep->PathfindGoal.z == goal.z)
|
||||
if (isThin && peep->PathfindGoal == goal)
|
||||
{
|
||||
/* Use of peep->PathfindHistory[]:
|
||||
* When walking to a goal, the peep PathfindHistory stores
|
||||
@@ -1353,7 +1346,7 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
||||
* directions it has not yet tried. */
|
||||
for (auto& pathfindHistory : peep->PathfindHistory)
|
||||
{
|
||||
if (pathfindHistory.x == loc.x && pathfindHistory.y == loc.y && pathfindHistory.z == loc.z)
|
||||
if (pathfindHistory == loc)
|
||||
{
|
||||
/* Fix broken PathfindHistory[i].direction
|
||||
* which have untried directions that are not
|
||||
@@ -1401,16 +1394,15 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
||||
|
||||
/* If this is a new goal for the peep. Store it and reset the peep's
|
||||
* PathfindHistory. */
|
||||
if (!direction_valid(peep->PathfindGoal.direction) || peep->PathfindGoal.x != goal.x || peep->PathfindGoal.y != goal.y
|
||||
|| peep->PathfindGoal.z != goal.z)
|
||||
if (!direction_valid(peep->PathfindGoal.direction) || peep->PathfindGoal != goal)
|
||||
{
|
||||
peep->PathfindGoal.x = goal.x;
|
||||
peep->PathfindGoal.y = goal.y;
|
||||
peep->PathfindGoal.z = goal.z;
|
||||
peep->PathfindGoal.direction = 0;
|
||||
peep->PathfindGoal = { goal, 0 };
|
||||
|
||||
// Clear pathfinding history
|
||||
std::fill(std::begin(peep->PathfindHistory), std::end(peep->PathfindHistory), rct12_xyzd8{ 0xFF, 0xFF, 0xFF, 0xFF });
|
||||
TileCoordsXYZD nullPos;
|
||||
nullPos.setNull();
|
||||
|
||||
std::fill(std::begin(peep->PathfindHistory), std::end(peep->PathfindHistory), nullPos);
|
||||
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
||||
if (_pathFindDebug)
|
||||
{
|
||||
@@ -1466,14 +1458,17 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
||||
_peepPathFindNumJunctions = _peepPathFindMaxJunctions;
|
||||
|
||||
// Initialise _peepPathFindHistory.
|
||||
std::memset(static_cast<void*>(_peepPathFindHistory), 0xFF, sizeof(_peepPathFindHistory));
|
||||
|
||||
for (auto& entry : _peepPathFindHistory)
|
||||
{
|
||||
entry.location.setNull();
|
||||
entry.direction = INVALID_DIRECTION;
|
||||
}
|
||||
|
||||
/* The pathfinding will only use elements
|
||||
* 1.._peepPathFindMaxJunctions, so the starting point
|
||||
* is placed in element 0 */
|
||||
_peepPathFindHistory[0].location.x = static_cast<uint8_t>(loc.x);
|
||||
_peepPathFindHistory[0].location.y = static_cast<uint8_t>(loc.y);
|
||||
_peepPathFindHistory[0].location.z = loc.z;
|
||||
_peepPathFindHistory[0].location = loc;
|
||||
_peepPathFindHistory[0].direction = 0xF;
|
||||
|
||||
uint16_t score = 0xFFFF;
|
||||
@@ -1586,8 +1581,7 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
||||
{
|
||||
for (int32_t i = 0; i < 4; ++i)
|
||||
{
|
||||
if (peep->PathfindHistory[i].x == loc.x && peep->PathfindHistory[i].y == loc.y
|
||||
&& peep->PathfindHistory[i].z == loc.z)
|
||||
if (peep->PathfindHistory[i] == loc)
|
||||
{
|
||||
/* Peep remembers this junction, so remove the
|
||||
* chosen_edge from those left to try. */
|
||||
@@ -1611,10 +1605,7 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep)
|
||||
* and remember this junction. */
|
||||
int32_t i = peep->PathfindGoal.direction++;
|
||||
peep->PathfindGoal.direction &= 3;
|
||||
peep->PathfindHistory[i].x = static_cast<uint8_t>(loc.x);
|
||||
peep->PathfindHistory[i].y = static_cast<uint8_t>(loc.y);
|
||||
peep->PathfindHistory[i].z = loc.z;
|
||||
peep->PathfindHistory[i].direction = permitted_edges;
|
||||
peep->PathfindHistory[i] = { loc, permitted_edges };
|
||||
/* Remove the chosen_edge from those left to try. */
|
||||
peep->PathfindHistory[i].direction &= ~(1 << chosen_edge);
|
||||
/* Also remove the edge through which the peep
|
||||
@@ -2312,9 +2303,7 @@ void Peep::ResetPathfindGoal()
|
||||
}
|
||||
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
|
||||
|
||||
PathfindGoal.x = 0xFF;
|
||||
PathfindGoal.y = 0xFF;
|
||||
PathfindGoal.z = 0xFF;
|
||||
PathfindGoal.setNull();
|
||||
PathfindGoal.direction = INVALID_DIRECTION;
|
||||
}
|
||||
|
||||
|
||||
@@ -616,8 +616,8 @@ struct Peep : SpriteBase
|
||||
ride_id_t InteractionRideIndex;
|
||||
uint32_t Id;
|
||||
uint8_t PathCheckOptimisation; // see peep.checkForPath
|
||||
rct12_xyzd8 PathfindGoal;
|
||||
std::array<rct12_xyzd8, 4> PathfindHistory;
|
||||
TileCoordsXYZD PathfindGoal;
|
||||
std::array<TileCoordsXYZD, 4> PathfindHistory;
|
||||
uint8_t WalkingFrameNum;
|
||||
uint32_t PeepFlags;
|
||||
|
||||
|
||||
@@ -1366,6 +1366,10 @@ public:
|
||||
|
||||
void ImportEntityPeep(Peep* dst, const RCT2SpritePeep* src)
|
||||
{
|
||||
const auto isNullLocation = [](const rct12_xyzd8& pos) {
|
||||
return pos.x == 0xFF && pos.y == 0xFF && pos.z == 0xFF && pos.direction == INVALID_DIRECTION;
|
||||
};
|
||||
|
||||
ImportEntityCommonProperties(static_cast<SpriteBase*>(dst), src);
|
||||
if (is_user_string_id(src->name_string_idx))
|
||||
{
|
||||
@@ -1402,10 +1406,28 @@ public:
|
||||
dst->Id = src->id;
|
||||
dst->PathCheckOptimisation = src->path_check_optimisation;
|
||||
dst->PeepFlags = src->peep_flags;
|
||||
dst->PathfindGoal = src->pathfind_goal;
|
||||
if (isNullLocation(src->pathfind_goal))
|
||||
{
|
||||
dst->PathfindGoal.setNull();
|
||||
dst->PathfindGoal.direction = INVALID_DIRECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst->PathfindGoal = { src->pathfind_goal.x, src->pathfind_goal.y, src->pathfind_goal.z,
|
||||
src->pathfind_goal.direction };
|
||||
}
|
||||
for (size_t i = 0; i < std::size(src->pathfind_history); i++)
|
||||
{
|
||||
dst->PathfindHistory[i] = src->pathfind_history[i];
|
||||
if (isNullLocation(src->pathfind_history[i]))
|
||||
{
|
||||
dst->PathfindHistory[i].setNull();
|
||||
dst->PathfindHistory[i].direction = INVALID_DIRECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst->PathfindHistory[i] = { src->pathfind_history[i].x, src->pathfind_history[i].y, src->pathfind_history[i].z,
|
||||
src->pathfind_history[i].direction };
|
||||
}
|
||||
}
|
||||
dst->WalkingFrameNum = src->no_action_frame_num;
|
||||
}
|
||||
|
||||
@@ -268,6 +268,12 @@ struct CoordsXYZ : public CoordsXY
|
||||
{
|
||||
return ToTileStart() + CoordsXYZ{ COORDS_XY_HALF_TILE, COORDS_XY_HALF_TILE, 0 };
|
||||
}
|
||||
|
||||
void setNull()
|
||||
{
|
||||
CoordsXY::setNull();
|
||||
z = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct CoordsXYRangedZ : public CoordsXY
|
||||
@@ -459,6 +465,12 @@ struct TileCoordsXYZ : public TileCoordsXY
|
||||
}
|
||||
return { x * COORDS_XY_STEP, y * COORDS_XY_STEP, z * COORDS_Z_STEP };
|
||||
}
|
||||
|
||||
void setNull()
|
||||
{
|
||||
TileCoordsXY::setNull();
|
||||
z = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -615,6 +627,12 @@ struct TileCoordsXYZD : public TileCoordsXYZ
|
||||
{
|
||||
}
|
||||
|
||||
TileCoordsXYZD(const TileCoordsXYZ& t_, Direction d_)
|
||||
: TileCoordsXYZ(t_)
|
||||
, direction(d_)
|
||||
{
|
||||
}
|
||||
|
||||
TileCoordsXYZD(const TileCoordsXY& t_, int32_t z_, Direction d_)
|
||||
: TileCoordsXYZ(t_, z_)
|
||||
, direction(d_)
|
||||
@@ -649,6 +667,12 @@ struct TileCoordsXYZD : public TileCoordsXYZ
|
||||
}
|
||||
return { x * COORDS_XY_STEP, y * COORDS_XY_STEP, z * COORDS_Z_STEP, direction };
|
||||
}
|
||||
|
||||
void setNull()
|
||||
{
|
||||
TileCoordsXYZ::setNull();
|
||||
direction = INVALID_DIRECTION;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user