mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
Refactor duck to C++
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
85B468FC1D96822F000F1DB5 /* paint_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = 85B468FB1D96822F000F1DB5 /* paint_helpers.c */; };
|
||||
85B468FD1D96822F000F1DB5 /* paint_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = 85B468FB1D96822F000F1DB5 /* paint_helpers.c */; };
|
||||
8DED2F20E0D63A1DCFCE0197 /* banner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEEAE6E8AC49B6F288E69B40 /* banner.cpp */; };
|
||||
B94C3C5FC4DBBB864434DE83 /* Duck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5D1DB5BE280897DCDEBFCED /* Duck.cpp */; };
|
||||
C606CCBE1DB4054000FE4015 /* compat.c in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAB1DB4054000FE4015 /* compat.c */; };
|
||||
C606CCBF1DB4054000FE4015 /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAC1DB4054000FE4015 /* data.c */; };
|
||||
C606CCC01DB4054000FE4015 /* FunctionCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */; };
|
||||
@@ -485,6 +486,7 @@
|
||||
D4F5B5EF1DAD8A4300AB6075 /* CursorData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4F5B5EC1DAD8A4300AB6075 /* CursorData.cpp */; };
|
||||
D4F5B5F01DAD8A4300AB6075 /* Cursors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4F5B5ED1DAD8A4300AB6075 /* Cursors.cpp */; };
|
||||
F2CC500E17C9411FBA859888 /* Climate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 242F470FE91956ACA4078F6A /* Climate.cpp */; };
|
||||
F408D5E134FE5B423BE5443F /* Duck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5D1DB5BE280897DCDEBFCED /* Duck.cpp */; };
|
||||
F61331C839858250899F1E9B /* Balloon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 437490DBD74ECF60C3363559 /* Balloon.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -549,6 +551,7 @@
|
||||
791166FA1D7486EF005912EA /* NetworkServerAdvertiser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkServerAdvertiser.h; sourceTree = "<group>"; };
|
||||
8594C05F1D885CF600235E93 /* track_data_old.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_data_old.c; sourceTree = "<group>"; };
|
||||
85B468FB1D96822F000F1DB5 /* paint_helpers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = paint_helpers.c; sourceTree = "<group>"; };
|
||||
A5D1DB5BE280897DCDEBFCED /* Duck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Duck.cpp; sourceTree = "<group>"; };
|
||||
C606CCAB1DB4054000FE4015 /* compat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = compat.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
|
||||
C606CCAC1DB4054000FE4015 /* data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = data.c; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
|
||||
C606CCAD1DB4054000FE4015 /* data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = data.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
@@ -1000,7 +1003,6 @@
|
||||
D44271DA1CC81B3200D84D28 /* banner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = banner.c; sourceTree = "<group>"; };
|
||||
D44271D91CC81B3200D84D28 /* balloon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = balloon.c; sourceTree = "<group>"; };
|
||||
D44271DB1CC81B3200D84D28 /* banner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = banner.h; sourceTree = "<group>"; };
|
||||
D44271DE1CC81B3200D84D28 /* duck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = duck.c; sourceTree = "<group>"; };
|
||||
D44271DF1CC81B3200D84D28 /* entrance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = entrance.h; sourceTree = "<group>"; };
|
||||
D44271E01CC81B3200D84D28 /* footpath.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = footpath.c; sourceTree = "<group>"; };
|
||||
D44271E11CC81B3200D84D28 /* footpath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = footpath.h; sourceTree = "<group>"; };
|
||||
@@ -2046,6 +2048,7 @@
|
||||
D44271D81CC81B3200D84D28 /* world */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A5D1DB5BE280897DCDEBFCED /* Duck.cpp */,
|
||||
EC3C3FED9FA55B65F65D706F /* Climate.h */,
|
||||
242F470FE91956ACA4078F6A /* Climate.cpp */,
|
||||
437490DBD74ECF60C3363559 /* Balloon.cpp */,
|
||||
@@ -2702,6 +2705,7 @@
|
||||
6876808CD662C4B16392A9B4 /* Balloon.cpp in Sources */,
|
||||
7D02D519C9A56A1FB9854FE7 /* Climate.cpp in Sources */,
|
||||
689149B0417A68D6765F09CD /* banner.cpp in Sources */,
|
||||
F408D5E134FE5B423BE5443F /* Duck.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2727,7 +2731,6 @@
|
||||
791166FB1D7486EF005912EA /* NetworkServerAdvertiser.cpp in Sources */,
|
||||
D44272441CC81B3200D84D28 /* cable_lift.c in Sources */,
|
||||
C647C6911E1D0CA000C7FB21 /* AudioMixer.cpp in Sources */,
|
||||
D442729C1CC81B3200D84D28 /* duck.c in Sources */,
|
||||
C65A88921E1B1148000368D7 /* AudioChannel.cpp in Sources */,
|
||||
C686F91D1CDBC3B7009F9BFC /* multi_dimension_roller_coaster.c in Sources */,
|
||||
C686F8B31CDBC37E009F9BFC /* surface.c in Sources */,
|
||||
@@ -3061,6 +3064,7 @@
|
||||
F61331C839858250899F1E9B /* Balloon.cpp in Sources */,
|
||||
F2CC500E17C9411FBA859888 /* Climate.cpp in Sources */,
|
||||
8DED2F20E0D63A1DCFCE0197 /* banner.cpp in Sources */,
|
||||
B94C3C5FC4DBBB864434DE83 /* Duck.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -337,8 +337,8 @@
|
||||
<ClCompile Include="windows\maze_construction.c" />
|
||||
<ClCompile Include="world\Balloon.cpp" />
|
||||
<ClCompile Include="world\banner.cpp" />
|
||||
<ClCompile Include="world\duck.c" />
|
||||
<ClCompile Include="world\entrance.cpp" />
|
||||
<ClCompile Include="world\Duck.cpp" />
|
||||
<ClCompile Include="world\money_effect.c" />
|
||||
<ClCompile Include="world\particle.c" />
|
||||
<ClCompile Include="util\sawyercoding.c" />
|
||||
|
||||
@@ -32,7 +32,7 @@ const uint32 vehicle_particle_base_sprites[] = {
|
||||
22577, 22589, 22601, 22613, 22625
|
||||
};
|
||||
|
||||
extern const uint8 * duck_animations[];
|
||||
extern const uint8 * DuckAnimations[];
|
||||
|
||||
/**
|
||||
* rct2: 0x00672AC9
|
||||
@@ -189,7 +189,7 @@ void misc_paint(rct_sprite *misc, sint32 imageDirection)
|
||||
|
||||
rct_duck duck = misc->duck;
|
||||
|
||||
uint8 imageOffset = duck_animations[duck.state][duck.frame];
|
||||
uint8 imageOffset = DuckAnimations[duck.state][duck.frame];
|
||||
uint32 imageId = 23133 + (imageOffset * 4) + (imageDirection / 8);
|
||||
sub_98196C(imageId, 0, 0, 1, 1, 0, duck.z, get_current_rotation());
|
||||
break;
|
||||
|
||||
@@ -7017,7 +7017,7 @@ static void sub_6DB807(rct_vehicle *vehicle)
|
||||
sprite_move(x, y, z, (rct_sprite*)vehicle);
|
||||
}
|
||||
|
||||
extern const rct_xy16 duck_move_offset[4];
|
||||
extern const rct_xy16 DuckMoveOffset[4];
|
||||
|
||||
/**
|
||||
* Collision Detection
|
||||
@@ -7123,8 +7123,8 @@ static bool vehicle_update_motion_collision_detection(
|
||||
|
||||
uint32 offsetSpriteDirection = (vehicle->sprite_direction + 4) & 31;
|
||||
uint32 offsetDirection = offsetSpriteDirection >> 3;
|
||||
uint32 next_x_diff = abs(x + duck_move_offset[offsetDirection].x - collideVehicle->x);
|
||||
uint32 next_y_diff = abs(y + duck_move_offset[offsetDirection].y - collideVehicle->y);
|
||||
uint32 next_x_diff = abs(x + DuckMoveOffset[offsetDirection].x - collideVehicle->x);
|
||||
uint32 next_y_diff = abs(y + DuckMoveOffset[offsetDirection].y - collideVehicle->y);
|
||||
|
||||
if (next_x_diff + next_y_diff < x_diff + y_diff){
|
||||
mayCollide = true;
|
||||
|
||||
362
src/openrct2/world/Duck.cpp
Normal file
362
src/openrct2/world/Duck.cpp
Normal file
@@ -0,0 +1,362 @@
|
||||
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#include "../core/Util.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "../audio/audio.h"
|
||||
#include "../game.h"
|
||||
#include "../localisation/date.h"
|
||||
#include "../scenario/scenario.h"
|
||||
#include "sprite.h"
|
||||
}
|
||||
|
||||
enum DUCK_STATE
|
||||
{
|
||||
FLY_TO_WATER,
|
||||
SWIM,
|
||||
DRINK,
|
||||
DOUBLE_DRINK,
|
||||
FLY_AWAY
|
||||
};
|
||||
|
||||
static void duck_update_fly_to_water(rct_duck * duck);
|
||||
static void duck_update_swim(rct_duck * duck);
|
||||
static void duck_update_drink(rct_duck * duck);
|
||||
static void duck_update_double_drink(rct_duck * duck);
|
||||
static void duck_update_fly_away(rct_duck * duck);
|
||||
|
||||
static const rct_xy16 DuckMoveOffset[4] =
|
||||
{
|
||||
{ -1, 0 },
|
||||
{ 0, 1 },
|
||||
{ 1, 0 },
|
||||
{ 0, -1 },
|
||||
};
|
||||
|
||||
static const uint8 DuckAnimationFlyToWater[] =
|
||||
{
|
||||
8, 9, 10, 11, 12, 13
|
||||
};
|
||||
|
||||
static const uint8 DuckAnimationSwim[] =
|
||||
{
|
||||
0
|
||||
};
|
||||
|
||||
static const uint8 DuckAnimationDrink[] =
|
||||
{
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0xFF
|
||||
};
|
||||
|
||||
static const uint8 DuckAnimationDoubleDrink[] =
|
||||
{
|
||||
4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
|
||||
6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 0, 0, 0, 0, 0xFF
|
||||
};
|
||||
|
||||
static const uint8 DuckAnimationFlyAway[] =
|
||||
{
|
||||
8, 9, 10, 11, 12, 13
|
||||
};
|
||||
|
||||
static const uint8 * DuckAnimations[] =
|
||||
{
|
||||
DuckAnimationFlyToWater, // FLY_TO_WATER
|
||||
DuckAnimationSwim, // SWIM
|
||||
DuckAnimationDrink, // DRINK
|
||||
DuckAnimationDoubleDrink, // DOUBLE_DRINK
|
||||
DuckAnimationFlyAway, // FLY_AWAY
|
||||
};
|
||||
|
||||
static void duck_invalidate(rct_duck *duck)
|
||||
{
|
||||
invalidate_sprite_0((rct_sprite *)duck);
|
||||
}
|
||||
|
||||
static void duck_update_fly_to_water(rct_duck *duck)
|
||||
{
|
||||
if ((gCurrentTicks & 3) != 0) return;
|
||||
|
||||
duck->frame++;
|
||||
if (duck->frame >= Util::CountOf(DuckAnimationFlyToWater))
|
||||
{
|
||||
duck->frame = 0;
|
||||
}
|
||||
|
||||
duck_invalidate(duck);
|
||||
sint32 manhattanDistance = abs(duck->target_x - duck->x) + abs(duck->target_y - duck->y);
|
||||
sint32 direction = duck->sprite_direction >> 3;
|
||||
sint32 x = duck->x + DuckMoveOffset[direction].x;
|
||||
sint32 y = duck->y + DuckMoveOffset[direction].y;
|
||||
sint32 manhattanDistanceN = abs(duck->target_x - x) + abs(duck->target_y - y);
|
||||
|
||||
rct_map_element * mapElement = map_get_surface_element_at(duck->target_x >> 5, duck->target_y >> 5);
|
||||
sint32 waterHeight = mapElement->properties.surface.terrain & 0x1F;
|
||||
if (waterHeight == 0)
|
||||
{
|
||||
duck->state = DUCK_STATE::FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
waterHeight <<= 4;
|
||||
sint32 z = abs(duck->z - waterHeight);
|
||||
|
||||
if (manhattanDistanceN <= manhattanDistance)
|
||||
{
|
||||
if (z > manhattanDistanceN)
|
||||
{
|
||||
z = duck->z - 2;
|
||||
if (waterHeight >= duck->z)
|
||||
{
|
||||
z += 4;
|
||||
}
|
||||
duck->frame = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
z = duck->z;
|
||||
}
|
||||
sprite_move(x, y, z, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (z > 4)
|
||||
{
|
||||
duck->state = DUCK_STATE::FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
duck->state = DUCK_STATE::SWIM;
|
||||
duck->frame = 0;
|
||||
duck_update_swim(duck);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00674282
|
||||
*/
|
||||
static void duck_update_swim(rct_duck *duck)
|
||||
{
|
||||
if ((gCurrentTicks + duck->sprite_index) & 3)
|
||||
return;
|
||||
|
||||
uint32 randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) < 0x666)
|
||||
{
|
||||
if (randomNumber & 0x80000000)
|
||||
{
|
||||
duck->state = DUCK_STATE::DOUBLE_DRINK;
|
||||
duck->frame = -1;
|
||||
duck_update_double_drink(duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
duck->state = DUCK_STATE::DRINK;
|
||||
duck->frame = -1;
|
||||
duck_update_drink(duck);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sint32 currentMonth = date_get_month(gDateMonthsElapsed);
|
||||
if (currentMonth >= MONTH_SEPTEMBER && (randomNumber >> 16) < 218)
|
||||
{
|
||||
duck->state = DUCK_STATE::FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
duck_invalidate(duck);
|
||||
sint32 landZ = map_element_height(duck->x, duck->y);
|
||||
sint32 waterZ = (landZ >> 16) & 0xFFFF;
|
||||
landZ &= 0xFFFF;
|
||||
|
||||
if (duck->z < landZ || waterZ == 0)
|
||||
{
|
||||
duck->state = DUCK_STATE::FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
duck->z = waterZ;
|
||||
randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) <= 0xAAA)
|
||||
{
|
||||
randomNumber >>= 16;
|
||||
duck->sprite_direction = randomNumber & 0x18;
|
||||
}
|
||||
|
||||
sint32 direction = duck->sprite_direction >> 3;
|
||||
sint32 x = duck->x + DuckMoveOffset[direction].x;
|
||||
sint32 y = duck->y + DuckMoveOffset[direction].y;
|
||||
landZ = map_element_height(x, y);
|
||||
waterZ = (landZ >> 16) & 0xFFFF;
|
||||
landZ &= 0xFFFF;
|
||||
|
||||
if (duck->z >= landZ && duck->z == waterZ)
|
||||
{
|
||||
sprite_move(x, y, waterZ, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void duck_update_drink(rct_duck * duck)
|
||||
{
|
||||
duck->frame++;
|
||||
if (DuckAnimationDrink[duck->frame] == 0xFF)
|
||||
{
|
||||
duck->state = DUCK_STATE::SWIM;
|
||||
duck->frame = 0;
|
||||
duck_update_swim(duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
static void duck_update_double_drink(rct_duck * duck)
|
||||
{
|
||||
duck->frame++;
|
||||
if (DuckAnimationDoubleDrink[duck->frame] == 0xFF)
|
||||
{
|
||||
duck->state = DUCK_STATE::SWIM;
|
||||
duck->frame = 0;
|
||||
duck_update_swim(duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
static void duck_update_fly_away(rct_duck * duck)
|
||||
{
|
||||
if ((gCurrentTicks & 3) == 0)
|
||||
{
|
||||
duck->frame++;
|
||||
if (duck->frame >= Util::CountOf(DuckAnimationFlyAway))
|
||||
{
|
||||
duck->frame = 0;
|
||||
}
|
||||
|
||||
duck_invalidate(duck);
|
||||
sint32 direction = duck->sprite_direction >> 3;
|
||||
sint32 x = duck->x + (DuckMoveOffset[direction].x * 2);
|
||||
sint32 y = duck->y + (DuckMoveOffset[direction].y * 2);
|
||||
if (map_is_location_valid(x, y))
|
||||
{
|
||||
sprite_remove((rct_sprite *)duck);
|
||||
}
|
||||
else
|
||||
{
|
||||
sint32 z = min(duck->z + 2, 496);
|
||||
sprite_move(x, y, z, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void create_duck(sint32 targetX, sint32 targetY)
|
||||
{
|
||||
rct_sprite * sprite = create_sprite(2);
|
||||
if (sprite != nullptr)
|
||||
{
|
||||
sprite->duck.sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite->duck.misc_identifier = SPRITE_MISC_DUCK;
|
||||
sprite->duck.var_14 = 9;
|
||||
sprite->duck.var_09 = 0xC;
|
||||
sprite->duck.var_15 = 9;
|
||||
sint32 offset_xy = scenario_rand() & 0x1E;
|
||||
targetX += offset_xy;
|
||||
targetY += offset_xy;
|
||||
sprite->duck.target_x = targetX;
|
||||
sprite->duck.target_y = targetY;
|
||||
uint8 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;
|
||||
}
|
||||
}
|
||||
|
||||
void duck_update(rct_duck * duck)
|
||||
{
|
||||
switch ((DUCK_STATE)duck->state) {
|
||||
case DUCK_STATE::FLY_TO_WATER:
|
||||
duck_update_fly_to_water(duck);
|
||||
break;
|
||||
case DUCK_STATE::SWIM:
|
||||
duck_update_swim(duck);
|
||||
break;
|
||||
case DUCK_STATE::DRINK:
|
||||
duck_update_drink(duck);
|
||||
break;
|
||||
case DUCK_STATE::DOUBLE_DRINK:
|
||||
duck_update_double_drink(duck);
|
||||
break;
|
||||
case DUCK_STATE::FLY_AWAY:
|
||||
duck_update_fly_away(duck);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void duck_press(rct_duck * duck)
|
||||
{
|
||||
audio_play_sound_at_location(SOUND_QUACK, duck->x, duck->y, duck->z);
|
||||
}
|
||||
|
||||
void duck_remove_all()
|
||||
{
|
||||
uint16 nextSpriteIndex;
|
||||
for (uint16 spriteIndex = gSpriteListHead[SPRITE_LIST_MISC]; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex)
|
||||
{
|
||||
rct_unk_sprite * sprite = &(get_sprite(spriteIndex)->unknown);
|
||||
nextSpriteIndex = sprite->next;
|
||||
if (sprite->misc_identifier == SPRITE_MISC_DUCK)
|
||||
{
|
||||
sprite_remove((rct_sprite *)sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#include "../audio/audio.h"
|
||||
#include "../game.h"
|
||||
#include "../localisation/date.h"
|
||||
#include "../scenario/scenario.h"
|
||||
#include "sprite.h"
|
||||
|
||||
enum {
|
||||
DUCK_STATE_FLY_TO_WATER,
|
||||
DUCK_STATE_SWIM,
|
||||
DUCK_STATE_DRINK,
|
||||
DUCK_STATE_DOUBLE_DRINK,
|
||||
DUCK_STATE_FLY_AWAY
|
||||
};
|
||||
|
||||
static void duck_update_fly_to_water(rct_duck *duck);
|
||||
static void duck_update_swim(rct_duck *duck);
|
||||
static void duck_update_drink(rct_duck *duck);
|
||||
static void duck_update_double_drink(rct_duck *duck);
|
||||
static void duck_update_fly_away(rct_duck *duck);
|
||||
|
||||
// rct2: 0x009A3B04
|
||||
const rct_xy16 duck_move_offset[4] = {
|
||||
{ -1, 0 },
|
||||
{ 0, 1 },
|
||||
{ 1, 0 },
|
||||
{ 0, -1 }
|
||||
};
|
||||
|
||||
/** rct2: 0x0097F06C */
|
||||
static const uint8 duck_fly_to_water_animation[] = {
|
||||
8, 9, 10, 11, 12, 13
|
||||
};
|
||||
|
||||
/** rct2: 0x0097F072 */
|
||||
static const uint8 duck_swim_animation[] = {
|
||||
0
|
||||
};
|
||||
|
||||
// rct2: 0x0097F073
|
||||
static const uint8 duck_drink_animation[] = {
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0xFF
|
||||
};
|
||||
|
||||
// rct2: 0x0097F08C
|
||||
static const uint8 duck_double_drink_animation[] = {
|
||||
4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
|
||||
6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 0, 0, 0, 0, 0xFF
|
||||
};
|
||||
|
||||
/** rct2: 0x0097F0B4 */
|
||||
static const uint8 duck_fly_away_animation[] = {
|
||||
8, 9, 10, 11, 12, 13
|
||||
};
|
||||
|
||||
/** rct2: 0x0097F058 */
|
||||
const uint8 * duck_animations[] = {
|
||||
duck_fly_to_water_animation, // DUCK_STATE_FLY_TO_WATER
|
||||
duck_swim_animation, // DUCK_STATE_SWIM
|
||||
duck_drink_animation, // DUCK_STATE_DRINK
|
||||
duck_double_drink_animation, // DUCK_STATE_DOUBLE_DRINK
|
||||
duck_fly_away_animation, // DUCK_STATE_FLY_AWAY
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0067440F
|
||||
*/
|
||||
void create_duck(sint32 targetX, sint32 targetY)
|
||||
{
|
||||
rct_sprite* sprite = create_sprite(2);
|
||||
if (sprite != NULL) {
|
||||
sprite->duck.sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite->duck.misc_identifier = SPRITE_MISC_DUCK;
|
||||
sprite->duck.var_14 = 9;
|
||||
sprite->duck.var_09 = 0xC;
|
||||
sprite->duck.var_15 = 9;
|
||||
sint32 offset_xy = scenario_rand() & 0x1E;
|
||||
targetX += offset_xy;
|
||||
targetY += offset_xy;
|
||||
sprite->duck.target_x = targetX;
|
||||
sprite->duck.target_y = targetY;
|
||||
uint8 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006740E8
|
||||
*/
|
||||
void duck_update(rct_duck *duck)
|
||||
{
|
||||
switch (duck->state) {
|
||||
case DUCK_STATE_FLY_TO_WATER:
|
||||
duck_update_fly_to_water(duck);
|
||||
break;
|
||||
case DUCK_STATE_SWIM:
|
||||
duck_update_swim(duck);
|
||||
break;
|
||||
case DUCK_STATE_DRINK:
|
||||
duck_update_drink(duck);
|
||||
break;
|
||||
case DUCK_STATE_DOUBLE_DRINK:
|
||||
duck_update_double_drink(duck);
|
||||
break;
|
||||
case DUCK_STATE_FLY_AWAY:
|
||||
duck_update_fly_away(duck);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void duck_invalidate(rct_duck *duck)
|
||||
{
|
||||
invalidate_sprite_0((rct_sprite*)duck);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00674108
|
||||
*/
|
||||
static void duck_update_fly_to_water(rct_duck *duck)
|
||||
{
|
||||
if (gCurrentTicks & 3)
|
||||
return;
|
||||
|
||||
duck->frame++;
|
||||
if (duck->frame >= countof(duck_fly_to_water_animation))
|
||||
duck->frame = 0;
|
||||
|
||||
duck_invalidate(duck);
|
||||
sint32 manhattanDistance = abs(duck->target_x - duck->x) + abs(duck->target_y - duck->y);
|
||||
sint32 direction = duck->sprite_direction >> 3;
|
||||
sint32 x = duck->x + duck_move_offset[direction].x;
|
||||
sint32 y = duck->y + duck_move_offset[direction].y;
|
||||
sint32 manhattanDistanceN = abs(duck->target_x - x) + abs(duck->target_y - y);
|
||||
|
||||
rct_map_element *mapElement = map_get_surface_element_at(duck->target_x >> 5, duck->target_y >> 5);
|
||||
sint32 waterHeight = mapElement->properties.surface.terrain & 0x1F;
|
||||
if (waterHeight == 0) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
waterHeight <<= 4;
|
||||
sint32 z = abs(duck->z - waterHeight);
|
||||
|
||||
if (manhattanDistanceN <= manhattanDistance) {
|
||||
if (z > manhattanDistanceN) {
|
||||
z = duck->z - 2;
|
||||
if (waterHeight >= duck->z)
|
||||
z += 4;
|
||||
|
||||
duck->frame = 1;
|
||||
} else {
|
||||
z = duck->z;
|
||||
}
|
||||
sprite_move(x, y, z, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
} else {
|
||||
if (z > 4) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
} else {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->frame = 0;
|
||||
duck_update_swim(duck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00674282
|
||||
*/
|
||||
static void duck_update_swim(rct_duck *duck)
|
||||
{
|
||||
if ((gCurrentTicks + duck->sprite_index) & 3)
|
||||
return;
|
||||
|
||||
uint32 randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) < 0x666) {
|
||||
if (randomNumber & 0x80000000) {
|
||||
duck->state = DUCK_STATE_DOUBLE_DRINK;
|
||||
duck->frame = -1;
|
||||
duck_update_double_drink(duck);
|
||||
} else {
|
||||
duck->state = DUCK_STATE_DRINK;
|
||||
duck->frame = -1;
|
||||
duck_update_drink(duck);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sint32 currentMonth = date_get_month(gDateMonthsElapsed);
|
||||
if (currentMonth >= MONTH_SEPTEMBER && (randomNumber >> 16) < 218) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
|
||||
duck_invalidate(duck);
|
||||
sint32 landZ = map_element_height(duck->x, duck->y);
|
||||
sint32 waterZ = (landZ >> 16) & 0xFFFF;
|
||||
landZ &= 0xFFFF;
|
||||
|
||||
if (duck->z < landZ || waterZ == 0) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
|
||||
duck->z = waterZ;
|
||||
randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) <= 0xAAA) {
|
||||
randomNumber >>= 16;
|
||||
duck->sprite_direction = randomNumber & 0x18;
|
||||
}
|
||||
|
||||
sint32 direction = duck->sprite_direction >> 3;
|
||||
sint32 x = duck->x + duck_move_offset[direction].x;
|
||||
sint32 y = duck->y + duck_move_offset[direction].y;
|
||||
landZ = map_element_height(x, y);
|
||||
waterZ = (landZ >> 16) & 0xFFFF;
|
||||
landZ &= 0xFFFF;
|
||||
|
||||
if (duck->z < landZ || duck->z != waterZ)
|
||||
return;
|
||||
|
||||
sprite_move(x, y, waterZ, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00674357
|
||||
*/
|
||||
static void duck_update_drink(rct_duck *duck)
|
||||
{
|
||||
duck->frame++;
|
||||
if (duck_drink_animation[duck->frame] == 0xFF) {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->frame = 0;
|
||||
duck_update_swim(duck);
|
||||
} else {
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00674372
|
||||
*/
|
||||
static void duck_update_double_drink(rct_duck *duck)
|
||||
{
|
||||
duck->frame++;
|
||||
if (duck_double_drink_animation[duck->frame] == 0xFF) {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->frame = 0;
|
||||
duck_update_swim(duck);
|
||||
} else {
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0067438D
|
||||
*/
|
||||
static void duck_update_fly_away(rct_duck *duck)
|
||||
{
|
||||
if (gCurrentTicks & 3)
|
||||
return;
|
||||
|
||||
duck->frame++;
|
||||
if (duck->frame >= countof(duck_fly_away_animation))
|
||||
duck->frame = 0;
|
||||
|
||||
duck_invalidate(duck);
|
||||
sint32 direction = duck->sprite_direction >> 3;
|
||||
sint32 x = duck->x + (duck_move_offset[direction].x * 2);
|
||||
sint32 y = duck->y + (duck_move_offset[direction].y * 2);
|
||||
if (x < 0 || y < 0 || x >= (32 * 256) || y >= (32 * 256)) {
|
||||
sprite_remove((rct_sprite*)duck);
|
||||
return;
|
||||
}
|
||||
|
||||
sint32 z = min(duck->z + 2, 496);
|
||||
sprite_move(x, y, z, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E895D
|
||||
*/
|
||||
void duck_press(rct_duck *duck)
|
||||
{
|
||||
audio_play_sound_at_location(SOUND_QUACK, duck->x, duck->y, duck->z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00674576
|
||||
*/
|
||||
void duck_remove_all()
|
||||
{
|
||||
rct_unk_sprite* sprite;
|
||||
uint16 spriteIndex, nextSpriteIndex;
|
||||
|
||||
for (spriteIndex = gSpriteListHead[SPRITE_LIST_MISC]; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) {
|
||||
sprite = &(get_sprite(spriteIndex)->unknown);
|
||||
nextSpriteIndex = sprite->next;
|
||||
if (sprite->misc_identifier == SPRITE_MISC_DUCK)
|
||||
sprite_remove((rct_sprite*)sprite);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user