/** * * rct2: 0x006D2F4C */ static void track_design_save_push_tile_element(sint32 x, sint32 y, rct_tile_element *tileElement) { if (_trackSavedTileElementsCount < TRACK_MAX_SAVED_TILE_ELEMENTS) { _trackSavedTileElements[_trackSavedTileElementsCount++] = tileElement; map_invalidate_tile_full(x, y); } }
GameActionResult::Ptr Execute() const override { gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LAND_PURCHASE; gCommandPosition.x = _location.x; gCommandPosition.y = _location.y; gCommandPosition.z = _location.z / 8; // Find empty or next appropriate peep spawn to use sint32 peepSpawnIndex = -1; for (sint32 i = 0; i < MAX_PEEP_SPAWNS; i++) { if (gPeepSpawns[i].x == PEEP_SPAWN_UNDEFINED) { peepSpawnIndex = i; break; } } // If no empty peep spawns exist, use peep spawn next to last one set. if (peepSpawnIndex == -1) { peepSpawnIndex = _nextPeepSpawnIndex; _nextPeepSpawnIndex = (peepSpawnIndex + 1) % MAX_PEEP_SPAWNS; // Before the new location is set, clear the old location sint32 prevX = gPeepSpawns[peepSpawnIndex].x; gPeepSpawns[peepSpawnIndex].x = PEEP_SPAWN_UNDEFINED; map_invalidate_tile_full(prevX, gPeepSpawns[peepSpawnIndex].y); } // Shift the spawn point to the middle of the tile sint32 middleX, middleY; middleX = _location.x + 16 + (word_981D6C[_location.direction].x * 15); middleY = _location.y + 16 + (word_981D6C[_location.direction].y * 15); // Set peep spawn gPeepSpawns[peepSpawnIndex].x = middleX; gPeepSpawns[peepSpawnIndex].y = middleY; gPeepSpawns[peepSpawnIndex].z = _location.z; gPeepSpawns[peepSpawnIndex].direction = _location.direction; // Invalidate tile map_invalidate_tile_full(_location.x, _location.y); return std::make_unique<GameActionResult>(); }
/** * * rct2: 0x006D2F4C */ static void track_design_save_push_map_element(sint32 x, sint32 y, rct_map_element *mapElement) { if (_trackSavedMapElementsCount < TRACK_MAX_SAVED_MAP_ELEMENTS) { _trackSavedMapElements[_trackSavedMapElementsCount++] = mapElement; map_invalidate_tile_full(x, y); #ifndef NO_RCT2 // Required as drawing still uses 0xFFFFFFFF as a list terminator _trackSavedMapElements[_trackSavedMapElementsCount] = (rct_map_element*)-1; #endif } }
static money32 BannerPlace(sint16 x, sint16 y, uint8 pathBaseHeight, uint8 direction, uint8 colour, uint8 type, uint8 *bannerIndex, uint8 flags) { gCommandPosition.x = x + 16; gCommandPosition.y = y + 16; gCommandPosition.z = pathBaseHeight * 16; gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; if (game_is_paused() && !gCheatsBuildInPauseMode) { gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } if (!map_check_free_elements_and_reorganise(1)) { return MONEY32_UNDEFINED; } if (!map_is_location_valid(x, y)) { return MONEY32_UNDEFINED; } rct_tile_element* tileElement = map_get_first_element_at(x / 32, y / 32); bool pathFound = false; do { if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_PATH) continue; if (tileElement->base_height != pathBaseHeight * 2 && tileElement->base_height != (pathBaseHeight - 1) * 2) continue; if (!(tileElement->properties.path.edges & (1 << direction))) continue; pathFound = true; break; } while (!tile_element_is_last_for_tile(tileElement++)); if (!pathFound) { gGameCommandErrorText = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS; return MONEY32_UNDEFINED; } if (!map_can_build_at(x, y, pathBaseHeight * 16)) { return MONEY32_UNDEFINED; } uint8 baseHeight = (pathBaseHeight + 1) * 2; tileElement = map_get_banner_element_at(x / 32, y / 32, baseHeight, direction); if (tileElement != nullptr) { gGameCommandErrorText = STR_BANNER_SIGN_IN_THE_WAY; return MONEY32_UNDEFINED; } *bannerIndex = create_new_banner(flags); if (*bannerIndex == BANNER_NULL) { return MONEY32_UNDEFINED; } if (flags & GAME_COMMAND_FLAG_APPLY) { if (gGameCommandNestLevel == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { LocationXYZ16 coord; coord.x = x + 16; coord.y = y + 16; coord.z = tile_element_height(coord.x, coord.y); network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); } rct_tile_element* newTileElement = tile_element_insert(x / 32, y / 32, baseHeight, 0); assert(newTileElement != nullptr); gBanners[*bannerIndex].type = type; gBanners[*bannerIndex].colour = colour; gBanners[*bannerIndex].x = x / 32; gBanners[*bannerIndex].y = y / 32; newTileElement->type = TILE_ELEMENT_TYPE_BANNER; newTileElement->clearance_height = newTileElement->base_height + 2; newTileElement->properties.banner.position = direction; newTileElement->properties.banner.flags = 0xFF; newTileElement->properties.banner.unused = 0; newTileElement->properties.banner.index = *bannerIndex; if (flags & GAME_COMMAND_FLAG_GHOST) { newTileElement->flags |= TILE_ELEMENT_FLAG_GHOST; } map_invalidate_tile_full(x, y); map_animation_create(MAP_ANIMATION_TYPE_BANNER, x, y, newTileElement->base_height); } rct_scenery_entry *bannerEntry = get_banner_entry(type); if (bannerEntry == nullptr) { return MONEY32_UNDEFINED; } if (gParkFlags & PARK_FLAGS_NO_MONEY) { return 0; } return bannerEntry->banner.price; }
static money32 RideEntranceExitPlace(sint16 x, sint16 y, sint16 z, uint8 direction, uint8 flags, uint8 rideIndex, uint8 stationNum, bool isExit) { // Remember when in Unknown station num mode rideIndex is unknown and z is set // When in known station num mode rideIndex is known and z is unknown money32 cost = 0; gCommandPosition.x = x; gCommandPosition.y = y; if (!map_check_free_elements_and_reorganise(1)) { return MONEY32_UNDEFINED; } if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && game_is_paused() && !gCheatsBuildInPauseMode) { gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } if (stationNum == 0xFF) { z *= 16; if (flags & GAME_COMMAND_FLAG_APPLY) { return MONEY32_UNDEFINED; } if (!gCheatsSandboxMode && !map_is_location_owned(x, y, z)) { return MONEY32_UNDEFINED; } sint16 clear_z = z / 8 + (isExit ? 5 : 7); if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost)) { return MONEY32_UNDEFINED; } if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) { gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER; return MONEY32_UNDEFINED; } if (z / 8 > 244) { gGameCommandErrorText = STR_TOO_HIGH; return MONEY32_UNDEFINED; } } else { if (rideIndex >= MAX_RIDES) { log_warning("Invalid game command for ride %u", rideIndex); return MONEY32_UNDEFINED; } rct_ride* ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_NULL) { log_warning("Invalid game command for ride %u", rideIndex); return MONEY32_UNDEFINED; } if (ride->status != RIDE_STATUS_CLOSED) { gGameCommandErrorText = STR_MUST_BE_CLOSED_FIRST; return MONEY32_UNDEFINED; } if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) { gGameCommandErrorText = STR_NOT_ALLOWED_TO_MODIFY_STATION; return MONEY32_UNDEFINED; } ride_clear_for_construction(rideIndex); ride_remove_peeps(rideIndex); bool requiresRemove = false; rct_xy16 removeCoord = { 0, 0 }; if (isExit) { if (ride->exits[stationNum] != 0xFFFF) { if (flags & GAME_COMMAND_FLAG_GHOST) { gGameCommandErrorText = 0; return MONEY32_UNDEFINED; } removeCoord.x = (ride->exits[stationNum] & 0xFF) * 32; removeCoord.y = ((ride->exits[stationNum] >> 8) & 0xFF) * 32; requiresRemove = true; } } else if (ride->entrances[stationNum] != 0xFFFF) { if (flags & GAME_COMMAND_FLAG_GHOST) { gGameCommandErrorText = 0; return MONEY32_UNDEFINED; } removeCoord.x = (ride->entrances[stationNum] & 0xFF) * 32; removeCoord.y = ((ride->entrances[stationNum] >> 8) & 0xFF) * 32; requiresRemove = true; } if (requiresRemove) { money32 success = game_do_command( removeCoord.x, flags, removeCoord.y, rideIndex, GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT, stationNum, 0 ); if (success == MONEY32_UNDEFINED) { return MONEY32_UNDEFINED; } } z = ride->station_heights[stationNum] * 8; gCommandPosition.z = z; if ((flags & GAME_COMMAND_FLAG_APPLY) && !(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && !(flags & GAME_COMMAND_FLAG_GHOST)) { footpath_remove_litter(x, y, z); wall_remove_at_z(x, y, z); } if (!gCheatsSandboxMode && !map_is_location_owned(x, y, z)) { return MONEY32_UNDEFINED; } sint8 clear_z = (z / 8) + (isExit ? 5 : 7); if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, &cost)) { return MONEY32_UNDEFINED; } if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) { gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER; return MONEY32_UNDEFINED; } if (z / 8 > 244) { gGameCommandErrorText = STR_TOO_HIGH; return MONEY32_UNDEFINED; } if (flags & GAME_COMMAND_FLAG_APPLY) { rct_xyz16 coord; coord.x = x + 16; coord.y = y + 16; coord.z = map_element_height(coord.x, coord.y); network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); rct_map_element* mapElement = map_element_insert(x / 32, y / 32, z / 8, 0xF); assert(mapElement != NULL); mapElement->clearance_height = clear_z; mapElement->properties.entrance.type = isExit; mapElement->properties.entrance.index = stationNum << 4; mapElement->properties.entrance.ride_index = rideIndex; mapElement->type = MAP_ELEMENT_TYPE_ENTRANCE | direction; if (flags & GAME_COMMAND_FLAG_GHOST) { mapElement->flags |= MAP_ELEMENT_FLAG_GHOST; } if (isExit) { ride->exits[stationNum] = (x / 32) | (y / 32 << 8); } else { ride->entrances[stationNum] = (x / 32) | (y / 32 << 8); ride->last_peep_in_queue[stationNum] = SPRITE_INDEX_NULL; ride->queue_length[stationNum] = 0; map_animation_create(MAP_ANIMATION_TYPE_RIDE_ENTRANCE, x, y, z / 8); } footpath_queue_chain_reset(); if (!(flags & GAME_COMMAND_FLAG_GHOST)) { maze_entrance_hedge_removal(x, y, mapElement); } footpath_connect_edges(x, y, mapElement, flags); sub_6A759F(); map_invalidate_tile_full(x, y); } }