Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #8584: Duck spawn search now uses entire map #9743

Merged
merged 5 commits into from
Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions distribution/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Fix: [#7690] Problem with guests freezing on certain tiles of path.
- Fix: [#7883] Headless server log is stored incorrectly if server name contains CJK in Ubuntu
- Fix: [#8136] Excessive lateral G penalty is too excessive.
- Fix: [#8584] Duck spawning function does not check tiles with x or y coordinate of 0..64 (Original bug)
- Fix: [#9179] Crash when modifying a ride occasionally.
- Fix: [#9533] Door sounds not playing.
- Fix: [#9574] Text overflow in scenario objective window when using CJK languages.
Expand Down
2 changes: 1 addition & 1 deletion src/openrct2/network/Network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
// This string specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "16"
#define NETWORK_STREAM_VERSION "17"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION

static Peep* _pickup_peep = nullptr;
Expand Down
70 changes: 40 additions & 30 deletions src/openrct2/scenario/Scenario.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "../ParkImporter.h"
#include "../audio/audio.h"
#include "../config/Config.h"
#include "../core/Guard.hpp"
#include "../core/Random.hpp"
#include "../interface/Viewport.h"
#include "../localisation/Date.h"
Expand Down Expand Up @@ -415,60 +416,69 @@ void scenario_update()
}
scenario_update_daynight_cycle();
}

/**
*
* rct2: 0x006744A9
*/
static int32_t scenario_create_ducks()
{
int32_t i, j, r, c, x, y, waterZ, centreWaterZ, x2, y2;
CoordsXY centrePos;
centrePos.x = 64 + (scenario_rand_max(MAXIMUM_MAP_SIZE_PRACTICAL) * 32);
Gymnasiast marked this conversation as resolved.
Show resolved Hide resolved
centrePos.y = 64 + (scenario_rand_max(MAXIMUM_MAP_SIZE_PRACTICAL) * 32);

r = scenario_rand();
x = ((r >> 16) & 0xFFFF) & 0x7F;
y = (r & 0xFFFF) & 0x7F;
x = (x + 64) * 32;
y = (y + 64) * 32;
Guard::Assert(map_is_location_valid(centrePos));

if (!map_is_location_in_park({ x, y }))
if (!map_is_location_in_park(centrePos))
return 0;

centreWaterZ = (tile_element_water_height({ x, y }));
int32_t centreWaterZ = (tile_element_water_height(centrePos));
if (centreWaterZ == 0)
return 0;

// Check 7x7 area around centre tile
x2 = x - (32 * 3);
y2 = y - (32 * 3);
c = 0;
for (i = 0; i < 7; i++)
// Check NxN area around centre tile defined by SquareSize
constexpr int32_t SquareSize = 7;
constexpr int32_t SquareCentre = SquareSize / 2;

CoordsXY innerPos{ centrePos.x - (32 * SquareCentre), centrePos.y - (32 * SquareCentre) };
int32_t waterTiles = 0;
for (int32_t y = 0; y < SquareSize; y++)
{
for (j = 0; j < 7; j++)
for (int32_t x = 0; x < SquareSize; x++)
{
waterZ = (tile_element_water_height({ x2, y2 }));
if (!map_is_location_valid(innerPos))
continue;

if (!map_is_location_in_park(innerPos))
continue;

int32_t waterZ = (tile_element_water_height(innerPos));
if (waterZ == centreWaterZ)
c++;
waterTiles++;

x2 += 32;
innerPos.x += 32;
}
x2 -= 224;
y2 += 32;
innerPos.x -= SquareSize * 32;
innerPos.y += 32;
}

// Must be at least 25 water tiles of the same height in 7x7 area
if (c < 25)
if (waterTiles < 25)
return 0;

// Set x, y to the centre of the tile
x += 16;
y += 16;
c = (scenario_rand() & 3) + 2;
for (i = 0; i < c; i++)
{
r = scenario_rand();
x2 = (r >> 16) & 0x7F;
y2 = (r & 0xFFFF) & 0x7F;
create_duck(x + x2 - 64, y + y2 - 64);
centrePos.x += 16;
centrePos.y += 16;

int32_t duckCount = (scenario_rand() & 3) + 2;
for (int32_t i = 0; i < duckCount; i++)
{
int32_t r = scenario_rand();
innerPos.x = (r >> 16) & 0x7F;
innerPos.y = (r & 0xFFFF) & 0x7F;

CoordsXY targetPos{ centrePos.x + innerPos.x - 64, centrePos.y + innerPos.y - 64 };
Guard::Assert(map_is_location_valid(targetPos));
create_duck(targetPos);
}

return 1;
Expand Down
67 changes: 35 additions & 32 deletions src/openrct2/world/Duck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,42 +305,45 @@ uint32_t rct_duck::GetFrameImage(int32_t direction) const
return imageId;
}

void create_duck(int32_t targetX, int32_t targetY)
void create_duck(const CoordsXY& pos)
{
rct_sprite* sprite = create_sprite(SPRITE_IDENTIFIER_MISC);
if (sprite != nullptr)
if (sprite == nullptr)
return;

CoordsXY targetPos = pos;

int32_t offsetXY = scenario_rand() & 0x1E;
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;
uint8_t direction = scenario_rand() & 3;
switch (direction)
{
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;
int32_t offsetXY = scenario_rand() & 0x1E;
targetX += offsetXY;
targetY += offsetXY;
sprite->duck.target_x = targetX;
sprite->duck.target_y = targetY;
uint8_t direction = scenario_rand() & 3;
switch (direction)
{
case 0:
targetX = 8191 - (scenario_rand() & 0x3F);
break;
case 1:
targetY = scenario_rand() & 0x3F;
break;
case 2:
targetX = scenario_rand() & 0x3F;
break;
case 3:
targetY = 8191 - (scenario_rand() & 0x3F);
break;
}
sprite->duck.sprite_direction = direction << 3;
sprite_move(targetX, targetY, 496, sprite);
sprite->duck.state = DUCK_STATE::FLY_TO_WATER;
sprite->duck.frame = 0;
case 0:
targetPos.x = 8191 - (scenario_rand() & 0x3F);
break;
case 1:
targetPos.y = scenario_rand() & 0x3F;
break;
case 2:
targetPos.x = scenario_rand() & 0x3F;
break;
case 3:
targetPos.y = 8191 - (scenario_rand() & 0x3F);
break;
}
sprite->duck.sprite_direction = direction << 3;
sprite_move(targetPos.x, targetPos.y, 496, sprite);
sprite->duck.state = DUCK_STATE::FLY_TO_WATER;
sprite->duck.frame = 0;
}

void duck_update(rct_duck* duck)
Expand Down
2 changes: 1 addition & 1 deletion src/openrct2/world/Sprite.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ void balloon_update(rct_balloon* balloon);
///////////////////////////////////////////////////////////////
// Duck
///////////////////////////////////////////////////////////////
void create_duck(int32_t targetX, int32_t targetY);
void create_duck(const CoordsXY& pos);
void duck_update(rct_duck* duck);
void duck_press(rct_duck* duck);
void duck_remove_all();
Expand Down