Merge pull request #12 from IntelOrca/develop

Fast forward
This commit is contained in:
Michael Steenbeek 2015-05-12 14:29:58 +02:00
commit e17986fbd6
73 changed files with 3509 additions and 810 deletions

View File

@ -2678,7 +2678,7 @@ STR_2676 :???
STR_2677 :???
STR_2678 :???
STR_2679 :???
STR_2680 :???
STR_2680 :Alle onderzoeken zijn voltooid
STR_2681 :{MEDIUMFONT}{BLACK}Krijg 5.000 extra geld
STR_2682 :{MEDIUMFONT}{BLACK}Wissel tussen betaalde en gratis entree
STR_2683 :{MEDIUMFONT}{BLACK}Alle bezoekers hebben een maximale tevredenheid

View File

@ -3459,3 +3459,4 @@ STR_5122 :Show all vehicles sharing a track/ride type
STR_5123 :Renew rides
STR_5124 :No Six Flags
STR_5125 :All destructable
STR_5126 :Random title music

View File

@ -3471,3 +3471,4 @@ STR_5122 :Show all vehicles sharing a track/ride type
STR_5123 :Renew rides
STR_5124 :No Six Flags
STR_5125 :All destructable
STR_5126 :Random title music

View File

@ -842,7 +842,7 @@ STR_0837 :Unable to initialize graphics system
STR_0838 :CD key code {INT32} is not valid for your RollerCoaster Tycoon 2 CD !{WINDOW_COLOUR_1}{WINDOW_COLOUR_1}Please un-install RollerCoaster Tycoon 2% and re-install with the correct CD Key Code
STR_0839 :{UINT16} x {UINT16}
STR_0840 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{UINT16} x {UINT16}
STR_0841 :Desktop window
STR_0841 :En une fenêtre
STR_0842 :640x480 plein écran
STR_0843 :800x600 plein écran
STR_0844 :1024x768 plein écran
@ -1336,10 +1336,10 @@ STR_1331 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VEL
STR_1332 :{VELOCITY}
STR_1333 :{STRINGID} - {STRINGID}{POP16}
STR_1334 :{STRINGID} - {STRINGID} {COMMA16}
STR_1335 :{STRINGID} - Entrance{POP16}{POP16}
STR_1336 :{STRINGID} - Station {POP16}{COMMA16} Entrance
STR_1337 :{STRINGID} - Exit{POP16}{POP16}
STR_1338 :{STRINGID} - Station {POP16}{COMMA16} Exit
STR_1335 :{STRINGID} - Entrée{POP16}{POP16}
STR_1336 :{STRINGID} - Entrée de station {POP16}{COMMA16}
STR_1337 :{STRINGID} - Sortie{POP16}{POP16}
STR_1338 :{STRINGID} - Sortie de station {POP16}{COMMA16}
STR_1339 :{BLACK}No test results yet...
STR_1340 :{WINDOW_COLOUR_2}Max. speed: {BLACK}{VELOCITY}
STR_1341 :{WINDOW_COLOUR_2}Ride time: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID}
@ -1416,7 +1416,7 @@ STR_1411 :{STRINGID} in the way
STR_1412 :{WINDOW_COLOUR_3}Data logging not available for this type of ride
STR_1413 :{WINDOW_COLOUR_3}Data logging will start when next {STRINGID} leaves {STRINGID}
STR_1414 :{SMALLFONT}{BLACK}{DURATION}
STR_1415 :{WINDOW_COLOUR_2}Velocity
STR_1415 :{WINDOW_COLOUR_2}Vitesse
STR_1416 :{WINDOW_COLOUR_2}Altitude
STR_1417 :{WINDOW_COLOUR_2}Vert.G's
STR_1418 :{WINDOW_COLOUR_2}Lat.G's
@ -1436,9 +1436,9 @@ STR_1431 :Marche
STR_1432 :Heading for {STRINGID}
STR_1433 :Queuing for {STRINGID}
STR_1434 :Drowning
STR_1435 :On {STRINGID}
STR_1436 :In {STRINGID}
STR_1437 :At {STRINGID}
STR_1435 :En {STRINGID}
STR_1436 :Dans {STRINGID}
STR_1437 :A {STRINGID}
STR_1438 :Sitting
STR_1439 :(select location)
STR_1440 :Mowing grass
@ -1469,7 +1469,7 @@ STR_1464 :Helix up (small)
STR_1465 :Helix up (large)
STR_1466 :Helix down (small)
STR_1467 :Helix down (large)
STR_1468 :Staff
STR_1468 :Personnel
STR_1469 :Ride must start and end with stations
STR_1470 :Station not long enough
STR_1471 :{WINDOW_COLOUR_2}Vitesse:
@ -2681,37 +2681,37 @@ STR_2676 :???
STR_2677 :???
STR_2678 :???
STR_2679 :???
STR_2680 :???
STR_2681 :???
STR_2682 :???
STR_2683 :???
STR_2684 :???
STR_2685 :???
STR_2686 :???
STR_2687 :???
STR_2688 :???
STR_2689 :???
STR_2690 :???
STR_2691 :???
STR_2692 :???
STR_2693 :???
STR_2694 :???
STR_2695 :???
STR_2696 :???
STR_2680 :All research complete
STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by 5,000
STR_2682 :{MEDIUMFONT}{BLACK}Toggle between Free and Paid Entry
STR_2683 :{MEDIUMFONT}{BLACK}Increases every peeps happiness to max
STR_2684 :{MEDIUMFONT}{BLACK}Large group of peeps arrive
STR_2685 :Simplex Noise Parameters
STR_2686 :{WINDOW_COLOUR_2}Low:
STR_2687 :{WINDOW_COLOUR_2}High:
STR_2688 :{WINDOW_COLOUR_2}Base Frequency:
STR_2689 :{WINDOW_COLOUR_2}Octaves:
STR_2690 :Map Generation
STR_2691 :{WINDOW_COLOUR_2}Base height:
STR_2692 :{WINDOW_COLOUR_2}Water level:
STR_2693 :{WINDOW_COLOUR_2}Terrain:
STR_2694 :Generate
STR_2695 :Random terrain
STR_2696 :Place trees
STR_2697 :???
STR_2698 :???
STR_2699 :???
STR_2700 :???
STR_2701 :???
STR_2702 :???
STR_2703 :???
STR_2704 :???
STR_2705 :???
STR_2706 :???
STR_2707 :???
STR_2708 :???
STR_2709 :???
STR_2710 :???
STR_2700 :Autosave frequency
STR_2701 :Every week
STR_2702 :Every 2 weeks
STR_2703 :Every month
STR_2704 :Every 4 months
STR_2705 :Every year
STR_2706 :Jamais
STR_2707 :Open new window
STR_2708 :{WINDOW_COLOUR_1}Are you sure you want to overwrite {STRINGID}?
STR_2709 :Overwrite
STR_2710 :Type the name of the file.
STR_2711 :;
STR_2712 :=
STR_2713 :,
@ -2719,50 +2719,50 @@ STR_2714 :-
STR_2715 :.
STR_2716 :/
STR_2717 :'
STR_2718 :???
STR_2719 :???
STR_2720 :???
STR_2721 :???
STR_2722 :???
STR_2723 :???
STR_2724 :???
STR_2725 :???
STR_2726 :???
STR_2727 :???
STR_2728 :???
STR_2729 :???
STR_2730 :???
STR_2731 :???
STR_2732 :???
STR_2733 :???
STR_2734 :???
STR_2735 :???
STR_2718 :(up)
STR_2719 :(nouveau fichier)
STR_2720 :{UINT16}s
STR_2721 :{UINT16}s
STR_2722 :{UINT16}m {UINT16}s
STR_2723 :{UINT16}m {UINT16}s
STR_2724 :{UINT16}mins:{UINT16}s
STR_2725 :{UINT16}m {UINT16}s
STR_2726 :{UINT16}m
STR_2727 :{UINT16}m
STR_2728 :{UINT16}h {UINT16}m
STR_2729 :{UINT16}h {UINT16}m
STR_2730 :{UINT16}h {UINT16}m
STR_2731 :{UINT16}h {UINT16}m
STR_2732 :{COMMA16}ft
STR_2733 :{COMMA16}m
STR_2734 :{COMMA16}mph
STR_2735 :{COMMA16}km/h
STR_2736 :{MONTH}, an {COMMA16}
STR_2737 :{STRINGID} {MONTH}, an {COMMA16}
STR_2738 :???
STR_2739 :???
STR_2740 :???
STR_2741 :???
STR_2742 :???
STR_2743 :???
STR_2738 :Title screen music
STR_2739 :Aucun
STR_2740 :RollerCoaster Tycoon 1
STR_2741 :RollerCoaster Tycoon 2
STR_2742 :css50.dat n'est pas trouvé
STR_2743 :Copy data\css17.dat from your RCT1 installation to data\css50.dat in your RCT2 installation.
STR_2744 :[
STR_2745 :\
STR_2746 :]
STR_2747 :{ENDQUOTES}
STR_2748 :Bar
STR_2749 :???
STR_2750 :???
STR_2751 :???
STR_2752 :???
STR_2753 :???
STR_2754 :???
STR_2755 :???
STR_2756 :???
STR_2757 :???
STR_2758 :???
STR_2759 :???
STR_2749 :Mon nouveau scénario
STR_2750 :Move all items to top
STR_2751 :Move all items to bottom
STR_2752 :Clear grass
STR_2753 :Mowed grass
STR_2754 :Water plants
STR_2755 :Fix vandalism
STR_2756 :Remove litter
STR_2757 :Force Sun
STR_2758 :Force Thunder
STR_2759 :Zero Clearance
# New strings used in the cheats window previously these were ???
STR_2760 :+5K Money
STR_2760 :+5000 d'argent
STR_2761 :Pay For Entrance
STR_2762 :Pay For Rides
STR_2763 :???
@ -2771,19 +2771,19 @@ STR_2765 :Large Tram
STR_2766 :???
STR_2767 :Freeze Climate
STR_2768 :Unfreeze Climate
STR_2769 :Open Park
STR_2770 :Close Park
STR_2769 :Ouvrir le parc
STR_2770 :Fermer le parc
STR_2771 :Slower Gamespeed
STR_2772 :Faster Gamespeed
STR_2773 :Windowed
STR_2774 :Fullscreen
STR_2775 :Fullscreen (desktop)
STR_2773 :En une fenêtre
STR_2774 :Plein écran
STR_2775 :Plein écran (desktop)
STR_2776 :Langue
STR_2777 :{MOVE_X}{SMALLFONT}{STRING}
STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING}
# End of new strings
STR_2779 :???
STR_2780 :???
STR_2779 :Viewport #{COMMA16}
STR_2780 :Extra viewport
STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID}{STRINGID}
STR_2782 :SHIFT +
STR_2783 :CTRL +
@ -2798,14 +2798,14 @@ STR_2791 :Enter name
STR_2792 :Please enter your name for the scenario chart:
STR_2793 :{SMALLFONT}(Completed by {STRINGID})
STR_2794 :{WINDOW_COLOUR_2}Completed by: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} with a company value of: {BLACK}{CURRENCY}
STR_2795 :Sort
STR_2795 :Trier
STR_2796 :{SMALLFONT}{BLACK}Sort the ride list into order using the information type displayed
STR_2797 :Scroll view when pointer at screen edge
STR_2798 :{SMALLFONT}{BLACK}Select whether to scroll the view when the mouse pointer is at the screen edge
STR_2799 :{SMALLFONT}{BLACK}View or change control key assignments
STR_2800 :{WINDOW_COLOUR_2}Total admissions: {BLACK}{COMMA32}
STR_2801 :{WINDOW_COLOUR_2}Income from admissions: {BLACK}{CURRENCY2DP}
STR_2802 :Map
STR_2802 :Plan
STR_2803 :{SMALLFONT}{BLACK}Show these guests highlighted on map
STR_2804 :{SMALLFONT}{BLACK}Show these staff members highlighted on map
STR_2805 :{SMALLFONT}{BLACK}Show map of park
@ -2984,7 +2984,7 @@ STR_2977 :Staff member name
STR_2978 :Enter new name for this member of staff:
STR_2979 :Can't name staff member...
STR_2980 :Too many banners in game
STR_2981 :{RED}No entry - -
STR_2981 :{RED}Accès interdit - -
STR_2982 :Banner text
STR_2983 :Enter new text for this banner:
STR_2984 :Can't set new text for banner...
@ -3059,7 +3059,7 @@ STR_3052 :Golf hole D
STR_3053 :Golf hole E
STR_3054 :Loading...
STR_3055 :Blanc
STR_3056 :Translucent
STR_3056 :Transparent
STR_3057 :{WINDOW_COLOUR_2}Construction Marker:
STR_3058 :Brick walls
STR_3059 :Hedges
@ -3160,9 +3160,9 @@ STR_3153 :{SMALLFONT}{BLACK}Scroll {STRINGID} down fast
STR_3154 :{SMALLFONT}{BLACK}Scroll {STRINGID} up/down
STR_3155 :
STR_3156 :
STR_3157 :map
STR_3158 :graph
STR_3159 :list
STR_3157 :plan
STR_3158 :graphique
STR_3159 :liste
STR_3160 :RollerCoaster Tycoon 2: Première visite...
STR_3161 :RollerCoaster Tycoon 2: Checking object files...
STR_3162 :Unable to allocate enough memory
@ -3170,8 +3170,8 @@ STR_3163 :Installing new data:
STR_3164 :{BLACK}{COMMA16} selected (maximum {COMMA16})
STR_3165 :
STR_3166 :{BLACK}(ID:
STR_3167 :{WINDOW_COLOUR_2}Includes: {BLACK}{COMMA16} objects
STR_3168 :{WINDOW_COLOUR_2}Text: {BLACK}{STRINGID}
STR_3167 :{WINDOW_COLOUR_2}Inclut: {BLACK}{COMMA16} objets
STR_3168 :{WINDOW_COLOUR_2}Texte: {BLACK}{STRINGID}
STR_3169 :Data for the following object not found:
STR_3170 :Not enough space for graphics
STR_3171 :Too many objects of this type selected
@ -3208,7 +3208,7 @@ STR_3201 :Sélection des objets
STR_3202 :Editeur de paysage
STR_3203 :Liste d'inventions
STR_3204 :Sélection des options
STR_3205 :Objective Selection
STR_3205 :Selection d'objectif
STR_3206 :Sauvegarder scénario
STR_3207 :Roller Coaster Designer
STR_3208 :Track Designs Manager
@ -3289,9 +3289,9 @@ STR_3282 :{SMALLFONT}{BLACK}Choisir objectif et nom du parc
STR_3283 :{SMALLFONT}{BLACK}Select rides to be preserved
STR_3284 :Sélection des objectifs
STR_3285 :Preserved Rides
STR_3286 :{SMALLFONT}{BLACK}Select objective for this scenario
STR_3286 :{SMALLFONT}{BLACK}Selecter un objectif pour ce scénario
STR_3287 :{WINDOW_COLOUR_2}Objectif:
STR_3288 :{SMALLFONT}{BLACK}Select climate
STR_3288 :{SMALLFONT}{BLACK}Selecter climat
STR_3289 :{WINDOW_COLOUR_2}Climat:
STR_3290 :Frais et humide
STR_3291 :Chaud
@ -3325,11 +3325,11 @@ STR_3318 :{SMALLFONT}{BLACK}Select which group this scenario appears in
STR_3319 :{WINDOW_COLOUR_2}Scenario Group:
STR_3320 :Unable to save scenario file...
STR_3321 :New objects installed successfully
STR_3322 :{WINDOW_COLOUR_2}Objective: {BLACK}{STRINGID}
STR_3322 :{WINDOW_COLOUR_2}Objectif: {BLACK}{STRINGID}
STR_3323 :Missing object data, ID:
STR_3324 :Requires Add-On Pack:
STR_3325 :Requires an Add-On Pack
STR_3326 :{WINDOW_COLOUR_2}(no image)
STR_3326 :{WINDOW_COLOUR_2}(aucune image)
STR_3327 :Starting positions for people not set
STR_3328 :Can't advance to next editor stage...
STR_3329 :Park entrance not yet built
@ -3450,3 +3450,11 @@ STR_3443 :Page 4
STR_3444 :Page 5
STR_3445 :Définir Zone de Patrouille
STR_3446 :Annuler Zone de Patrouille
# New strings, cleaner
STR_5120 :Show finances button on toolbar
STR_5121 :Show research button on toolbar
STR_5122 :Show all vehicles sharing a track/ride type
STR_5123 :Renouveler attr.
STR_5124 :Pas de Six Flags
STR_5125 :All destructable

View File

@ -2737,8 +2737,8 @@ STR_2732 :???
STR_2733 :???
STR_2734 :???
STR_2735 :???
STR_2736 :???
STR_2737 :???
STR_2736 :{MONTH}, Year {COMMA16}
STR_2737 :{STRINGID} {MONTH}, Year {COMMA16}
STR_2738 :???
STR_2739 :???
STR_2740 :???

View File

@ -2737,8 +2737,8 @@ STR_2732 :???
STR_2733 :???
STR_2734 :???
STR_2735 :???
STR_2736 :???
STR_2737 :???
STR_2736 :{MONTH}, año {COMMA16}
STR_2737 :{STRINGID} {MONTH}, año {COMMA16}
STR_2738 :???
STR_2739 :???
STR_2740 :???

View File

@ -2739,8 +2739,8 @@ STR_2732 :???
STR_2733 :???
STR_2734 :???
STR_2735 :???
STR_2736 :???
STR_2737 :???
STR_2736 :{MONTH}, Year {COMMA16}
STR_2737 :{STRINGID} {MONTH}, Year {COMMA16}
STR_2738 :???
STR_2739 :???
STR_2740 :???

View File

@ -1,7 +1,7 @@
# Version numbers to update
!define /ifndef APPV_MAJOR 0
!define /ifndef APPV_MINOR 2
!define /ifndef APPV_MAINT 0
!define /ifndef APPV_MINOR 0
!define /ifndef APPV_MAINT 2
!define /ifndef APPV_BUILD 0
!define /ifndef APPV_EXTRA "-beta"
@ -488,9 +488,14 @@ DoUninstall: ; You have the same version as this installer. This allows you to
Quit
InstallerIsOlder:
MessageBox MB_OK|MB_ICONSTOP \
"You have a newer version of ${APPNAME}.$\nSetup will now exit."
Quit
;MessageBox MB_OK|MB_ICONSTOP \
; "You have a newer version of ${APPNAME}.$\nSetup will now exit."
;Quit
MessageBox MB_OK|MB_ICONSTOP \
"You have a newer version of ${APPNAME}.$\nPlease note downgrading is currently untested."
MessageBox MB_OK|MB_ICONQUESTION \
"Welcome to ${APPNAMEANDVERSION} Setup.$\nThis will allow you to downgrade from version $OLDVERSION."
Goto FinishCallback
FinishCallback:
ClearErrors

View File

@ -58,7 +58,12 @@ The aim is to completely decompile RollerCoaster Tycoon 2 into C so that cross-p
# 2 Downloading the game / Building the source code
A third-party offers [downloadable precompiled builds](https://openrct2.com/download). However, building the project is always recommended.
A couple of third parties offer downloadable precompiled builds. However, building the project is always recommended
[OpenRCT2.com](https://openrct2.com/download)
[OpenRCT.net](https://openrct.net/builds.php)
There is also a Launcher available from [OpenRCT.net](https://openrct.net/download) that will automatically update your build so that you always have the current version as they are released.
## 2.1 Prerequisites
### Windows:
@ -132,6 +137,8 @@ Translations are in progress for German, Dutch, French, Hungarian, Polish, Spani
# 5 More information
- [GitHub](https://github.com/IntelOrca/OpenRCT2)
- [Facebook](https://www.facebook.com/OpenRCT2)
- [Automated Builds](https://openrct2.com/download)
- [Automated builds](https://openrct2.com/download)
- [Secondary site for automated builds](https://openrct.net/builds.php)
- [Launcher that keeps your copy up-to-date](https://openrct.net/download)
- [rct2 subreddit](http://www.reddit.com/r/rct/)
- [openrct2 subreddit](http://www.reddit.com/r/openrct2)

View File

@ -316,6 +316,15 @@
#define RCT2_ADDRESS_TRACK_LIST 0x00F441EC
#define RCT2_ADDRESS_CTRL_PRESS_Z_COORDINATE 0x00F64ECC
#define RCT2_ADDRESS_SHIFT_PRESS_X_COORDINATE 0x00F64ECE
#define RCT2_ADDRESS_SHIFT_PRESS_Y_COORDINATE 0x00F64ED0
#define RCT2_ADDRESS_SHIFT_PRESS_Z_VECTOR 0x00F64ED2
#define RCT2_ADDRESS_SCENERY_Z_COORDINATE 0x00F64ED4
#define RCT2_ADDRESS_SCENERY_TOOL_CTRL_PRESSED 0x00F64F12
#define RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED 0x00F64F13
#define RCT2_ADDRESS_CURRENT_MONTH_YEAR 0x00F663A8
#define RCT2_ADDRESS_CURRENT_MONTH_TICKS 0x00F663AA
#define RCT2_ADDRESS_SCENARIO_TICKS 0x00F663AC

View File

@ -1427,13 +1427,8 @@ int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z)
RCT2_GLOBAL(0x00F438AD, uint8) = 0;
int volume = 0;
if (ebx == 0x8001) {
sint16 x2 = x & 0xFFE0; // round by 32
sint16 y2 = y & 0xFFE0;
if (x2 < 0x1FFF && y2 < 0x1FFF) {
rct_map_element* mapelement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[((y2 * 256 + x2) & 0xFFFF) / 8];
while (map_element_get_type(mapelement) != MAP_ELEMENT_TYPE_SURFACE) {
mapelement++;
}
rct_map_element* mapelement = map_get_surface_element_at(x / 32, y / 32);
if (mapelement) {
if ((mapelement->base_height * 8) - 5 > z) {
RCT2_GLOBAL(0x00F438AD, uint8) = 10;
}
@ -1554,13 +1549,19 @@ void start_title_music()
case 2:
musicPathId = PATH_ID_CSS17;
break;
case 3:
if (rand() & 1)
musicPathId = PATH_ID_CSS50;
else
musicPathId = PATH_ID_CSS17;
break;
}
if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) && RCT2_GLOBAL(0x009AF59D, uint8) & 1
&& RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) {
if (!RCT2_GLOBAL(0x009AF600, uint8)) {
#ifdef USE_MIXER
gTitleMusicChannel = Mixer_Play_Music(musicPathId);
gTitleMusicChannel = Mixer_Play_Music(musicPathId, true);
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
int result = sound_channel_load_file2(3, (char*)get_file_path(musicPathId), 0);

View File

@ -31,21 +31,64 @@ extern "C" {
Mixer gMixer;
Sample::Sample()
Source::~Source()
{
}
unsigned long Source::GetSome(unsigned long offset, const uint8** data, unsigned long length)
{
if (offset >= Length()) {
return 0;
}
unsigned long size = length;
if (offset + length > Length()) {
size = Length() - offset;
}
return Read(offset, data, size);
}
unsigned long Source::Length()
{
return length;
}
const AudioFormat& Source::Format()
{
return format;
}
Source_Null::Source_Null()
{
length = 0;
}
unsigned long Source_Null::Read(unsigned long offset, const uint8** data, unsigned long length)
{
return 0;
}
Source_Sample::Source_Sample()
{
data = 0;
length = 0;
issdlwav = false;
}
Sample::~Sample()
Source_Sample::~Source_Sample()
{
Unload();
}
bool Sample::Load(const char* filename)
unsigned long Source_Sample::Read(unsigned long offset, const uint8** data, unsigned long length)
{
log_verbose("Sample::Load(%s)", filename);
*data = &Source_Sample::data[offset];
return length;
}
bool Source_Sample::LoadWAV(const char* filename)
{
log_verbose("Source_Sample::LoadWAV(%s)", filename);
utf8 utf8filename[512];
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
@ -75,9 +118,9 @@ bool Sample::Load(const char* filename)
return true;
}
bool Sample::LoadCSS1(const char* filename, unsigned int offset)
bool Source_Sample::LoadCSS1(const char* filename, unsigned int offset)
{
log_verbose("Sample::LoadCSS1(%s, %d)", filename, offset);
log_verbose("Source_Sample::LoadCSS1(%s, %d)", filename, offset);
utf8 utf8filename[512];
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
@ -107,13 +150,18 @@ bool Sample::LoadCSS1(const char* filename, unsigned int offset)
format.freq = waveformat.nSamplesPerSec;
format.format = AUDIO_S16LSB;
format.channels = waveformat.nChannels;
data = new uint8[length];
data = new (std::nothrow) uint8[length];
if (!data) {
log_verbose("Unable to allocate data");
SDL_RWclose(rw);
return false;
}
SDL_RWread(rw, data, length, 1);
SDL_RWclose(rw);
return true;
}
void Sample::Unload()
void Source_Sample::Unload()
{
if (data) {
if (issdlwav) {
@ -127,16 +175,11 @@ void Sample::Unload()
length = 0;
}
bool Sample::Loaded()
bool Source_Sample::Convert(AudioFormat format)
{
return data != 0;
}
bool Sample::Convert(AudioFormat format)
{
if(Sample::format.format != format.format || Sample::format.channels != format.channels || Sample::format.freq != format.freq){
if(Source_Sample::format.format != format.format || Source_Sample::format.channels != format.channels || Source_Sample::format.freq != format.freq){
SDL_AudioCVT cvt;
if (SDL_BuildAudioCVT(&cvt, Sample::format.format, Sample::format.channels, Sample::format.freq, format.format, format.channels, format.freq) < 0) {
if (SDL_BuildAudioCVT(&cvt, Source_Sample::format.format, Source_Sample::format.channels, Source_Sample::format.freq, format.format, format.channels, format.freq) < 0) {
return false;
}
cvt.len = length;
@ -149,69 +192,149 @@ bool Sample::Convert(AudioFormat format)
Unload();
data = cvt.buf;
length = cvt.len_cvt;
Sample::format = format;
Source_Sample::format = format;
return true;
}
return false;
}
const uint8* Sample::Data()
Source_SampleStream::Source_SampleStream()
{
return data;
length = 0;
rw = NULL;
buffer = 0;
buffersize = 0;
}
unsigned long Sample::Length()
Source_SampleStream::~Source_SampleStream()
{
return length;
Unload();
}
Stream::Stream()
unsigned long Source_SampleStream::Read(unsigned long offset, const uint8** data, unsigned long length)
{
sourcetype = SOURCE_NONE;
if (length > buffersize) {
if (buffer) {
delete[] buffer;
}
buffer = new (std::nothrow) uint8[length];
if (!buffer) {
return 0;
}
buffersize = length;
}
Sint64 currentposition = SDL_RWtell(rw);
if (currentposition == -1) {
return 0;
}
if (currentposition - databegin != offset) {
Sint64 newposition = SDL_RWseek(rw, databegin + offset, SEEK_SET);
if (newposition == -1) {
return 0;
}
currentposition = newposition;
}
*data = buffer;
int read = SDL_RWread(rw, buffer, 1, length);
if (read == -1) {
return 0;
}
return read;
}
unsigned long Stream::GetSome(unsigned long offset, const uint8** data, unsigned long length)
bool Source_SampleStream::LoadWAV(SDL_RWops* rw)
{
unsigned long size = length;
switch(sourcetype) {
case SOURCE_SAMPLE:
if (offset >= sample->Length()) {
return 0;
}
if (offset + length > sample->Length()) {
size = sample->Length() - offset;
}
*data = &sample->Data()[offset];
return size;
break;
Unload();
if (rw == NULL) {
return false;
}
Source_SampleStream::rw = rw;
Uint32 chunk_id = SDL_ReadLE32(rw);
const Uint32 RIFF = 0x46464952;
if (chunk_id != RIFF) {
log_verbose("Not a WAV file");
return false;
}
Uint32 chunk_size = SDL_ReadLE32(rw);
Uint32 chunk_format = SDL_ReadLE32(rw);
const Uint32 WAVE = 0x45564157;
if (chunk_format != WAVE) {
log_verbose("Not in WAVE format");
return false;
}
const Uint32 FMT = 0x20746D66;
Uint32 fmtchunk_size = FindChunk(rw, FMT);
if (!fmtchunk_size) {
log_verbose("Could not find FMT chunk");
return false;
}
Uint64 chunkstart = SDL_RWtell(rw);
PCMWAVEFORMAT waveformat;
SDL_RWread(rw, &waveformat, sizeof(waveformat), 1);
SDL_RWseek(rw, chunkstart + fmtchunk_size, RW_SEEK_SET);
if (waveformat.wf.wFormatTag != WAVE_FORMAT_PCM) {
log_verbose("Not in proper format");
return false;
}
format.freq = waveformat.wf.nSamplesPerSec;
switch (waveformat.wBitsPerSample) {
case 8:
format.format = AUDIO_U8;
break;
case 16:
format.format = AUDIO_S16LSB;
break;
default:
log_verbose("Invalid bits per sample");
return false;
break;
}
format.channels = waveformat.wf.nChannels;
const Uint32 DATA = 0x61746164;
Uint32 datachunk_size = FindChunk(rw, DATA);
if (!datachunk_size) {
log_verbose("Could not find DATA chunk");
return false;
}
length = datachunk_size;
databegin = SDL_RWtell(rw);
return true;
}
Uint32 Source_SampleStream::FindChunk(SDL_RWops* rw, Uint32 wanted_id)
{
Uint32 subchunk_id = SDL_ReadLE32(rw);
Uint32 subchunk_size = SDL_ReadLE32(rw);
if (subchunk_id == wanted_id) {
return subchunk_size;
}
const Uint32 FACT = 0x74636166;
const Uint32 LIST = 0x5453494c;
const Uint32 BEXT = 0x74786562;
const Uint32 JUNK = 0x4B4E554A;
while (subchunk_id == FACT || subchunk_id == LIST || subchunk_id == BEXT || subchunk_id == JUNK) {
SDL_RWseek(rw, subchunk_size, RW_SEEK_CUR);
subchunk_id = SDL_ReadLE32(rw);
subchunk_size = SDL_ReadLE32(rw);
if (subchunk_id == wanted_id) {
return subchunk_size;
}
}
return 0;
}
unsigned long Stream::Length()
void Source_SampleStream::Unload()
{
switch(sourcetype) {
case SOURCE_SAMPLE:
return sample->Length();
break;
if (rw) {
SDL_RWclose(rw);
rw = NULL;
}
return 0;
}
void Stream::SetSource_Sample(Sample& sample)
{
sourcetype = SOURCE_SAMPLE;
Stream::sample = &sample;
}
const AudioFormat* Stream::Format()
{
switch(sourcetype) {
case SOURCE_SAMPLE:
return &sample->format;
break;
length = 0;
if (buffer) {
delete[] buffer;
buffer = 0;
}
return 0;
buffersize = 0;
}
Channel::Channel()
@ -220,10 +343,13 @@ Channel::Channel()
SetRate(1);
SetVolume(SDL_MIX_MAXVOLUME);
oldvolume = 0;
oldvolume_l = 0;
oldvolume_r = 0;
SetPan(0.5f);
done = true;
stopping = false;
stream = 0;
source = 0;
deletesourceondone = false;
}
Channel::~Channel()
@ -232,11 +358,14 @@ Channel::~Channel()
speex_resampler_destroy(resampler);
resampler = 0;
}
if (deletesourceondone) {
delete source;
}
}
void Channel::Play(Stream& stream, int loop = MIXER_LOOP_NONE)
void Channel::Play(Source& source, int loop = MIXER_LOOP_NONE)
{
Channel::stream = &stream;
Channel::source = &source;
Channel::loop = loop;
offset = 0;
done = false;
@ -270,8 +399,15 @@ void Channel::SetPan(float pan)
if (pan < 0) {
Channel::pan = 0;
}
volume_l = (float)sin((1.0 - Channel::pan) * M_PI / 2.0);
volume_r = (float)sin(Channel::pan * M_PI / 2.0);
double decibels = (abs(Channel::pan - 0.5) * 2.0) * 100.0;
double attenuation = pow(10, decibels / 20.0);
if (Channel::pan <= 0.5) {
volume_l = 1.0;
volume_r = float(1.0 / attenuation);
} else {
volume_r = 1.0;
volume_l = float(1.0 / attenuation);
}
}
bool Channel::IsPlaying()
@ -286,14 +422,25 @@ unsigned long Channel::GetOffset()
bool Channel::SetOffset(unsigned long offset)
{
if (stream && offset < stream->Length()) {
int samplesize = stream->Format()->channels * stream->Format()->BytesPerSample();
if (source && offset < source->Length()) {
int samplesize = source->Format().channels * source->Format().BytesPerSample();
Channel::offset = (offset / samplesize) * samplesize;
return true;
}
return false;
}
Mixer::Mixer()
{
effectbuffer = 0;
for (int i = 0; i < countof(css1sources); i++) {
css1sources[i] = 0;
}
for (int i = 0; i < countof(musicsources); i++) {
musicsources[i] = 0;
}
}
void Mixer::Init(const char* device)
{
Close();
@ -310,10 +457,15 @@ void Mixer::Init(const char* device)
format.channels = have.channels;
format.freq = have.freq;
const char* filename = get_file_path(PATH_ID_CSS1);
for (int i = 0; i < SOUND_MAXID; i++) {
css1samples[i].LoadCSS1(filename, i);
css1samples[i].Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional
css1streams[i].SetSource_Sample(css1samples[i]);
for (int i = 0; i < countof(css1sources); i++) {
Source_Sample* source_sample = new Source_Sample;
if (source_sample->LoadCSS1(filename, i)) {
source_sample->Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional
css1sources[i] = source_sample;
} else {
css1sources[i] = &source_null;
delete source_sample;
}
}
effectbuffer = new uint8[(have.samples * format.BytesPerSample() * format.channels)];
SDL_PauseAudioDevice(deviceid, 0);
@ -328,7 +480,22 @@ void Mixer::Close()
}
Unlock();
SDL_CloseAudioDevice(deviceid);
delete[] effectbuffer;
for (int i = 0; i < countof(css1sources); i++) {
if (css1sources[i] && css1sources[i] != &source_null) {
delete css1sources[i];
css1sources[i] = 0;
}
}
for (int i = 0; i < countof(musicsources); i++) {
if (musicsources[i] && musicsources[i] != &source_null) {
delete musicsources[i];
musicsources[i] = 0;
}
}
if (effectbuffer) {
delete[] effectbuffer;
effectbuffer = 0;
}
}
void Mixer::Lock()
@ -341,13 +508,14 @@ void Mixer::Unlock()
SDL_UnlockAudioDevice(deviceid);
}
Channel* Mixer::Play(Stream& stream, int loop, bool deleteondone)
Channel* Mixer::Play(Source& source, int loop, bool deleteondone, bool deletesourceondone)
{
Lock();
Channel* newchannel = new (std::nothrow) Channel();
Channel* newchannel = new (std::nothrow) Channel;
if (newchannel) {
newchannel->Play(stream, loop);
newchannel->Play(source, loop);
newchannel->deleteondone = deleteondone;
newchannel->deletesourceondone = deletesourceondone;
newchannel->stopping = false;
channels.push_back(newchannel);
}
@ -364,13 +532,20 @@ void Mixer::Stop(Channel& channel)
bool Mixer::LoadMusic(int pathid)
{
if (pathid >= PATH_ID_END) {
if (pathid >= countof(musicsources)) {
return false;
}
if (!musicsamples[pathid].Loaded()) {
if (!musicsources[pathid]) {
const char* filename = get_file_path(pathid);
musicstreams[pathid].SetSource_Sample(musicsamples[pathid]);
return musicsamples[pathid].Load(filename);
Source_Sample* source_sample = new Source_Sample;
if (source_sample->LoadWAV(filename)) {
musicsources[pathid] = source_sample;
return true;
} else {
delete source_sample;
musicsources[pathid] = &source_null;
return false;
}
} else {
return true;
}
@ -394,8 +569,8 @@ void SDLCALL Mixer::Callback(void* arg, uint8* stream, int length)
void Mixer::MixChannel(Channel& channel, uint8* data, int length)
{
if (channel.stream && !channel.done) {
AudioFormat streamformat = *channel.stream->Format();
if (channel.source && channel.source->Length() > 0 && !channel.done) {
AudioFormat streamformat = channel.source->Format();
int loaded = 0;
SDL_AudioCVT cvt;
cvt.len_ratio = 1;
@ -409,9 +584,9 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
}
int samplestoread = (int)((samples - samplesloaded) * rate);
int lengthloaded = 0;
if (channel.offset < channel.stream->Length()) {
if (channel.offset < channel.source->Length()) {
bool mustconvert = false;
if (MustConvert(*channel.stream)) {
if (MustConvert(*channel.source)) {
if (SDL_BuildAudioCVT(&cvt, streamformat.format, streamformat.channels, streamformat.freq, Mixer::format.format, Mixer::format.channels, Mixer::format.freq) == -1) {
break;
}
@ -420,7 +595,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
const uint8* datastream = 0;
int toread = (int)(samplestoread / cvt.len_ratio) * samplesize;
int readfromstream = (channel.stream->GetSome(channel.offset, &datastream, toread));
int readfromstream = (channel.source->GetSome(channel.offset, &datastream, toread));
if (readfromstream == 0) {
break;
}
@ -519,7 +694,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
loaded += lengthloaded;
if (channel.loop != 0 && channel.offset >= channel.stream->Length()) {
if (channel.loop != 0 && channel.offset >= channel.source->Length()) {
if (channel.loop != -1) {
channel.loop--;
}
@ -528,7 +703,9 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
} while(loaded < length && channel.loop != 0 && !channel.stopping);
channel.oldvolume = channel.volume;
if (channel.loop == 0 && channel.offset >= channel.stream->Length()) {
channel.oldvolume_l = channel.volume_l;
channel.oldvolume_r = channel.volume_r;
if (channel.loop == 0 && channel.offset >= channel.source->Length()) {
channel.done = true;
}
}
@ -536,21 +713,19 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
void Mixer::EffectPanS16(Channel& channel, sint16* data, int length)
{
float left = channel.volume_l;
float right = channel.volume_r;
for (int i = 0; i < length * 2; i += 2) {
data[i] = (sint16)(data[i] * left);
data[i + 1] = (sint16)(data[i + 1] * right);
float t = (float)i / (length * 2);
data[i] = (sint16)(data[i] * ((1.0 - t) * channel.oldvolume_l + t * channel.volume_l));
data[i + 1] = (sint16)(data[i + 1] * ((1.0 - t) * channel.oldvolume_r + t * channel.volume_r));
}
}
void Mixer::EffectPanU8(Channel& channel, uint8* data, int length)
{
float left = channel.volume_l;
float right = channel.volume_r;
for (int i = 0; i < length * 2; i += 2) {
data[i] = (uint8)(data[i] * left);
data[i + 1] = (uint8)(data[i + 1] * right);
float t = (float)i / (length * 2);
data[i] = (uint8)(data[i] * ((1.0 - t) * channel.oldvolume_l + t * channel.volume_l));
data[i + 1] = (uint8)(data[i + 1] * ((1.0 - t) * channel.oldvolume_r + t * channel.volume_r));
}
}
@ -574,13 +749,10 @@ void Mixer::EffectFadeU8(uint8* data, int length, int startvolume, int endvolume
}
}
bool Mixer::MustConvert(Stream& stream)
bool Mixer::MustConvert(Source& source)
{
const AudioFormat* streamformat = stream.Format();
if (!streamformat) {
return false;
}
if (streamformat->format != format.format || streamformat->channels != format.channels || streamformat->freq != format.freq) {
const AudioFormat sourceformat = source.Format();
if (sourceformat.format != format.format || sourceformat.channels != format.channels || sourceformat.freq != format.freq) {
return true;
}
return false;
@ -609,11 +781,11 @@ void Mixer_Init(const char* device)
void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone)
{
if (id >= SOUND_MAXID) {
if (id >= countof(gMixer.css1sources)) {
return 0;
}
gMixer.Lock();
Channel* channel = gMixer.Play(gMixer.css1streams[id], loop, deleteondone != 0);
Channel* channel = gMixer.Play(*gMixer.css1sources[id], loop, deleteondone != 0, false);
if (channel) {
channel->SetVolume(volume);
channel->SetPan(pan);
@ -664,10 +836,33 @@ int Mixer_Channel_SetOffset(void* channel, unsigned long offset)
return ((Channel*)channel)->SetOffset(offset);
}
void* Mixer_Play_Music(int pathid)
void* Mixer_Play_Music(int pathid, int streaming)
{
if (gMixer.LoadMusic(pathid)) {
return gMixer.Play(gMixer.musicstreams[pathid], MIXER_LOOP_INFINITE, false);
if (streaming) {
const char* filename = get_file_path(pathid);
utf8 utf8filename[512];
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb");
if (rw == NULL) {
return 0;
}
Source_SampleStream* source_samplestream = new Source_SampleStream;
if (source_samplestream->LoadWAV(rw)) {
Channel* channel = gMixer.Play(*source_samplestream, MIXER_LOOP_INFINITE, false, true);
if (!channel) {
delete source_samplestream;
}
return channel;
} else {
delete source_samplestream;
return 0;
}
} else {
if (gMixer.LoadMusic(pathid)) {
return gMixer.Play(*gMixer.musicsources[pathid], MIXER_LOOP_INFINITE, false, false);
}
}
return 0;
}

View File

@ -43,45 +43,73 @@ struct AudioFormat {
int channels;
};
class Sample
class Source
{
public:
Sample();
~Sample();
bool Load(const char* filename);
bool LoadCSS1(const char* filename, unsigned int offset);
void Unload();
bool Loaded();
bool Convert(AudioFormat format);
const uint8* Data();
unsigned long Length();
friend class Stream;
private:
AudioFormat format;
uint8* data;
unsigned long length;
bool issdlwav;
};
class Stream
{
public:
Stream();
virtual ~Source();
unsigned long GetSome(unsigned long offset, const uint8** data, unsigned long length);
unsigned long Length();
void SetSource_Sample(Sample& sample);
const AudioFormat* Format();
const AudioFormat& Format();
friend class Mixer;
protected:
virtual unsigned long Read(unsigned long offset, const uint8** data, unsigned long length) = 0;
AudioFormat format;
unsigned long length;
};
class Source_Null : public Source
{
public:
Source_Null();
protected:
unsigned long Read(unsigned long offset, const uint8** data, unsigned long length);
};
class Source_Sample : public Source
{
public:
Source_Sample();
~Source_Sample();
bool LoadWAV(const char* filename);
bool LoadCSS1(const char* filename, unsigned int offset);
friend class Mixer;
protected:
bool Convert(AudioFormat format);
private:
enum {
SOURCE_NONE = 0,
SOURCE_SAMPLE
} sourcetype;
Sample* sample;
void Unload();
uint8* data;
bool issdlwav;
protected:
unsigned long Read(unsigned long offset, const uint8** data, unsigned long length);
};
class Source_SampleStream : public Source
{
public:
Source_SampleStream();
~Source_SampleStream();
bool LoadWAV(SDL_RWops* rw);
private:
Uint32 FindChunk(SDL_RWops* rw, Uint32 wanted_id);
void Unload();
SDL_RWops* rw;
Uint64 databegin;
uint8* buffer;
unsigned long buffersize;
protected:
unsigned long Read(unsigned long offset, const uint8** data, unsigned long length);
};
class Channel
@ -89,7 +117,7 @@ class Channel
public:
Channel();
~Channel();
void Play(Stream& stream, int loop);
void Play(Source& source, int loop);
void SetRate(double rate);
void SetVolume(int volume);
void SetPan(float pan);
@ -105,28 +133,31 @@ private:
double rate;
int volume;
float volume_l, volume_r;
float oldvolume_l, oldvolume_r;
float pan;
bool done;
bool deleteondone;
bool deletesourceondone;
bool stopping;
int oldvolume;
SpeexResamplerState* resampler;
Stream* stream;
Source* source;
};
class Mixer
{
public:
Mixer();
void Init(const char* device);
void Close();
void Lock();
void Unlock();
Channel* Play(Stream& stream, int loop, bool deleteondone);
Channel* Play(Source& source, int loop, bool deleteondone, bool deletesourceondone);
void Stop(Channel& channel);
bool LoadMusic(int pathid);
Stream css1streams[SOUND_MAXID];
Stream musicstreams[PATH_ID_END];
Source* css1sources[SOUND_MAXID];
Source* musicsources[PATH_ID_END];
private:
static void SDLCALL Callback(void* arg, uint8* data, int length);
@ -135,14 +166,13 @@ private:
void EffectPanU8(Channel& channel, uint8* data, int length);
void EffectFadeS16(sint16* data, int length, int startvolume, int endvolume);
void EffectFadeU8(uint8* data, int length, int startvolume, int endvolume);
bool MustConvert(Stream& stream);
bool MustConvert(Source& source);
bool Convert(SDL_AudioCVT& cvt, const uint8* data, unsigned long length, uint8** dataout);
SDL_AudioDeviceID deviceid;
AudioFormat format;
uint8* effectbuffer;
Sample css1samples[SOUND_MAXID];
Sample musicsamples[PATH_ID_END];
std::list<Channel*> channels;
Source_Null source_null;
};
extern "C"
@ -158,7 +188,7 @@ void Mixer_Channel_Rate(void* channel, double rate);
int Mixer_Channel_IsPlaying(void* channel);
unsigned long Mixer_Channel_GetOffset(void* channel);
int Mixer_Channel_SetOffset(void* channel, unsigned long offset);
void* Mixer_Play_Music(int pathid);
void* Mixer_Play_Music(int pathid, int streaming);
static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (SDL_pow(10, (float)volume / 2000))); };
static float DStoMixerPan(int pan) { return (((float)pan + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2; };

View File

@ -1006,11 +1006,11 @@ void gfx_draw_string(rct_drawpixelinfo *dpi, char *buffer, int colour, int x, in
skip_char = 1;
break;
}
ebx = *((uint16*)(buffer - 3));
eax = ebx & 0x7FFFF;
g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[eax]);
uint32 image_id = *((uint32*)(buffer - 3));
uint32 image_offset = image_id & 0x7FFFF;
g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_offset]);
gfx_draw_sprite(dpi, ebx, max_x, max_y, 0);
gfx_draw_sprite(dpi, image_id, max_x, max_y, 0);
max_x = max_x + g1_element->width;
break;

View File

@ -265,7 +265,7 @@ void sub_6BD3A4()
for (int i = 200; i < 204; i++)
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[i] = STAFF_MODE_WALK;
sub_6C0C3F();
staff_update_greyed_patrol_areas();
}
/**

View File

@ -244,7 +244,7 @@ void game_update()
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESET ||
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_NORMAL
) {
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32)) {
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_VIEWPORT_SCROLLING) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_VIEWPORT_SCROLLING;
break;
}
@ -358,7 +358,7 @@ static int game_check_affordability(int cost)
}
RCT2_GLOBAL(0x13CE952, uint32) = cost;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 827;
return 0x80000000;
return MONEY32_UNDEFINED;
}
static uint32 game_do_command_table[58];
@ -411,13 +411,13 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
}
cost = *ebx;
if (cost != 0x80000000) {
if (cost != MONEY32_UNDEFINED) {
// Check funds
insufficientFunds = 0;
if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & 4) && !(flags & 0x20) && cost != 0)
insufficientFunds = game_check_affordability(cost);
if (insufficientFunds != 0x80000000) {
if (insufficientFunds != MONEY32_UNDEFINED) {
*ebx = original_ebx;
*edx = original_edx;
*esi = original_esi;
@ -438,7 +438,7 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
}
*edx = *ebx;
if (*edx != 0x80000000 && *edx < cost)
if (*edx != MONEY32_UNDEFINED && *edx < cost)
cost = *edx;
// Decrement nest count
@ -470,7 +470,7 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
if (RCT2_GLOBAL(0x009A8C28, uint8) == 0 && (flags & 1) && RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8) && !(flags & 8))
window_error_open(RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16), RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16));
return 0x80000000;
return MONEY32_UNDEFINED;
}
void pause_toggle()
@ -655,11 +655,11 @@ int game_load_save(const char *path)
if (!load_success){
set_load_objects_fail_reason();
if (RCT2_GLOBAL(0x9DE518,uint32) & (1<<5)){
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5){
RCT2_GLOBAL(0x14241BC, uint32) = 2;
//call 0x0040705E Sets cursor position and something else. Calls maybe wind func 8 probably pointless
RCT2_GLOBAL(0x14241BC, uint32) = 0;
RCT2_GLOBAL(0x9DE518, uint32) &= ~(1<<5);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5;
}
title_load();
rct2_endupdate();
@ -797,7 +797,7 @@ char save_game()
path_set_extension(path, ".SV6");
if (scenario_save(path, gConfigGeneral.save_plugin_data ? 1 : 0)) {
game_do_command(0, 1047, 0, -1, GAME_COMMAND_0, 0, 0);
game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
gfx_invalidate_screen();
return 1;
} else {
@ -874,21 +874,21 @@ void game_load_or_quit_no_save_prompt()
#pragma region Game command function table
static uint32 game_do_command_table[58] = {
0x006B2FC5,
0,
0x0066397F,
0,
0x006C511D,
0x006C5B69,
0,
0x006B3F0F,
0x006B49D9,
0,
0,
0x006B52D4,
0, // 10
0,
0x006660A8,
0x0066640B,
0x006E0E01,
0,
0x006E08F4,
0x006E650F,
0,
@ -897,17 +897,17 @@ static uint32 game_do_command_table[58] = {
0, // use new_game_command_table, original: 0x00663CCD, // 20
0x006B53E9,
0x00698D6C, // text input
0x0068C542,
0x0068C6D1,
0,
0,
0x0068BC01,
0x006E66A0,
0x006E6878,
0,
0,
0x006C5AE9,
0, // use new_game_command_table, original: 0x006BEFA1, 29
0x006C09D1, // 30
0x006C0B83,
0x006C0BB5,
0x00669C6D,
0, // 30
0,
0,
0,
0,
0x006649BD,
0x006666E7,
@ -916,20 +916,20 @@ static uint32 game_do_command_table[58] = {
0,
0, // 40
0x006E519A,
0x006E5597,
0,
0x006B893C,
0x006B8E1B,
0,
0,
0,
0x006D13FE,
0,
0x006CDEE4,
0x006B9E6D, // 50
0x006BA058,
0x006E0F26,
0x006E56B5,
0x006B909A,
0x006BA16A,
0, // 50
0,
0,
0,
0,
0,
0x006648E3,
0
};
@ -937,21 +937,21 @@ static uint32 game_do_command_table[58] = {
void game_command_emptysub(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) {}
static GAME_COMMAND_POINTER* new_game_command_table[58] = {
game_command_emptysub,
game_command_set_ride_appearance,
game_command_emptysub,
game_pause_toggle,
game_command_emptysub,
game_command_emptysub,
game_load_or_quit,
game_command_emptysub,
game_command_emptysub,
game_command_demolish_ride,
game_command_set_ride_status,
game_command_emptysub,
game_command_set_ride_name, // 10
game_command_set_ride_setting,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_remove_scenery,
game_command_emptysub,
game_command_emptysub,
game_command_place_footpath,
@ -960,16 +960,16 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = {
game_command_change_surface_style, // 20
game_command_emptysub,
game_command_emptysub,
game_command_raise_land,
game_command_lower_land,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_raise_water,
game_command_lower_water,
game_command_emptysub,
game_command_hire_new_staff_member, //game_command_emptysub,
game_command_emptysub, // 30
game_command_emptysub,
game_command_emptysub,
game_command_set_staff_patrol, // 30
game_command_fire_staff_member,
game_command_set_staff_order,
game_command_set_park_name,
game_command_set_park_open,
game_command_emptysub,
@ -979,20 +979,20 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = {
game_command_set_park_entrance_fee,
game_command_update_staff_colour, // 40
game_command_emptysub,
game_command_remove_fence,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_remove_large_scenery,
game_command_set_current_loan,
game_command_set_research_funding,
game_command_emptysub,
game_command_start_campaign,
game_command_emptysub,
game_command_emptysub, // 50
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_place_banner, // 50
game_command_remove_banner,
game_command_set_scenery_colour,
game_command_set_fence_colour,
game_command_set_large_scenery_colour,
game_command_set_banner_colour,
game_command_emptysub,
game_command_clear_scenery
};

View File

@ -24,7 +24,7 @@
#include "common.h"
enum GAME_COMMAND {
GAME_COMMAND_0,
GAME_COMMAND_SET_RIDE_APPEARANCE,
GAME_COMMAND_1,
GAME_COMMAND_TOGGLE_PAUSE, // 2
GAME_COMMAND_3, //Has something to do with ride construction
@ -68,14 +68,14 @@ enum GAME_COMMAND {
GAME_COMMAND_41,
GAME_COMMAND_REMOVE_FENCE,
GAME_COMMAND_43,
GAME_COMMAND_44,
GAME_COMMAND_REMOVE_LARGE_SCENERY,
GAME_COMMAND_SET_CURRENT_LOAN, // 45
GAME_COMMAND_SET_RESEARCH_FUNDING, // 46
GAME_COMMAND_47,
GAME_COMMAND_START_MARKETING_CAMPAIGN, // 48
GAME_COMMAND_49,
GAME_COMMAND_50, // New banner? (possibly scenery)
GAME_COMMAND_51, // Remove banner
GAME_COMMAND_PLACE_BANNER, // New banner? (possibly scenery)
GAME_COMMAND_REMOVE_BANNER, // Remove banner
GAME_COMMAND_52,
GAME_COMMAND_53,
GAME_COMMAND_54,

View File

@ -283,7 +283,7 @@ static void game_handle_input_mouse(int x, int y, int state)
if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) ||
w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) ||
!(RCT2_GLOBAL(0x9DE518, uint32)&(1 << 3)))break;
!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) break;
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
@ -298,7 +298,7 @@ static void game_handle_input_mouse(int x, int y, int state)
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
if (RCT2_GLOBAL(0x9DE52E, rct_windownumber) != w->number)break;
if ((RCT2_GLOBAL(0x9DE518, uint32)&(1 << 3))){
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)){
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)
@ -308,7 +308,7 @@ static void game_handle_input_mouse(int x, int y, int state)
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_UP], x, y, 0, (int)RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), (int)w, 0, 0);
}
else{
if ((RCT2_GLOBAL(0x9DE518, uint32) & (1 << 4)))
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_4))
break;
viewport_interaction_left_click(x, y);
@ -811,7 +811,7 @@ void process_mouse_over(int x, int y)
switch (window->widgets[widgetId].type){
case WWT_VIEWPORT:
if ((RCT2_GLOBAL(0x9DE518, int) & 0x8) == 0) {
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, int) & INPUT_FLAG_TOOL_ACTIVE) == 0) {
if (viewport_interaction_left_over(x, y)) {
sub_6ED990(CURSOR_HAND_POINT);
return;
@ -897,7 +897,7 @@ void process_mouse_over(int x, int y)
*/
void process_mouse_tool(int x, int y)
{
if (RCT2_GLOBAL(0x9DE518, uint32) & (1 << 3))
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
{
rct_window* w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8),
@ -951,9 +951,9 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
window_event_mouse_down_call(w, widgetIndex);
}
if (RCT2_GLOBAL(0x009DE518, uint32) & 1) return;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED) return;
RCT2_GLOBAL(0x009DE518, uint32) |= 1;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_WIDGET_PRESSED;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, widgetIndex);
return;
case 3:
@ -976,9 +976,9 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
if (cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
goto dropdown_cleanup;
dropdown_index = -1;
if (RCT2_GLOBAL(0x9DE518, uint32) & 2){
if (!(RCT2_GLOBAL(0x9DE518, uint32) & 4)){
RCT2_GLOBAL(0x9DE518, uint32) |= (1 << 2);
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_DROPDOWN_STAY_OPEN){
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_DROPDOWN_MOUSE_UP)){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_MOUSE_UP;
return;
}
}
@ -986,8 +986,8 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
window_close_by_class(WC_DROPDOWN);
cursor_w = window_find_by_number(cursor_w_class, cursor_w_number);
if (RCT2_GLOBAL(0x9DE518, uint32) & 1) {
RCT2_GLOBAL(0x9DE518, uint32) &= 0xFFFE;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= 0xFFFE;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex);
}
@ -1030,8 +1030,8 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
RCT2_GLOBAL(0x9DE528, uint16) = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) != 5){
// Hold down widget and drag outside of area??
if (RCT2_GLOBAL(0x9DE518, uint32) & 1){
RCT2_GLOBAL(0x9DE518, uint32) &= 0xFFFE;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= 0xFFFE;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex);
}
return;

View File

@ -26,11 +26,12 @@
enum {
INPUT_FLAG_WIDGET_PRESSED = (1 << 0),
// Related to dropdowns, set on flag 0x80
INPUT_FLAG_1 = (1 << 1),
// The dropdown can stay open if the mouse is released, set on flag DROPDOWN_FLAG_STAY_OPEN
INPUT_FLAG_DROPDOWN_STAY_OPEN = (1 << 1),
// Related to dropdowns
INPUT_FLAG_2 = (1 << 2),
// The mouse has been released and the dropdown is still open
// INPUT_FLAG_DROPDOWN_STAY_OPEN is already set if this happens
INPUT_FLAG_DROPDOWN_MOUSE_UP = (1 << 2),
INPUT_FLAG_TOOL_ACTIVE = (1 << 3),

View File

@ -45,19 +45,34 @@ struct paint_struct{
uint32 var_04;
uint16 attached_x; // 0x08
uint16 attached_y; // 0x0A
uint8 var_0C;
uint8 pad_0D;
paint_struct* next_attached_ps; //0x0E
uint8 pad_12[2];
union {
struct {
uint8 var_0C;
uint8 pad_0D;
paint_struct* next_attached_ps; //0x0E
uint16 pad_12;
};
struct {
uint16 some_x; // 0x0C
uint16 some_y; // 0x0E
uint16 other_x; // 0x10
uint16 other_y; // 0x12
};
};
uint16 x; // 0x14
uint16 y; // 0x16
uint8 pad_18[2];
uint16 var_18;
uint8 var_1A;
uint8 pad_1B;
uint8 var_1B;
paint_struct* attached_ps; //0x1C
paint_struct* var_20;
paint_struct* var_24;
uint8 sprite_type; //0x28
uint8 var_29;
uint16 pad_2A;
uint16 map_x; // 0x2C
uint16 map_y; // 0x2E
rct_map_element *mapElement; // 0x30
};
/**
@ -1346,6 +1361,133 @@ void sub_0x68B6C2(){
}
}
void sub_688217_helper(uint16 ax, uint8 flag)
{
paint_struct *ps;
paint_struct *ps_next = RCT2_GLOBAL(0x00EE7884, paint_struct*);
do {
ps = ps_next;
ps_next = ps_next->var_24;
if (ps_next == NULL) return;
} while (ax > ps_next->var_18);
RCT2_GLOBAL(0x00F1AD14, paint_struct*) = ps;
do {
ps = ps->var_24;
if (ps == NULL) break;
if (ps->var_18 > ax + 1) {
ps->var_1B = 1 << 7;
} else if (ps->var_18 == ax + 1) {
ps->var_1B = (1 << 1) | (1 << 0);
} else if (ps->var_18 == ax) {
ps->var_1B = flag | (1 << 0);
}
} while (ps->var_18 <= ax + 1);
ps = RCT2_GLOBAL(0x00F1AD14, paint_struct*);
while (true) {
while (true) {
ps_next = ps->var_24;
if (ps_next == NULL) return;
if (ps_next->var_1B & (1 << 7)) return;
if (ps_next->var_1B & (1 << 0)) break;
ps = ps_next;
}
ps_next->var_1B &= ~(1 << 0);
RCT2_GLOBAL(0x00F1AD18, paint_struct*) = ps;
uint16 my_attached_x = ps_next->attached_x;
uint16 my_attached_y = ps_next->attached_y;
uint16 my_some_x = ps_next->some_x;
uint16 my_some_y = ps_next->some_y;
uint16 my_other_x = ps_next->other_x;
uint16 my_other_y = ps_next->other_y;
while (true) {
ps = ps_next;
ps_next = ps_next->var_24;
if (ps_next == NULL) break;
if (ps_next->var_1B & (1 << 7)) break;
if (!(ps_next->var_1B & (1 << 1))) continue;
int yes = 0;
switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) {
case 0:
if (my_some_y >= ps_next->some_x && my_other_y >= ps_next->attached_y && my_other_x >= ps_next->attached_x
&& !(my_some_x < ps_next->some_y && my_attached_y < ps_next->other_y && my_attached_x < ps_next->other_x))
yes = 1;
break;
case 1:
if (my_some_y >= ps_next->some_x && my_other_y >= ps_next->attached_y && my_other_x < ps_next->attached_x
&& !(my_some_x < ps_next->some_y && my_attached_y < ps_next->other_y && my_attached_x >= ps_next->other_x))
yes = 1;
break;
case 2:
if (my_some_y >= ps_next->some_x && my_other_y < ps_next->attached_y && my_other_x < ps_next->attached_x
&& !(my_some_x < ps_next->some_y && my_attached_y >= ps_next->other_y && my_attached_x >= ps_next->other_x))
yes = 1;
break;
case 3:
if (my_some_y >= ps_next->some_x && my_other_y < ps_next->attached_y && my_other_x >= ps_next->attached_x
&& !(my_some_x < ps_next->some_y && my_attached_y >= ps_next->other_y && my_attached_x < ps_next->other_x))
yes = 1;
break;
}
if (yes) {
ps->var_24 = ps_next->var_24;
paint_struct *ps_temp = RCT2_GLOBAL(0x00F1AD18, paint_struct*)->var_24;
RCT2_GLOBAL(0x00F1AD18, paint_struct*)->var_24 = ps_next;
ps_next->var_24 = ps_temp;
ps_next = ps;
}
}
ps = RCT2_GLOBAL(0x00F1AD18, paint_struct*);
}
}
/**
*
* rct2: 0x00688217
*/
void sub_688217()
{
paint_struct *ps = RCT2_GLOBAL(0x00EE7888, paint_struct*);
paint_struct *ps_next;
RCT2_GLOBAL(0x00EE7888, uint32) += 0x34; // 0x34 is size of paint_struct?
RCT2_GLOBAL(0x00EE7884, paint_struct*) = ps;
ps->var_24 = NULL;
uint32 edi = RCT2_GLOBAL(0x00F1AD0C, uint32);
if (edi == -1)
return;
do {
ps_next = RCT2_GLOBAL(0x00F1A50C + 4 * edi, paint_struct*);
if (ps_next != NULL) {
ps->var_24 = ps_next;
do {
ps = ps_next;
ps_next = ps_next->var_24;
} while (ps_next != NULL);
}
} while (++edi <= RCT2_GLOBAL(0x00F1AD10, uint32));
uint32 eax = RCT2_GLOBAL(0x00F1AD0C, uint32);
sub_688217_helper(eax & 0xFFFF, 1 << 1);
eax = RCT2_GLOBAL(0x00F1AD0C, uint32);
while (++eax < RCT2_GLOBAL(0x00F1AD10, uint32))
sub_688217_helper(eax & 0xFFFF, 0);
}
/**
*
* rct2:0x00685CBF
@ -1439,7 +1581,8 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in
sub_0x68615B(0xEE788C); //Memory copy
sub_0x68B6C2();
//RCT2_CALLPROC_X(0x68B6C2, 0, 0, 0, 0, 0, 0, 0); //Big function call 4 rotation versions
RCT2_CALLPROC_X(0x688217, start_x, ebx, ecx, (int)bits_pointer, esi, (int)dpi2, ebp); //Move memory
sub_688217();
//RCT2_CALLPROC_X(0x688217, start_x, ebx, ecx, (int)bits_pointer, esi, (int)dpi2, ebp); //Move memory
sub_688485();
//RCT2_CALLPROC_EBPSAFE(0x688485); //Big function call
@ -1466,10 +1609,10 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in
* viewport: edi
*/
void sub_688972(int screenX, int screenY, sint16 *x, sint16 *y, rct_viewport **viewport) {
int my_x, my_y, z;
int my_x, my_y, z, interactionType;
rct_viewport *myViewport;
get_map_coordinates_from_pos(screenX, screenY, 0xFFFE, &my_x, &my_y, &z, NULL, &myViewport);
if (z == 0) {
get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_TERRAIN, &my_x, &my_y, &interactionType, NULL, &myViewport);
if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) {
*x = 0x8000;
return;
}
@ -1727,6 +1870,79 @@ void viewport_set_visibility(uint8 mode)
}
}
/**
* Stores some info about the element pointed at, if requested for this particular type through the interaction mask.
* rct2: 0x00688697
*/
void store_interaction_info(paint_struct *ps)
{
if (RCT2_GLOBAL(0x0141F569, uint8) == 0) return;
if (ps->sprite_type == VIEWPORT_INTERACTION_ITEM_NONE
|| ps->sprite_type == 11 // 11 as a type seems to not exist, maybe part of the typo mentioned later on.
|| ps->sprite_type > VIEWPORT_INTERACTION_ITEM_BANNER) return;
uint16 mask;
if (ps->sprite_type == VIEWPORT_INTERACTION_ITEM_BANNER)
// I think CS made a typo here. Let's replicate the original behaviour.
mask = 1 << (ps->sprite_type - 3);
else
mask = 1 << (ps->sprite_type - 1);
if (!(RCT2_GLOBAL(0x009AC154, uint16) & mask)) {
RCT2_GLOBAL(0x009AC148, uint8) = ps->sprite_type;
RCT2_GLOBAL(0x009AC149, uint8) = ps->var_29;
RCT2_GLOBAL(0x009AC14C, uint32) = ps->map_x;
RCT2_GLOBAL(0x009AC14E, uint32) = ps->map_y;
RCT2_GLOBAL(0x009AC150, rct_map_element*) = ps->mapElement;
}
}
/**
* rct2: 0x0068862C
*/
void sub_68862C()
{
rct_drawpixelinfo *dpi = RCT2_GLOBAL(0x0140E9A8, rct_drawpixelinfo*);
paint_struct *ps = RCT2_GLOBAL(0x00EE7884, paint_struct*), *old_ps, *next_ps, *attached_ps;
uint32 eax = 0xBBBBBBBB, ebx = 0xBBBBBBBB, ecx = 0xBBBBBBBB, edx = 0xBBBBBBBB, esi = 0xBBBBBBBB, edi = 0xBBBBBBBB, ebp = 0xBBBBBBBB;
while ((ps = ps->var_24) != NULL) {
old_ps = ps;
next_ps = ps;
while (next_ps != NULL) {
ps = next_ps;
ebx = ps->image_id;
ecx = ps->x;
edx = ps->y;
edi = (uint32)dpi;
ebp = (uint32)ps;
//sub_679023(ps->image_id, ps->x, ps->y, dpi);
RCT2_CALLFUNC_X(0x00679023, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
store_interaction_info(ps);
next_ps = ps->var_20;
}
attached_ps = ps->attached_ps;
while (attached_ps != NULL) {
esi = (uint32)attached_ps;
ebp = (uint32)ps;
ecx = (attached_ps->attached_x + ps->x) & 0xFFFF;
edx = (attached_ps->attached_y + ps->y) & 0xFFFF;
ebx = attached_ps->image_id;
//sub_679023(ebx, ecx, edx, dpi);
RCT2_CALLFUNC_X(0x00679023, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
store_interaction_info(ps);
attached_ps = attached_ps->next_attached_ps;
}
ps = old_ps;
}
}
/**
*
* rct2: 0x00685ADC
@ -1739,7 +1955,7 @@ void viewport_set_visibility(uint8 mode)
* mapElement: edx
* viewport: edi
*/
void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *z, rct_map_element **mapElement, rct_viewport **viewport)
void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *interactionType, rct_map_element **mapElement, rct_viewport **viewport)
{
RCT2_GLOBAL(0x9AC154, uint16_t) = flags & 0xFFFF;
RCT2_GLOBAL(0x9AC148, uint8_t) = 0;
@ -1772,12 +1988,12 @@ void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, i
RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*) = dpi;
sub_0x68615B(0xEE788C);
sub_0x68B6C2();
RCT2_CALLPROC_X(0x688217, 0, 0, 0, 0, 0, 0, 0);
RCT2_CALLPROC_X(0x68862C, 0, 0, 0, 0, 0, 0, 0);
sub_688217();
sub_68862C();
}
if (viewport != NULL) *viewport = myviewport;
}
if (z != NULL) *z = RCT2_GLOBAL(0x9AC148, uint8_t);
if (interactionType != NULL) *interactionType = RCT2_GLOBAL(0x9AC148, uint8_t);
if (x != NULL) *x = (int)RCT2_GLOBAL(0x9AC14C, int16_t);
if (y != NULL) *y = (int)RCT2_GLOBAL(0x9AC14E, int16_t);
if (mapElement != NULL) *mapElement = RCT2_GLOBAL(0x9AC150, rct_map_element*);

View File

@ -46,10 +46,11 @@ enum {
enum {
VIEWPORT_INTERACTION_ITEM_NONE,
VIEWPORT_INTERACTION_ITEM_SPRITE = 2,
VIEWPORT_INTERACTION_ITEM_TERRAIN,
VIEWPORT_INTERACTION_ITEM_SPRITE,
VIEWPORT_INTERACTION_ITEM_RIDE,
VIEWPORT_INTERACTION_ITEM_SCENERY = 5,
VIEWPORT_INTERACTION_ITEM_WATER,
VIEWPORT_INTERACTION_ITEM_SCENERY,
VIEWPORT_INTERACTION_ITEM_FOOTPATH,
VIEWPORT_INTERACTION_ITEM_FOOTPATH_ITEM,
VIEWPORT_INTERACTION_ITEM_PARK,
@ -59,6 +60,21 @@ enum {
};
enum {
VIEWPORT_INTERACTION_MASK_NONE = 0,
VIEWPORT_INTERACTION_MASK_TERRAIN = ~(1 << (VIEWPORT_INTERACTION_ITEM_TERRAIN - 1)),
VIEWPORT_INTERACTION_MASK_SPRITE = ~(1 << (VIEWPORT_INTERACTION_ITEM_SPRITE - 1)),
VIEWPORT_INTERACTION_MASK_RIDE = ~(1 << (VIEWPORT_INTERACTION_ITEM_RIDE - 1)),
VIEWPORT_INTERACTION_MASK_WATER = ~(1 << (VIEWPORT_INTERACTION_ITEM_WATER - 1)),
VIEWPORT_INTERACTION_MASK_SCENERY = ~(1 << (VIEWPORT_INTERACTION_ITEM_SCENERY - 1)),
VIEWPORT_INTERACTION_MASK_FOOTPATH = ~(1 << (VIEWPORT_INTERACTION_ITEM_FOOTPATH - 1)),
VIEWPORT_INTERACTION_MASK_FOOTPATH_ITEM = ~(1 << (VIEWPORT_INTERACTION_ITEM_FOOTPATH_ITEM - 1)),
VIEWPORT_INTERACTION_MASK_PARK = ~(1 << (VIEWPORT_INTERACTION_ITEM_PARK - 1)),
VIEWPORT_INTERACTION_MASK_WALL = ~(1 << (VIEWPORT_INTERACTION_ITEM_WALL - 1)),
VIEWPORT_INTERACTION_MASK_LARGE_SCENERY = ~(1 << (VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY - 1)),
VIEWPORT_INTERACTION_MASK_BANNER = ~(1 << (VIEWPORT_INTERACTION_ITEM_BANNER - 2)), // Note the -2 for BANNER
};
typedef struct {
int type;
int x;
@ -97,7 +113,7 @@ void show_construction_rights();
void hide_construction_rights();
void viewport_set_visibility(uint8 mode);
void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *z, rct_map_element **mapElement, rct_viewport **viewport);
void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *interactionType, rct_map_element **mapElement, rct_viewport **viewport);
int viewport_interaction_get_item_left(int x, int y, viewport_interaction_info *info);
int viewport_interaction_left_over(int x, int y);
@ -105,5 +121,6 @@ int viewport_interaction_left_click(int x, int y);
int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info *info);
int viewport_interaction_right_over(int x, int y);
int viewport_interaction_right_click(int x, int y);
void sub_68A15E(int screenX, int screenY, short *x, short *y, int *direction, rct_map_element **mapElement);
#endif

View File

@ -29,6 +29,7 @@
#include "../world/map.h"
#include "../world/scenery.h"
#include "../world/sprite.h"
#include "../input.h"
#include "viewport.h"
static void viewport_interaction_remove_scenery(rct_map_element *mapElement, int x, int y);
@ -58,7 +59,7 @@ int viewport_interaction_get_item_left(int x, int y, viewport_interaction_info *
if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) && s6Info->var_000 != 6)
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
get_map_coordinates_from_pos(x, y, 0xFF79, &info->x, &info->y, &info->type, &info->mapElement, NULL);
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_SPRITE & VIEWPORT_INTERACTION_MASK_RIDE & VIEWPORT_INTERACTION_MASK_PARK, &info->x, &info->y, &info->type, &info->mapElement, NULL);
mapElement = info->mapElement;
sprite = (rct_sprite*)mapElement;
@ -178,7 +179,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info
if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) && s6Info->var_000 != 6)
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
get_map_coordinates_from_pos(x, y, 9, &info->x, &info->y, &info->type, &info->mapElement, NULL);
get_map_coordinates_from_pos(x, y, ~(VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER), &info->x, &info->y, &info->type, &info->mapElement, NULL);
mapElement = info->mapElement;
sprite = (rct_sprite*)mapElement;
@ -264,7 +265,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info
return info->type;
}
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & 0x48) != 0x48)
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & (INPUT_FLAG_6 | INPUT_FLAG_TOOL_ACTIVE)) != (INPUT_FLAG_6 | INPUT_FLAG_TOOL_ACTIVE))
if (window_find_by_class(WC_RIDE_CONSTRUCTION) == NULL && window_find_by_class(WC_FOOTPATH) == NULL)
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
@ -283,7 +284,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info
return info->type;
case VIEWPORT_INTERACTION_ITEM_FOOTPATH_ITEM:
sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[mapElement->properties.path.additions & 0x0F];
sceneryEntry = g_pathBitSceneryEntries[(mapElement->properties.path.additions & 0x0F) - 1];
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1164;
if (mapElement->flags & 0x20) {
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = 3124;
@ -473,7 +474,7 @@ static void viewport_interaction_remove_park_wall(rct_map_element *mapElement, i
{
rct_scenery_entry* sceneryEntry;
sceneryEntry = g_wallSceneryEntries[mapElement->properties.fence.slope];
sceneryEntry = g_wallSceneryEntries[mapElement->properties.fence.type];
if (sceneryEntry->wall.var_0D != 0xFF){
window_sign_small_open(mapElement->properties.fence.item[0]);
} else {
@ -496,12 +497,9 @@ static void viewport_interaction_remove_park_wall(rct_map_element *mapElement, i
*/
static void viewport_interaction_remove_large_scenery(rct_map_element *mapElement, int x, int y)
{
int ebx;
rct_scenery_entry* sceneryEntry;
ebx = mapElement->properties.scenerymultiple.type;
ebx |= (mapElement->properties.scenerymultiple.index & 0x3) << 8;
sceneryEntry = g_largeSceneryEntries[ebx];
sceneryEntry = g_largeSceneryEntries[mapElement->properties.scenerymultiple.type & MAP_ELEMENT_LARGE_TYPE_MASK];
if (sceneryEntry->large_scenery.var_11 != 0xFF){
int id = (mapElement->type & 0xC0) |
@ -514,8 +512,8 @@ static void viewport_interaction_remove_large_scenery(rct_map_element *mapElemen
x,
1 | ((mapElement->type & 0x3) << 8),
y,
mapElement->base_height | ((mapElement->properties.scenerymultiple.index >> 2) << 8),
GAME_COMMAND_44,
mapElement->base_height | ((mapElement->properties.scenerymultiple.type >> 10) << 8),
GAME_COMMAND_REMOVE_LARGE_SCENERY,
0,
0
);
@ -560,4 +558,72 @@ static rct_peep *viewport_interaction_get_closest_peep(int x, int y, int maxDist
}
return closestPeep;
}
/**
*
* rct2: 0x0068A15E
*/
void sub_68A15E(int screenX, int screenY, short *x, short *y, int *direction, rct_map_element **mapElement)
{
int my_x, my_y, z, interactionType;
rct_map_element *myMapElement;
rct_viewport *viewport;
get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER, &my_x, &my_y, &interactionType, &myMapElement, &viewport);
if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) {
*x = 0x8000;
return;
}
RCT2_GLOBAL(0x00F1AD3E, uint8) = interactionType;
RCT2_GLOBAL(0x00F1AD30, rct_map_element*) = myMapElement;
if (interactionType == VIEWPORT_INTERACTION_ITEM_WATER) {
z = myMapElement->properties.surface.terrain;
z = (z & MAP_ELEMENT_WATER_HEIGHT_MASK) << 4;
}
RCT2_GLOBAL(0x00F1AD3C, uint16) = z;
RCT2_GLOBAL(0x00F1AD34, sint16) = my_x;
RCT2_GLOBAL(0x00F1AD36, sint16) = my_y;
RCT2_GLOBAL(0x00F1AD38, sint16) = my_x + 31;
RCT2_GLOBAL(0x00F1AD3A, sint16) = my_y + 31;
rct_xy16 start_vp_pos = screen_coord_to_viewport_coord(viewport, screenX, screenY);
rct_xy16 map_pos = { my_x + 16, my_y + 16 };
for (int i = 0; i < 5; i++) {
if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 4) {
z = map_element_height(map_pos.x, map_pos.y);
} else {
z = RCT2_GLOBAL(0x00F1AD3C, uint16);
}
map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z);
map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, sint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, sint16));
map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, sint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, sint16));
}
// Determine to which edge the cursor is closest
int myDirection;
int mod_x = map_pos.x & 0x1F;
int mod_y = map_pos.y & 0x1F;
if (mod_x < mod_y) {
if (mod_x + mod_y < 32) {
myDirection = 0;
} else {
myDirection = 1;
}
} else {
if (mod_x + mod_y < 32) {
myDirection = 3;
} else {
myDirection = 2;
}
}
*x = map_pos.x & ~0x1F;
*y = map_pos.y & ~0x1F;
if (direction != NULL) *direction = myDirection;
if (mapElement != NULL) *mapElement = myMapElement;
}

View File

@ -192,6 +192,8 @@ enum {
STR_LOCATE_SUBJECT_TIP = 1027,
STR_OFF_EDGE_OF_MAP = 1028,
STR_CAN_ONLY_BUILD_THIS_ON_LAND = 1034,
STR_LOAD_GAME_DIALOG_TITLE = 1036,
STR_LOAD_LANDSCAPE_DIALOG_TITLE = 1037,
STR_CONVERT_SAVED_GAME_TO_SCENARIO_1038 = 1038,
@ -319,6 +321,7 @@ enum {
STR_BUILD_FOOTPATH_TIP = 1173,
STR_BANNER_SIGN_IN_THE_WAY = 1174,
STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH = 1175,
STR_CANT_BUILD_FOOTPATH_HERE = 1176,
STR_CANT_REMOVE_FOOTPATH_FROM_HERE = 1177,
@ -377,6 +380,7 @@ enum {
STR_SHOPS_STALLS_TIP = 1228,
STR_ROTATE_OBJECTS_90 = 1327,
STR_LEVEL_LAND_REQUIRED = 1328,
STR_LAUNCH_SPEED = 1329,
STR_LAUNCH_SPEED_TIP = 1330,
@ -739,6 +743,8 @@ enum {
STR_CANT_DEMOLISH_RIDE = 2248,
STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS = 2252,
STR_RESEARCH_TRANSPORT_RIDES = 2253,
STR_RESEARCH_GENTLE_RIDES = 2254,
STR_RESEARCH_ROLLER_COASTERS = 2255,
@ -1066,6 +1072,8 @@ enum {
STR_MUSIC_ACKNOWLEDGEMENTS_ELLIPSIS = 2862,
STR_MUSIC_ACKNOWLEDGEMENTS = 2863,
STR_TOO_MANY_BANNERS_IN_GAME = 2980,
STR_CHANGE_BANNER_TEXT_TIP = 2986,
STR_SET_AS_NO_ENTRY_BANNER_TIP = 2987,
STR_DEMOLISH_BANNER_TIP = 2988,

View File

@ -26,7 +26,7 @@
typedef int rct_expenditure_type;
enum {
RCT_EXPENDITURE_TYPE_RIDE_CONSRUCTION,
RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION,
RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS,
RCT_EXPENDITURE_TYPE_LAND_PURCHASE,
RCT_EXPENDITURE_TYPE_LANDSCAPING,

View File

@ -907,10 +907,11 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo*
chunk += 1038;
}
scenery_type->large_scenery.var_0C = (uint32)chunk;
scenery_type->large_scenery.tiles = (rct_large_scenery_tile*)chunk;
// skip over large scenery tiles
while (*((uint16*)chunk) != 0xFFFF){
chunk += 9;
chunk += sizeof(rct_large_scenery_tile);
}
chunk += 2;
@ -937,7 +938,7 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo*
rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi;
scenery_type->name = 0;
scenery_type->image = 0;
scenery_type->large_scenery.var_0C = 0;
scenery_type->large_scenery.tiles = 0;
scenery_type->large_scenery.scenery_tab_id = 0;
scenery_type->large_scenery.var_12 = 0;
scenery_type->large_scenery.var_16 = 0;

View File

@ -175,6 +175,21 @@ static void sub_693BE5(rct_peep* peep, uint8 al){
sub_693B58(peep);
}
/**
*
* rct2: 0x0069A512
*/
void remove_peep_from_ride(rct_peep* peep)
{
if (peep->state == PEEP_STATE_QUEUING) {
remove_peep_from_queue(peep);
}
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_1;
peep_window_state_update(peep);
sub_693BE5(peep, 0);
}
static void peep_state_reset(rct_peep* peep){
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_1;
@ -198,8 +213,8 @@ void peep_check_if_lost(rct_peep* peep){
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;
peep->happiness_growth_rate = max(peep->happiness_growth_rate - 30, 0);
}
/* rct2: 0x69C26B
@ -211,8 +226,7 @@ void peep_check_cant_find_ride(rct_peep* peep){
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->happiness_growth_rate = max(peep->happiness_growth_rate - 30, 0);
}
peep->var_C6--;
@ -237,8 +251,7 @@ void peep_check_cant_find_exit(rct_peep* peep){
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;
peep->happiness_growth_rate = max(peep->happiness_growth_rate - 30, 0);
}
if (--peep->var_C6 == 0) peep->var_C6 = 90;
@ -558,7 +571,7 @@ void peep_sprite_remove(rct_peep* peep){
//RCT2_CALLPROC_X(0x69A535, 0, 0, 0, 0, (int)peep, 0, 0);
//return;
RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0);
remove_peep_from_ride(peep);
invalidate_sprite((rct_sprite*)peep);
window_close_by_number(WC_PEEP, peep->sprite_index);
@ -575,7 +588,7 @@ void peep_sprite_remove(rct_peep* peep){
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] = 0;
peep->type = 0xFF;
sub_6C0C3F();
staff_update_greyed_patrol_areas();
peep->type = PEEP_TYPE_STAFF;
news_item_disable_news(NEWS_ITEM_PEEP, peep->sprite_index);
@ -3109,7 +3122,7 @@ static int peep_update_walking_find_bench(rct_peep* peep){
uint8 additions = map_element->properties.path.additions & 0xF;
if (!additions) return 0;
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!(sceneryEntry->path_bit.var_06 & 0x2))return 0;
@ -3186,7 +3199,7 @@ static int peep_update_walking_find_bin(rct_peep* peep){
uint8 additions = map_element->properties.path.additions & 0xF;
if (!additions) return 0;
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!(sceneryEntry->path_bit.var_06 & 0x1))return 0;
@ -3263,7 +3276,7 @@ static void peep_update_walking_break_scenery(rct_peep* peep){
uint8 additions = map_element->properties.path.additions & 0xF;
if (!additions) return;
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!(sceneryEntry->path_bit.var_06 & 0x4))return;
@ -3439,7 +3452,7 @@ static void peep_update_using_bin(rct_peep* peep){
return;
}
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!(sceneryEntry->path_bit.var_06 & 1)){
peep_state_reset(peep);
return;
@ -3830,7 +3843,7 @@ static int peep_update_patrolling_find_bin(rct_peep* peep){
if (additions == 0)return 0;
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!(sceneryEntry->path_bit.var_06 & 1))
return 0;
@ -4123,7 +4136,7 @@ static void peep_update_walking(rct_peep* peep){
if (additions){
if (!(map_element->properties.path.additions & 0x80)){
rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!(sceneryEntry->path_bit.var_06 & 0x2)) ebp = 9;
}
@ -4564,7 +4577,7 @@ void peep_update_crowd_noise()
// Load and play crowd noise
#ifdef USE_MIXER
if (!gCrowdSoundChannel) {
gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2);
gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2, false);
}
if (gCrowdSoundChannel) {
Mixer_Channel_Volume(gCrowdSoundChannel, DStoMixerVolume(volume));

View File

@ -389,7 +389,7 @@ typedef struct {
uint8 energy; // 0x38
uint8 energy_growth_rate; // 0x39
uint8 happiness; // 0x3A
sint8 happiness_growth_rate; // 0x3B
uint8 happiness_growth_rate; // 0x3B
uint8 nausea; // 0x3C
uint8 nausea_growth_rate; // 0x3D
uint8 hunger; // 0x3E
@ -570,6 +570,7 @@ int peep_check_easteregg_name(int index, rct_peep *peep);
int peep_get_easteregg_name_id(rct_peep *peep);
int peep_is_mechanic(rct_peep *peep);
int peep_has_food(rct_peep* peep);
void peep_sprite_remove(rct_peep* peep);
void peep_window_state_update(rct_peep* peep);
void peep_decrement_num_riders(rct_peep* peep);
@ -583,6 +584,7 @@ void peep_insert_new_thought(rct_peep *peep, uint8 thought_type, uint8 thought_a
void peep_set_map_tooltip(rct_peep *peep);
void sub_693B58(rct_peep* peep);
void remove_peep_from_ride(rct_peep* peep);
void remove_peep_from_queue(rct_peep* peep);
#endif

View File

@ -70,7 +70,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
RCT2_GLOBAL(0x009DEA62, uint16) = _dx;
if (RCT2_GLOBAL(0x13573C8, uint16) < 0x190) {
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_PEOPLE_IN_GAME;
return;
}
@ -82,7 +82,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
}
if (i == STAFF_MAX_COUNT) {
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_STAFF_IN_GAME;
return;
}
@ -96,7 +96,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
if (newPeep == NULL)
{
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_PEOPLE_IN_GAME;
return;
}
@ -211,6 +211,95 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
*edi = newPeep->sprite_index;
}
/**
*
* rct2: 0x006C0BB5
*/
void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 40;
uint8 order_id = *ebx >> 8;
uint16 sprite_id = *edx;
if(*ebx & GAME_COMMAND_FLAG_APPLY){
rct_peep *peep = &g_sprite_list[sprite_id].peep;
if(order_id & 0x80){ // change costume
uint8 sprite_type = order_id & ~0x80;
sprite_type += 4;
peep->sprite_type = sprite_type;
peep->flags &= ~PEEP_FLAGS_SLOW_WALK;
if(RCT2_ADDRESS(0x00982134, uint8)[sprite_type] & 1){
peep->flags |= PEEP_FLAGS_SLOW_WALK;
}
peep->action_frame = 0;
sub_693B58(peep);
invalidate_sprite((rct_sprite*)peep);
window_invalidate_by_number(WC_PEEP, sprite_id);
window_invalidate_by_class(WC_STAFF_LIST);
}else{
peep->staff_orders = order_id;
window_invalidate_by_number(WC_PEEP, sprite_id);
window_invalidate_by_class(WC_STAFF_LIST);
}
}
*ebx = 0;
}
/**
*
* rct2: 0x006C09D1
*/
void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
if(*ebx & GAME_COMMAND_FLAG_APPLY){
int x = *eax;
int y = *ecx;
uint16 sprite_id = *edx;
rct_peep *peep = &g_sprite_list[sprite_id].peep;
int patrolOffset = peep->staff_id * (64 * 64 / 8);
int patrolIndex = ((x & 0x1F80) >> 7) | ((y & 0x1F80) >> 1);
int mask = 1 << (patrolIndex & 0x1F);
int base = patrolIndex >> 5;
uint32 *patrolBits = (uint32*)(0x013B0E72 + patrolOffset + (base * 4));
*patrolBits ^= mask;
int ispatrolling = 0;
for(int i = 0; i < 128; i++){
ispatrolling |= *(uint32*)(0x013B0E72 + patrolOffset + (i * 4));
}
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] &= ~2;
if(ispatrolling){
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] |= 2;
}
for(int y2 = 0; y2 < 4; y2++){
for(int x2 = 0; x2 < 4; x2++){
map_invalidate_tile_full((x & 0x1F80) + (x2 * 32), (y & 0x1F80) + (y2 * 32));
}
}
staff_update_greyed_patrol_areas();
}
*ebx = 0;
}
/**
*
* rct2: 0x006C0B83
*/
void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 40;
if(*ebx & GAME_COMMAND_FLAG_APPLY){
window_close_by_class(WC_FIRE_PROMPT);
uint16 sprite_id = *edx;
rct_peep *peep = &g_sprite_list[sprite_id].peep;
remove_peep_from_ride(peep);
peep_sprite_remove(peep);
}
*ebx = 0;
}
/*
* Updates the colour of the given staff type.
*/
@ -233,29 +322,33 @@ uint16 hire_new_staff_member(uint8 staffType)
int result = game_do_command_p(GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
if (result == 0x80000000)
if (result == MONEY32_UNDEFINED)
return 0xFFFF;
return edi;
}
void sub_6C0C3F()
/**
*
* rct2: 0x006C0C3F
*/
void staff_update_greyed_patrol_areas()
{
register rct_peep* peep;
rct_peep* peep;
for (register uint8 staff_type = 0; staff_type < STAFF_TYPE_COUNT; ++staff_type)
for (int staff_type = 0; staff_type < STAFF_TYPE_COUNT; ++staff_type)
{
for (register uint8 i = 0; i < 128; ++i)
RCT2_ADDRESS(0x13B0E72 + (staff_type + STAFF_MAX_COUNT) * 512, uint32)[i] = 0;
for (int i = 0; i < 128; ++i)
RCT2_ADDRESS(0x13B0E72 + ((staff_type + STAFF_MAX_COUNT) * 512), uint32)[i] = 0;
for (register uint16 sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_index != SPRITE_INDEX_NULL; sprite_index = peep->next)
for (uint16 sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_index != SPRITE_INDEX_NULL; sprite_index = peep->next)
{
peep = GET_PEEP(sprite_index);
if (peep->type == PEEP_TYPE_STAFF && staff_type == peep->staff_type)
{
for (register uint8 i = 0; i < 128; ++i)
RCT2_ADDRESS(0x13B0E72 + (staff_type + STAFF_MAX_COUNT) * 512, uint32)[i] |= RCT2_ADDRESS(0x13B0E72 + peep->staff_id * 512, uint32)[i];
for (int i = 0; i < 128; ++i)
RCT2_ADDRESS(0x13B0E72 + ((staff_type + STAFF_MAX_COUNT) * 512), uint32)[i] |= RCT2_ADDRESS(0x13B0E72 + (peep->staff_id * 512), uint32)[i];
}
}

View File

@ -51,10 +51,13 @@ enum STAFF_ORDERS{
void game_command_update_staff_colour(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_hire_new_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void update_staff_colour(uint8 staffType, uint16 color);
uint16 hire_new_staff_member(uint8 staffType);
void sub_6C0C3F();
void staff_update_greyed_patrol_areas();
int mechanic_is_location_in_patrol(rct_peep *mechanic, int x, int y);
void staff_reset_stats();

View File

@ -191,6 +191,7 @@ static void platform_resize(int width, int height)
rct_drawpixelinfo *screenDPI;
int newScreenBufferSize;
void *newScreenBuffer;
uint32 flags;
if (_surface != NULL)
SDL_FreeSurface(_surface);
@ -247,6 +248,18 @@ static void platform_resize(int width, int height)
window_relocate_windows(width, height);
gfx_invalidate_screen();
// Check if the window has been resized in windowed mode and update the config file accordingly
// This is called in rct2_update_2 and is only called after resizing a window has finished
flags = SDL_GetWindowFlags(gWindow);
if ((flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED |
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) == 0) {
if (width != gConfigGeneral.window_width || height != gConfigGeneral.window_height) {
gConfigGeneral.window_width = width;
gConfigGeneral.window_height = height;
config_save_default();
}
}
}
void platform_update_palette(char* colours, int start_index, int num_colours)

View File

@ -62,7 +62,7 @@ bool rct1_read_sc4(const char *path, rct1_s4 *s4)
long length, decodedLength;
bool success;
if (!readentirefile(path, &buffer, &length)) {
if (!readentirefile(path, (void**)&buffer, &length)) {
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3011;
return 0;
@ -92,7 +92,7 @@ bool rct1_read_sv4(const char *path, rct1_s4 *s4)
long length, decodedLength;
bool success;
if (!readentirefile(path, &buffer, &length)) {
if (!readentirefile(path, (void**)&buffer, &length)) {
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3011;
return 0;
@ -230,17 +230,17 @@ void rct1_fix_landscape()
s6Info->category = 4;
format_string(s6Info->details, STR_NO_DETAILS_YET, NULL);
s6Info->name[0] = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) & PARK_FLAGS_NO_MONEY) {
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) |= PARK_FLAGS_NO_MONEY_SCENARIO;
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) {
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_NO_MONEY_SCENARIO;
} else {
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) &= PARK_FLAGS_NO_MONEY_SCENARIO;
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_NO_MONEY_SCENARIO;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) == MONEY_FREE) {
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) |= PARK_FLAGS_PARK_FREE_ENTRY;
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_PARK_FREE_ENTRY;
} else {
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) &= ~PARK_FLAGS_PARK_FREE_ENTRY;
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_PARK_FREE_ENTRY;
}
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) &= ~PARK_FLAGS_18;
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_18;
RCT2_GLOBAL(RCT2_ADDRESS_GUEST_INITIAL_CASH, money16) = clamp(
MONEY(10,00),
RCT2_GLOBAL(RCT2_ADDRESS_GUEST_INITIAL_CASH, money16),

View File

@ -72,6 +72,7 @@ int rct2_init()
RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) = 0;
RCT2_GLOBAL(0x009AC310, char*) = RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, char*);
get_system_time();
srand(time(0));
RCT2_GLOBAL(0x009DEA69, short) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, short);
RCT2_GLOBAL(0x009DEA6B, short) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, short);
if (!rct2_init_directories())

View File

@ -27,12 +27,14 @@
#include "../localisation/date.h"
#include "../localisation/localisation.h"
#include "../management/finance.h"
#include "../management/marketing.h"
#include "../management/news_item.h"
#include "../peep/peep.h"
#include "../peep/staff.h"
#include "../scenario.h"
#include "../util/util.h"
#include "../windows/error.h"
#include "../world/banner.h"
#include "../world/map.h"
#include "../world/sprite.h"
#include "ride.h"
@ -556,7 +558,7 @@ int ride_create_ride(ride_list_item listItem)
esi = GAME_COMMAND_6;
game_do_command_p(esi, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return ebx == 0x80000000 ? -1 : edi;
return ebx == MONEY32_UNDEFINED ? -1 : edi;
}
/**
@ -2445,32 +2447,34 @@ int ride_music_params_update(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint
uint8 vol1 = -1;
uint8 vol2 = -1;
if (pany < 0) {
pany = -pany;
int panx2 = panx;
int pany2 = pany;
if (pany2 < 0) {
pany2 = -pany2;
}
if (pany > 6143) {
pany = 6143;
if (pany2 > 6143) {
pany2 = 6143;
}
pany -= 2048;
if (pany > 0) {
pany = -((pany / 4) - 1024) / 4;
vol1 = (uint8)pany;
if (pany >= 256) {
pany2 -= 2048;
if (pany2 > 0) {
pany2 = -((pany2 / 4) - 1024) / 4;
vol1 = (uint8)pany2;
if (pany2 >= 256) {
vol1 = -1;
}
}
if (panx < 0) {
panx = -panx;
if (panx2 < 0) {
panx2 = -panx2;
}
if (panx > 6143) {
panx = 6143;
if (panx2 > 6143) {
panx2 = 6143;
}
panx -= 2048;
if (panx > 0) {
panx = -((panx / 4) - 1024) / 4;
vol2 = (uint8)panx;
if (panx >= 256) {
panx2 -= 2048;
if (panx2 > 0) {
panx2 = -((panx2 / 4) - 1024) / 4;
vol2 = (uint8)panx2;
if (panx2 >= 256) {
vol2 = -1;
}
}
@ -2660,7 +2664,7 @@ void ride_music_update_final()
rct_ride_music_info* ride_music_info = &RCT2_GLOBAL(0x009AF1C8, rct_ride_music_info*)[ride_music_params->tuneid];
#ifdef USE_MIXER
rct_ride_music* ride_music = &gRideMusicList[ebx];
ride_music->sound_channel = Mixer_Play_Music(ride_music_info->pathid);
ride_music->sound_channel = Mixer_Play_Music(ride_music_info->pathid, true);
if (ride_music->sound_channel) {
ride_music->volume = ride_music_params->volume;
ride_music->pan = ride_music_params->pan;
@ -2676,7 +2680,7 @@ void ride_music_update_final()
}
Mixer_Channel_SetOffset(ride_music->sound_channel, offset);
} else {
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0;
//RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0;
}
#else
const char* filename = get_file_path(ride_music_info->pathid);
@ -2781,13 +2785,13 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *
if (setting == 0){
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN){
RCT2_GLOBAL(0x141E9AC, uint16) = 1796;
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
return;
}
if (ride->status != RIDE_STATUS_CLOSED){
RCT2_GLOBAL(0x141E9AC, uint16) = 1006;
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
return;
}
}
@ -2796,7 +2800,7 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *
if (setting == 0 || setting == 4 || setting == 8 || setting == 9)
{
RCT2_GLOBAL(0x141E9AC, uint16) = 1797;
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
return;
}
}
@ -2805,7 +2809,7 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *
ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT &&
new_value > 1){
RCT2_GLOBAL(0x141E9AC, uint16) = 3141;
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
return;
}
@ -3590,6 +3594,262 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
*ebx = 0;
}
/**
*
* rct2: 0x006CB7FB
*/
int ride_get_refund_price(int ride_id)
{
uint8 oldpaused = RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8);
RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = 0;
RCT2_GLOBAL(0x00F4413A, int) = 0;
for(int x = 0; x < 8192; x += 32){
for(int y = 0; y < 8192; y += 32){
int tile_idx = ((y * 256) + x) / 32;
rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx];
do{
if((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_TRACK && map_element->properties.track.ride_index == ride_id){
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = x;
ebx = ((map_element->type & MAP_ELEMENT_DIRECTION_MASK) << 8) | 0x01;
ecx = y;
edx = map_element->properties.track.type;
edi = map_element->base_height * 8;
if(map_element->properties.track.type == 101){
edx = 2 << 8 | map_element->properties.track.ride_index;
int oldeax = eax;
int oldebx = ebx;
int oldecx = ecx;
int oldedx = edx;
ebx = oldebx;
ebx |= 0 << 0;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx = oldebx;
ebx |= 1 << 8;
ecx = oldecx;
ecx += 16;
edx = oldedx;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx = oldebx;
ebx |= 2 << 8;
eax = oldeax;
eax += 16;
ecx = oldecx;
ecx += 16;
edx = oldedx;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx = oldebx;
ebx |= 3 << 8;
eax = oldeax;
eax += 16;
ecx = oldecx;
edx = oldedx;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
}else{
edx |= 0xFF << 8;
edx &= ((map_element->properties.track.sequence & 0xF) << 8) | 0xFF;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_4, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
}
y -= 32;
break;
}
map_element++;
}while(!((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
}
}
RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = oldpaused;
return RCT2_GLOBAL(0x00F4413A, int);
}
/**
*
* rct2: 0x006B49D9
*/
void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
uint8 ride_id = *(uint8*)edx;
RCT2_GLOBAL(0x009DEA5E, uint16) = 0;
RCT2_GLOBAL(0x009DEA60, uint16) = 0;
RCT2_GLOBAL(0x009DEA62, uint16) = 0;
rct_ride *ride = &g_ride_list[ride_id];
int x = 0, y = 0, z = 0;
if(ride->overall_view != (uint16)-1){
x = ((ride->overall_view & 0xFF) * 32) + 16;
y = ((ride->overall_view >> 8) * 32) + 16;
z = map_element_height(x, y);
RCT2_GLOBAL(0x009DEA5E, uint16) = x;
RCT2_GLOBAL(0x009DEA60, uint16) = y;
RCT2_GLOBAL(0x009DEA62, uint16) = z;
}
if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8)){
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
*ebx = MONEY32_UNDEFINED;
return;
}else{
if(*ebx & GAME_COMMAND_FLAG_APPLY){
if(!(*ebx & 8)){
window_close_by_number(WC_RIDE_CONSTRUCTION, ride_id);
}
window_close_by_number(WC_RIDE, ride_id);
window_close_by_number(WC_DEMOLISH_RIDE_PROMPT, ride_id);
window_close_by_class(WC_NEW_CAMPAIGN);
if(RCT2_GLOBAL(0x01358103, uint8) && ride_id == RCT2_GLOBAL(0x01358117, uint8)){
RCT2_GLOBAL(0x01358103, uint8) = 0;
}
if(RCT2_GLOBAL(0x01358107, uint8) && ride_id == RCT2_GLOBAL(0x0135811B, uint8)){
RCT2_GLOBAL(0x01358107, uint8) = 0;
}
ride_clear_for_construction(ride_id);
ride_remove_peeps(ride_id);
RCT2_CALLPROC_X(0x00696707, 0, 0, 0, ride_id, 0, 0, 0);
*ebx = ride_get_refund_price(ride_id);
RCT2_CALLPROC(0x006CB945);
news_item_disable_news(NEWS_ITEM_RIDE, ride_id);
for(int i = 0; i < MAX_BANNERS; i++){
rct_banner *banner = &gBanners[i];
if(banner->type != BANNER_NULL && banner->flags & BANNER_FLAG_2 && banner->colour == ride_id){
banner->flags &= 0xFB;
banner->string_idx = 778;
}
}
uint16 spriteIndex;
rct_peep *peep;
FOR_ALL_GUESTS(spriteIndex, peep){
uint8 ride_id_bit = ride_id & 0x3;
uint8 ride_id_offset = ride_id / 8;
peep->rides_been_on[ride_id_offset] &= ~(1 << ride_id_bit); // clear ride from potentially being in rides_been_on
if(peep->state == PEEP_STATE_WATCHING){
if(peep->current_ride == ride_id){
peep->current_ride = MAX_RIDES;
if(peep->time_to_stand >= 50){ // make peep stop watching the ride
peep->time_to_stand = 50;
}
}
}
// remove any free voucher for this ride from peep
if(peep->item_standard_flags & PEEP_ITEM_VOUCHER){
if(peep->voucher_type == VOUCHER_TYPE_RIDE_FREE && peep->voucher_arguments == ride_id){
peep->item_standard_flags &= ~(PEEP_ITEM_VOUCHER);
}
}
// remove any photos of this ride from peep
if(peep->item_standard_flags & PEEP_ITEM_PHOTO){
if(peep->photo1_ride_ref == ride_id){
peep->item_standard_flags &= ~PEEP_ITEM_PHOTO;
}
}
if(peep->item_extra_flags && PEEP_ITEM_PHOTO2){
if(peep->photo2_ride_ref == ride_id){
peep->item_extra_flags &= ~PEEP_ITEM_PHOTO2;
}
}
if(peep->item_extra_flags && PEEP_ITEM_PHOTO3){
if(peep->photo3_ride_ref == ride_id){
peep->item_extra_flags &= ~PEEP_ITEM_PHOTO3;
}
}
if(peep->item_extra_flags && PEEP_ITEM_PHOTO4){
if(peep->photo4_ride_ref == ride_id){
peep->item_extra_flags &= ~PEEP_ITEM_PHOTO4;
}
}
if(peep->guest_heading_to_ride_id == ride_id){
peep->guest_heading_to_ride_id = MAX_RIDES;
}
if(peep->favourite_ride == ride_id){
peep->favourite_ride = MAX_RIDES;
}
for (int i = 0; i < PEEP_MAX_THOUGHTS; i++) {
if(peep->thoughts[i].item == ride_id){
// 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;
}
}
}
user_string_free(ride->name);
ride->type = RIDE_TYPE_NULL;
window_invalidate_by_class(WC_RIDE_LIST);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, money32) = calculate_park_value();
RCT2_GLOBAL(0x009DEA5E, uint16) = x;
RCT2_GLOBAL(0x009DEA60, uint16) = y;
RCT2_GLOBAL(0x009DEA62, uint16) = z;
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
return;
}else{
*ebx = 0;
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
return;
}
}
}
/**
*
* rct2: 0x006B2FC5
*/
void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
if(*ebx & GAME_COMMAND_FLAG_APPLY){
uint8 ride_id = *edx;
uint8 type = *ebx >> 8;
uint8 value = *edx >> 8;
int index = *edi;
rct_ride *ride = &g_ride_list[ride_id];
switch(type){
case 0:
ride->track_colour_main[index] = value;
gfx_invalidate_screen();
break;
case 1:
ride->track_colour_additional[index] = value;
gfx_invalidate_screen();
break;
case 2:
*((uint8*)(&ride->vehicle_colours[index])) = value;
RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0);
break;
case 3:
*((uint8*)(&ride->vehicle_colours[index]) + 1) = value;
RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0);
break;
case 4:
ride->track_colour_supports[index] = value;
gfx_invalidate_screen();
break;
case 5:
ride->colour_scheme_type &= ~(RIDE_COLOUR_SCHEME_DIFFERENT_PER_TRAIN | RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR);
ride->colour_scheme_type |= value;
for(int i = 1; i < countof(ride->vehicle_colours); i++){
ride->vehicle_colours[i] = ride->vehicle_colours[0];
ride->vehicle_colours_extended[i] = ride->vehicle_colours_extended[0];
}
RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0);
break;
case 6:
ride->entrance_style = value;
RCT2_GLOBAL(0x01358840, uint8) = value;
gfx_invalidate_screen();
break;
case 7:
ride->vehicle_colours_extended[index] = value;
RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0);
break;
}
window_invalidate_by_number(WC_RIDE, ride_id);
}
*ebx = 0;
}
bool ride_type_has_flag(int rideType, int flag)
{
return (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (rideType * 8), uint32) & flag) != 0;

View File

@ -764,6 +764,9 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e
void ride_set_name(int rideIndex, const char *name);
void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
int ride_get_refund_price(int ride_id);
void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
int get_var_10E_unk_1(rct_ride* ride);
int get_var_10E_unk_2(rct_ride* ride);

View File

@ -784,7 +784,7 @@ int sub_6D2189(int* cost, uint8* ride_id){
edx = track_design->type | (entry_index << 8);
esi = GAME_COMMAND_6;
if (0x80000000 == game_do_command_p(GAME_COMMAND_6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp)) return 1;
if (MONEY32_UNDEFINED == game_do_command_p(GAME_COMMAND_6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp)) return 1;
// bh
*ride_id = edi & 0xFF;
@ -840,7 +840,7 @@ int sub_6D2189(int* cost, uint8* ride_id){
edi = sub_6D01B3((*ride_id << 8) | bl, map_size, map_size, z);
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = backup_park_flags;
if (edi != 0x80000000){
if (edi != MONEY32_UNDEFINED){
if (!find_object_in_entry_group(&track_design->vehicle_object, &entry_type, &entry_index)){
RCT2_GLOBAL(0xF44151, uint8) |= 4;

View File

@ -314,7 +314,7 @@ int scenario_load_and_play_from_path(const char *path)
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PROFIT, money32) = 0;
RCT2_GLOBAL(0x01358334, money32) = 0;
RCT2_GLOBAL(0x01358338, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_ADMISSIONS, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, uint32) = 0;
RCT2_GLOBAL(0x013587D8, uint16) = 63;
@ -517,7 +517,7 @@ void scenario_objectives_check()
park_value = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, sint32);
if ( scenario_completed_company_value != 0x80000000)
if ( scenario_completed_company_value != MONEY32_UNDEFINED)
return;
switch (objective_type) {

View File

@ -201,7 +201,7 @@ static void window_banner_mouseup()
window_close(w);
break;
case WIDX_BANNER_DEMOLISH:
game_do_command(x, 1, y, map_element->base_height | (map_element->properties.banner.position << 8), GAME_COMMAND_51, 0, 0);
game_do_command(x, 1, y, map_element->base_height | (map_element->properties.banner.position << 8), GAME_COMMAND_REMOVE_BANNER, 0, 0);
break;
case WIDX_BANNER_TEXT:
window_text_input_open(w, WIDX_BANNER_TEXT, 2982, 2983, gBanners[w->number].string_idx, 0, 32);
@ -244,7 +244,7 @@ static void window_banner_mousedown(int widgetIndex, rct_window*w, rct_widget* w
widget->top + w->y,
widget->bottom - widget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
13,
widget->right - widget->left - 3);

View File

@ -103,7 +103,7 @@ void window_clear_scenery_open()
window_init_scroll_widgets(window);
window_push_others_below(window);
RCT2_GLOBAL(0x00F1AD62, uint32) = 0x80000000;
RCT2_GLOBAL(0x00F1AD62, uint32) = MONEY32_UNDEFINED;
window->colours[0] = 24;
window->colours[1] = 24;
window->colours[2] = 24;
@ -209,7 +209,7 @@ static void window_clear_scenery_paint()
// Draw cost amount
x = (window_clear_scenery_widgets[WIDX_PREVIEW].left + window_clear_scenery_widgets[WIDX_PREVIEW].right) / 2 + w->x;
y = window_clear_scenery_widgets[WIDX_PREVIEW].bottom + w->y + 5;
if (RCT2_GLOBAL(0x00F1AD62, uint32) != 0x80000000 && RCT2_GLOBAL(0x00F1AD62, uint32) != 0)
if (RCT2_GLOBAL(0x00F1AD62, uint32) != MONEY32_UNDEFINED && RCT2_GLOBAL(0x00F1AD62, uint32) != 0)
gfx_draw_string_centred(dpi, 986, x, y, 0, (void*)0x00F1AD62);
}

View File

@ -136,9 +136,9 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo
memcpy((void*)0x009DEBA4, gDropdownItemsFormat, 40 * 2);
memcpy((void*)0x009DEBF4, gDropdownItemsArgs, 40 * 8);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(INPUT_FLAG_1 | INPUT_FLAG_2);
if (flags & 0x80)
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_1;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP);
if (flags & DROPDOWN_FLAG_STAY_OPEN)
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_STAY_OPEN;
window_dropdown_close();
_dropdown_num_columns = 1;
@ -213,9 +213,9 @@ void window_dropdown_show_image(int x, int y, int extray, uint8 colour, uint8 fl
memcpy((void*)0x009DEBA4, gDropdownItemsFormat, 40 * 2);
memcpy((void*)0x009DEBF4, gDropdownItemsArgs, 40 * 8);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(INPUT_FLAG_1 | INPUT_FLAG_2);
if (flags & 0x80)
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_1;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP);
if (flags & DROPDOWN_FLAG_STAY_OPEN)
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_STAY_OPEN;
// Close existing dropdown
window_dropdown_close();
@ -411,19 +411,6 @@ void window_dropdown_show_colour_available(rct_window *w, rct_widget *widget, ui
if (availableColours & (1 << i))
numItems++;
// Show dropdown
window_dropdown_show_image(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
dropdownColour,
0x80,
numItems,
12,
12,
gAppropriateImageDropdownItemsPerRow[numItems]
);
// Set items
for (i = 0; i < 32; i++) {
if (availableColours & (1 << i)) {
@ -434,4 +421,18 @@ void window_dropdown_show_colour_available(rct_window *w, rct_widget *widget, ui
gDropdownItemsArgs[i] = ((uint64)i << 32) | (0x20000000 | (i << 19) | 5059);
}
}
// Show dropdown
window_dropdown_show_image(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
dropdownColour,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
12,
12,
gAppropriateImageDropdownItemsPerRow[numItems]
);
}

View File

@ -25,6 +25,11 @@
#define DROPDOWN_SEPARATOR 0
enum
{
DROPDOWN_FLAG_STAY_OPEN = (1 << 7)
};
extern int gAppropriateImageDropdownItemsPerRow[];
extern int gDropdownNumItems;

View File

@ -214,7 +214,7 @@ void window_editor_object_selection_open()
400,
(uint32*)window_editor_object_selection_events,
WC_EDITOR_OBJECT_SELECTION,
WF_STICK_TO_FRONT
WF_10
);
window->widgets = window_editor_object_selection_widgets;

View File

@ -507,7 +507,7 @@ static void window_editor_objective_options_show_objective_dropdown(rct_window *
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
dropdownWidget->right - dropdownWidget->left - 3
);
@ -537,7 +537,7 @@ static void window_editor_objective_options_show_climate_dropdown(rct_window *w)
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
4,
dropdownWidget->right - dropdownWidget->left - 3
);
@ -561,7 +561,7 @@ static void window_editor_objective_options_show_category_dropdown(rct_window *w
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
5,
dropdownWidget->right - dropdownWidget->left - 3
);

View File

@ -1049,7 +1049,7 @@ static void window_editor_scenario_options_park_mousedown(int widgetIndex, rct_w
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top - 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
2,
dropdownWidget->right - dropdownWidget->left - 3
);

View File

@ -865,7 +865,7 @@ static void window_finances_financial_graph_paint()
money32 *balanceHistory = RCT2_ADDRESS(RCT2_ADDRESS_BALANCE_HISTORY, money32);
for (i = 0; i < 64; i++) {
money32 balance = balanceHistory[i];
if (balance == 0x80000000)
if (balance == MONEY32_UNDEFINED)
continue;
// Modifier balance then keep halfing until less than 127 pixels
@ -983,7 +983,7 @@ static void window_finances_park_value_graph_paint()
money32 *parkValueHistory = RCT2_ADDRESS(RCT2_ADDRESS_PARK_VALUE_HISTORY, money32);
for (i = 0; i < 64; i++) {
money32 balance = parkValueHistory[i];
if (balance == 0x80000000)
if (balance == MONEY32_UNDEFINED)
continue;
// Modifier balance then keep halfing until less than 255 pixels
@ -1101,7 +1101,7 @@ static void window_finances_profit_graph_paint()
money32 *weeklyProfitHistory = RCT2_ADDRESS(RCT2_ADDRESS_WEEKLY_PROFIT_HISTORY, money32);
for (i = 0; i < 64; i++) {
money32 balance = weeklyProfitHistory[i];
if (balance == 0x80000000)
if (balance == MONEY32_UNDEFINED)
continue;
// Modifier balance then keep halfing until less than 127 pixels
@ -1375,7 +1375,7 @@ static void window_finances_research_mousedown(int widgetIndex, rct_window *w, r
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
4,
dropdownWidget->right - dropdownWidget->left - 3
);

View File

@ -667,15 +667,15 @@ static void window_footpath_mousedown_slope(int slope)
*/
static void window_footpath_set_provisional_path_at_point(int x, int y)
{
int z, slope, pathType;
int slope, pathType, interactionType;
rct_map_element *mapElement;
map_invalidate_selection_rect();
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 2);
get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement, NULL);
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, &x, &y, &interactionType, &mapElement, NULL);
if (z == 0) {
if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) {
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0);
footpath_provisional_update();
} else {
@ -695,7 +695,7 @@ static void window_footpath_set_provisional_path_at_point(int x, int y)
// Set provisional path
slope = RCT2_ADDRESS(0x0098D8B4, uint8)[mapElement->properties.surface.slope & 0x1F];
if (z == 6)
if (interactionType == VIEWPORT_INTERACTION_ITEM_FOOTPATH)
slope = mapElement->properties.surface.slope & 7;
pathType = (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_TYPE, uint8) << 7) + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, uint8);
@ -752,7 +752,7 @@ static void window_footpath_set_selection_start_bridge_at_point(int screenX, int
*/
static void window_footpath_place_path_at_point(int x, int y)
{
int z, presentType, selectedType, cost;
int interactionType, presentType, selectedType, z, cost;
rct_map_element *mapElement;
if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) != 0)
@ -760,13 +760,13 @@ static void window_footpath_place_path_at_point(int x, int y)
footpath_provisional_update();
get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement, NULL);
if (z == 0)
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, &x, &y, &interactionType, &mapElement, NULL);
if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE)
return;
// Set path
presentType = RCT2_ADDRESS(0x0098D8B4, uint8)[mapElement->properties.path.type & 0x1F];
if (z == 6)
if (interactionType == VIEWPORT_INTERACTION_ITEM_FOOTPATH)
presentType = mapElement->properties.path.type & 7;
z = mapElement->base_height;
selectedType = (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_TYPE, uint8) << 7) + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, uint8);

View File

@ -33,6 +33,7 @@
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../world/footpath.h"
#include "../input.h"
#include "dropdown.h"
#include "error.h"
@ -555,7 +556,7 @@ void window_guest_overview_close(){
window_get_register(w);
if (RCT2_GLOBAL(0x9DE518,uint32) & (1<<3)){
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE){
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS,rct_windowclass) &&
w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER,rct_windownumber))
tool_cancel();
@ -622,7 +623,7 @@ void window_guest_overview_mouse_up(){
w->var_48C = peep->x;
RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0);
remove_peep_from_ride(peep);
invalidate_sprite((rct_sprite*)peep);
sprite_move(0x8000, peep->y, peep->z, (rct_sprite*)peep);
@ -645,7 +646,7 @@ void window_guest_overview_mouse_up(){
/* rct2: 0x696AA0 */
void window_guest_set_page(rct_window* w, int page){
if (RCT2_GLOBAL(0x9DE518,uint32) & (1 << 3))
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
{
if(w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) &&
w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass))
@ -1157,9 +1158,9 @@ void window_guest_overview_tool_update(){
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1;
int ebx;
get_map_coordinates_from_pos(x, y, 0, NULL, NULL, &ebx, NULL, NULL);
if (ebx == 0)
int interactionType;
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_NONE, NULL, NULL, &interactionType, NULL, NULL);
if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE)
return;
x--;
@ -1171,7 +1172,7 @@ void window_guest_overview_tool_update(){
rct_peep* peep;
peep = GET_PEEP(w->number);
ebx = (RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2])[22];
int ebx = (RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2])[22];
ebx += w->var_492 >> 2;
int ebp = peep->tshirt_colour << 19;
@ -1237,8 +1238,7 @@ void window_guest_overview_tool_down(){
peep->action_sprite_type = 0xFF;
peep->var_C4 = 0;
peep->happiness_growth_rate -= 10;
if (peep->happiness_growth_rate < 0)peep->happiness_growth_rate = 0;
peep->happiness_growth_rate = max(peep->happiness_growth_rate - 10, 0);
sub_693B58(peep);
tool_cancel();

View File

@ -339,7 +339,7 @@ static void window_guest_list_mousedown(int widgetIndex, rct_window*w, rct_widge
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
_window_guest_list_num_pages,
widget->right - widget->left - 3
);
@ -363,7 +363,7 @@ static void window_guest_list_mousedown(int widgetIndex, rct_window*w, rct_widge
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
2,
widget->right - widget->left - 3
);

View File

@ -255,6 +255,10 @@ static void window_loadsave_mouseup()
char filename[MAX_PATH], filter[MAX_PATH];
int result;
strcpy(filename, _directory);
if (_type & LOADSAVETYPE_SAVE){
strcat(filename, (char*)RCT2_ADDRESS_SCENARIO_NAME);
}
memset(filter, '\0', MAX_PATH);
strncpy(filter, "*", MAX_PATH);
strncat(filter, _extension, MAX_PATH);
@ -605,7 +609,7 @@ static void window_loadsave_select(rct_window *w, const char *path)
if (scenario_save((char*)path, gConfigGeneral.save_plugin_data ? 1 : 0)) {
window_close(w);
game_do_command(0, 1047, 0, -1, GAME_COMMAND_0, 0, 0);
game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
gfx_invalidate_screen();
}
else {

View File

@ -319,8 +319,8 @@ static void window_map_mouseup()
RCT2_GLOBAL(0x9E32D2, sint8) = 0;
if (!(RCT2_GLOBAL(0x9DE518, sint32) & (1 << 6))) // Remove?
RCT2_GLOBAL(0x9DE518, sint32) |= (1 << 6);
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, sint32) & INPUT_FLAG_6)) // Remove?
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, sint32) |= INPUT_FLAG_6;
show_gridlines();
show_land_rights();
@ -369,14 +369,19 @@ static void window_map_mouseup()
*/
static void window_map_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
{
// The normal map window doesn't have widget 8 or 9.
// I assume these widgets refer to the Scenario Editor's map window.
if (widgetIndex == 8) {
// These widgets all refer to the Scenario Editor's map window.
if (widgetIndex == WIDX_MAP_SIZE_SPINNER_UP) {
RCT2_CALLPROC_X(0x0068D641, 0, 0, 0, widgetIndex, (int)w, 0, 0);
}
else if (widgetIndex == 9) {
else if (widgetIndex == WIDX_MAP_SIZE_SPINNER_DOWN) {
RCT2_CALLPROC_X(0x0068D6B4, 0, 0, 0, widgetIndex, (int)w, 0, 0);
}
else if (widgetIndex == WIDX_SET_LAND_RIGHTS)
{
// When unselecting the land rights tool, reset the size so the number doesn't
// stay in the map window.
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
}
}
/**

View File

@ -273,7 +273,7 @@ static void window_new_campaign_mousedown(int widgetIndex, rct_window *w, rct_wi
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
dropdownWidget->right - dropdownWidget->left - 3
);
@ -295,7 +295,7 @@ static void window_new_campaign_mousedown(int widgetIndex, rct_window *w, rct_wi
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
dropdownWidget->right - dropdownWidget->left - 3
);

View File

@ -221,7 +221,7 @@ void window_options_open()
if (w != NULL)
return;
w = window_create_centred(WW, WH, (uint32*)window_options_events, WC_OPTIONS, WF_STICK_TO_FRONT);
w = window_create_centred(WW, WH, (uint32*)window_options_events, WC_OPTIONS, 0);
w->widgets = window_options_widgets;
w->enabled_widgets =
(1ULL << WIDX_CLOSE) |
@ -396,12 +396,15 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsChecked = gConfigGeneral.show_height_as_units ? 1 : 2;
break;
case WIDX_TITLE_MUSIC_DROPDOWN:
num_items = 3;
num_items = 4;
for (i = 0; i < num_items; i++) {
for (i = 0; i < num_items - 1; i++) {
gDropdownItemsFormat[i] = 1142;
gDropdownItemsArgs[i] = 2739 + i;
}
// Random title music
gDropdownItemsFormat[3] = 1142;
gDropdownItemsArgs[3] = 5126;
window_options_show_dropdown(w, widget, num_items);
@ -556,7 +559,7 @@ static void window_options_dropdown()
window_options_update_height_markers();
break;
case WIDX_TITLE_MUSIC_DROPDOWN:
if (dropdownIndex == 1 && !platform_file_exists(get_file_path(PATH_ID_CSS50))) {
if ((dropdownIndex == 1 || dropdownIndex == 3) && !platform_file_exists(get_file_path(PATH_ID_CSS50))) {
window_error_open(2742, 2743);
} else {
gConfigSound.title_music = (sint8)dropdownIndex;
@ -837,7 +840,7 @@ static void window_options_paint()
gfx_draw_string_left(dpi, 2738, w, 12, w->x + 10, w->y + window_options_widgets[WIDX_TITLE_MUSIC].top + 1);
gfx_draw_string_left(
dpi,
2739 + gConfigSound.title_music,
(gConfigSound.title_music == 3 ? 5126 : 2739 + gConfigSound.title_music),
NULL,
12,
w->x + window_options_widgets[WIDX_TITLE_MUSIC].left + 1,
@ -866,7 +869,7 @@ static void window_options_show_dropdown(rct_window *w, rct_widget *widget, int
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
num_items,
widget->right - widget->left - 3
);

View File

@ -472,7 +472,7 @@ static void window_research_funding_mousedown(int widgetIndex, rct_window *w, rc
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
4,
dropdownWidget->right - dropdownWidget->left - 3
);

View File

@ -2308,7 +2308,7 @@ static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_wi
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
widget->right - dropdownWidget->left
);
@ -2321,7 +2321,7 @@ static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_wi
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
ride->var_0CC,
widget->right - dropdownWidget->left
);
@ -2343,7 +2343,7 @@ static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_wi
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
maxCars - minCars + 1,
widget->right - dropdownWidget->left
);
@ -2759,7 +2759,7 @@ static void window_ride_mode_dropdown(rct_window *w, rct_widget *widget)
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
numAvailableModes,
widget->right - dropdownWidget->left
);
@ -2791,7 +2791,7 @@ static void window_ride_load_dropdown(rct_window *w, rct_widget *widget)
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
5,
widget->right - dropdownWidget->left
);
@ -3323,7 +3323,7 @@ static void window_ride_maintenance_mousedown(int widgetIndex, rct_window *w, rc
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
7,
widget->right - dropdownWidget->left
);
@ -3545,9 +3545,9 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y)
newColourScheme = (uint8)(*((uint16*)&w->var_494));
int z;
int interactionType;
get_map_coordinates_from_pos(x, y, -5, &x, &y, &z, &mapElement, NULL);
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_RIDE, &x, &y, &interactionType, &mapElement, NULL);
// Get map coordinates from point
/*int eax, ebx, ecx, edx, esi, edi, ebp;
eax = x;
@ -3558,7 +3558,7 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y)
y = ecx & 0xFFFF;
mapElement = (rct_map_element*)edx;*/
if ((/*ebx*/z & 0xFF) != 3)
if (interactionType != VIEWPORT_INTERACTION_ITEM_RIDE)
return;
if (mapElement->properties.track.ride_index != w->number)
return;
@ -3676,7 +3676,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
4,
widget->right - dropdownWidget->left
);
@ -3703,7 +3703,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
4,
widget->right - dropdownWidget->left
);
@ -3725,7 +3725,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
countof(window_ride_entrance_style_list),
widget->right - dropdownWidget->left
);
@ -3743,7 +3743,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
rideEntry->max_cars_in_train > 1 ? 3 : 2,
widget->right - dropdownWidget->left
);
@ -3766,7 +3766,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0x80,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
widget->right - dropdownWidget->left
);
@ -3808,22 +3808,22 @@ static void window_ride_colour_dropdown()
window_invalidate(w);
break;
case WIDX_TRACK_MAIN_COLOUR:
game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0);
game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0);
break;
case WIDX_TRACK_ADDITIONAL_COLOUR:
game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0);
game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0);
break;
case WIDX_TRACK_SUPPORT_COLOUR:
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0);
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0);
break;
case WIDX_MAZE_STYLE_DROPDOWN:
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0);
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0);
break;
case WIDX_ENTRANCE_STYLE_DROPDOWN:
game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_0, 0, 0);
game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
break;
case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN:
game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, 0, 0);
game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
w->var_48C = 0;
break;
case WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN:
@ -3831,13 +3831,13 @@ static void window_ride_colour_dropdown()
window_invalidate(w);
break;
case WIDX_VEHICLE_MAIN_COLOUR:
game_do_command(0, (2 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0);
game_do_command(0, (2 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0);
break;
case WIDX_VEHICLE_ADDITIONAL_COLOUR_1:
game_do_command(0, (3 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0);
game_do_command(0, (3 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0);
break;
case WIDX_VEHICLE_ADDITIONAL_COLOUR_2:
game_do_command(0, (7 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0);
game_do_command(0, (7 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0);
break;
}
}
@ -4327,21 +4327,24 @@ static void window_ride_music_mousedown(int widgetIndex, rct_window *w, rct_widg
window_ride_current_music_style_order[numItems++] = MUSIC_STYLE_CUSTOM_MUSIC_2;
}
for (i = 0; i < numItems; i++) {
gDropdownItemsFormat[i] = 1142;
gDropdownItemsArgs[i] = STR_MUSIC_STYLE_START + window_ride_current_music_style_order[i];
}
window_dropdown_show_text_custom_width(
w->x + dropdownWidget->left,
w->y + dropdownWidget->top,
dropdownWidget->bottom - dropdownWidget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
numItems,
widget->right - dropdownWidget->left
);
for (i = 0; i < numItems; i++) {
gDropdownItemsFormat[i] = 1142;
if (window_ride_current_music_style_order[i] == ride->music)
gDropdownItemsChecked = (1 << i);
gDropdownItemsArgs[i] = STR_MUSIC_STYLE_START + window_ride_current_music_style_order[i];
}
}

View File

@ -169,7 +169,7 @@ rct_window *window_construction_open()
window_push_others_right(w);
show_gridlines();
RCT2_GLOBAL(0xF44070, uint32) = 0x80000000;
RCT2_GLOBAL(0xF44070, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(0xF440CD, uint8) = 8;
RCT2_GLOBAL(0xF440CE, uint8) = 18;
RCT2_GLOBAL(0xF440CF, uint8) = 4;
@ -307,7 +307,7 @@ void window_construction_mouseup_demolish(rct_window* w){
RCT2_CALLPROC_X(0x6C9BA5, 0, 0, 0, 0, (int)w, 0, 0);
return;
RCT2_GLOBAL(0xF44070, uint32) = 0x80000000;
RCT2_GLOBAL(0xF44070, uint32) = MONEY32_UNDEFINED;
sub_6C9627();
RCT2_GLOBAL(0xF440B8, uint8) = 3;
@ -440,7 +440,7 @@ void window_construction_paint()
short string_y = RCT2_GLOBAL(0x9D7C08, int16_t) + w->y - 23;
if (RCT2_GLOBAL(0xF440A6, uint8_t) != 4) gfx_draw_string_centred(dpi, 1407, string_x, string_y, 0, w);
string_y += 11;
if (RCT2_GLOBAL(0xF44070, uint32_t) != 0x80000000 && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32_t) & 0x800))
if (RCT2_GLOBAL(0xF44070, uint32_t) != MONEY32_UNDEFINED && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32_t) & 0x800))
gfx_draw_string_centred(dpi, 1408, string_x, string_y, 0, (void*)0xF44070);
}

View File

@ -253,7 +253,15 @@ static void window_ride_list_mousedown(int widgetIndex, rct_window*w, rct_widget
gDropdownItemsFormat[i] = 1142;
gDropdownItemsArgs[i] = STR_STATUS + i;
}
window_dropdown_show_text_custom_width(w->x + widget->left, w->y + widget->top, widget->bottom - widget->top, w->colours[1], 0x80, numItems, widget->right - widget->left - 3);
window_dropdown_show_text_custom_width(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top,
w->colours[1],
DROPDOWN_FLAG_STAY_OPEN,
numItems,
widget->right - widget->left - 3
);
gDropdownItemsChecked |= (1 << _window_ride_list_information_type);
}
}

View File

@ -458,13 +458,13 @@ void window_scenery_open()
window_scenery_update_scroll(window);
show_gridlines();
window_scenery_rotation = 3;
RCT2_GLOBAL(0x00F64F12, uint8) = 0;
RCT2_GLOBAL(0x00F64F13, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_CTRL_PRESSED, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED, uint8) = 0;
window->scenery.selected_scenery_id = -1;
window->scenery.hover_counter = 0;
window_push_others_below(window);
RCT2_GLOBAL(0x00F64F0D, uint8) = 0;
RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000;
RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(0x00F64EC0, uint16) = 0;
window_scenery_is_repaint_scenery_tool_on = 0; // repaint colored scenery tool state
window_scenery_is_build_cluster_tool_on = 0; // build cluster tool state
@ -503,9 +503,9 @@ void window_scenery_close() {
window_get_register(w);
RCT2_CALLPROC_EBPSAFE(0x006E2712);
scenery_remove_ghost_tool_placement();
hide_gridlines();
RCT2_CALLPROC_X(0x006CB70A, 0, 0, 0, 0, 0, 0, 0);
viewport_set_visibility(0);
if (window_scenery_is_scenery_tool_active())
tool_cancel();
@ -543,7 +543,7 @@ static void window_scenery_mouseup()
case WIDX_SCENERY_ROTATE_OBJECTS_BUTTON:
window_scenery_rotation++;
window_scenery_rotation = window_scenery_rotation % 4;
RCT2_CALLPROC_EBPSAFE(0x006E2712);
scenery_remove_ghost_tool_placement();
window_invalidate(w);
break;
case WIDX_SCENERY_REPAINT_SCENERY_BUTTON:
@ -643,7 +643,7 @@ static void window_scenery_mousedown(int widgetIndex, rct_window* w, rct_widget*
if (widgetIndex >= WIDX_SCENERY_TAB_1 && widgetIndex <= WIDX_SCENERY_TAB_20) {
window_scenery_active_tab_index = widgetIndex - WIDX_SCENERY_TAB_1;
window_invalidate(w);
RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000;
RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED;
window_scenery_update_scroll(w);
}
}
@ -817,7 +817,7 @@ void window_scenery_scrollmousedown()
window_scenery_is_repaint_scenery_tool_on &= 0xFE;
sound_play_panned(4, (w->width >> 1) + w->x, 0, 0, 0);
w->scenery.hover_counter = -16;
RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000;
RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED;
window_invalidate(w);
}
@ -1057,7 +1057,7 @@ void window_scenery_paint()
price = sceneryEntry->small_scenery.price * 10;
}
if (w->scenery.selected_scenery_id == -1 && RCT2_GLOBAL(0x00F64EB4, uint32) != 0x80000000) {
if (w->scenery.selected_scenery_id == -1 && RCT2_GLOBAL(0x00F64EB4, uint32) != MONEY32_UNDEFINED) {
price = RCT2_GLOBAL(0x00F64EB4, uint32);
}

View File

@ -174,9 +174,7 @@ void window_sign_open(rct_windownumber number)
while (1){
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) {
int ebx = map_element->properties.scenerymultiple.type;
ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8;
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx];
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[map_element->properties.scenerymultiple.type & MAP_ELEMENT_LARGE_TYPE_MASK];
if (scenery_entry->large_scenery.var_11 != 0xFF){
int id = (map_element->type & 0xC0) |
((map_element->properties.scenerymultiple.colour[0] & 0xE0) >> 2) |
@ -242,9 +240,7 @@ static void window_sign_mouseup()
case WIDX_SIGN_DEMOLISH:
while (1){
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) {
int ebx = map_element->properties.scenerymultiple.type;
ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8;
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx];
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[map_element->properties.scenerymultiple.type & MAP_ELEMENT_LARGE_TYPE_MASK];
if (scenery_entry->large_scenery.var_11 != 0xFF){
int id = (map_element->type & 0xC0) |
((map_element->properties.scenerymultiple.colour[0] & 0xE0) >> 2) |
@ -259,8 +255,8 @@ static void window_sign_mouseup()
x,
1 | ((map_element->type&0x3) << 8),
y,
map_element->base_height | ((map_element->properties.scenerymultiple.index >> 2) << 8),
GAME_COMMAND_44,
map_element->base_height | ((map_element->properties.scenerymultiple.type >> 10) << 8),
GAME_COMMAND_REMOVE_LARGE_SCENERY,
0,
0);
break;
@ -323,9 +319,7 @@ static void window_sign_dropdown()
while (1){
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) {
int ebx = map_element->properties.scenerymultiple.type;
ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8;
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx];
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[map_element->properties.scenerymultiple.type & MAP_ELEMENT_LARGE_TYPE_MASK];
if (scenery_entry->large_scenery.var_11 != 0xFF){
int id = (map_element->type & 0xC0) |
((map_element->properties.scenerymultiple.colour[0] & 0xE0) >> 2) |
@ -337,7 +331,7 @@ static void window_sign_dropdown()
map_element++;
}
int edx = map_element->base_height | ((map_element->properties.scenerymultiple.index >> 2) << 8);
int edx = map_element->base_height | ((map_element->properties.scenerymultiple.type >> 10) << 8);
int ebp = w->list_information_type | (w->var_492 << 8);
int ebx = (map_element->type & 0x3) << 8;
RCT2_CALLPROC_X(0x6B9B05, x, ebx, y, edx, 0, w->number, ebp);
@ -501,7 +495,7 @@ void window_sign_small_open(rct_windownumber number){
while (1){
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) {
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope];
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.type];
if (scenery_entry->wall.var_0D != 0xFF){
if (map_element->properties.fence.item[0] == w->number)
break;
@ -515,7 +509,7 @@ void window_sign_small_open(rct_windownumber number){
w->list_information_type = map_element->properties.fence.item[1] & 0x1F;
w->var_492 = (map_element->properties.fence.item[1] >> 5) | ((map_element->flags&0x60) >> 2);
w->var_48C = map_element->properties.fence.slope;
w->var_48C = map_element->properties.fence.type;
view_x += 16;
view_y += 16;
@ -564,7 +558,7 @@ static void window_sign_small_mouseup()
case WIDX_SIGN_DEMOLISH:
while (1){
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) {
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope];
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.type];
if (scenery_entry->wall.var_0D != 0xFF){
if (map_element->properties.fence.item[0] == w->number)
break;
@ -626,7 +620,7 @@ static void window_sign_small_dropdown()
while (1){
if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) {
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope];
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.type];
if (scenery_entry->wall.var_0D != 0xFF){
if (map_element->properties.fence.item[0] == w->number)
break;

View File

@ -30,6 +30,7 @@
#include "../world/footpath.h"
#include "../world/sprite.h"
#include "../world/scenery.h"
#include "../input.h"
#include "dropdown.h"
#include "error.h"
@ -375,7 +376,7 @@ void window_staff_overview_close()
window_get_register(w);
if (RCT2_GLOBAL(0x9DE518, uint32) & (1 << 3)){
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE){
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) &&
w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
@ -388,7 +389,7 @@ void window_staff_overview_close()
*/
void window_staff_set_page(rct_window* w, int page)
{
if (RCT2_GLOBAL(0x9DE518,uint32) & (1 << 3))
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
{
if(w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) &&
w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass))
@ -457,7 +458,7 @@ void window_staff_overview_mouseup()
w->var_48C = peep->x;
RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0);
remove_peep_from_ride(peep);
invalidate_sprite((rct_sprite*)peep);
sprite_move( 0x8000, peep->y, peep->z, (rct_sprite*)peep);
@ -573,19 +574,18 @@ void window_staff_overview_dropdown()
for (int i = 0; i < 128; i++)
{
RCT2_GLOBAL(0x13B0E72 + ebx + i * 4, uint32) = 0;
RCT2_ADDRESS(0x13B0E72 + (peep->staff_id * 512), uint32)[i] = 0;
}
RCT2_GLOBAL(RCT2_ADDRESS_STAFF_MODE_ARRAY + edi, uint16) &= 0xFD; // bug??
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] &= ~2;
window_invalidate(w);
//RCT2_CALLPROC_EBPSAFE(0x006C0C3F);
sub_6C0C3F();
gfx_invalidate_screen();
staff_update_greyed_patrol_areas();
}
else {
if (!tool_set(w, widgetIndex, 22)) {
show_gridlines();
RCT2_GLOBAL(0x009DEA50, sint16) = w->number;
window_invalidate(w);
gfx_invalidate_screen();
}
}
}
@ -1085,9 +1085,9 @@ void window_staff_overview_tool_update(){
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1;
int z;
get_map_coordinates_from_pos(x, y, 0, NULL, NULL, &z, NULL, NULL);
if (z == 0)
int interactionType;
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_NONE, NULL, NULL, &interactionType, NULL, NULL);
if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE)
return;
x--;
@ -1357,7 +1357,7 @@ void window_staff_options_mousedown(int widgetIndex, rct_window* w, rct_widget*
int y = widget->top + w->y;
int extray = widget->bottom - widget->top + 1;
int width = widget->right - widget->left - 3;
window_dropdown_show_text_custom_width(x, y, extray, w->colours[1], 0x80, no_entries, width);
window_dropdown_show_text_custom_width(x, y, extray, w->colours[1], DROPDOWN_FLAG_STAY_OPEN, no_entries, width);
// See above note.
gDropdownItemsChecked = item_checked;

View File

@ -130,7 +130,7 @@ static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widge
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[0] | 0x80,
0x80,
DROPDOWN_FLAG_STAY_OPEN,
3
);
} else if (widgetIndex == WIDX_GAME_TOOLS) {
@ -143,7 +143,7 @@ static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widge
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[0] | 0x80,
0x80,
DROPDOWN_FLAG_STAY_OPEN,
4
);
}

View File

@ -116,7 +116,7 @@ void window_scenarioselect_open()
334,
(uint32*)window_scenarioselect_events,
WC_SCENARIO_SELECT,
WF_STICK_TO_FRONT | WF_10
WF_10
);
window->widgets = window_scenarioselect_widgets;

File diff suppressed because it is too large Load Diff

View File

@ -300,75 +300,6 @@ static void window_track_place_draw_mini_preview()
}
}
/**
*
* rct2: 0x0068A15E
*/
static void sub_68A15E(int screenX, int screenY, short *x, short *y, int *direction, rct_map_element **mapElement)
{
int my_x, my_y, z;
rct_map_element *myMapElement;
rct_viewport *viewport;
get_map_coordinates_from_pos(screenX, screenY, 0xFFF6, &my_x, &my_y, &z, &myMapElement, &viewport);
if (z == 0) {
*x = 0x8000;
return;
}
RCT2_GLOBAL(0x00F1AD3E, uint8) = z;
RCT2_GLOBAL(0x00F1AD30, rct_map_element*) = myMapElement;
if (z == 4) {
// myMapElement appears to be water
z = myMapElement->properties.surface.terrain;
z = (z & MAP_ELEMENT_WATER_HEIGHT_MASK) << 4;
}
RCT2_GLOBAL(0x00F1AD3C, uint16) = z;
RCT2_GLOBAL(0x00F1AD34, sint16) = my_x;
RCT2_GLOBAL(0x00F1AD36, sint16) = my_y;
RCT2_GLOBAL(0x00F1AD38, sint16) = my_x + 31;
RCT2_GLOBAL(0x00F1AD3A, sint16) = my_y + 31;
rct_xy16 start_vp_pos = screen_coord_to_viewport_coord(viewport, screenX, screenY);
rct_xy16 map_pos = { my_x + 16, my_y + 16 };
for (int i = 0; i < 5; i++) {
if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 4) {
z = map_element_height(map_pos.x, map_pos.y);
} else {
z = RCT2_GLOBAL(0x00F1AD3C, uint16);
}
map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z);
map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, sint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, sint16));
map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, sint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, sint16));
}
// Determine to which edge the cursor is closest
int myDirection;
int mod_x = map_pos.x & 0x1F;
int mod_y = map_pos.y & 0x1F;
if (mod_x < mod_y) {
if (mod_x + mod_y < 32) {
myDirection = 0;
} else {
myDirection = 1;
}
} else {
if (mod_x + mod_y < 32) {
myDirection = 3;
} else {
myDirection = 2;
}
}
*x = map_pos.x & ~0x1F;
*y = map_pos.y & ~0x1F;
if (direction != NULL) *direction = myDirection;
if (mapElement != NULL) *mapElement = myMapElement;
}
/**
*
* rct2: 0x006D017F

View File

@ -176,7 +176,7 @@ static void window_viewport_mouseup()
case WIDX_LOCATE:
mainWindow = window_get_main();
if (mainWindow != NULL) {
get_map_coordinates_from_pos(w->x + (w->width / 2), w->y + (w->height / 2), 0, &x, &y, NULL, NULL, NULL);
get_map_coordinates_from_pos(w->x + (w->width / 2), w->y + (w->height / 2), VIEWPORT_INTERACTION_MASK_NONE, &x, &y, NULL, NULL, NULL);
window_scroll_to_location(mainWindow, x, y, map_element_height(x, y));
}
break;

View File

@ -19,6 +19,8 @@
*****************************************************************************/
#include "../addresses.h"
#include "../game.h"
#include "../localisation/localisation.h"
#include "banner.h"
rct_banner *gBanners = (rct_banner*)0x0135A124;
@ -32,3 +34,34 @@ void banner_init() {
gBanners[i].type = BANNER_NULL;
}
}
/* rct2: 0x006BA278
* Creates a new banner and returns the index of the banner
* If the flag GAME_COMMAND_FLAG_APPLY is NOT set then returns
* the first unused index but does NOT mark the banner as created.
* returns 0xFF on failure.
*/
int create_new_banner(uint8 flags){
int banner_index = 0;
for (; banner_index < MAX_BANNERS; banner_index++){
if (gBanners[banner_index].type == BANNER_NULL){
break;
}
}
if (banner_index == MAX_BANNERS){
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_BANNERS_IN_GAME;
return BANNER_NULL;
}
if (flags & GAME_COMMAND_FLAG_APPLY){
rct_banner* banner = &gBanners[banner_index];
banner->flags = 0;
banner->type = 0;
banner->string_idx = 778;
banner->colour = 2;
banner->text_colour = 2;
}
return banner_index;
}

View File

@ -44,5 +44,6 @@ enum{
extern rct_banner *gBanners;
void banner_init();
int create_new_banner(uint8 flags);
#endif

View File

@ -191,8 +191,6 @@ void climate_update()
}
void climate_force_weather(uint8 weather){
gClimateNextWeather = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER, sint8) = weather;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER_GLOOM, sint8) = climate_weather_data[weather].gloom_level;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, sint8) = climate_weather_data[weather].rain_level;

View File

@ -24,6 +24,7 @@
#include "../util/util.h"
#include "footpath.h"
#include "map.h"
#include "scenery.h"
void sub_673883(int x, int y, int z);
void sub_69A48B(int x, int y, int z);
@ -201,8 +202,8 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement
}
if (RCT2_GLOBAL(0x00F3EF88, uint16) != 0) {
uint8 *unk = RCT2_ADDRESS(0x009ADA50, uint8*)[RCT2_GLOBAL(0x00F3EF88, uint16)];
uint16 unk6 = RCT2_GLOBAL(unk + 6, uint16);
rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[RCT2_GLOBAL(0x00F3EF88, uint16) - 1];
uint16 unk6 = scenery_entry->path_bit.var_06;
if ((unk6 & 0x80) && (mapElement->properties.path.type & 4)) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH;
@ -224,13 +225,13 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement
return MONEY32_UNDEFINED;
}
RCT2_GLOBAL(0x00F3EFD9, money32) += RCT2_GLOBAL(unk + 10, money16);
RCT2_GLOBAL(0x00F3EFD9, money32) += scenery_entry->path_bit.price;
}
if (flags & (1 << 4))
return MONEY32_UNDEFINED;
if (!(flags & (1 << 6))) {
if (flags & (1 << 6)) {
if (mapElement->properties.path.additions & 0x0F) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NONE;
return MONEY32_UNDEFINED;
@ -259,8 +260,8 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement
mapElement->properties.path.additions = (mapElement->properties.path.additions & 0xF0) | RCT2_GLOBAL(0x00F3EF88, uint8);
mapElement->flags &= ~0x20;
if (RCT2_GLOBAL(0x00F3EF88, uint16) != 0) {
uint8 *unk = RCT2_ADDRESS(0x009ADA50, uint8*)[RCT2_GLOBAL(0x00F3EF88, uint16)];
uint16 unk6 = RCT2_GLOBAL(unk + 6, uint16);
rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[RCT2_GLOBAL(0x00F3EF88, uint16) - 1];
uint16 unk6 = scenery_entry->path_bit.var_06;
if (unk6 & 1)
mapElement->properties.path.addition_status = 255;
}
@ -288,7 +289,7 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement
return RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : RCT2_GLOBAL(0x00F3EFD9, money32);
}
static money32 footpath_place_real(int type, int x, int y, int z, int slope, int flags)
static money32 footpath_place_real(int type, int x, int y, int z, int slope, int flags, uint8 path_bit_type)
{
rct_map_element *mapElement;
@ -307,7 +308,7 @@ static money32 footpath_place_real(int type, int x, int y, int z, int slope, int
RCT2_GLOBAL(0x00F3EFD9, money32) = 0;
RCT2_GLOBAL(0x00F3EFA4, uint8) = 0;
RCT2_GLOBAL(0x00F3EF88, uint16) = 0; // di
RCT2_GLOBAL(0x00F3EF88, uint16) = path_bit_type; // di
if (x >= RCT2_GLOBAL(0x01358830, uint16) || y >= RCT2_GLOBAL(0x01358830, uint16)) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_OFF_EDGE_OF_MAP;
@ -344,7 +345,7 @@ void remove_banners_at_element(int x, int y, rct_map_element* mapElement){
if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH)return;
else if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_BANNER)continue;
game_do_command(x, 1, y, mapElement->base_height | mapElement->properties.banner.position << 8, GAME_COMMAND_51, 0, 0);
game_do_command(x, 1, y, mapElement->base_height | mapElement->properties.banner.position << 8, GAME_COMMAND_REMOVE_BANNER, 0, 0);
mapElement--;
}
}
@ -393,7 +394,7 @@ void game_command_place_footpath(int *eax, int *ebx, int *ecx, int *edx, int *es
if (*ebx & (1 << 5))
RCT2_CALLFUNC_X(0x006A61DE, eax, ebx, ecx, edx, esi, edi, ebp);
else
*ebx = footpath_place_real((*edx >> 8) & 0xFF, *eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, (*ebx >> 8) & 0xFF, *ebx & 0xFF);
*ebx = footpath_place_real((*edx >> 8) & 0xFF, *eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, (*ebx >> 8) & 0xFF, *ebx & 0xFF, *edi & 0xFF);
}
/**
@ -490,23 +491,22 @@ void footpath_provisional_update()
*/
void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement)
{
int z;
int z, interactionType;
rct_map_element *myMapElement;
rct_viewport *viewport;
get_map_coordinates_from_pos(screenX, screenY, 0xFFDF, x, y, &z, &myMapElement, &viewport);
if (z != 6 || !(viewport->flags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_VERTICAL))) {
get_map_coordinates_from_pos(screenX, screenY, 0xFFDE, x, y, &z, &myMapElement, &viewport);
if (z == 0) {
get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_FOOTPATH, x, y, &interactionType, &myMapElement, &viewport);
if (interactionType != VIEWPORT_INTERACTION_ITEM_FOOTPATH || !(viewport->flags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_VERTICAL))) {
get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, x, y, &interactionType, &myMapElement, &viewport);
if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) {
if (x != NULL) *x = 0x8000;
return;
}
}
RCT2_GLOBAL(0x00F1AD3E, uint8) = z;
RCT2_GLOBAL(0x00F1AD3E, uint8) = interactionType;
RCT2_GLOBAL(0x00F1AD30, rct_map_element*) = myMapElement;
if (z == 6) {
// mapElement appears to be a footpath
if (interactionType == VIEWPORT_INTERACTION_ITEM_FOOTPATH) {
z = myMapElement->base_height * 8;
if (myMapElement->properties.path.type & (1 << 2))
z += 8;
@ -572,10 +572,10 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y,
void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement)
{
// First check if we point at an entrance or exit. In that case, we would want the path coming from the entrance/exit.
int z;
int interactionType;
rct_viewport *viewport;
get_map_coordinates_from_pos(screenX, screenY, 0xFFFB, x, y, &z, mapElement, &viewport);
if (z == 3
get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_RIDE, x, y, &interactionType, mapElement, &viewport);
if (interactionType == VIEWPORT_INTERACTION_ITEM_RIDE
&& viewport->flags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_VERTICAL)
&& map_element_get_type(*mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) {
int ebp = (*mapElement)->properties.entrance.type << 4;
@ -589,8 +589,8 @@ void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y,
}
}
get_map_coordinates_from_pos(screenX, screenY, 0xFFDA, x, y, &z, mapElement, &viewport);
if (z == 3 && map_element_get_type(*mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) {
get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_RIDE & VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, x, y, &interactionType, mapElement, &viewport);
if (interactionType == VIEWPORT_INTERACTION_ITEM_RIDE && map_element_get_type(*mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) {
int ebp = (*mapElement)->properties.entrance.type << 4;
int bl = (*mapElement)->properties.entrance.index & 0xF; // Seems to be always 0?
// The table at 0x0097B974 is only 48 bytes big

View File

@ -48,5 +48,6 @@ void footpath_provisional_remove();
void footpath_provisional_update();
void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement);
void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement);
void sub_673883(int x, int y, int z);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -64,13 +64,12 @@ typedef struct {
} rct_map_element_entrance_properties;
typedef struct {
uint8 slope; //4
uint8 type; //4
uint8 item[3]; //5
} rct_map_element_fence_properties;
typedef struct {
uint8 type; //4
uint8 index; //5
uint16 type; //4
uint8 colour[2]; //6
} rct_map_element_scenerymultiple_properties;
@ -130,6 +129,7 @@ enum {
};
enum {
MAP_ELEMENT_FLAG_5 = (1 << 4),
MAP_ELEMENT_FLAG_BROKEN = (1 << 5),
MAP_ELEMENT_FLAG_LAST_TILE = (1 << 7)
};
@ -212,6 +212,8 @@ enum {
#define MAX_MAP_ELEMENTS 196608
#define MAX_TILE_MAP_ELEMENT_POINTERS (256 * 256)
#define MAP_ELEMENT_LARGE_TYPE_MASK 0x3FF
#define TILE_UNDEFINED_MAP_ELEMENT (rct_map_element*)-1
typedef struct {
@ -271,9 +273,23 @@ int sub_68B044();
rct_map_element *map_element_insert(int x, int y, int z, int flags);
int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl);
int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl);
int sub_6BA278(int ebx);
void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_set_banner_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
#define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x]))
#define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x])

View File

@ -48,7 +48,7 @@ void map_animation_create(int type, int x, int y, int z)
{
rct_map_animation *aobj = &gAnimatedObjects[0];
int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16);
for (; numAnimatedObjects > 0; aobj++) {
for (int i = 0; i < numAnimatedObjects; i++, aobj++) {
if (aobj->x != x)
continue;
if (aobj->y != y)

View File

@ -109,4 +109,90 @@ void scenery_increase_age(int x, int y, rct_map_element *mapElement)
mapElement->properties.scenery.age++;
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
}
}
/* 0x006E2712 */
void scenery_remove_ghost_tool_placement(){
sint16 x, y, z;
x = RCT2_GLOBAL(0x00F64EC4, sint16);
y = RCT2_GLOBAL(0x00F64EC6, sint16);
z = RCT2_GLOBAL(0x00F64F09, uint8);
if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 0)){
RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 0);
game_do_command(
x,
105 | (RCT2_GLOBAL(0x00F64F0C, uint8) << 8),
y,
z | (RCT2_GLOBAL(0x00F64EDA, uint8) << 8),
GAME_COMMAND_REMOVE_SCENERY,
0,
0);
}
if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 1)){
RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 1);
rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
do{
if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH)
continue;
if (map_element->base_height != z)
continue;
game_do_command(
x,
233 | (RCT2_GLOBAL(0x00F64F0F, uint8) << 8),
y,
z | (RCT2_GLOBAL(0x00F64F10, uint8) << 8),
GAME_COMMAND_PLACE_PATH,
RCT2_GLOBAL(0x00F64EAC, uint32) & 0xFFFF0000,
0);
break;
} while (!map_element_is_last_for_tile(map_element++));
}
if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 2)){
RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 2);
game_do_command(
x,
105 | (RCT2_GLOBAL(0x00F64F0C, uint8) << 8),
y,
RCT2_GLOBAL(0x00F64F11, uint8) |(z << 8),
GAME_COMMAND_REMOVE_FENCE,
0,
0);
}
if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 3)){
RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 3);
game_do_command(
x,
105 | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8),
y,
z,
GAME_COMMAND_REMOVE_LARGE_SCENERY,
0,
0);
}
if (RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 4)){
RCT2_GLOBAL(0x00F64F0D, uint8) &= ~(1 << 4);
game_do_command(
x,
105,
y,
z | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8),
GAME_COMMAND_REMOVE_BANNER,
0,
0);
}
}

View File

@ -56,14 +56,27 @@ typedef enum {
SMALL_SCENERY_FLAG18 = (1 << 17), // 0x20000
SMALL_SCENERY_FLAG19 = (1 << 18), // 0x40000
SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000
SMALL_SCENERY_FLAG20 = (1 << 20), // 0x100000
SMALL_SCENERY_FLAG21 = (1 << 21), // 0x200000
SMALL_SCENERY_FLAG22 = (1 << 22), // 0x400000
SMALL_SCENERY_FLAG23 = (1 << 23), // 0x800000
SMALL_SCENERY_FLAG24 = (1 << 24), // 0x1000000
SMALL_SCENERY_FLAG25 = (1 << 25), // 0x2000000
} SMALL_SCENERY_FLAGS;
typedef struct {
sint16 x_offset;
sint16 y_offset;
sint16 z_offset;
uint8 pad_6[3];
} rct_large_scenery_tile;
typedef struct {
uint8 tool_id; // 0x06
uint8 flags; // 0x07
sint16 price; // 0x08
sint16 removal_price; // 0x0A
uint32 var_0C;
rct_large_scenery_tile* tiles; // 0x0C
uint8 scenery_tab_id; // 0x10
uint8 var_11;
uint32 var_12;
@ -141,6 +154,9 @@ enum {
#define g_largeSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].chunks)
#define g_wallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_WALLS].chunks)
#define g_bannerSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_BANNERS].chunks)
// Often 0x009ADA50 is used for pathBits this is 1 entry before g_pathBitSceneryEntries and is used
// because 0 represents no path bits on a path. So remember to remove 1 when using it for 0x009ADA50
#define g_pathBitSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_PATH_BITS].chunks)
#define g_scenerySetEntries ((rct_scenery_set_entry**)object_entry_groups[OBJECT_TYPE_SCENERY_SETS].chunks)
@ -159,5 +175,6 @@ void init_scenery();
void scenery_update_tile(int x, int y);
void scenery_update_age(int x, int y, rct_map_element *mapElement);
void scenery_set_default_placement_configuration();
void scenery_remove_ghost_tool_placement();
#endif