mirror of https://github.com/OpenRCT2/OpenRCT2.git
refactor balloon, duck and money effect
This commit is contained in:
parent
1a877e637d
commit
3062bbf3b6
|
@ -107,6 +107,9 @@
|
|||
</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\windows\maze_construction.c" />
|
||||
<ClCompile Include="..\src\world\balloon.c" />
|
||||
<ClCompile Include="..\src\world\duck.c" />
|
||||
<ClCompile Include="..\src\world\money_effect.c" />
|
||||
<ClCompile Include="..\test\management\finance_test.c" />
|
||||
<ClCompile Include="..\test\ride\ride_ratings_test.c" />
|
||||
<ClCompile Include="..\test\tests.c" />
|
||||
|
|
|
@ -522,6 +522,15 @@
|
|||
<ClCompile Include="..\src\windows\server_list.c">
|
||||
<Filter>Source\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\world\duck.c">
|
||||
<Filter>Source\World</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\world\balloon.c">
|
||||
<Filter>Source\World</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\world\money_effect.c">
|
||||
<Filter>Source\World</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\src\management\award.h">
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
#include "../audio/audio.h"
|
||||
#include "../scenario.h"
|
||||
#include "sprite.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006736C7
|
||||
*/
|
||||
void create_balloon(int x, int y, int z, int colour, uint8 bl)
|
||||
{
|
||||
rct_sprite* sprite = create_sprite(2);
|
||||
if (sprite != NULL) {
|
||||
sprite->balloon.var_14 = 13;
|
||||
sprite->balloon.var_09 = 22;
|
||||
sprite->balloon.var_15 = 11;
|
||||
sprite->balloon.sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, sprite);
|
||||
sprite->balloon.misc_identifier = SPRITE_MISC_BALLOON;
|
||||
sprite->balloon.var_26 = 0;
|
||||
sprite->balloon.colour = colour;
|
||||
sprite->balloon.popped = bl;
|
||||
}
|
||||
}
|
||||
|
||||
void balloon_pop(rct_balloon *balloon)
|
||||
{
|
||||
balloon->popped = 1;
|
||||
balloon->var_26 = 0;
|
||||
sound_play_panned(SOUND_BALLOON_POP, 0x8001, balloon->x, balloon->y, balloon->z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0067342C
|
||||
*/
|
||||
void balloon_update(rct_balloon *balloon)
|
||||
{
|
||||
invalidate_sprite_2((rct_sprite*)balloon);
|
||||
if (balloon->popped == 1) {
|
||||
balloon->var_26 += 256;
|
||||
if (balloon->var_26 >= 1280)
|
||||
sprite_remove((rct_sprite*)balloon);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int original_var26a = balloon->var_26a;
|
||||
balloon->var_26a += 85;
|
||||
if (original_var26a < 255 - 85)
|
||||
return;
|
||||
|
||||
balloon->var_26b++;
|
||||
sprite_move(balloon->x, balloon->y, balloon->z + 1, (rct_sprite*)balloon);
|
||||
|
||||
int maxZ = 1967 - ((balloon->x ^ balloon->y) & 31);
|
||||
if (balloon->z < maxZ)
|
||||
return;
|
||||
|
||||
balloon_pop(balloon);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E88ED
|
||||
*/
|
||||
void balloon_press(rct_balloon *balloon)
|
||||
{
|
||||
if (balloon->popped == 1)
|
||||
return;
|
||||
|
||||
uint32 random = rand();
|
||||
if ((balloon->var_0A & 7) || (random & 0xFFFF) < 0x2000) {
|
||||
balloon_pop(balloon);
|
||||
return;
|
||||
}
|
||||
|
||||
sprite_move(
|
||||
balloon->x + ((random & 0x80000000) ? -6 : 6),
|
||||
balloon->y,
|
||||
balloon->z,
|
||||
(rct_sprite*)balloon
|
||||
);
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
#include "../addresses.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../localisation/date.h"
|
||||
#include "../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
|
||||
static const rct_xy16 duck_move_offset[] = {
|
||||
{ -1, 0 },
|
||||
{ 0, 1 },
|
||||
{ 1, 0 },
|
||||
{ 0, -1 }
|
||||
};
|
||||
|
||||
// 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, 255
|
||||
};
|
||||
|
||||
// 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, 255
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0067440F
|
||||
*/
|
||||
void create_duck(int targetX, int 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;
|
||||
int 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.var_26 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674108
|
||||
*/
|
||||
static void duck_update_fly_to_water(rct_duck *duck)
|
||||
{
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3)
|
||||
return;
|
||||
|
||||
duck->var_26++;
|
||||
if (duck->var_26 >= 6)
|
||||
duck->var_26 = 0;
|
||||
|
||||
duck_invalidate(duck);
|
||||
int manhattanDistance = abs(duck->target_x - duck->x) + abs(duck->target_y - duck->y);
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + duck_move_offset[direction].x;
|
||||
int y = duck->y + duck_move_offset[direction].y;
|
||||
int 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);
|
||||
int waterHeight = mapElement->properties.surface.terrain & 0x1F;
|
||||
if (waterHeight == 0) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
waterHeight <<= 4;
|
||||
int z = abs(duck->z - waterHeight);
|
||||
|
||||
if (manhattanDistanceN <= manhattanDistance) {
|
||||
if (z > manhattanDistanceN) {
|
||||
z = duck->z - 2;
|
||||
if (waterHeight >= duck->z)
|
||||
z += 4;
|
||||
|
||||
duck->var_26 = 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->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674282
|
||||
*/
|
||||
static void duck_update_swim(rct_duck *duck)
|
||||
{
|
||||
if ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) + duck->var_0A) & 3)
|
||||
return;
|
||||
|
||||
uint32 randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) < 0x666) {
|
||||
if (randomNumber & 0x80000000) {
|
||||
duck->state = DUCK_STATE_DOUBLE_DRINK;
|
||||
duck->var_26 = -1;
|
||||
duck_update_double_drink(duck);
|
||||
} else {
|
||||
duck->state = DUCK_STATE_DRINK;
|
||||
duck->var_26 = -1;
|
||||
duck_update_drink(duck);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int currentMonth = date_get_month(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16));
|
||||
if (currentMonth >= MONTH_SEPTEMBER && (randomNumber >> 16) < 218) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
|
||||
duck_invalidate(duck);
|
||||
int landZ = map_element_height(duck->x, duck->y);
|
||||
int 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;
|
||||
}
|
||||
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + duck_move_offset[direction].x;
|
||||
int 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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674357
|
||||
*/
|
||||
static void duck_update_drink(rct_duck *duck)
|
||||
{
|
||||
duck->var_26++;
|
||||
if (duck_drink_animation[duck->var_26] == 255) {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
} else {
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674372
|
||||
*/
|
||||
static void duck_update_double_drink(rct_duck *duck)
|
||||
{
|
||||
duck->var_26++;
|
||||
if (duck_double_drink_animation[duck->var_26] == 255) {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
} else {
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0067438D
|
||||
*/
|
||||
static void duck_update_fly_away(rct_duck *duck)
|
||||
{
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3)
|
||||
return;
|
||||
|
||||
duck->var_26++;
|
||||
if (duck->var_26 >= 6)
|
||||
duck->var_26 = 0;
|
||||
|
||||
duck_invalidate(duck);
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + (duck_move_offset[direction].x * 2);
|
||||
int 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;
|
||||
}
|
||||
|
||||
int z = z = min(duck->z + 2, 496);
|
||||
sprite_move(x, y, z, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x006E895D
|
||||
*/
|
||||
void duck_press(rct_duck *duck)
|
||||
{
|
||||
sound_play_panned(SOUND_QUACK, 0x8001, duck->x, duck->y, duck->z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674576
|
||||
*/
|
||||
void duck_remove_all()
|
||||
{
|
||||
rct_unk_sprite* sprite;
|
||||
uint16 spriteIndex, nextSpriteIndex;
|
||||
|
||||
for (spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_MISC, uint16); spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) {
|
||||
sprite = &(g_sprite_list[spriteIndex].unknown);
|
||||
nextSpriteIndex = sprite->next;
|
||||
if (sprite->misc_identifier == SPRITE_MISC_DUCK)
|
||||
sprite_remove((rct_sprite*)sprite);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
#include "../localisation/localisation.h"
|
||||
#include "../interface/viewport.h"
|
||||
#include "../interface/window.h"
|
||||
#include "sprite.h"
|
||||
|
||||
static const rct_xy16 _moneyEffectMoveOffset[] = {
|
||||
{ 1, -1 },
|
||||
{ 1, 1 },
|
||||
{ -1, 1 },
|
||||
{ -1, -1 }
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0067351F
|
||||
*/
|
||||
void money_effect_create_at(money32 value, int x, int y, int z)
|
||||
{
|
||||
rct_money_effect *moneyEffect;
|
||||
rct_string_id stringId;
|
||||
char buffer[128];
|
||||
|
||||
moneyEffect = (rct_money_effect*)create_sprite(2);
|
||||
if (moneyEffect == NULL)
|
||||
return;
|
||||
|
||||
moneyEffect->value = value;
|
||||
moneyEffect->var_14 = 64;
|
||||
moneyEffect->var_09 = 20;
|
||||
moneyEffect->var_15 = 30;
|
||||
moneyEffect->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, (rct_sprite*)moneyEffect);
|
||||
moneyEffect->misc_identifier = SPRITE_MISC_MONEY_EFFECT;
|
||||
moneyEffect->num_movements = 0;
|
||||
moneyEffect->move_delay = 0;
|
||||
|
||||
stringId = 1388;
|
||||
if (value < 0) {
|
||||
value *= -1;
|
||||
stringId = 1399;
|
||||
}
|
||||
format_string(buffer, stringId, &value);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224;
|
||||
moneyEffect->offset_x = -(gfx_get_string_width(buffer) / 2);
|
||||
moneyEffect->wiggle = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0069C5D0
|
||||
*/
|
||||
void money_effect_create(money32 value)
|
||||
{
|
||||
rct_window *mainWindow;
|
||||
rct_viewport *mainViewport;
|
||||
rct_xyz16 mapPosition;
|
||||
|
||||
mapPosition.x = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16);
|
||||
mapPosition.y = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16);
|
||||
mapPosition.z = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16);
|
||||
if (mapPosition.x == (sint16)0x8000) {
|
||||
mainWindow = window_get_main();
|
||||
if (mainWindow == NULL)
|
||||
return;
|
||||
|
||||
mainViewport = mainWindow->viewport;
|
||||
screen_get_map_xy(
|
||||
mainViewport->x + (mainViewport->width / 2),
|
||||
mainViewport->y + (mainViewport->height / 2),
|
||||
&mapPosition.x,
|
||||
&mapPosition.y,
|
||||
NULL
|
||||
);
|
||||
if (mapPosition.x == (sint16)0x8000)
|
||||
return;
|
||||
|
||||
mapPosition.z = map_element_height(mapPosition.x, mapPosition.y) & 0xFFFF;
|
||||
}
|
||||
mapPosition.z += 10;
|
||||
money_effect_create_at(-value, mapPosition.x, mapPosition.y, mapPosition.z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00673232
|
||||
*/
|
||||
void money_effect_update(rct_money_effect *moneyEffect)
|
||||
{
|
||||
invalidate_sprite_2((rct_sprite*)moneyEffect);
|
||||
moneyEffect->wiggle++;
|
||||
if (moneyEffect->wiggle >= 22)
|
||||
moneyEffect->wiggle = 0;
|
||||
|
||||
moneyEffect->move_delay++;
|
||||
if (moneyEffect->move_delay < 2)
|
||||
return;
|
||||
|
||||
moneyEffect->move_delay = 0;
|
||||
int x = moneyEffect->x + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].x;
|
||||
int y = moneyEffect->y + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].y;
|
||||
int z = moneyEffect->z;
|
||||
sprite_move(x, y, z, (rct_sprite*)moneyEffect);
|
||||
|
||||
moneyEffect->num_movements++;
|
||||
if (moneyEffect->num_movements < 55)
|
||||
return;
|
||||
|
||||
sprite_remove((rct_sprite*)moneyEffect);
|
||||
}
|
|
@ -27,500 +27,9 @@
|
|||
#include "fountain.h"
|
||||
#include "sprite.h"
|
||||
|
||||
enum {
|
||||
DUCK_STATE_FLY_TO_WATER,
|
||||
DUCK_STATE_SWIM,
|
||||
DUCK_STATE_DRINK,
|
||||
DUCK_STATE_DOUBLE_DRINK,
|
||||
DUCK_STATE_FLY_AWAY
|
||||
};
|
||||
|
||||
rct_sprite* g_sprite_list = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite);
|
||||
|
||||
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: 0x006736C7
|
||||
*/
|
||||
void create_balloon(int x, int y, int z, int colour, uint8 bl)
|
||||
{
|
||||
rct_sprite* sprite = create_sprite(2);
|
||||
if (sprite != NULL)
|
||||
{
|
||||
sprite->balloon.var_14 = 13;
|
||||
sprite->balloon.var_09 = 22;
|
||||
sprite->balloon.var_15 = 11;
|
||||
sprite->balloon.sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, sprite);
|
||||
sprite->balloon.misc_identifier = SPRITE_MISC_BALLOON;
|
||||
sprite->balloon.var_26 = 0;
|
||||
sprite->balloon.colour = colour;
|
||||
sprite->balloon.popped = bl;
|
||||
}
|
||||
}
|
||||
|
||||
void balloon_pop(rct_balloon *balloon)
|
||||
{
|
||||
balloon->popped = 1;
|
||||
balloon->var_26 = 0;
|
||||
sound_play_panned(SOUND_BALLOON_POP, 0x8001, balloon->x, balloon->y, balloon->z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0067342C
|
||||
*/
|
||||
void balloon_update(rct_balloon *balloon)
|
||||
{
|
||||
invalidate_sprite_2((rct_sprite*)balloon);
|
||||
if (balloon->popped == 1) {
|
||||
balloon->var_26 += 256;
|
||||
if (balloon->var_26 >= 1280)
|
||||
sprite_remove((rct_sprite*)balloon);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int original_var26a = balloon->var_26a;
|
||||
balloon->var_26a += 85;
|
||||
if (original_var26a < 255 - 85)
|
||||
return;
|
||||
|
||||
balloon->var_26b++;
|
||||
sprite_move(balloon->x, balloon->y, balloon->z + 1, (rct_sprite*)balloon);
|
||||
|
||||
int maxZ = 1967 - ((balloon->x ^ balloon->y) & 31);
|
||||
if (balloon->z < maxZ)
|
||||
return;
|
||||
|
||||
balloon_pop(balloon);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E88ED
|
||||
*/
|
||||
void balloon_press(rct_balloon *balloon)
|
||||
{
|
||||
if (balloon->popped == 1)
|
||||
return;
|
||||
|
||||
uint32 random = scenario_rand();
|
||||
if ((balloon->var_0A & 7) || (random & 0xFFFF) < 0x2000) {
|
||||
balloon_pop(balloon);
|
||||
return;
|
||||
}
|
||||
|
||||
sprite_move(
|
||||
balloon->x + ((random & 0x80000000) ? -6 : 6),
|
||||
balloon->y,
|
||||
balloon->z,
|
||||
(rct_sprite*)balloon
|
||||
);
|
||||
}
|
||||
|
||||
// rct2: 0x009A3B04
|
||||
static const rct_xy16 duck_move_offset[] = {
|
||||
{ -1, 0 },
|
||||
{ 0, 1 },
|
||||
{ 1, 0 },
|
||||
{ 0, -1 }
|
||||
};
|
||||
|
||||
// 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, 255
|
||||
};
|
||||
|
||||
// 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, 255
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0067440F
|
||||
*/
|
||||
void create_duck(int targetX, int 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;
|
||||
int 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.var_26 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674108
|
||||
*/
|
||||
static void duck_update_fly_to_water(rct_duck *duck)
|
||||
{
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3)
|
||||
return;
|
||||
|
||||
duck->var_26++;
|
||||
if (duck->var_26 >= 6)
|
||||
duck->var_26 = 0;
|
||||
|
||||
duck_invalidate(duck);
|
||||
int manhattanDistance = abs(duck->target_x - duck->x) + abs(duck->target_y - duck->y);
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + duck_move_offset[direction].x;
|
||||
int y = duck->y + duck_move_offset[direction].y;
|
||||
int 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);
|
||||
int waterHeight = mapElement->properties.surface.terrain & 0x1F;
|
||||
if (waterHeight == 0) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
waterHeight <<= 4;
|
||||
int z = abs(duck->z - waterHeight);
|
||||
|
||||
if (manhattanDistanceN <= manhattanDistance) {
|
||||
if (z > manhattanDistanceN) {
|
||||
z = duck->z - 2;
|
||||
if (waterHeight >= duck->z)
|
||||
z += 4;
|
||||
|
||||
duck->var_26 = 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->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674282
|
||||
*/
|
||||
static void duck_update_swim(rct_duck *duck)
|
||||
{
|
||||
if ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) + duck->var_0A) & 3)
|
||||
return;
|
||||
|
||||
uint32 randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) < 0x666) {
|
||||
if (randomNumber & 0x80000000) {
|
||||
duck->state = DUCK_STATE_DOUBLE_DRINK;
|
||||
duck->var_26 = -1;
|
||||
duck_update_double_drink(duck);
|
||||
} else {
|
||||
duck->state = DUCK_STATE_DRINK;
|
||||
duck->var_26 = -1;
|
||||
duck_update_drink(duck);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int currentMonth = date_get_month(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16));
|
||||
if (currentMonth >= MONTH_SEPTEMBER && (randomNumber >> 16) < 218) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
|
||||
duck_invalidate(duck);
|
||||
int landZ = map_element_height(duck->x, duck->y);
|
||||
int 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;
|
||||
}
|
||||
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + duck_move_offset[direction].x;
|
||||
int 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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674357
|
||||
*/
|
||||
static void duck_update_drink(rct_duck *duck)
|
||||
{
|
||||
duck->var_26++;
|
||||
if (duck_drink_animation[duck->var_26] == 255) {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
} else {
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674372
|
||||
*/
|
||||
static void duck_update_double_drink(rct_duck *duck)
|
||||
{
|
||||
duck->var_26++;
|
||||
if (duck_double_drink_animation[duck->var_26] == 255) {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
} else {
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0067438D
|
||||
*/
|
||||
static void duck_update_fly_away(rct_duck *duck)
|
||||
{
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3)
|
||||
return;
|
||||
|
||||
duck->var_26++;
|
||||
if (duck->var_26 >= 6)
|
||||
duck->var_26 = 0;
|
||||
|
||||
duck_invalidate(duck);
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + (duck_move_offset[direction].x * 2);
|
||||
int 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;
|
||||
}
|
||||
|
||||
int z = z = min(duck->z + 2, 496);
|
||||
sprite_move(x, y, z, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x006E895D
|
||||
*/
|
||||
void duck_press(rct_duck *duck)
|
||||
{
|
||||
sound_play_panned(SOUND_QUACK, 0x8001, duck->x, duck->y, duck->z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674576
|
||||
*/
|
||||
void duck_remove_all()
|
||||
{
|
||||
rct_unk_sprite* sprite;
|
||||
uint16 spriteIndex, nextSpriteIndex;
|
||||
|
||||
for (spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_MISC, uint16); spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) {
|
||||
sprite = &(g_sprite_list[spriteIndex].unknown);
|
||||
nextSpriteIndex = sprite->next;
|
||||
if (sprite->misc_identifier == SPRITE_MISC_DUCK)
|
||||
sprite_remove((rct_sprite*)sprite);
|
||||
}
|
||||
}
|
||||
|
||||
static const rct_xy16 _moneyEffectMoveOffset[] = {
|
||||
{ 1, -1 },
|
||||
{ 1, 1 },
|
||||
{ -1, 1 },
|
||||
{ -1, -1 }
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0067351F
|
||||
*/
|
||||
void money_effect_create_at(money32 value, int x, int y, int z)
|
||||
{
|
||||
rct_money_effect *moneyEffect;
|
||||
rct_string_id stringId;
|
||||
char buffer[128];
|
||||
|
||||
moneyEffect = (rct_money_effect*)create_sprite(2);
|
||||
if (moneyEffect == NULL)
|
||||
return;
|
||||
|
||||
moneyEffect->value = value;
|
||||
moneyEffect->var_14 = 64;
|
||||
moneyEffect->var_09 = 20;
|
||||
moneyEffect->var_15 = 30;
|
||||
moneyEffect->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, (rct_sprite*)moneyEffect);
|
||||
moneyEffect->misc_identifier = SPRITE_MISC_MONEY_EFFECT;
|
||||
moneyEffect->num_movements = 0;
|
||||
moneyEffect->move_delay = 0;
|
||||
|
||||
stringId = 1388;
|
||||
if (value < 0) {
|
||||
value *= -1;
|
||||
stringId = 1399;
|
||||
}
|
||||
format_string(buffer, stringId, &value);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224;
|
||||
moneyEffect->offset_x = -(gfx_get_string_width(buffer) / 2);
|
||||
moneyEffect->wiggle = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0069C5D0
|
||||
*/
|
||||
void money_effect_create(money32 value)
|
||||
{
|
||||
rct_window *mainWindow;
|
||||
rct_viewport *mainViewport;
|
||||
rct_xyz16 mapPosition;
|
||||
|
||||
mapPosition.x = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16);
|
||||
mapPosition.y = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16);
|
||||
mapPosition.z = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16);
|
||||
if (mapPosition.x == (sint16)0x8000) {
|
||||
mainWindow = window_get_main();
|
||||
if (mainWindow == NULL)
|
||||
return;
|
||||
|
||||
mainViewport = mainWindow->viewport;
|
||||
screen_get_map_xy(
|
||||
mainViewport->x + (mainViewport->width / 2),
|
||||
mainViewport->y + (mainViewport->height / 2),
|
||||
&mapPosition.x,
|
||||
&mapPosition.y,
|
||||
NULL
|
||||
);
|
||||
if (mapPosition.x == (sint16)0x8000)
|
||||
return;
|
||||
|
||||
mapPosition.z = map_element_height(mapPosition.x, mapPosition.y) & 0xFFFF;
|
||||
}
|
||||
mapPosition.z += 10;
|
||||
money_effect_create_at(-value, mapPosition.x, mapPosition.y, mapPosition.z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00673232
|
||||
*/
|
||||
void money_effect_update(rct_money_effect *moneyEffect)
|
||||
{
|
||||
invalidate_sprite_2((rct_sprite*)moneyEffect);
|
||||
moneyEffect->wiggle++;
|
||||
if (moneyEffect->wiggle >= 22)
|
||||
moneyEffect->wiggle = 0;
|
||||
|
||||
moneyEffect->move_delay++;
|
||||
if (moneyEffect->move_delay < 2)
|
||||
return;
|
||||
|
||||
moneyEffect->move_delay = 0;
|
||||
int x = moneyEffect->x + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].x;
|
||||
int y = moneyEffect->y + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].y;
|
||||
int z = moneyEffect->z;
|
||||
sprite_move(x, y, z, (rct_sprite*)moneyEffect);
|
||||
|
||||
moneyEffect->num_movements++;
|
||||
if (moneyEffect->num_movements < 55)
|
||||
return;
|
||||
|
||||
sprite_remove((rct_sprite*)moneyEffect);
|
||||
}
|
||||
|
||||
void invalidate_sprite_max_zoom(rct_sprite *sprite, int maxZoom)
|
||||
static void invalidate_sprite_max_zoom(rct_sprite *sprite, int maxZoom)
|
||||
{
|
||||
if (sprite->unknown.sprite_left == (sint16)0x8000) return;
|
||||
|
||||
|
|
|
@ -243,12 +243,6 @@ enum {
|
|||
// rct2: 0x010E63BC
|
||||
extern rct_sprite* g_sprite_list;
|
||||
|
||||
void create_balloon(int x, int y, int z, int colour, uint8 bl);
|
||||
void balloon_press(rct_balloon *balloon);
|
||||
void create_duck(int targetX, int targetY);
|
||||
void duck_press(rct_duck *duck);
|
||||
void duck_remove_all();
|
||||
void money_effect_create(money32 value);
|
||||
rct_sprite *create_sprite(uint8 bl);
|
||||
void reset_sprite_list();
|
||||
void reset_0x69EBE4();
|
||||
|
@ -265,4 +259,25 @@ void sub_6738E1(int x, int y, int z);
|
|||
void sprite_misc_3_create(int x, int y, int z);
|
||||
void sprite_misc_5_create(int x, int y, int z);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Balloon
|
||||
///////////////////////////////////////////////////////////////
|
||||
void create_balloon(int x, int y, int z, int colour, uint8 bl);
|
||||
void balloon_update(rct_balloon *balloon);
|
||||
void balloon_press(rct_balloon *balloon);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Duck
|
||||
///////////////////////////////////////////////////////////////
|
||||
void create_duck(int targetX, int targetY);
|
||||
void duck_update(rct_duck *duck);
|
||||
void duck_press(rct_duck *duck);
|
||||
void duck_remove_all();
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Money effect
|
||||
///////////////////////////////////////////////////////////////
|
||||
void money_effect_create(money32 value);
|
||||
void money_effect_update(rct_money_effect *moneyEffect);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue