mirror of https://github.com/OpenRCT2/OpenRCT2.git
parent
fa3332f47a
commit
d8b5060eb9
|
@ -243,11 +243,12 @@ static void window_track_place_update(rct_window* w)
|
|||
|
||||
static GameActionResult::Ptr FindValidTrackDesignPlaceHeight(CoordsXYZ& loc, uint32_t flags)
|
||||
{
|
||||
for (int32_t i = 0; i < 7; i++)
|
||||
GameActionResult::Ptr res;
|
||||
for (int32_t i = 0; i < 7; i++, loc.z += 8)
|
||||
{
|
||||
auto tdAction = TrackDesignAction(CoordsXYZD{ loc.x, loc.y, loc.z, _currentTrackPieceDirection }, *_trackDesign);
|
||||
tdAction.SetFlags(flags);
|
||||
auto res = GameActions::Query(&tdAction);
|
||||
res = GameActions::Query(&tdAction);
|
||||
|
||||
// If successful dont keep trying.
|
||||
// If failure due to no money then increasing height only makes problem worse
|
||||
|
@ -255,15 +256,9 @@ static GameActionResult::Ptr FindValidTrackDesignPlaceHeight(CoordsXYZ& loc, uin
|
|||
{
|
||||
return res;
|
||||
}
|
||||
// Return the last attempts error up the chain
|
||||
if (i == 6)
|
||||
{
|
||||
}
|
||||
return res;
|
||||
}
|
||||
loc.z += 8;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -73,7 +73,6 @@ bool gDoSingleUpdate = false;
|
|||
float gDayNightCycle = 0;
|
||||
bool gInUpdateCode = false;
|
||||
bool gInMapInitCode = false;
|
||||
int32_t gGameCommandNestLevel;
|
||||
std::string gCurrentLoadedPath;
|
||||
|
||||
bool gLoadKeepWindowsOpen = false;
|
||||
|
@ -284,160 +283,6 @@ void update_palette_effects()
|
|||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069C62C
|
||||
*
|
||||
* @param cost (ebp)
|
||||
*/
|
||||
static int32_t game_check_affordability(int32_t cost, uint32_t flags)
|
||||
{
|
||||
if (finance_check_affordability(cost, flags))
|
||||
return cost;
|
||||
|
||||
set_format_arg(0, uint32_t, cost);
|
||||
gGameCommandErrorText = STR_NOT_ENOUGH_CASH_REQUIRES;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006677F2
|
||||
*
|
||||
* @param ebx flags
|
||||
* @param esi command
|
||||
*/
|
||||
int32_t game_do_command(int32_t eax, int32_t ebx, int32_t ecx, int32_t edx, int32_t esi, int32_t edi, int32_t ebp)
|
||||
{
|
||||
return game_do_command_p(esi, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006677F2 with pointers as arguments
|
||||
*
|
||||
* @param ebx flags
|
||||
* @param esi command
|
||||
*/
|
||||
int32_t game_do_command_p(
|
||||
uint32_t command, int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp)
|
||||
{
|
||||
int32_t cost, flags;
|
||||
int32_t original_ebx, original_edx, original_esi, original_edi, original_ebp;
|
||||
|
||||
*esi = command;
|
||||
original_ebx = *ebx;
|
||||
original_edx = *edx;
|
||||
original_esi = *esi;
|
||||
original_edi = *edi;
|
||||
original_ebp = *ebp;
|
||||
|
||||
if (command >= std::size(new_game_command_table))
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
flags = *ebx;
|
||||
|
||||
auto* replayManager = GetContext()->GetReplayManager();
|
||||
if (replayManager->IsReplaying())
|
||||
{
|
||||
// We only accept replay commands as long the replay is active.
|
||||
if ((flags & GAME_COMMAND_FLAG_REPLAY) == 0)
|
||||
{
|
||||
// TODO: Introduce proper error.
|
||||
gGameCommandErrorText = STR_CHEAT_BUILD_IN_PAUSE_MODE;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
if (gGameCommandNestLevel == 0)
|
||||
{
|
||||
gGameCommandErrorText = STR_NONE;
|
||||
}
|
||||
|
||||
// Increment nest count
|
||||
gGameCommandNestLevel++;
|
||||
|
||||
*ebx &= ~GAME_COMMAND_FLAG_APPLY;
|
||||
|
||||
// Make sure the camera position won't change if the command skips setting them.
|
||||
gCommandPosition.x = LOCATION_NULL;
|
||||
gCommandPosition.y = LOCATION_NULL;
|
||||
gCommandPosition.z = LOCATION_NULL;
|
||||
|
||||
// First call for validity and price check
|
||||
new_game_command_table[command](eax, ebx, ecx, edx, esi, edi, ebp);
|
||||
cost = *ebx;
|
||||
|
||||
if (cost != MONEY32_UNDEFINED)
|
||||
{
|
||||
// Check funds
|
||||
int32_t insufficientFunds = 0;
|
||||
if (gGameCommandNestLevel == 1 && !(flags & GAME_COMMAND_FLAG_NO_SPEND) && cost != 0)
|
||||
insufficientFunds = game_check_affordability(cost, flags);
|
||||
|
||||
if (insufficientFunds != MONEY32_UNDEFINED)
|
||||
{
|
||||
*ebx = original_ebx;
|
||||
*edx = original_edx;
|
||||
*esi = original_esi;
|
||||
*edi = original_edi;
|
||||
*ebp = original_ebp;
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_APPLY))
|
||||
{
|
||||
// Decrement nest count
|
||||
gGameCommandNestLevel--;
|
||||
return cost;
|
||||
}
|
||||
|
||||
// Second call to actually perform the operation
|
||||
new_game_command_table[command](eax, ebx, ecx, edx, esi, edi, ebp);
|
||||
|
||||
*edx = *ebx;
|
||||
|
||||
if (*edx != MONEY32_UNDEFINED && *edx < cost)
|
||||
cost = *edx;
|
||||
|
||||
// Decrement nest count
|
||||
gGameCommandNestLevel--;
|
||||
if (gGameCommandNestLevel != 0)
|
||||
return cost;
|
||||
|
||||
// Check if money is required.
|
||||
if (finance_check_money_required(flags))
|
||||
{
|
||||
// Update money balance
|
||||
finance_payment(cost, gCommandExpenditureType);
|
||||
|
||||
// Create a +/- money text effect
|
||||
if (cost != 0 && game_is_not_paused())
|
||||
rct_money_effect::Create(cost);
|
||||
}
|
||||
|
||||
// Start autosave timer after game command
|
||||
if (gLastAutoSaveUpdate == AUTOSAVE_PAUSE)
|
||||
gLastAutoSaveUpdate = platform_get_ticks();
|
||||
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
// Error occurred
|
||||
|
||||
// Decrement nest count
|
||||
gGameCommandNestLevel--;
|
||||
|
||||
// Show error window
|
||||
if (gGameCommandNestLevel == 0 && (flags & GAME_COMMAND_FLAG_APPLY) && !(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)
|
||||
&& !(flags & GAME_COMMAND_FLAG_NETWORKED) && !(flags & GAME_COMMAND_FLAG_GHOST))
|
||||
{
|
||||
context_show_error(gGameCommandErrorTitle, gGameCommandErrorText);
|
||||
}
|
||||
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
void pause_toggle()
|
||||
{
|
||||
|
@ -996,17 +841,3 @@ void game_load_or_quit_no_save_prompt()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = {
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, game_command_place_track_design,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, NULL,
|
||||
};
|
||||
|
|
|
@ -66,7 +66,7 @@ enum GAME_COMMAND
|
|||
GAME_COMMAND_REMOVE_LARGE_SCENERY, // GA
|
||||
GAME_COMMAND_SET_CURRENT_LOAN, // GA
|
||||
GAME_COMMAND_SET_RESEARCH_FUNDING, // GA
|
||||
GAME_COMMAND_PLACE_TRACK_DESIGN,
|
||||
GAME_COMMAND_PLACE_TRACK_DESIGN, // GA
|
||||
GAME_COMMAND_START_MARKETING_CAMPAIGN, // GA
|
||||
GAME_COMMAND_PLACE_MAZE_DESIGN, // GA
|
||||
GAME_COMMAND_PLACE_BANNER, // GA
|
||||
|
@ -90,7 +90,7 @@ enum GAME_COMMAND
|
|||
GAME_COMMAND_BALLOON_PRESS, // GA
|
||||
GAME_COMMAND_MODIFY_TILE, // GA
|
||||
GAME_COMMAND_EDIT_SCENARIO_OPTIONS, // GA
|
||||
GAME_COMMAND_PLACE_PEEP_SPAWN, // GA, TODO: refactor to separate array for just game actions
|
||||
GAME_COMMAND_PLACE_PEEP_SPAWN, // GA
|
||||
GAME_COMMAND_SET_CLIMATE, // GA
|
||||
GAME_COMMAND_SET_COLOUR_SCHEME, // GA
|
||||
GAME_COMMAND_SET_STAFF_COSTUME, // GA
|
||||
|
@ -128,14 +128,9 @@ enum
|
|||
ERROR_TYPE_FILE_LOAD = 255
|
||||
};
|
||||
|
||||
using GAME_COMMAND_POINTER = void(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
|
||||
extern rct_string_id gGameCommandErrorTitle;
|
||||
extern rct_string_id gGameCommandErrorText;
|
||||
|
||||
extern GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT];
|
||||
|
||||
extern uint32_t gCurrentTicks;
|
||||
extern uint32_t gCurrentRealTimeTicks;
|
||||
|
||||
|
@ -146,7 +141,6 @@ extern bool gDoSingleUpdate;
|
|||
extern float gDayNightCycle;
|
||||
extern bool gInUpdateCode;
|
||||
extern bool gInMapInitCode;
|
||||
extern int32_t gGameCommandNestLevel;
|
||||
extern std::string gCurrentLoadedPath;
|
||||
|
||||
extern bool gLoadKeepWindowsOpen;
|
||||
|
@ -158,10 +152,6 @@ void game_create_windows();
|
|||
void reset_all_sprite_quadrant_placements();
|
||||
void update_palette_effects();
|
||||
|
||||
int32_t game_do_command(int32_t eax, int32_t ebx, int32_t ecx, int32_t edx, int32_t esi, int32_t edi, int32_t ebp);
|
||||
int32_t game_do_command_p(
|
||||
uint32_t command, int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
|
||||
void game_load_or_quit_no_save_prompt();
|
||||
void load_from_sv6(const char* path);
|
||||
void game_load_init();
|
||||
|
|
|
@ -218,7 +218,6 @@ void GameState::Update()
|
|||
pause_toggle();
|
||||
}
|
||||
|
||||
gGameCommandNestLevel = 0;
|
||||
gDoSingleUpdate = false;
|
||||
gInUpdateCode = false;
|
||||
}
|
||||
|
|
|
@ -1934,195 +1934,6 @@ static bool track_design_place_preview(TrackDesign* td6, money32* cost, Ride** o
|
|||
}
|
||||
}
|
||||
|
||||
static money32 place_track_design(int16_t x, int16_t y, int16_t z, uint8_t flags, ride_id_t* outRideIndex)
|
||||
{
|
||||
*outRideIndex = RIDE_ID_NULL;
|
||||
|
||||
gCommandPosition.x = x + 16;
|
||||
gCommandPosition.y = y + 16;
|
||||
gCommandPosition.z = z;
|
||||
|
||||
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED))
|
||||
{
|
||||
if (game_is_paused() && !gCheatsBuildInPauseMode)
|
||||
{
|
||||
gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
TrackDesign* td6 = gActiveTrackDesign;
|
||||
if (td6 == nullptr)
|
||||
{
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
rct_object_entry* rideEntryObject = &td6->vehicle_object;
|
||||
|
||||
uint8_t entryType, entryIndex;
|
||||
if (!find_object_in_entry_group(rideEntryObject, &entryType, &entryIndex))
|
||||
{
|
||||
entryIndex = 0xFF;
|
||||
}
|
||||
// Force a fallback if the entry is not invented yet a td6 of it is selected, which can happen in select-by-track-type mode.
|
||||
else if (!ride_entry_is_invented(entryIndex) && !gCheatsIgnoreResearchStatus)
|
||||
{
|
||||
entryIndex = 0xFF;
|
||||
}
|
||||
|
||||
// The rest of the cases are handled by the code in ride_create()
|
||||
if (RideGroupManager::RideTypeHasRideGroups(td6->type) && entryIndex == 0xFF)
|
||||
{
|
||||
const ObjectRepositoryItem* ori = object_repository_find_object_by_name(rideEntryObject->name);
|
||||
if (ori != nullptr)
|
||||
{
|
||||
uint8_t rideGroupIndex = ori->RideInfo.RideGroupIndex;
|
||||
const RideGroup* td6RideGroup = RideGroupManager::RideGroupFind(td6->type, rideGroupIndex);
|
||||
|
||||
uint8_t* availableRideEntries = get_ride_entry_indices_for_ride_type(td6->type);
|
||||
for (uint8_t* rei = availableRideEntries; *rei != RIDE_ENTRY_INDEX_NULL; rei++)
|
||||
{
|
||||
rct_ride_entry* ire = get_ride_entry(*rei);
|
||||
|
||||
if (!ride_entry_is_invented(*rei) && !gCheatsIgnoreResearchStatus)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const RideGroup* irg = RideGroupManager::GetRideGroup(td6->type, ire);
|
||||
if (td6RideGroup->Equals(irg))
|
||||
{
|
||||
entryIndex = *rei;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ride_id_t rideIndex;
|
||||
uint8_t rideColour;
|
||||
money32 createRideResult = ride_create_command(td6->type, entryIndex, flags, &rideIndex, &rideColour);
|
||||
if (createRideResult == MONEY32_UNDEFINED)
|
||||
{
|
||||
gGameCommandErrorTitle = STR_CANT_CREATE_NEW_RIDE_ATTRACTION;
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
auto ride = get_ride(rideIndex);
|
||||
if (ride == nullptr)
|
||||
{
|
||||
log_warning("Invalid game command for track placement, ride id = %d", rideIndex);
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
money32 cost = 0;
|
||||
if (!(flags & GAME_COMMAND_FLAG_APPLY))
|
||||
{
|
||||
_trackDesignDontPlaceScenery = false;
|
||||
cost = place_virtual_track(td6, PTD_OPERATION_PLACE_QUERY, true, ride, x, y, z);
|
||||
if (_trackDesignPlaceStateSceneryUnavailable)
|
||||
{
|
||||
_trackDesignDontPlaceScenery = true;
|
||||
cost = place_virtual_track(td6, PTD_OPERATION_PLACE_QUERY, false, ride, x, y, z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t operation;
|
||||
if (flags & GAME_COMMAND_FLAG_GHOST)
|
||||
{
|
||||
operation = PTD_OPERATION_PLACE_GHOST;
|
||||
}
|
||||
else
|
||||
{
|
||||
operation = PTD_OPERATION_PLACE;
|
||||
}
|
||||
|
||||
cost = place_virtual_track(td6, operation, !_trackDesignDontPlaceScenery, ride, x, y, z);
|
||||
}
|
||||
|
||||
if (cost == MONEY32_UNDEFINED || !(flags & GAME_COMMAND_FLAG_APPLY))
|
||||
{
|
||||
rct_string_id error_reason = gGameCommandErrorText;
|
||||
ride_action_modify(ride, RIDE_MODIFY_DEMOLISH, flags);
|
||||
gGameCommandErrorText = error_reason;
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
||||
*outRideIndex = ride->id;
|
||||
return cost;
|
||||
}
|
||||
|
||||
if (entryIndex != 0xFF)
|
||||
{
|
||||
auto colour = ride_get_unused_preset_vehicle_colour(entryIndex);
|
||||
auto rideSetVehicleAction = RideSetVehicleAction(ride->id, RideSetVehicleType::RideEntry, entryIndex, colour);
|
||||
flags& GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&rideSetVehicleAction)
|
||||
: GameActions::QueryNested(&rideSetVehicleAction);
|
||||
}
|
||||
|
||||
set_operating_setting_nested(ride->id, RideSetSetting::Mode, td6->ride_mode, flags);
|
||||
auto rideSetVehicleAction2 = RideSetVehicleAction(ride->id, RideSetVehicleType::NumTrains, td6->number_of_trains);
|
||||
flags& GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&rideSetVehicleAction2)
|
||||
: GameActions::QueryNested(&rideSetVehicleAction2);
|
||||
auto rideSetVehicleAction3 = RideSetVehicleAction(
|
||||
ride->id, RideSetVehicleType::NumCarsPerTrain, td6->number_of_cars_per_train);
|
||||
flags& GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&rideSetVehicleAction3)
|
||||
: GameActions::QueryNested(&rideSetVehicleAction3);
|
||||
set_operating_setting_nested(ride->id, RideSetSetting::Departure, td6->depart_flags, flags);
|
||||
set_operating_setting_nested(ride->id, RideSetSetting::MinWaitingTime, td6->min_waiting_time, flags);
|
||||
set_operating_setting_nested(ride->id, RideSetSetting::MaxWaitingTime, td6->max_waiting_time, flags);
|
||||
set_operating_setting_nested(ride->id, RideSetSetting::Operation, td6->operation_setting, flags);
|
||||
set_operating_setting_nested(ride->id, RideSetSetting::LiftHillSpeed, td6->lift_hill_speed & 0x1F, flags);
|
||||
|
||||
uint8_t num_circuits = td6->num_circuits;
|
||||
if (num_circuits == 0)
|
||||
{
|
||||
num_circuits = 1;
|
||||
}
|
||||
set_operating_setting_nested(ride->id, RideSetSetting::NumCircuits, num_circuits, flags);
|
||||
ride->SetToDefaultInspectionInterval();
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NOT_CUSTOM_DESIGN;
|
||||
ride->colour_scheme_type = td6->colour_scheme;
|
||||
|
||||
ride->entrance_style = td6->entrance_style;
|
||||
|
||||
for (int32_t i = 0; i < RCT12_NUM_COLOUR_SCHEMES; i++)
|
||||
{
|
||||
ride->track_colour[i].main = td6->track_spine_colour[i];
|
||||
ride->track_colour[i].additional = td6->track_rail_colour[i];
|
||||
ride->track_colour[i].supports = td6->track_support_colour[i];
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < MAX_VEHICLES_PER_RIDE; i++)
|
||||
{
|
||||
ride->vehicle_colours[i].Body = td6->vehicle_colours[i].body_colour;
|
||||
ride->vehicle_colours[i].Trim = td6->vehicle_colours[i].trim_colour;
|
||||
ride->vehicle_colours[i].Ternary = td6->vehicle_additional_colour[i];
|
||||
}
|
||||
|
||||
ride_set_name(ride, td6->name.c_str(), flags);
|
||||
|
||||
gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
|
||||
*outRideIndex = ride->id;
|
||||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D13FE
|
||||
*/
|
||||
void game_command_place_track_design(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, [[maybe_unused]] int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi,
|
||||
[[maybe_unused]] int32_t* ebp)
|
||||
{
|
||||
int16_t x = *eax & 0xFFFF;
|
||||
int16_t y = *ecx & 0xFFFF;
|
||||
int16_t z = *edi & 0xFFFF;
|
||||
uint8_t flags = *ebx;
|
||||
ride_id_t rideIndex;
|
||||
*ebx = place_track_design(x, y, z, flags, &rideIndex);
|
||||
*edi = rideIndex;
|
||||
}
|
||||
|
||||
#pragma region Track Design Preview
|
||||
|
||||
/**
|
||||
|
|
|
@ -209,9 +209,6 @@ void track_design_mirror(TrackDesign* td6);
|
|||
int32_t place_virtual_track(
|
||||
TrackDesign* td6, uint8_t ptdOperation, bool placeScenery, Ride* ride, int16_t x, int16_t y, int16_t z);
|
||||
|
||||
void game_command_place_track_design(
|
||||
int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Track design preview
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue