mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-22 06:23:04 +01:00
2486 lines
67 KiB
C
2486 lines
67 KiB
C
/*****************************************************************************
|
|
* Copyright (c) 2014 Ted John
|
|
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
|
*
|
|
* This file is part of 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.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*****************************************************************************/
|
|
|
|
#include "../addresses.h"
|
|
#include "../audio/audio.h"
|
|
#include "../audio/mixer.h"
|
|
#include "../interface/window.h"
|
|
#include "../localisation/localisation.h"
|
|
#include "../management/news_item.h"
|
|
#include "../ride/ride.h"
|
|
#include "../scenario.h"
|
|
#include "../sprites.h"
|
|
#include "../world/sprite.h"
|
|
#include "../world/scenery.h"
|
|
#include "peep.h"
|
|
#include "staff.h"
|
|
|
|
static void peep_update(rct_peep *peep);
|
|
static int peep_has_empty_container(rct_peep* peep);
|
|
static int peep_has_food_standard_flag(rct_peep* peep);
|
|
static int peep_has_food_extra_flag(rct_peep* peep);
|
|
static int peep_should_find_bench(rct_peep* peep);
|
|
|
|
const char *gPeepEasterEggNames[] = {
|
|
"MICHAEL SCHUMACHER",
|
|
"JACQUES VILLENEUVE",
|
|
"DAMON HILL",
|
|
"MR BEAN",
|
|
"CHRIS SAWYER",
|
|
"KATIE BRAYSHAW",
|
|
"MELANIE WARN",
|
|
"SIMON FOSTER",
|
|
"JOHN WARDLEY",
|
|
"LISA STIRLING",
|
|
"DONALD MACRAE",
|
|
"KATHERINE MCGOWAN",
|
|
"FRANCES MCGOWAN",
|
|
"CORINA MASSOURA",
|
|
"CAROL YOUNG",
|
|
"MIA SHERIDAN",
|
|
"KATIE RODGER",
|
|
"EMMA GARRELL",
|
|
"JOANNE BARTON",
|
|
"FELICITY ANDERSON",
|
|
"KATIE SMITH",
|
|
"EILIDH BELL",
|
|
"NANCY STILLWAGON",
|
|
"ANDY HINE",
|
|
"ELISSA WHITE",
|
|
"DAVID ELLIS"
|
|
};
|
|
|
|
int peep_get_staff_count()
|
|
{
|
|
uint16 spriteIndex;
|
|
rct_peep *peep;
|
|
int count = 0;
|
|
|
|
FOR_ALL_STAFF(spriteIndex, peep)
|
|
count++;
|
|
|
|
return count;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x0068F0A9
|
|
*/
|
|
void peep_update_all()
|
|
{
|
|
int i;
|
|
uint16 spriteIndex;
|
|
rct_peep* peep;
|
|
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)
|
|
return;
|
|
|
|
spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
|
i = 0;
|
|
while (spriteIndex != SPRITE_INDEX_NULL) {
|
|
peep = &(g_sprite_list[spriteIndex].peep);
|
|
spriteIndex = peep->next;
|
|
|
|
if ((i & 0x7F) != (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x7F)) {
|
|
peep_update(peep);
|
|
} else {
|
|
RCT2_CALLPROC_X(0x0068F41A, 0, 0, 0, i, (int)peep, 0, 0);
|
|
if (peep->linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_PEEP)
|
|
peep_update(peep);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
/* some sort of check to see if peep is connected to the ground?? */
|
|
int sub_68F3AE(rct_peep* peep){
|
|
peep->var_C4++;
|
|
if ((peep->var_C4 & 0xF) != (peep->sprite_index & 0xF))return 1;
|
|
|
|
rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
|
|
|
|
uint8 map_type = MAP_ELEMENT_TYPE_PATH;
|
|
if (peep->next_var_29 & ((1 << 4) | (1 << 3))){
|
|
map_type = MAP_ELEMENT_TYPE_SURFACE;
|
|
}
|
|
|
|
int z = peep->next_z;
|
|
|
|
do {
|
|
if (map_element_get_type(map_element) == map_type){
|
|
if (z == map_element->base_height)return 1;
|
|
}
|
|
} while (!map_element_is_last_for_tile(map_element++));
|
|
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_FALLING;
|
|
peep_window_state_update(peep);
|
|
return 0;
|
|
}
|
|
|
|
void sub_693B58(rct_peep* peep){
|
|
int ebx;
|
|
if (peep->action >= 0xFE){
|
|
ebx = RCT2_ADDRESS(0x981D8C, uint8)[peep->var_6D];
|
|
}
|
|
else{
|
|
ebx = RCT2_ADDRESS(0x981D8F, uint8)[peep->action];
|
|
}
|
|
if (ebx == peep->var_6E)return;
|
|
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
peep->var_6E = ebx;
|
|
|
|
uint8* edx = RCT2_ADDRESS(0x98270C, uint8*)[peep->sprite_type * 2];
|
|
peep->var_14 = edx[ebx * 4];
|
|
peep->var_09 = edx[ebx * 4 + 1];
|
|
peep->var_15 = edx[ebx * 4 + 2];
|
|
// This is pointless as nothing will have changed.
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
}
|
|
|
|
static void peep_state_reset(rct_peep* peep){
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_1;
|
|
peep_window_state_update(peep);
|
|
|
|
RCT2_CALLPROC_X(0x00693BE5, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
|
|
/* rct2: 0x69C308
|
|
* Check if lost.
|
|
*/
|
|
void peep_check_if_lost(rct_peep* peep){
|
|
if (!(peep->flags & PEEP_FLAGS_LOST)){
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, uint16) < 2)return;
|
|
peep->flags ^= PEEP_FLAGS_21;
|
|
|
|
if (!(peep->flags & PEEP_FLAGS_21)) return;
|
|
|
|
peep->var_F4++;
|
|
if (peep->var_F4 != 254)return;
|
|
peep->var_F4 = 230;
|
|
}
|
|
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_LOST, 0xFF);
|
|
if (peep->happiness_growth_rate < 30) peep->happiness_growth_rate = 0;
|
|
else peep->happiness_growth_rate -= 30;
|
|
}
|
|
|
|
/* rct2: 0x69C26B
|
|
* Check if cant find ride.
|
|
*/
|
|
void peep_check_cant_find_ride(rct_peep* peep){
|
|
if (peep->guest_heading_to_ride_id == 0xFF) return;
|
|
|
|
if (peep->var_C6 == 30 || peep->var_C6 == 60){
|
|
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_FIND, peep->guest_heading_to_ride_id);
|
|
|
|
if (peep->happiness_growth_rate < 30) peep->happiness_growth_rate = 0;
|
|
else peep->happiness_growth_rate -= 30;
|
|
}
|
|
|
|
peep->var_C6--;
|
|
if (peep->var_C6 != 0)return;
|
|
|
|
peep->guest_heading_to_ride_id = 0xFF;
|
|
rct_window* w = window_find_by_number(WC_PEEP, peep->sprite_index);
|
|
|
|
if (w){
|
|
window_event_invalidate_call(w);
|
|
}
|
|
|
|
widget_invalidate_by_number(WC_PEEP, peep->sprite_index, 12);
|
|
}
|
|
|
|
/* rct2: 0x69C2D0
|
|
* Check if cant find exit.
|
|
*/
|
|
void peep_check_cant_find_exit(rct_peep* peep){
|
|
if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK))return;
|
|
|
|
if (peep->var_C6 == 1){
|
|
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_FIND_EXIT, 0xFF);
|
|
|
|
if (peep->happiness_growth_rate < 30) peep->happiness_growth_rate = 0;
|
|
else peep->happiness_growth_rate -= 30;
|
|
}
|
|
|
|
if (--peep->var_C6 == 0) peep->var_C6 = 90;
|
|
}
|
|
|
|
/* rct2: 0x6939EB
|
|
* Possibly peep update action frame.
|
|
* Also used to move peeps to the correct position to
|
|
* start an action. Returns 0 if the correct destination
|
|
* has not yet been reached.
|
|
*/
|
|
int sub_6939EB(sint16* x, sint16* y, rct_peep* peep){
|
|
RCT2_GLOBAL(0xF1AEF0, uint8) = peep->var_70;
|
|
if (peep->action == 0xFE){
|
|
peep->action = 0xFF;
|
|
}
|
|
|
|
*x = peep->x - peep->destination_x;
|
|
*y = peep->y - peep->destination_y;
|
|
|
|
int x_delta = abs(*x);
|
|
int y_delta = abs(*y);
|
|
|
|
if (peep->action >= 0xFE){
|
|
if (x_delta + y_delta <= peep->destination_tolerence){
|
|
return 0;
|
|
}
|
|
int direction = 0;
|
|
if (x_delta < y_delta){
|
|
direction = 8;
|
|
if (*y >= 0){
|
|
direction = 24;
|
|
}
|
|
}
|
|
else{
|
|
direction = 16;
|
|
if (*x >= 0){
|
|
direction = 0;
|
|
}
|
|
}
|
|
peep->sprite_direction = direction;
|
|
*x = peep->x + RCT2_ADDRESS(0x981D7C, uint16)[direction / 4];
|
|
*y = peep->y + RCT2_ADDRESS(0x981D7E, uint16)[direction / 4];
|
|
int ebx = peep->var_E0 + 1;
|
|
uint32* edi = RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2];
|
|
uint8* _edi = (uint8*)(edi[peep->var_6E * 2 + 1]);
|
|
if (ebx >= *_edi){
|
|
ebx = 0;
|
|
}
|
|
peep->var_E0 = ebx;
|
|
peep->var_70 = _edi[ebx + 1];
|
|
return 1;
|
|
}
|
|
|
|
int* edi = RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2];
|
|
uint8* _edi = (uint8*)(edi[peep->var_6E * 2 + 1]);
|
|
peep->action_frame++;
|
|
int ebx = _edi[peep->action_frame + 1];
|
|
|
|
// If last frame of action
|
|
if (ebx == 0xFF){
|
|
peep->var_70 = 0;
|
|
peep->action = 0xFF;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
*x = peep->x;
|
|
*y = peep->y;
|
|
return 1;
|
|
}
|
|
peep->var_70 = ebx;
|
|
|
|
// If not throwing up and not at the frame where sick appears.
|
|
if (peep->action != PEEP_ACTION_THROW_UP || peep->action_frame != 15){
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
*x = peep->x;
|
|
*y = peep->y;
|
|
return 1;
|
|
}
|
|
|
|
// We are throwing up
|
|
peep->hunger /= 2;
|
|
peep->nausea_growth_rate /= 2;
|
|
|
|
if (peep->nausea < 30)
|
|
peep->nausea = 0;
|
|
else
|
|
peep->nausea -= 30;
|
|
|
|
peep->var_45 |= (1 << 2);
|
|
|
|
// Create sick at location
|
|
RCT2_CALLPROC_X(0x67375D, peep->x, peep->sprite_direction, peep->y, peep->z, 0, 0, peep->sprite_index & 1);
|
|
|
|
int sound_id = (scenario_rand() & 3) + 24;
|
|
|
|
sound_play_panned(sound_id, 0x8001, peep->x, peep->y, peep->z);
|
|
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
*x = peep->x;
|
|
*y = peep->y;
|
|
return 1;
|
|
}
|
|
/**
|
|
* rct2: 0x0069A409
|
|
* Decreases rider count if on/entering a ride.
|
|
*/
|
|
void peep_decrement_num_riders(rct_peep* peep){
|
|
if (peep->state == PEEP_STATE_ON_RIDE
|
|
|| peep->state == PEEP_STATE_ENTERING_RIDE){
|
|
|
|
rct_ride* ride = GET_RIDE(peep->current_ride);
|
|
ride->num_riders--;
|
|
ride->var_14D |= 0xC;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x0069A42F
|
|
* Call after changing a peeps state to insure that
|
|
* all relevant windows update. Note also increase ride
|
|
* count if on/entering a ride.
|
|
*/
|
|
void peep_window_state_update(rct_peep* peep){
|
|
|
|
rct_window* w = window_find_by_number(WC_PEEP, peep->sprite_index);
|
|
if (w){
|
|
RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0);
|
|
}
|
|
|
|
if (peep->type == PEEP_TYPE_GUEST){
|
|
// Update action label
|
|
widget_invalidate_by_number(WC_PEEP, peep->sprite_index, 12);
|
|
|
|
if (peep->state == PEEP_STATE_ON_RIDE || peep->state == PEEP_STATE_ENTERING_RIDE){
|
|
rct_ride* ride = GET_RIDE(peep->current_ride);
|
|
ride->num_riders++;
|
|
ride->var_14D |= 0xC;
|
|
}
|
|
|
|
window_invalidate_by_class(WC_GUEST_LIST);
|
|
}
|
|
else{
|
|
// Update action label
|
|
widget_invalidate_by_number(WC_PEEP, peep->sprite_index, 9);
|
|
window_invalidate_by_class(WC_STAFF_LIST);
|
|
}
|
|
}
|
|
|
|
/** New function removes peep from
|
|
* park existance. Works with staff.
|
|
*/
|
|
void peep_remove(rct_peep* peep){
|
|
if (peep->type == PEEP_TYPE_GUEST){
|
|
if (peep->var_2A == 0){
|
|
RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16)--;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_BTM_TOOLBAR_DIRTY_FLAGS, uint16) |= BTM_TB_DIRTY_FLAG_PEEP_COUNT;
|
|
}
|
|
if (peep->state == PEEP_STATE_ENTERING_PARK){
|
|
RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK, uint16)--;
|
|
}
|
|
}
|
|
RCT2_CALLPROC_X(0x69A535, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x690028
|
|
* Falling and its subset drowning
|
|
*/
|
|
void peep_update_falling(rct_peep* peep){
|
|
if (peep->action == PEEP_ACTION_DROWNING){
|
|
// Check to see if we are ready to drown.
|
|
sint16 x, y;
|
|
sub_6939EB(&x, &y, peep);
|
|
//RCT2_CALLPROC_X(0x6939EB, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (peep->action == PEEP_ACTION_DROWNING) return;
|
|
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x80000)){
|
|
RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx;
|
|
RCT2_GLOBAL(0x13CE954, uint32) = peep->id;
|
|
news_item_add_to_queue(NEWS_ITEM_BLANK, 2347, peep->x | (peep->y << 16));
|
|
}
|
|
RCT2_GLOBAL(0x135882E, uint16) += 25;
|
|
if (RCT2_GLOBAL(0x135882E, uint16) > 1000){
|
|
RCT2_GLOBAL(0x135882E, uint16) = 1000;
|
|
}
|
|
peep_remove(peep);
|
|
return;
|
|
}
|
|
|
|
// If not drowning then falling. Note: peeps 'fall' after leaving a ride/enter the park.
|
|
|
|
rct_map_element *map_element = map_get_first_element_at(peep->x / 32, peep->y / 32);
|
|
rct_map_element *saved_map = NULL;
|
|
int saved_height = 0;
|
|
|
|
do {
|
|
// If a path check if we are on it
|
|
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH){
|
|
int height = map_height_from_slope(peep->x, peep->y, map_element->properties.surface.slope)
|
|
+ map_element->base_height * 8;
|
|
|
|
if (height < peep->z - 1 || height - 4 > peep->z) continue;
|
|
|
|
saved_height = height;
|
|
saved_map = map_element;
|
|
break;
|
|
} // If a surface get the height and see if we are on it
|
|
else if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SURFACE){
|
|
// If the surface is water check to see if we could be drowning
|
|
if (map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK){
|
|
int height = (map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) * 16;
|
|
|
|
if (height - 4 >= peep->z && height < peep->z + 20){
|
|
// Looks like we are drowning!
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
sprite_move(peep->x, peep->y, height, (rct_sprite*)peep);
|
|
// Drop balloon if held
|
|
if (peep->item_standard_flags & PEEP_ITEM_BALLOON){
|
|
peep->item_standard_flags &= ~PEEP_ITEM_BALLOON;
|
|
|
|
if (peep->sprite_type == 19 && peep->x != 0x8000){
|
|
create_balloon(peep->x, peep->y, height, peep->balloon_colour);
|
|
peep->var_45 |= (1 << 3);
|
|
RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
}
|
|
|
|
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_DROWNING, -1);
|
|
|
|
peep->action = PEEP_ACTION_DROWNING;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
peep_window_state_update(peep);
|
|
return;
|
|
}
|
|
}
|
|
int map_height = map_element_height(0xFFFF & peep->x, 0xFFFF & peep->y) & 0xFFFF;
|
|
if (map_height < peep->z || map_height - 4 > peep->z) continue;
|
|
saved_height = map_height;
|
|
saved_map = map_element;
|
|
} // If not a path or surface go see next element
|
|
else continue;
|
|
} while (!map_element_is_last_for_tile(map_element++));
|
|
|
|
// This will be null if peep is falling
|
|
if (saved_map == NULL){
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
if (peep->z <= 1){
|
|
// Remove peep if it has gone to the void
|
|
peep_remove(peep);
|
|
return;
|
|
}
|
|
sprite_move(peep->x, peep->y, peep->z - 2, (rct_sprite*)peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
sprite_move(peep->x, peep->y, saved_height, (rct_sprite*)peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
peep->next_x = peep->x & 0xFFE0;
|
|
peep->next_y = peep->y & 0xFFE0;
|
|
peep->next_z = saved_map->base_height;
|
|
|
|
int edx = saved_map->properties.surface.slope & 0x7;
|
|
if (saved_map->type != MAP_ELEMENT_TYPE_PATH){
|
|
edx = 8;
|
|
}
|
|
peep->next_var_29 = edx;
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_1;
|
|
peep_window_state_update(peep);
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x00691677
|
|
*/
|
|
void peep_try_get_up_from_sitting(rct_peep* peep){
|
|
// Eats all food first
|
|
if (peep_has_food(peep))return;
|
|
|
|
peep->time_to_sitdown--;
|
|
if (peep->time_to_sitdown) return;
|
|
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_WALKING;
|
|
peep_window_state_update(peep);
|
|
|
|
// Set destination to the center of the tile.
|
|
peep->destination_x = (peep->x & 0xFFE0) + 16;
|
|
peep->destination_y = (peep->y & 0xFFE0) + 16;
|
|
peep->destination_tolerence = 5;
|
|
sub_693B58(peep);
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x0069152B
|
|
*/
|
|
void peep_update_sitting(rct_peep* peep){
|
|
if (peep->sub_state == 0){
|
|
if (!sub_68F3AE(peep))return;
|
|
//691541
|
|
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
|
|
|
|
int ebx = peep->var_37 & 0x7;
|
|
int x = (peep->x & 0xFFE0) + RCT2_ADDRESS(0x981F2C, uint16)[ebx * 2];
|
|
int y = (peep->y & 0xFFE0) + RCT2_ADDRESS(0x981F2E, uint16)[ebx * 2];
|
|
int z = peep->z;
|
|
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
sprite_move(x, y, z, (rct_sprite*)peep);
|
|
|
|
peep->sprite_direction = ((peep->var_37 + 2) & 3) * 8;
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
peep->action = 254;
|
|
peep->var_6F = 7;
|
|
RCT2_CALLPROC_X(0x693BAB, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
|
|
peep->sub_state++;
|
|
|
|
// Sets time to sit on seat
|
|
peep->time_to_sitdown = (129 - peep->energy) * 16 + 50;
|
|
}
|
|
else if (peep->sub_state == 1){
|
|
if (peep->action < 0xFE){
|
|
sint16 x, y;
|
|
sub_6939EB(&x, &y, peep);
|
|
//RCT2_CALLPROC_X(0x6939EB, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (peep->action != 0xFF) return;
|
|
|
|
peep->action = 0xFE;
|
|
peep_try_get_up_from_sitting(peep);
|
|
return;
|
|
}
|
|
|
|
if ((peep->flags & PEEP_FLAGS_LEAVING_PARK)){
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_WALKING;
|
|
peep_window_state_update(peep);
|
|
|
|
// Set destination to the center of the tile
|
|
peep->destination_x = (peep->x & 0xFFE0) + 16;
|
|
peep->destination_y = (peep->y & 0xFFE0) + 16;
|
|
peep->destination_tolerence = 5;
|
|
sub_693B58(peep);
|
|
return;
|
|
}
|
|
|
|
if (peep->sprite_type == 0x15){
|
|
peep_try_get_up_from_sitting(peep);
|
|
return;
|
|
}
|
|
|
|
if (peep_has_food(peep)){
|
|
if ((scenario_rand() & 0xFFFF) > 1310){
|
|
peep_try_get_up_from_sitting(peep);
|
|
return;
|
|
}
|
|
peep->action = PEEP_ACTION_SITTING_EAT_FOOD;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
|
|
int rand = scenario_rand();
|
|
if ((rand & 0xFFFF) > 131){
|
|
peep_try_get_up_from_sitting(peep);
|
|
return;
|
|
}
|
|
if (peep->sprite_type == 0x13 || peep->sprite_type == 0x1E){
|
|
peep_try_get_up_from_sitting(peep);
|
|
return;
|
|
}
|
|
|
|
peep->action = PEEP_ACTION_SITTING_LOOK_AROUND_LEFT;
|
|
if (rand & 0x80000000){
|
|
peep->action = PEEP_ACTION_SITTING_LOOK_AROUND_RIGHT;
|
|
}
|
|
|
|
if (rand & 0x40000000){
|
|
peep->action = PEEP_ACTION_SITTING_CHECK_WATCH;
|
|
}
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* rct2: 0x691A30
|
|
* Also used by entering_ride and queueing_front */
|
|
static void peep_update_leaving_ride(rct_peep* peep){
|
|
RCT2_CALLPROC_X(RCT2_ADDRESS(0x9820DC, int)[peep->sub_state], 0, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x69185D
|
|
*/
|
|
static void peep_update_queuing(rct_peep* peep){
|
|
if (!sub_68F3AE(peep)){
|
|
RCT2_CALLPROC_X(0x6966A9, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
return;
|
|
}
|
|
rct_ride* ride = GET_RIDE(peep->current_ride);
|
|
if (ride->status == RIDE_STATUS_CLOSED || ride->status == RIDE_STATUS_TESTING){
|
|
RCT2_CALLPROC_X(0x6966A9, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_1;
|
|
peep_window_state_update(peep);
|
|
return;
|
|
}
|
|
|
|
if (peep->sub_state != 0xA){
|
|
if (peep->var_74 == 0xFFFF){
|
|
//Happens every time peep goes onto ride.
|
|
peep->destination_tolerence = 0;
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_QUEUING_FRONT;
|
|
peep_window_state_update(peep);
|
|
peep->sub_state = 0;
|
|
return;
|
|
}
|
|
//Give up queueing for the ride
|
|
peep->sprite_direction ^= (1 << 4);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
RCT2_CALLPROC_X(0x6966A9, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_1;
|
|
peep_window_state_update(peep);
|
|
return;
|
|
}
|
|
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (peep->action < 0xFE)return;
|
|
if (peep->sprite_type == 0){
|
|
if (peep->var_7A >= 2000 && (0xFFFF & scenario_rand()) <= 119){
|
|
// Look at watch
|
|
peep->action = PEEP_ACTION_CHECK_WATCH;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
}
|
|
if (peep->var_7A >= 3500 && (0xFFFF & scenario_rand()) <= 93)
|
|
{
|
|
//Create the ive been waiting in line ages thought
|
|
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_QUEUING_AGES, peep->current_ride);
|
|
}
|
|
}
|
|
else{
|
|
if (!(peep->var_7A & 0x3F) && peep->action == 0xFE && peep->var_6F == 2){
|
|
switch (peep->sprite_type){
|
|
case 0xF:
|
|
case 0x10:
|
|
case 0x11:
|
|
case 0x12:
|
|
case 0x14:
|
|
case 0x16:
|
|
case 0x18:
|
|
case 0x1F:
|
|
case 0x20:
|
|
case 0x21:
|
|
case 0x22:
|
|
case 0x23:
|
|
case 0x24:
|
|
case 0x25:
|
|
case 0x27:
|
|
case 0x29:
|
|
case 0x2A:
|
|
case 0x2B:
|
|
case 0x2C:
|
|
case 0x2D:
|
|
case 0x2E:
|
|
case 0x2F:
|
|
// Look at watch
|
|
peep->action = PEEP_ACTION_CHECK_WATCH;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (peep->var_7A < 4300) return;
|
|
|
|
if (peep->happiness <= 65 && (0xFFFF & scenario_rand()) < 2184){
|
|
//Give up queueing for the ride
|
|
peep->sprite_direction ^= (1 << 4);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
RCT2_CALLPROC_X(0x6966A9, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_1;
|
|
peep_window_state_update(peep);
|
|
}
|
|
}
|
|
|
|
/* rct2: 0x006BF567 */
|
|
static void peep_update_mowing(rct_peep* peep){
|
|
peep->var_E2 = 0;
|
|
if (!sub_68F3AE(peep))return;
|
|
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
while (1){
|
|
sint16 x = 0, y = 0;
|
|
if (sub_6939EB(&x, &y, peep)){
|
|
int eax = x, ebx, ecx = y, z, ebp, edi;
|
|
|
|
RCT2_CALLFUNC_X(0x662783, &eax, &ebx, &ecx, &z, (int*)&peep, &edi, &ebp);
|
|
x = eax;
|
|
y = ecx;
|
|
sprite_move(x, y, z, (rct_sprite*)peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
|
|
peep->var_37++;
|
|
|
|
if (peep->var_37 == 1){
|
|
RCT2_CALLPROC_X(0x00693BE5, 2, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
|
|
if (RCT2_ADDRESS(0x9929C8, uint16)[peep->var_37 * 2] == 0xFFFF){
|
|
peep_state_reset(peep);
|
|
return;
|
|
}
|
|
|
|
peep->destination_x = RCT2_ADDRESS(0x9929C8, uint16)[peep->var_37 * 2] + peep->next_x;
|
|
peep->destination_y = RCT2_ADDRESS(0x9929CA, uint16)[peep->var_37 * 2] + peep->next_y;
|
|
|
|
if (peep->var_37 != 7)continue;
|
|
|
|
rct_map_element *map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
|
|
|
|
for (; (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SURFACE); map_element++);
|
|
|
|
if ((map_element->properties.surface.terrain & MAP_ELEMENT_SURFACE_TERRAIN_MASK) == (TERRAIN_GRASS << 5)){
|
|
map_element->properties.surface.grass_length = 0;
|
|
gfx_invalidate_scrollingtext(peep->next_x, peep->next_y, map_element->base_height * 8, map_element->base_height * 8 + 16);
|
|
}
|
|
peep->staff_lawns_mown++;
|
|
peep->var_45 |= (1 << 5);
|
|
}
|
|
}
|
|
|
|
/* rct2: 0x006BF7E6 */
|
|
static void peep_update_watering(rct_peep* peep){
|
|
peep->var_E2 = 0;
|
|
if (peep->sub_state == 0){
|
|
if (!sub_68F3AE(peep))return;
|
|
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
|
|
|
|
peep->sprite_direction = (peep->var_37 & 3) << 3;
|
|
peep->action = PEEP_ACTION_STAFF_WATERING;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
peep->sub_state = 1;
|
|
}
|
|
else if (peep->sub_state == 1){
|
|
if (peep->action != PEEP_ACTION_NONE_2){
|
|
sint16 x, y;
|
|
sub_6939EB(&x, &y, peep);
|
|
return;
|
|
}
|
|
|
|
int x = peep->next_x + RCT2_ADDRESS(0x993CCC, sint16)[peep->var_37 * 2];
|
|
int y = peep->next_y + RCT2_ADDRESS(0x993CCE, sint16)[peep->var_37 * 2];
|
|
|
|
rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
|
|
|
|
for (;; map_element++){
|
|
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY){
|
|
if (abs(((int)peep->next_z) - map_element->base_height) <= 4){
|
|
rct_scenery_entry* scenery_entry = g_smallSceneryEntries[map_element->properties.scenery.type];
|
|
|
|
if (scenery_entry->small_scenery.flags& SMALL_SCENERY_FLAG6){
|
|
map_element->properties.scenery.age = 0;
|
|
gfx_invalidate_scrollingtext(x, y, map_element->base_height * 8, map_element->clearance_height * 8);
|
|
peep->staff_gardens_watered++;
|
|
peep->var_45 |= (1 << 4);
|
|
}
|
|
}
|
|
}
|
|
if (map_element_is_last_for_tile(map_element)) {
|
|
peep_state_reset(peep);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* rct2: 0x006BF6C9 */
|
|
static void peep_update_emptying_bin(rct_peep* peep){
|
|
peep->var_E2 = 0;
|
|
|
|
if (peep->sub_state == 0){
|
|
if (!sub_68F3AE(peep))return;
|
|
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
|
|
|
|
peep->sprite_direction = (peep->var_37 & 3) << 3;
|
|
peep->action = PEEP_ACTION_STAFF_EMPTY_BIN;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
peep->sub_state = 1;
|
|
}
|
|
else if (peep->sub_state == 1){
|
|
|
|
if (peep->action == PEEP_ACTION_NONE_2){
|
|
peep_state_reset(peep);
|
|
return;
|
|
}
|
|
|
|
sint16 x = 0, y = 0;
|
|
sub_6939EB(&x, &y, peep);
|
|
|
|
if (peep->action_frame != 11)return;
|
|
|
|
rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
|
|
|
|
for (;; map_element++) {
|
|
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH) {
|
|
if (peep->next_z == map_element->base_height)
|
|
break;
|
|
}
|
|
if (map_element_is_last_for_tile(map_element)) {
|
|
peep_state_reset(peep);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ((map_element->properties.path.additions & 0x0F) == 0) {
|
|
peep_state_reset(peep);
|
|
return;
|
|
}
|
|
|
|
rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[(map_element->properties.path.additions & 0xF) - 1];
|
|
if (
|
|
!(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG1)
|
|
|| map_element->flags & (1 << 5)
|
|
|| map_element->properties.path.additions & (1 << 7)
|
|
) {
|
|
peep_state_reset(peep);
|
|
return;
|
|
}
|
|
|
|
map_element->properties.path.addition_status = ((3 << peep->var_37) << peep->var_37);
|
|
|
|
gfx_invalidate_scrollingtext(peep->next_x, peep->next_y, map_element->base_height * 8, map_element->clearance_height * 8);
|
|
|
|
peep->staff_bins_emptied++;
|
|
peep->var_45 |= (1 << 4);
|
|
}
|
|
}
|
|
|
|
/* rct2: 0x6BF641 */
|
|
static void peep_update_sweeping(rct_peep* peep){
|
|
peep->var_E2 = 0;
|
|
if (!sub_68F3AE(peep))return;
|
|
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
if (peep->action == PEEP_ACTION_STAFF_SWEEP && peep->action_frame == 8){
|
|
//Remove sick at this location
|
|
RCT2_CALLPROC_X(0x6738E1, peep->x, 0, peep->y, peep->z, 0, 0, 0);
|
|
peep->staff_litter_swept++;
|
|
peep->var_45 |= (1 << 4);
|
|
}
|
|
sint16 x = 0, y = 0;
|
|
if (sub_6939EB(&x, &y, peep)){
|
|
int eax = x, ebx, ecx = y, z, ebp, edi;
|
|
|
|
RCT2_CALLFUNC_X(0x694921, &eax, &ebx, &ecx, &z, (int*)&peep, &edi, &ebp);
|
|
x = eax;
|
|
y = ecx;
|
|
sprite_move(x, y, z, (rct_sprite*)peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
|
|
peep->var_37++;
|
|
if (peep->var_37 != 2){
|
|
peep->action = PEEP_ACTION_STAFF_SWEEP;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
peep_state_reset(peep);
|
|
}
|
|
|
|
/* rct2: 0x6902A2 */
|
|
static void peep_update_1(rct_peep* peep){
|
|
if (!sub_68F3AE(peep))return;
|
|
|
|
peep_decrement_num_riders(peep);
|
|
|
|
if (peep->type == PEEP_TYPE_GUEST){
|
|
peep->state = PEEP_STATE_WALKING;
|
|
}
|
|
else{
|
|
peep->state = PEEP_STATE_PATROLLING;
|
|
}
|
|
peep_window_state_update(peep);
|
|
peep->destination_x = peep->x;
|
|
peep->destination_y = peep->y;
|
|
peep->destination_tolerence = 10;
|
|
peep->var_76 = 0;
|
|
peep->var_78 = peep->sprite_direction >> 3;
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x690009
|
|
*/
|
|
static void peep_update_picked(rct_peep* peep){
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x1F) return;
|
|
peep->sub_state++;
|
|
if (peep->sub_state == 13){
|
|
peep_insert_new_thought(peep, PEEP_THOUGHT_HELP, 0xFF);
|
|
}
|
|
}
|
|
|
|
/* rct2: 0x6914CD */
|
|
static void peep_update_leaving_park(rct_peep* peep){
|
|
if (peep->var_37 != 0){
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 2))return;
|
|
RCT2_CALLPROC_X(0x69A535, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
return;
|
|
}
|
|
|
|
sint16 x = 0, y = 0;
|
|
if (sub_6939EB(&x, &y, peep)){
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
sprite_move(x, y, peep->z, (rct_sprite*)peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
|
|
peep->var_2A = 1;
|
|
peep->destination_tolerence = 5;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16)--;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_BTM_TOOLBAR_DIRTY_FLAGS, uint16) |= BTM_TB_DIRTY_FLAG_PEEP_COUNT;
|
|
peep->var_37 = 1;
|
|
|
|
window_invalidate_by_class(WC_GUEST_LIST);
|
|
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 2))return;
|
|
RCT2_CALLPROC_X(0x69A535, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
|
|
/* rct2: 0x6916D6 */
|
|
static void peep_update_watching(rct_peep* peep){
|
|
if (peep->sub_state == 0){
|
|
if (!sub_68F3AE(peep))return;
|
|
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
|
|
|
|
peep->destination_x = peep->x;
|
|
peep->destination_y = peep->y;
|
|
|
|
peep->sprite_direction = (peep->var_37 & 3) * 8;
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
peep->action = 0xFE;
|
|
peep->var_6F = 2;
|
|
|
|
RCT2_CALLPROC_X(0x693BAB, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
|
|
peep->sub_state++;
|
|
|
|
peep->time_to_stand = clamp(0, ((129 - peep->energy) * 16 + 50) / 2, 255);
|
|
RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
else if (peep->sub_state == 1){
|
|
if (peep->action < 0xFE){
|
|
//6917F6
|
|
sint16 x = 0, y = 0;
|
|
sub_6939EB(&x, &y, peep);
|
|
|
|
if (peep->action != 0xFF)return;
|
|
peep->action = 0xFE;
|
|
}
|
|
else{
|
|
if (peep_has_food(peep)){
|
|
if ((scenario_rand() & 0xFFFF) <= 1310){
|
|
peep->action = PEEP_ACTION_CHECK_WATCH;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ((scenario_rand() & 0xFFFF) <= 655){
|
|
peep->action = PEEP_ACTION_TAKE_PHOTO;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
|
|
if ((peep->standing_flags & 1)){
|
|
if ((scenario_rand() & 0xFFFF) <= 655){
|
|
peep->action = PEEP_ACTION_WAVE;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
peep->standing_flags ^= (1 << 7);
|
|
if (!(peep->standing_flags & (1 << 7)))return;
|
|
|
|
peep->time_to_stand--;
|
|
if (peep->time_to_stand != 0)return;
|
|
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_WALKING;
|
|
peep_window_state_update(peep);
|
|
RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
// Send peep to the center of current tile.
|
|
peep->destination_x = (peep->x & 0xFFE0) + 16;
|
|
peep->destination_y = (peep->y & 0xFFE0) + 16;
|
|
peep->destination_tolerence = 5;
|
|
sub_693B58(peep);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x691451
|
|
*/
|
|
static void peep_update_entering_park(rct_peep* peep){
|
|
if (peep->var_37 != 1){
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if ((RCT2_GLOBAL(0xF1EE18, uint16) & 2)){
|
|
RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK, uint16)--;
|
|
RCT2_CALLPROC_X(0x69A535, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
return;
|
|
}
|
|
sint16 x = 0, y = 0;
|
|
if (sub_6939EB(&x, &y, peep)){
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
sprite_move(x, y, peep->z, (rct_sprite*)peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
return;
|
|
}
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_FALLING;
|
|
peep_window_state_update(peep);
|
|
|
|
peep->var_2A = 0;
|
|
peep->time_in_park = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, sint32);
|
|
RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16)++;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK, uint16)--;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_BTM_TOOLBAR_DIRTY_FLAGS, uint16) |= BTM_TB_DIRTY_FLAG_PEEP_COUNT;
|
|
window_invalidate_by_class(WC_GUEST_LIST);
|
|
}
|
|
|
|
/* rct2: 0x00690582*/
|
|
static int peep_update_walking_find_bench(rct_peep* peep){
|
|
if (!peep_should_find_bench(peep))return 0;
|
|
|
|
rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5);
|
|
|
|
for (;; map_element++){
|
|
if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH){
|
|
if (peep->next_z == map_element->base_height)break;
|
|
}
|
|
if (map_element->flags&MAP_ELEMENT_FLAG_LAST_TILE){
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
uint8 additions = map_element->properties.path.additions & 0xF;
|
|
|
|
if (!additions) return 0;
|
|
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
|
|
|
|
if (!(sceneryEntry->path_bit.var_06 & 0x2))return 0;
|
|
|
|
if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return 0;
|
|
|
|
if (map_element->properties.path.additions & 0x80)return 0;
|
|
|
|
int edges = (map_element->properties.path.edges & 0xF) ^ 0xF;
|
|
if (edges == 0) return 0;
|
|
|
|
uint8 chosen_edge = scenario_rand() & 0x3;
|
|
|
|
for (; !(edges & (1 << chosen_edge));)chosen_edge = (chosen_edge + 1) & 0x3;
|
|
|
|
uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[(peep->x & 0x1FE0 << 3) | (peep->y >> 5)];
|
|
uint8 free_edge = 3;
|
|
|
|
for (rct_sprite* sprite = &g_sprite_list[sprite_id]; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->unknown.var_02){
|
|
if (sprite->unknown.linked_list_type_offset != SPRITE_LINKEDLIST_OFFSET_PEEP)continue;
|
|
|
|
if (sprite->peep.state != PEEP_STATE_SITTING)continue;
|
|
|
|
if (peep->z != sprite->peep.z)continue;
|
|
|
|
if ((sprite->peep.var_37 & 0x3) != chosen_edge)continue;
|
|
|
|
free_edge &= ~(1 << ((sprite->peep.var_37 & 0x4) >> 2));
|
|
}
|
|
|
|
if (!free_edge) return 0;
|
|
|
|
free_edge ^= 0x3;
|
|
if (!free_edge){
|
|
if (scenario_rand() & 0x8000000) free_edge = 1;
|
|
}
|
|
|
|
peep->var_37 = ((free_edge & 1) << 2) | chosen_edge;
|
|
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_SITTING;
|
|
peep_window_state_update(peep);
|
|
|
|
peep->sub_state = 0;
|
|
|
|
int ebx = peep->var_37 & 0x7;
|
|
int x = (peep->x & 0xFFE0) + RCT2_ADDRESS(0x981F2C, uint16)[ebx * 2];
|
|
int y = (peep->y & 0xFFE0) + RCT2_ADDRESS(0x981F2E, uint16)[ebx * 2];
|
|
|
|
peep->destination_x = x;
|
|
peep->destination_y = y;
|
|
peep->destination_tolerence = 3;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int peep_update_walking_find_bin(rct_peep* peep){
|
|
if (!peep_has_empty_container(peep)) return 0;
|
|
|
|
if (peep->next_var_29 & 0x18)return 0;
|
|
|
|
rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5);
|
|
|
|
for (;; map_element++){
|
|
if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH){
|
|
if (peep->next_z == map_element->base_height)break;
|
|
}
|
|
if (map_element->flags&MAP_ELEMENT_FLAG_LAST_TILE){
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
uint8 additions = map_element->properties.path.additions & 0xF;
|
|
|
|
if (!additions) return 0;
|
|
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
|
|
|
|
if (!(sceneryEntry->path_bit.var_06 & 0x1))return 0;
|
|
|
|
if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return 0;
|
|
|
|
if (map_element->properties.path.additions & 0x80)return 0;
|
|
|
|
int edges = (map_element->properties.path.edges & 0xF) ^ 0xF;
|
|
if (edges == 0) return 0;
|
|
|
|
uint8 chosen_edge = scenario_rand() & 0x3;
|
|
|
|
//ecx
|
|
uint8 addition_status = map_element->properties.path.addition_status;
|
|
|
|
chosen_edge = ror8(ror8(addition_status, chosen_edge),chosen_edge);
|
|
|
|
|
|
|
|
for (uint8 free_edge = 4; free_edge != 0; free_edge--){
|
|
if (addition_status & 0x3){
|
|
if (edges&(1 << chosen_edge))break;
|
|
}
|
|
chosen_edge = (chosen_edge + 1) & 0x3;
|
|
addition_status = ror8(addition_status, 2);
|
|
if ((free_edge - 1) == 0) return 0;
|
|
}
|
|
|
|
peep->var_37 = chosen_edge;
|
|
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_USING_BIN;
|
|
peep_window_state_update(peep);
|
|
|
|
peep->sub_state = 0;
|
|
|
|
int ebx = peep->var_37 & 0x3;
|
|
int x = (peep->x & 0xFFE0) + RCT2_ADDRESS(0x992A4C, uint16)[ebx * 2];
|
|
int y = (peep->y & 0xFFE0) + RCT2_ADDRESS(0x992A4E, uint16)[ebx * 2];
|
|
|
|
peep->destination_x = x;
|
|
peep->destination_y = y;
|
|
peep->destination_tolerence = 3;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* rct2: 0x00690848*/
|
|
static void peep_update_walking_break_scenery(rct_peep* peep){
|
|
if (!(peep->flags & PEEP_FLAGS_ANGRY)){
|
|
if (peep->happiness >= 48) return;
|
|
if (peep->energy < 85) return;
|
|
if (peep->state != PEEP_STATE_WALKING) return;
|
|
|
|
if ((peep->var_E1 & 0xC0) != 0xC0 &&
|
|
(peep->var_E3 & 0xC0) != 0xC0) return;
|
|
|
|
if ((scenario_rand() & 0xFFFF) > 3276) return;
|
|
}
|
|
|
|
if (peep->next_var_29 & 0x18) return;
|
|
|
|
rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5);
|
|
|
|
for (;; map_element++){
|
|
if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH){
|
|
if (peep->next_z == map_element->base_height)break;
|
|
}
|
|
if (map_element->flags&MAP_ELEMENT_FLAG_LAST_TILE){
|
|
return;
|
|
}
|
|
}
|
|
|
|
uint8 additions = map_element->properties.path.additions & 0xF;
|
|
|
|
if (!additions) return;
|
|
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
|
|
|
|
if (!(sceneryEntry->path_bit.var_06 & 0x4))return;
|
|
|
|
if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return;
|
|
|
|
if (map_element->properties.path.additions & 0x80)return;
|
|
|
|
int edges = map_element->properties.path.edges & 0xF;
|
|
if (edges == 0xF) return;
|
|
|
|
rct_peep* inner_peep;
|
|
uint16 sprite_index;
|
|
|
|
FOR_ALL_STAFF(sprite_index, inner_peep){
|
|
if (inner_peep->staff_type != STAFF_TYPE_SECURITY)continue;
|
|
|
|
if (inner_peep->x == (sint16)SPRITE_LOCATION_NULL)continue;
|
|
|
|
int x_diff = abs(inner_peep->x - peep->x);
|
|
int y_diff = abs(inner_peep->y - peep->y);
|
|
|
|
if (max(x_diff, y_diff) < 224)return;
|
|
}
|
|
|
|
map_element->flags |= MAP_ELEMENT_FLAG_BROKEN;
|
|
|
|
map_invalidate_tile(
|
|
peep->next_x,
|
|
peep->next_y,
|
|
(map_element->base_height << 3) + 32,
|
|
map_element->base_height << 3);
|
|
|
|
peep->var_F3 = 0x10;
|
|
|
|
return;
|
|
}
|
|
|
|
/* rct2: 0x006912A3 */
|
|
static void peep_update_buying(rct_peep* peep)
|
|
{
|
|
RCT2_CALLPROC_X(0x006912A3, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
return;
|
|
if (!sub_68F3AE(peep))return;
|
|
|
|
rct_ride* ride = GET_RIDE(peep->current_ride);
|
|
if (ride->type == RIDE_TYPE_NULL || ride->status != RIDE_STATUS_OPEN){
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_FALLING;
|
|
peep_window_state_update(peep);
|
|
return;
|
|
}
|
|
|
|
if (ride->type == RIDE_TYPE_ATM){
|
|
//6913D9
|
|
}
|
|
|
|
if (peep->sub_state == 1){
|
|
//69138F
|
|
}
|
|
//6912E9
|
|
}
|
|
/* rct2: 0x0069030A */
|
|
static void peep_update_walking(rct_peep* peep){
|
|
//RCT2_CALLPROC_X(0x0069030A, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
//return;
|
|
|
|
if (!sub_68F3AE(peep))return;
|
|
|
|
if (peep->flags & PEEP_FLAGS_WAVING){
|
|
if (peep->action >= PEEP_ACTION_NONE_1){
|
|
if ((0xFFFF & scenario_rand()) < 936){
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
peep->action = PEEP_ACTION_WAVE_2;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (peep->flags & PEEP_FLAGS_PHOTO){
|
|
if (peep->action >= PEEP_ACTION_NONE_1){
|
|
if ((0xFFFF & scenario_rand()) < 936){
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
peep->action = PEEP_ACTION_TAKE_PHOTO;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (peep->flags & PEEP_FLAGS_PAINTING){
|
|
if (peep->action >= PEEP_ACTION_NONE_1){
|
|
if ((0xFFFF & scenario_rand()) < 936){
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
peep->action = PEEP_ACTION_DRAW_PICTURE;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (peep->flags & PEEP_FLAGS_LITTER){
|
|
if (!(peep->next_var_29 & 0x18)){
|
|
if ((0xFFFF & scenario_rand()) <= 4096){
|
|
int ebp = (scenario_rand() & 0x3) + 2;
|
|
int x = peep->x + (scenario_rand() & 0x7) - 3;
|
|
int y = peep->y + (scenario_rand() & 0x7) - 3;
|
|
int direction = (scenario_rand() & 0x3);
|
|
|
|
RCT2_CALLPROC_X(0x67375D, x, direction, y, peep->z, 0, 0, ebp);
|
|
}
|
|
}
|
|
}
|
|
else if (peep_has_empty_container(peep)){
|
|
if ((!(peep->next_var_29 & 0x18)) &&
|
|
((peep->sprite_index & 0x1FF) == (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x1FF))&&
|
|
((0xFFFF & scenario_rand()) <= 4096)){
|
|
|
|
uint8 pos_stnd = 0;
|
|
for (int container = peep->item_standard_flags &
|
|
(PEEP_ITEM_EMPTY_CAN |
|
|
PEEP_ITEM_EMPTY_BURGER_BOX |
|
|
PEEP_ITEM_EMPTY_CUP |
|
|
PEEP_ITEM_RUBBISH |
|
|
PEEP_ITEM_EMPTY_BOX |
|
|
PEEP_ITEM_EMPTY_BOTTLE); pos_stnd < 32; pos_stnd++)if (container&(1<<pos_stnd))break;
|
|
|
|
int bp = 0;
|
|
|
|
if (pos_stnd != 32){
|
|
peep->item_standard_flags &= ~(1 << pos_stnd);
|
|
bp = RCT2_ADDRESS(0x97EFCC, uint8)[pos_stnd];
|
|
}
|
|
else{
|
|
uint8 pos_extr = 0;
|
|
for (int container = peep->item_extra_flags &
|
|
(PEEP_ITEM_EMPTY_BOWL_RED |
|
|
PEEP_ITEM_EMPTY_DRINK_CARTON |
|
|
PEEP_ITEM_EMPTY_JUICE_CUP |
|
|
PEEP_ITEM_EMPTY_BOWL_BLUE); pos_extr < 32; pos_extr++)if (container&(1 << pos_extr))break;
|
|
peep->item_extra_flags &= ~(1 << pos_extr);
|
|
bp = RCT2_ADDRESS(0x97EFE8, uint8)[pos_extr];
|
|
}
|
|
|
|
peep->var_45 |= 8;
|
|
RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
|
|
int x = peep->x + (scenario_rand() & 0x7) - 3;
|
|
int y = peep->y + (scenario_rand() & 0x7) - 3;
|
|
int direction = (scenario_rand() & 0x3);
|
|
|
|
RCT2_CALLPROC_X(0x67375D, x, direction, y, peep->z, 0, 0, bp);
|
|
}
|
|
}
|
|
|
|
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
|
|
|
|
if ((peep->next_var_29 & 0x18) == 8){
|
|
rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5);
|
|
|
|
while ((map_element->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_SURFACE) map_element++;
|
|
|
|
int water_height = map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK;
|
|
if (water_height){
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
water_height *= 16;
|
|
sprite_move(peep->x, peep->y, water_height, (rct_sprite*)peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_FALLING;
|
|
peep_window_state_update(peep);
|
|
return;
|
|
}
|
|
}
|
|
|
|
peep_check_if_lost(peep);
|
|
peep_check_cant_find_ride(peep);
|
|
peep_check_cant_find_exit(peep);
|
|
|
|
if (peep_update_walking_find_bench(peep))return;
|
|
|
|
if (peep_update_walking_find_bin(peep))return;
|
|
|
|
peep_update_walking_break_scenery(peep);
|
|
|
|
if (peep->state != PEEP_STATE_WALKING)return;
|
|
|
|
if (peep->flags & PEEP_FLAGS_LEAVING_PARK)return;
|
|
|
|
if (peep->nausea > 140)return;
|
|
|
|
if (peep->happiness < 120)return;
|
|
|
|
if (peep->bathroom > 140)return;
|
|
|
|
uint16 chance = 13107;
|
|
if (peep_has_food(peep))chance = 2849;
|
|
|
|
if ((scenario_rand() & 0xFFFF) > chance)return;
|
|
|
|
if (peep->next_var_29 & 0x1C)return;
|
|
|
|
rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5);
|
|
|
|
for (;; map_element++){
|
|
if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH){
|
|
if (peep->next_z == map_element->base_height)break;
|
|
}
|
|
if (map_element->flags&MAP_ELEMENT_FLAG_LAST_TILE){
|
|
return;
|
|
}
|
|
}
|
|
|
|
uint8 additions = map_element->properties.path.additions & 0xF;
|
|
|
|
int ebp = 15;
|
|
|
|
if (additions){
|
|
if (!(map_element->properties.path.additions & 0x80)){
|
|
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
|
|
|
|
if (!(sceneryEntry->path_bit.var_06 & 0x2)) ebp = 9;
|
|
}
|
|
}
|
|
|
|
int edges = (map_element->properties.path.edges & 0xF) ^ 0xF;
|
|
if (edges == 0) return;
|
|
|
|
uint8 chosen_edge = scenario_rand() & 0x3;
|
|
|
|
for (; !(edges & (1 << chosen_edge));)chosen_edge = (chosen_edge + 1) & 3;
|
|
|
|
uint8 ride_to_view;
|
|
uint8 ride_seat_to_view;
|
|
{
|
|
int eax = chosen_edge, _ebx = 0, ecx, edx = 0, esi = (int)peep, _ebp = 0, edi = 0;
|
|
// Work out what to look at
|
|
if (RCT2_CALLFUNC_X(0x00690B99, &eax, &_ebx, &ecx, &edx, &esi, &edi, &_ebp) & 0x100)return;
|
|
|
|
ride_to_view = ecx & 0xFF;
|
|
ride_seat_to_view = (ecx & 0xFF00) >> 8;
|
|
}
|
|
|
|
uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[(peep->x & 0x1FE0 << 3) | (peep->y >> 5)];
|
|
for (rct_sprite* sprite = &g_sprite_list[sprite_id]; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->unknown.var_02){
|
|
if (sprite->unknown.linked_list_type_offset != SPRITE_LINKEDLIST_OFFSET_PEEP)continue;
|
|
|
|
if (sprite->peep.state != PEEP_STATE_WATCHING)continue;
|
|
|
|
if (peep->z != sprite->peep.z)continue;
|
|
|
|
if ((sprite->peep.var_37 & 0x3) != chosen_edge)continue;
|
|
|
|
ebp &= ~(1 << ((sprite->peep.var_37 & 0x1C) >> 2));
|
|
}
|
|
|
|
if (!ebp)return;
|
|
|
|
uint8 chosen_position = scenario_rand() & 0x3;
|
|
|
|
for (; !(ebp & (1 << chosen_position));)chosen_position = (chosen_position + 1) & 3;
|
|
|
|
peep->current_ride = ride_to_view;
|
|
peep->current_seat = ride_seat_to_view;
|
|
peep->var_37 = chosen_edge | (chosen_position << 2);
|
|
|
|
peep_decrement_num_riders(peep);
|
|
peep->state = PEEP_STATE_WATCHING;
|
|
peep_window_state_update(peep);
|
|
|
|
peep->sub_state = 0;
|
|
|
|
int ebx = peep->var_37 & 0x1F;
|
|
int x = (peep->x & 0xFFE0) + RCT2_ADDRESS(0x981F4C, uint16)[ebx * 2];
|
|
int y = (peep->y & 0xFFE0) + RCT2_ADDRESS(0x981F4E, uint16)[ebx * 2];
|
|
|
|
peep->destination_x = x;
|
|
peep->destination_y = y;
|
|
peep->destination_tolerence = 3;
|
|
|
|
if (peep->current_seat&1){
|
|
peep_insert_new_thought(peep, PEEP_THOUGHT_NEW_RIDE, 0xFF);
|
|
}
|
|
if (peep->current_ride == 0xFF){
|
|
peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SCENERY, 0xFF);
|
|
}
|
|
}
|
|
|
|
/* From peep_update */
|
|
static void peep_update_thoughts(rct_peep* peep){
|
|
// Thoughts must always have a gap of at least
|
|
// 220 ticks in age between them. In order to
|
|
// allow this when a thought is new it enters
|
|
// a holding zone. Before it becomes fresh.
|
|
int add_fresh = 1;
|
|
int fresh_thought = -1;
|
|
for (int i = 0; i < PEEP_MAX_THOUGHTS; i++) {
|
|
if (peep->thoughts[i].type == PEEP_THOUGHT_TYPE_NONE)
|
|
break;
|
|
|
|
|
|
if (peep->thoughts[i].var_2 == 1) {
|
|
add_fresh = 0;
|
|
// If thought is fresh we wait 220 ticks
|
|
// before allowing a new thought to become fresh.
|
|
if (++peep->thoughts[i].var_3 >= 220) {
|
|
peep->thoughts[i].var_3 = 0;
|
|
// Thought is no longer fresh
|
|
peep->thoughts[i].var_2++;
|
|
add_fresh = 1;
|
|
}
|
|
}
|
|
else if (peep->thoughts[i].var_2 > 1) {
|
|
if (++peep->thoughts[i].var_3 == 0) {
|
|
// When thought is older than ~6900 ticks remove it
|
|
if (++peep->thoughts[i].var_2 >= 28) {
|
|
peep->var_45 |= 1;
|
|
|
|
// Clear top thought, push others up
|
|
memmove(&peep->thoughts[i], &peep->thoughts[i + 1], sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1));
|
|
peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
fresh_thought = i;
|
|
}
|
|
}
|
|
// If there are no fresh thoughts
|
|
// a previously new thought can become
|
|
// fresh.
|
|
if (add_fresh && fresh_thought != -1) {
|
|
peep->thoughts[fresh_thought].var_2 = 1;
|
|
peep->var_45 |= 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x0068FC1E
|
|
*/
|
|
static void peep_update(rct_peep *peep)
|
|
{
|
|
//RCT2_CALLPROC_X(0x0068FC1E, 0, 0, 0, 0, (int)peep, 0, 0); return;
|
|
//return;
|
|
|
|
if (peep->type == PEEP_TYPE_GUEST) {
|
|
if (peep->var_AD != 255)
|
|
if (++peep->var_AE < 720)
|
|
peep->var_AD = 255;
|
|
|
|
peep_update_thoughts(peep);
|
|
}
|
|
|
|
// Walking speed logic
|
|
unsigned int stepsToTake = peep->energy;
|
|
if (stepsToTake < 95 && peep->state == PEEP_STATE_QUEUING)
|
|
stepsToTake = 95;
|
|
if ((peep->flags & PEEP_FLAGS_SLOW_WALK) && peep->state != PEEP_STATE_QUEUING)
|
|
stepsToTake /= 2;
|
|
if (peep->action == 255 && (peep->next_var_29 & 4)) {
|
|
stepsToTake /= 2;
|
|
if (peep->state == PEEP_STATE_QUEUING)
|
|
stepsToTake += stepsToTake / 2;
|
|
}
|
|
|
|
unsigned int carryCheck = peep->var_73 + stepsToTake;
|
|
peep->var_73 = carryCheck;
|
|
if (carryCheck <= 255) {
|
|
// loc_68FD3A
|
|
RCT2_CALLPROC_X(0x0068FD3A, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
} else {
|
|
// loc_68FD2F
|
|
//RCT2_CALLPROC_X(0x68FD2F, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
//return;
|
|
switch (peep->state) {
|
|
case PEEP_STATE_FALLING:
|
|
peep_update_falling(peep);
|
|
break;
|
|
case PEEP_STATE_1:
|
|
peep_update_1(peep);
|
|
break;
|
|
case PEEP_STATE_QUEUING_FRONT:
|
|
peep_update_leaving_ride(peep);
|
|
break;
|
|
case PEEP_STATE_ON_RIDE:
|
|
// No action
|
|
break;
|
|
case PEEP_STATE_LEAVING_RIDE:
|
|
peep_update_leaving_ride(peep);
|
|
break;
|
|
case PEEP_STATE_WALKING:
|
|
peep_update_walking(peep);
|
|
break;
|
|
case PEEP_STATE_QUEUING:
|
|
peep_update_queuing(peep);
|
|
break;
|
|
case PEEP_STATE_ENTERING_RIDE:
|
|
// Calls the same function as leaving ride
|
|
peep_update_leaving_ride(peep);
|
|
break;
|
|
case PEEP_STATE_SITTING:
|
|
peep_update_sitting(peep);
|
|
break;
|
|
case PEEP_STATE_PICKED:
|
|
peep_update_picked(peep);
|
|
break;
|
|
case PEEP_STATE_PATROLLING:
|
|
RCT2_CALLPROC_X(0x006BF1FD, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
break;
|
|
case PEEP_STATE_MOWING:
|
|
peep_update_mowing(peep);
|
|
break;
|
|
case PEEP_STATE_SWEEPING:
|
|
peep_update_sweeping(peep);
|
|
break;
|
|
case PEEP_STATE_ENTERING_PARK:
|
|
peep_update_entering_park(peep);
|
|
break;
|
|
case PEEP_STATE_LEAVING_PARK:
|
|
peep_update_leaving_park(peep);
|
|
break;
|
|
case PEEP_STATE_ANSWERING:
|
|
RCT2_CALLPROC_X(0x006C0CB8, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
break;
|
|
case PEEP_STATE_FIXING:
|
|
RCT2_CALLPROC_X(0x006C0E8B, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
break;
|
|
case PEEP_STATE_BUYING:
|
|
peep_update_buying(peep);
|
|
break;
|
|
case PEEP_STATE_WATCHING:
|
|
peep_update_watching(peep);
|
|
break;
|
|
case PEEP_STATE_EMPTYING_BIN:
|
|
peep_update_emptying_bin(peep);
|
|
break;
|
|
case PEEP_STATE_USING_BIN:
|
|
RCT2_CALLPROC_X(0x00691089, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
break;
|
|
case PEEP_STATE_WATERING:
|
|
peep_update_watering(peep);
|
|
break;
|
|
case PEEP_STATE_HEADING_TO_INSPECTION:
|
|
RCT2_CALLPROC_X(0x006C16D7, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
break;
|
|
case PEEP_STATE_INSPECTING:
|
|
RCT2_CALLPROC_X(0x006C0E8B, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
break;
|
|
//There shouldnt be any more
|
|
default:
|
|
RCT2_CALLPROC_X(0x0068FD2F, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x0069BF41
|
|
**/
|
|
void peep_problem_warnings_update()
|
|
{
|
|
rct_peep* peep;
|
|
rct_ride* ride;
|
|
uint16 spriteIndex;
|
|
uint16 guests_in_park = RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16);
|
|
int hunger_counter = 0, lost_counter = 0, noexit_counter = 0, thirst_counter = 0,
|
|
litter_counter = 0, disgust_counter = 0, bathroom_counter = 0 ,vandalism_counter = 0;
|
|
static int warning_throttle[7] = { 0, 0, 0, 0, 0, 0, 0 };
|
|
|
|
RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, sint16) = ride_get_count(); // refactor this to somewhere else
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
if (peep->var_2A != 0 || peep->thoughts[0].var_2 > 5)
|
|
continue;
|
|
|
|
switch (peep->thoughts[0].type) {
|
|
case PEEP_THOUGHT_TYPE_LOST: //0x10
|
|
lost_counter++;
|
|
break;
|
|
|
|
case PEEP_THOUGHT_TYPE_HUNGRY: // 0x14
|
|
if (peep->guest_heading_to_ride_id == -1){
|
|
hunger_counter++;
|
|
break;
|
|
}
|
|
ride = &g_ride_list[peep->guest_heading_to_ride_id];
|
|
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000))
|
|
hunger_counter++;
|
|
break;
|
|
|
|
case PEEP_THOUGHT_TYPE_THIRSTY:
|
|
if (peep->guest_heading_to_ride_id == -1){
|
|
thirst_counter++;
|
|
break;
|
|
}
|
|
ride = &g_ride_list[peep->guest_heading_to_ride_id];
|
|
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x1000000))
|
|
thirst_counter++;
|
|
break;
|
|
|
|
case PEEP_THOUGHT_TYPE_BATHROOM:
|
|
if (peep->guest_heading_to_ride_id == -1){
|
|
bathroom_counter++;
|
|
break;
|
|
}
|
|
ride = &g_ride_list[peep->guest_heading_to_ride_id];
|
|
if (!(RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x2000000))
|
|
bathroom_counter++;
|
|
break;
|
|
|
|
case PEEP_THOUGHT_TYPE_BAD_LITTER: // 0x1a
|
|
litter_counter++;
|
|
break;
|
|
case PEEP_THOUGHT_TYPE_CANT_FIND_EXIT: // 0x1b
|
|
noexit_counter++;
|
|
break;
|
|
case PEEP_THOUGHT_TYPE_PATH_DISGUSTING: // 0x1f
|
|
disgust_counter++;
|
|
break;
|
|
case PEEP_THOUGHT_TYPE_VANDALISM: //0x21
|
|
vandalism_counter++;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// could maybe be packed into a loop, would lose a lot of clarity though
|
|
if (warning_throttle[0])
|
|
--warning_throttle[0];
|
|
else if ( hunger_counter >= PEEP_HUNGER_WARNING_THRESHOLD && hunger_counter >= guests_in_park / 16) {
|
|
warning_throttle[0] = 4;
|
|
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_ARE_HUNGRY, 20);
|
|
}
|
|
|
|
if (warning_throttle[1])
|
|
--warning_throttle[1];
|
|
else if (thirst_counter >= PEEP_THIRST_WARNING_THRESHOLD && thirst_counter >= guests_in_park / 16) {
|
|
warning_throttle[1] = 4;
|
|
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_ARE_THIRSTY, 21);
|
|
}
|
|
|
|
if (warning_throttle[2])
|
|
--warning_throttle[2];
|
|
else if (bathroom_counter >= PEEP_BATHROOM_WARNING_THRESHOLD && bathroom_counter >= guests_in_park / 16) {
|
|
warning_throttle[2] = 4;
|
|
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_CANT_FIND_BATHROOM, 22);
|
|
}
|
|
|
|
if (warning_throttle[3])
|
|
--warning_throttle[3];
|
|
else if (litter_counter >= PEEP_LITTER_WARNING_THRESHOLD && litter_counter >= guests_in_park / 32) {
|
|
warning_throttle[3] = 4;
|
|
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISLIKE_LITTER, 26);
|
|
}
|
|
|
|
if (warning_throttle[4])
|
|
--warning_throttle[4];
|
|
else if (disgust_counter >= PEEP_DISGUST_WARNING_THRESHOLD && disgust_counter >= guests_in_park / 32) {
|
|
warning_throttle[4] = 4;
|
|
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISGUSTED_BY_PATHS, 31);
|
|
}
|
|
|
|
if (warning_throttle[5])
|
|
--warning_throttle[5];
|
|
else if (vandalism_counter >= PEEP_VANDALISM_WARNING_THRESHOLD && vandalism_counter >= guests_in_park / 32) {
|
|
warning_throttle[5] = 4;
|
|
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISLIKE_VANDALISM, 33);
|
|
}
|
|
|
|
if (warning_throttle[6])
|
|
--warning_throttle[6];
|
|
else if (noexit_counter >= PEEP_NOEXIT_WARNING_THRESHOLD) {
|
|
warning_throttle[6] = 4;
|
|
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_GETTING_LOST_OR_STUCK, 27);
|
|
} else if (lost_counter >= PEEP_LOST_WARNING_THRESHOLD) {
|
|
warning_throttle[6] = 4;
|
|
news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_GETTING_LOST_OR_STUCK, 16);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BD18A
|
|
*/
|
|
void peep_update_crowd_noise()
|
|
{
|
|
rct_viewport *viewport;
|
|
uint16 spriteIndex;
|
|
rct_peep *peep;
|
|
int visiblePeeps;
|
|
|
|
if (!(RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)))
|
|
return;
|
|
|
|
if (RCT2_GLOBAL(0x009AF59C, uint8) != 0)
|
|
return;
|
|
|
|
if (!(RCT2_GLOBAL(0x009AF59D, uint8) & (1 << 0)))
|
|
return;
|
|
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
|
|
return;
|
|
|
|
viewport = RCT2_GLOBAL(0x00F438A4, rct_viewport*);
|
|
if (viewport == (rct_viewport*)-1)
|
|
return;
|
|
|
|
// Count the number of peeps visible
|
|
visiblePeeps = 0;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
if (peep->sprite_left == (sint16)0x8000)
|
|
continue;
|
|
if (viewport->view_x > peep->sprite_right)
|
|
continue;
|
|
if (viewport->view_x + viewport->view_width < peep->sprite_left)
|
|
continue;
|
|
if (viewport->view_y > peep->sprite_bottom)
|
|
continue;
|
|
if (viewport->view_y + viewport->view_height < peep->sprite_top)
|
|
continue;
|
|
|
|
visiblePeeps += peep->state == PEEP_STATE_QUEUING ? 1 : 2;
|
|
}
|
|
|
|
// This function doesn't account for the fact that the screen might be so big that 100 peeps could potentially be very
|
|
// spread out and therefore not produce any crowd noise. Perhaps a more sophisticated solution would check how many peeps
|
|
// were in close proximity to each other.
|
|
|
|
// Allows queuing peeps to make half as much noise, and at least 6 peeps must be visible for any crowd noise
|
|
visiblePeeps = (visiblePeeps / 2) - 6;
|
|
if (visiblePeeps < 0) {
|
|
// Mute crowd noise
|
|
if (RCT2_GLOBAL(0x009AF5FC, uint32) != 1) {
|
|
#ifdef USE_MIXER
|
|
Mixer_Stop_Channel(gCrowdSoundChannel);
|
|
gCrowdSoundChannel = 0;
|
|
#else
|
|
sound_channel_stop(2); //RCT2_CALLPROC_1(0x00401A05, int, 2);
|
|
#endif
|
|
RCT2_GLOBAL(0x009AF5FC, uint32) = 1;
|
|
}
|
|
} else {
|
|
sint32 volume;
|
|
|
|
// Formula to scale peeps to dB where peeps [0, 120] scales approximately logarithmically to [-3314, -150] dB/100
|
|
// 207360000 maybe related to DSBVOLUME_MIN which is -10,000 (dB/100)
|
|
volume = 120 - min(visiblePeeps, 120);
|
|
volume = volume * volume * volume * volume;
|
|
volume = (((207360000 - volume) >> viewport->zoom) - 207360000) / 65536 - 150;
|
|
|
|
// Check if crowd noise is already playing
|
|
if (RCT2_GLOBAL(0x009AF5FC, uint32) == 1) {
|
|
// Load and play crowd noise
|
|
#ifdef USE_MIXER
|
|
if (!gCrowdSoundChannel) {
|
|
gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2);
|
|
}
|
|
if (gCrowdSoundChannel) {
|
|
Mixer_Channel_Volume(gCrowdSoundChannel, DStoMixerVolume(volume));
|
|
RCT2_GLOBAL(0x009AF5FC, uint32) = volume;
|
|
}
|
|
#else
|
|
if (sound_channel_load_file2(2, (char*)get_file_path(PATH_ID_CSS2), 0)) {
|
|
sound_channel_play(2, 1, volume, 0, 0);
|
|
RCT2_GLOBAL(0x009AF5FC, uint32) = volume;
|
|
}
|
|
#endif
|
|
} else {
|
|
// Alter crowd noise volume
|
|
if (RCT2_GLOBAL(0x009AF5FC, uint32) != volume) {
|
|
#ifdef USE_MIXER
|
|
Mixer_Channel_Volume(gCrowdSoundChannel, DStoMixerVolume(volume));
|
|
#else
|
|
sound_channel_set_volume(2, volume);//RCT2_CALLPROC_2(0x00401AD3, int, int, 2, volume);
|
|
#endif
|
|
RCT2_GLOBAL(0x009AF5FC, uint32) = volume;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x0069BE9B
|
|
*/
|
|
void peep_applause()
|
|
{
|
|
uint16 spriteIndex;
|
|
rct_peep* peep;
|
|
|
|
FOR_ALL_GUESTS(spriteIndex, peep) {
|
|
if (peep->var_2A != 0)
|
|
continue;
|
|
|
|
// Release balloon
|
|
if (peep->item_standard_flags & PEEP_ITEM_BALLOON) {
|
|
peep->item_standard_flags &= ~PEEP_ITEM_BALLOON;
|
|
if (peep->x != 0x8000) {
|
|
create_balloon(peep->x, peep->y, peep->z + 9, peep->balloon_colour);
|
|
peep->var_45 |= 8;
|
|
RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
|
|
}
|
|
}
|
|
|
|
// Clap
|
|
if ((peep->state == PEEP_STATE_WALKING || peep->state == PEEP_STATE_QUEUING) && peep->action >= 254) {
|
|
peep->action = PEEP_ACTION_CLAP;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
}
|
|
}
|
|
|
|
// Play applause noise
|
|
sound_play_panned(SOUND_APPLAUSE, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2, 0, 0, 0);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x0069A05D
|
|
*/
|
|
rct_peep *peep_generate(int x, int y, int z)
|
|
{
|
|
int eax, ebx, ecx, edx, esi, edi, ebp;
|
|
eax = x;
|
|
ecx = y;
|
|
edx = z;
|
|
RCT2_CALLFUNC_X(0x0069A05D, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
|
return (rct_peep*)esi;
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x00698B0D
|
|
* peep.sprite_index (eax)
|
|
* thought.type (ebx)
|
|
* argument_1 (ecx & ebx)
|
|
* argument_2 (edx)
|
|
*/
|
|
void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argument_2){
|
|
rct_ride ride;
|
|
|
|
switch (peep->state){
|
|
case PEEP_STATE_FALLING:
|
|
*argument_1 = peep->action == PEEP_ACTION_DROWNING ? STR_DROWNING : STR_WALKING;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_1:
|
|
*argument_1 = STR_WALKING;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_ON_RIDE:
|
|
case PEEP_STATE_LEAVING_RIDE:
|
|
case PEEP_STATE_ENTERING_RIDE:
|
|
*argument_1 = STR_ON_RIDE;
|
|
ride = g_ride_list[peep->current_ride];
|
|
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride.type * 8, uint32) & 0x400000){
|
|
*argument_1 = STR_IN_RIDE;
|
|
}
|
|
*argument_1 |= (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
break;
|
|
case PEEP_STATE_BUYING:
|
|
ride = g_ride_list[peep->current_ride];
|
|
*argument_1 = STR_AT_RIDE | (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
break;
|
|
case PEEP_STATE_WALKING:
|
|
case PEEP_STATE_USING_BIN:
|
|
if (peep->guest_heading_to_ride_id != 0xFF){
|
|
ride = g_ride_list[peep->guest_heading_to_ride_id];
|
|
*argument_1 = STR_HEADING_FOR | (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
}
|
|
else{
|
|
*argument_1 = peep->flags & PEEP_FLAGS_LEAVING_PARK ? STR_LEAVING_PARK : STR_WALKING;
|
|
*argument_2 = 0;
|
|
}
|
|
break;
|
|
case PEEP_STATE_QUEUING_FRONT:
|
|
case PEEP_STATE_QUEUING:
|
|
ride = g_ride_list[peep->current_ride];
|
|
*argument_1 = STR_QUEUING_FOR | (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
break;
|
|
case PEEP_STATE_SITTING:
|
|
*argument_1 = STR_SITTING;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_WATCHING:
|
|
if (peep->current_ride != 0xFF){
|
|
ride = g_ride_list[peep->current_ride];
|
|
*argument_1 = STR_WATCHING_RIDE | (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
if (peep->current_seat & 0x1)
|
|
*argument_1 = STR_WATCHING_CONSTRUCTION_OF | (ride.name << 16);
|
|
else
|
|
*argument_1 = STR_WATCHING_RIDE | (ride.name << 16);
|
|
}
|
|
else{
|
|
*argument_1 = peep->current_seat & 0x1 ? STR_WATCHING_NEW_RIDE_BEING_CONSTRUCTED : STR_LOOKING_AT_SCENERY;
|
|
*argument_2 = 0;
|
|
}
|
|
break;
|
|
case PEEP_STATE_PICKED:
|
|
*argument_1 = STR_SELECT_LOCATION;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_PATROLLING:
|
|
case PEEP_STATE_ENTERING_PARK:
|
|
case PEEP_STATE_LEAVING_PARK:
|
|
*argument_1 = STR_WALKING;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_MOWING:
|
|
*argument_1 = STR_MOWING_GRASS;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_SWEEPING:
|
|
*argument_1 = STR_SWEEPING_FOOTPATH;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_WATERING:
|
|
*argument_1 = STR_WATERING_GARDENS;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_EMPTYING_BIN:
|
|
*argument_1 = STR_EMPTYING_LITTER_BIN;
|
|
*argument_2 = 0;
|
|
break;
|
|
case PEEP_STATE_ANSWERING:
|
|
if (peep->sub_state == 0){
|
|
*argument_1 = STR_WALKING;
|
|
*argument_2 = 0;
|
|
}
|
|
else if (peep->sub_state == 1){
|
|
*argument_1 = STR_ANSWERING_RADIO_CALL;
|
|
*argument_2 = 0;
|
|
}
|
|
else{
|
|
ride = g_ride_list[peep->current_ride];
|
|
*argument_1 = STR_RESPONDING_TO_RIDE_BREAKDOWN_CALL | (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
}
|
|
break;
|
|
case PEEP_STATE_FIXING:
|
|
ride = g_ride_list[peep->current_ride];
|
|
*argument_1 = STR_FIXING_RIDE | (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
break;
|
|
case PEEP_STATE_HEADING_TO_INSPECTION:
|
|
ride = g_ride_list[peep->current_ride];
|
|
*argument_1 = STR_HEADING_TO_RIDE_FOR_INSPECTION | (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
break;
|
|
case PEEP_STATE_INSPECTING:
|
|
ride = g_ride_list[peep->current_ride];
|
|
*argument_1 = STR_INSPECTING_RIDE | (ride.name << 16);
|
|
*argument_2 = ride.name_arguments;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x00698342
|
|
* thought.item (eax)
|
|
* thought.type (ebx)
|
|
* argument_1 (esi & ebx)
|
|
* argument_2 (esi+2)
|
|
*/
|
|
void get_arguments_from_thought(rct_peep_thought thought, uint32* argument_1, uint32* argument_2){
|
|
int esi = 0x9AC86C;
|
|
|
|
if ((RCT2_ADDRESS(0x981DB1, uint16)[thought.type] & 0xFF) & 1){
|
|
rct_ride* ride = &g_ride_list[thought.item];
|
|
esi = (int)(&(ride->name));
|
|
}
|
|
else if ((RCT2_ADDRESS(0x981DB1, uint16)[thought.type] & 0xFF) & 2){
|
|
if (thought.item < 0x20){
|
|
RCT2_GLOBAL(0x9AC86C, uint16) = thought.item + STR_ITEM_START;
|
|
}
|
|
else{
|
|
RCT2_GLOBAL(0x9AC86C, uint16) = thought.item + STR_ITEM2_START;
|
|
}
|
|
}
|
|
else if ((RCT2_ADDRESS(0x981DB1, uint16)[thought.type] & 0xFF) & 4){
|
|
if (thought.item < 0x20){
|
|
RCT2_GLOBAL(0x9AC86C, uint16) = thought.item + STR_ITEM_SINGULAR_START;
|
|
}
|
|
else
|
|
{
|
|
RCT2_GLOBAL(0x9AC86C, uint16) = thought.item + STR_ITEM2_SINGULAR_START;
|
|
}
|
|
}
|
|
else{
|
|
esi = 0x9AC864; //No thought?
|
|
}
|
|
*argument_1 = ((thought.type + STR_THOUGHT_START) & 0xFFFF) | (*((uint16*)esi) << 16);
|
|
*argument_2 = *((uint32*)(esi + 2)); //Always 0 apart from on rides?
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x00698827
|
|
* returns 1 on pickup (CF not set)
|
|
*/
|
|
int peep_can_be_picked_up(rct_peep* peep){
|
|
return RCT2_ADDRESS(0x982004, uint8)[peep->state] & 1;
|
|
}
|
|
|
|
enum{
|
|
PEEP_FACE_OFFSET_ANGRY = 0,
|
|
PEEP_FACE_OFFSET_VERY_VERY_SICK,
|
|
PEEP_FACE_OFFSET_VERY_SICK,
|
|
PEEP_FACE_OFFSET_SICK,
|
|
PEEP_FACE_OFFSET_VERY_TIRED,
|
|
PEEP_FACE_OFFSET_TIRED,
|
|
PEEP_FACE_OFFSET_VERY_VERY_UNHAPPY,
|
|
PEEP_FACE_OFFSET_VERY_UNHAPPY,
|
|
PEEP_FACE_OFFSET_UNHAPPY,
|
|
PEEP_FACE_OFFSET_NORMAL,
|
|
PEEP_FACE_OFFSET_HAPPY,
|
|
PEEP_FACE_OFFSET_VERY_HAPPY,
|
|
PEEP_FACE_OFFSET_VERY_VERY_HAPPY,
|
|
};
|
|
|
|
const int face_sprite_small[] = {
|
|
SPR_PEEP_SMALL_FACE_ANGRY,
|
|
SPR_PEEP_SMALL_FACE_VERY_VERY_SICK,
|
|
SPR_PEEP_SMALL_FACE_VERY_SICK,
|
|
SPR_PEEP_SMALL_FACE_SICK,
|
|
SPR_PEEP_SMALL_FACE_VERY_TIRED,
|
|
SPR_PEEP_SMALL_FACE_TIRED,
|
|
SPR_PEEP_SMALL_FACE_VERY_VERY_UNHAPPY,
|
|
SPR_PEEP_SMALL_FACE_VERY_UNHAPPY,
|
|
SPR_PEEP_SMALL_FACE_UNHAPPY,
|
|
SPR_PEEP_SMALL_FACE_NORMAL,
|
|
SPR_PEEP_SMALL_FACE_HAPPY,
|
|
SPR_PEEP_SMALL_FACE_VERY_HAPPY,
|
|
SPR_PEEP_SMALL_FACE_VERY_VERY_HAPPY,
|
|
};
|
|
|
|
const int face_sprite_large[] = {
|
|
SPR_PEEP_LARGE_FACE_ANGRY,
|
|
SPR_PEEP_LARGE_FACE_VERY_VERY_SICK,
|
|
SPR_PEEP_LARGE_FACE_VERY_SICK,
|
|
SPR_PEEP_LARGE_FACE_SICK,
|
|
SPR_PEEP_LARGE_FACE_VERY_TIRED,
|
|
SPR_PEEP_LARGE_FACE_TIRED,
|
|
SPR_PEEP_LARGE_FACE_VERY_VERY_UNHAPPY,
|
|
SPR_PEEP_LARGE_FACE_VERY_UNHAPPY,
|
|
SPR_PEEP_LARGE_FACE_UNHAPPY,
|
|
SPR_PEEP_LARGE_FACE_NORMAL,
|
|
SPR_PEEP_LARGE_FACE_HAPPY,
|
|
SPR_PEEP_LARGE_FACE_VERY_HAPPY,
|
|
SPR_PEEP_LARGE_FACE_VERY_VERY_HAPPY,
|
|
};
|
|
|
|
int get_face_sprite_offset(rct_peep *peep){
|
|
|
|
// ANGRY
|
|
if (peep->var_F3) return PEEP_FACE_OFFSET_ANGRY;
|
|
|
|
// VERY_VERY_SICK
|
|
if (peep->nausea > 200) return PEEP_FACE_OFFSET_VERY_VERY_SICK;
|
|
|
|
// VERY_SICK
|
|
if (peep->nausea > 170) return PEEP_FACE_OFFSET_VERY_SICK;
|
|
|
|
// SICK
|
|
if (peep->nausea > 140) return PEEP_FACE_OFFSET_SICK;
|
|
|
|
// VERY_TIRED
|
|
if (peep->energy < 46) return PEEP_FACE_OFFSET_VERY_TIRED;
|
|
|
|
// TIRED
|
|
if (peep->energy < 70) return PEEP_FACE_OFFSET_TIRED;
|
|
|
|
int offset = PEEP_FACE_OFFSET_VERY_VERY_UNHAPPY;
|
|
//There are 7 different happiness based faces
|
|
for (int i = 37; peep->happiness >= i; i += 37)
|
|
{
|
|
offset++;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
/**
|
|
* Function split into large and small sprite
|
|
* rct2: 0x00698721
|
|
*/
|
|
int get_peep_face_sprite_small(rct_peep *peep){
|
|
return face_sprite_small[get_face_sprite_offset(peep)];
|
|
}
|
|
|
|
/**
|
|
* Function split into large and small sprite
|
|
* rct2: 0x00698721
|
|
*/
|
|
int get_peep_face_sprite_large(rct_peep *peep){
|
|
return face_sprite_large[get_face_sprite_offset(peep)];
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x0069A5A0
|
|
* tests if a peep's name matches a cheat code, normally returns using a register flag
|
|
* @param index (eax)
|
|
* @param ride (esi)
|
|
*/
|
|
int peep_check_easteregg_name(int index, rct_peep *peep)
|
|
{
|
|
char buffer[256];
|
|
|
|
format_string(buffer, peep->name_string_idx, &peep->id);
|
|
return _stricmp(buffer, gPeepEasterEggNames[index]) == 0;
|
|
}
|
|
|
|
int peep_get_easteregg_name_id(rct_peep *peep)
|
|
{
|
|
char buffer[256];
|
|
int i;
|
|
|
|
format_string(buffer, peep->name_string_idx, &peep->id);
|
|
|
|
for (i = 0; i < countof(gPeepEasterEggNames); i++)
|
|
if (_stricmp(buffer, gPeepEasterEggNames[i]) == 0)
|
|
return i;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
int peep_is_mechanic(rct_peep *peep)
|
|
{
|
|
return (
|
|
peep->sprite_identifier == SPRITE_IDENTIFIER_PEEP &&
|
|
peep->type == PEEP_TYPE_STAFF &&
|
|
peep->staff_type == STAFF_TYPE_MECHANIC
|
|
);
|
|
}
|
|
|
|
static int peep_has_food_standard_flag(rct_peep* peep){
|
|
return peep->item_standard_flags &(
|
|
PEEP_ITEM_DRINK |
|
|
PEEP_ITEM_BURGER |
|
|
PEEP_ITEM_FRIES |
|
|
PEEP_ITEM_ICE_CREAM |
|
|
PEEP_ITEM_COTTON_CANDY |
|
|
PEEP_ITEM_PIZZA |
|
|
PEEP_ITEM_POPCORN |
|
|
PEEP_ITEM_HOT_DOG |
|
|
PEEP_ITEM_TENTACLE |
|
|
PEEP_ITEM_CANDY_APPLE |
|
|
PEEP_ITEM_DONUT |
|
|
PEEP_ITEM_COFFEE |
|
|
PEEP_ITEM_CHICKEN |
|
|
PEEP_ITEM_LEMONADE);
|
|
}
|
|
|
|
static int peep_has_food_extra_flag(rct_peep* peep){
|
|
return peep->item_extra_flags &(
|
|
PEEP_ITEM_PRETZEL |
|
|
PEEP_ITEM_CHOCOLATE |
|
|
PEEP_ITEM_ICED_TEA |
|
|
PEEP_ITEM_FUNNEL_CAKE |
|
|
PEEP_ITEM_BEEF_NOODLES |
|
|
PEEP_ITEM_FRIED_RICE_NOODLES |
|
|
PEEP_ITEM_WONTON_SOUP |
|
|
PEEP_ITEM_MEATBALL_SOUP |
|
|
PEEP_ITEM_FRUIT_JUICE |
|
|
PEEP_ITEM_SOYBEAN_MILK |
|
|
PEEP_ITEM_SU_JONGKWA |
|
|
PEEP_ITEM_SUB_SANDWICH |
|
|
PEEP_ITEM_COOKIE |
|
|
PEEP_ITEM_ROAST_SAUSAGE
|
|
);
|
|
}
|
|
|
|
/* To simplify check of 0x36BA3E0 and 0x11FF78
|
|
* returns 0 on no food.
|
|
*/
|
|
int peep_has_food(rct_peep* peep){
|
|
return peep_has_food_standard_flag(peep) ||
|
|
peep_has_food_extra_flag(peep);
|
|
}
|
|
|
|
static int peep_has_empty_container(rct_peep* peep){
|
|
return (peep->item_standard_flags &(
|
|
PEEP_ITEM_EMPTY_CAN |
|
|
PEEP_ITEM_EMPTY_BURGER_BOX |
|
|
PEEP_ITEM_EMPTY_CUP |
|
|
PEEP_ITEM_RUBBISH |
|
|
PEEP_ITEM_EMPTY_BOX |
|
|
PEEP_ITEM_EMPTY_BOTTLE
|
|
)) ||
|
|
(peep->item_extra_flags &(
|
|
PEEP_ITEM_EMPTY_BOWL_RED |
|
|
PEEP_ITEM_EMPTY_DRINK_CARTON |
|
|
PEEP_ITEM_EMPTY_JUICE_CUP |
|
|
PEEP_ITEM_EMPTY_BOWL_BLUE
|
|
));
|
|
}
|
|
|
|
/* Simplifies 0x690582. Returns 1 if should find bench*/
|
|
static int peep_should_find_bench(rct_peep* peep){
|
|
if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK)){
|
|
if (peep_has_food(peep)){
|
|
if (peep->hunger > 128 && peep->happiness > 128){
|
|
return 0;
|
|
}
|
|
}
|
|
if (peep->nausea <= 170 || peep->energy > 50){
|
|
return 0;
|
|
}
|
|
|
|
if (!(peep->next_var_29 & 0x1C)){
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* rct2: 0x699F5A
|
|
* al:thought_type
|
|
* ah:thought_arguments
|
|
* esi: peep
|
|
*/
|
|
void peep_insert_new_thought(rct_peep *peep, uint8 thought_type, uint8 thought_arguments){
|
|
int action = RCT2_ADDRESS(0x981DB0, uint16)[thought_type];
|
|
|
|
if (action != 0xFF && peep->action >= 254){
|
|
peep->action = action;
|
|
peep->action_frame = 0;
|
|
peep->var_70 = 0;
|
|
sub_693B58(peep);
|
|
invalidate_sprite((rct_sprite*)peep);
|
|
}
|
|
|
|
for (int i = 0; i < PEEP_MAX_THOUGHTS; ++i){
|
|
rct_peep_thought* thought = &peep->thoughts[i];
|
|
// Remove the oldest thought by setting it to NONE.
|
|
if (thought->type == PEEP_THOUGHT_TYPE_NONE) break;
|
|
|
|
if (thought->type == thought_type && thought->item == thought_arguments){
|
|
// If the thought type has not changed then we need to move
|
|
// it to the top of the thought list. This is done by first removing the
|
|
// existing thought and placing it at the top.
|
|
memmove(thought, thought + 1, sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1));
|
|
break;
|
|
}
|
|
}
|
|
|
|
memmove(&peep->thoughts[1], &peep->thoughts[0], sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - 1));
|
|
|
|
peep->thoughts[0].type = thought_type;
|
|
peep->thoughts[0].item = thought_arguments;
|
|
peep->thoughts[0].var_2 = 0;
|
|
peep->thoughts[0].var_3 = 0;
|
|
|
|
peep->var_45 |= (1 << 0);
|
|
}
|
|
|
|
void peep_set_map_tooltip(rct_peep *peep)
|
|
{
|
|
if (peep->type == PEEP_TYPE_GUEST) {
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = peep->flags & PEEP_FLAGS_TRACKING ? 1450 : 1449;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint32) = get_peep_face_sprite_small(peep);
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 6, uint16) = peep->name_string_idx;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 8, uint32) = peep->id;
|
|
|
|
uint32 arg0, arg1;
|
|
get_arguments_from_action(peep, &arg0, &arg1);
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 12, uint32) = arg0;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 16, uint32) = arg1;
|
|
} else {
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1451;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = peep->name_string_idx;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 4, uint32) = peep->id;
|
|
|
|
uint32 arg0, arg1;
|
|
get_arguments_from_action(peep, &arg0, &arg1);
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 8, uint32) = arg0;
|
|
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 12, uint32) = arg1;
|
|
}
|
|
}
|