コード例 #1
0
ファイル: Intent.cpp プロジェクト: OpenRCT2/OpenRCT2
void* Intent::GetPointerExtra(uint32_t key) const
{
    if (_Data.count(key) == 0)
    {
        return nullptr;
    }

    auto data = _Data.at(key);
    openrct2_assert(data.type == IntentData::DT_POINTER, "Actual type doesn't match requested type");
    return (void*)data.pointerVal;
}
コード例 #2
0
ファイル: Intent.cpp プロジェクト: OpenRCT2/OpenRCT2
uint32_t Intent::GetUIntExtra(uint32_t key) const
{
    if (_Data.count(key) == 0)
    {
        return 0;
    }

    auto data = _Data.at(key);
    openrct2_assert(data.type == IntentData::DT_INT, "Actual type doesn't match requested type");
    return data.intVal.unsignedInt;
}
コード例 #3
0
ファイル: Intent.cpp プロジェクト: OpenRCT2/OpenRCT2
close_callback Intent::GetCloseCallbackExtra(uint32_t key) const
{
    if (_Data.count(key) == 0)
    {
        return nullptr;
    }

    auto data = _Data.at(key);
    openrct2_assert(data.type == IntentData::DT_CLOSE_CALLBACK, "Actual type doesn't match requested type");
    return data.closeCallbackVal;
}
コード例 #4
0
ファイル: Intent.cpp プロジェクト: OpenRCT2/OpenRCT2
std::string Intent::GetStringExtra(uint32_t key) const
{
    if (_Data.count(key) == 0)
    {
        return std::string{};
    }

    auto data = _Data.at(key);
    openrct2_assert(data.type == IntentData::DT_STRING, "Actual type doesn't match requested type");
    return data.stringVal;
}
コード例 #5
0
ファイル: mapgen.c プロジェクト: trigger-death/OpenRCT2
void mapgen_generate_from_heightmap(mapgen_settings *settings)
{
    openrct2_assert(_heightMapData.width == _heightMapData.height, "Invalid height map size");
    openrct2_assert(_heightMapData.mono_bitmap != NULL, "No height map loaded");
    openrct2_assert(settings->simplex_high != settings->simplex_low, "Low and high setting cannot be the same");

    // Make a copy of the original height map that we can edit
    uint8 *dest = (uint8*)malloc(_heightMapData.width * _heightMapData.height);
    memcpy(dest, _heightMapData.mono_bitmap, _heightMapData.width * _heightMapData.width);

    map_init(_heightMapData.width + 2); // + 2 for the black tiles around the map

    if (settings->smooth_height_map)
    {
        mapgen_smooth_heightmap(dest, settings->smooth_strength);
    }

    uint8 maxValue = 255;
    uint8 minValue = 0;

    if (settings->normalize_height)
    {
        // Get highest and lowest pixel value
        maxValue = 0;
        minValue = 0xff;
        for (uint32 y = 0; y < _heightMapData.height; y++)
        {
            for (uint32 x = 0; x < _heightMapData.width; x++)
            {
                uint8 value = dest[x + y * _heightMapData.width];
                maxValue = max(maxValue, value);
                minValue = min(minValue, value);
            }
        }

        if (minValue == maxValue)
        {
            window_error_open(STR_HEIGHT_MAP_ERROR, STR_ERROR_CANNOT_NORMALIZE);
            free(dest);
            return;
        }
    }

    openrct2_assert(maxValue > minValue, "Input range is invalid");
    openrct2_assert(settings->simplex_high > settings->simplex_low, "Output range is invalid");

    const uint8 rangeIn = maxValue - minValue;
    const uint8 rangeOut = settings->simplex_high - settings->simplex_low;

    for (uint32 y = 0; y < _heightMapData.height; y++)
    {
        for (uint32 x = 0; x < _heightMapData.width; x++)
        {
            // The x and y axis are flipped in the world, so this uses y for x and x for y.
            rct_map_element *const surfaceElement = map_get_surface_element_at(y + 1, x + 1);

            // Read value from bitmap, and convert its range
            uint8 value = dest[x + y * _heightMapData.width];
            value = (uint8)((float)(value - minValue) / rangeIn * rangeOut) + settings->simplex_low;
            surfaceElement->base_height = value;

            // Floor to even number
            surfaceElement->base_height /= 2;
            surfaceElement->base_height *= 2;
            surfaceElement->clearance_height = surfaceElement->base_height;

            // Set water level
            if (surfaceElement->base_height < settings->water_level)
            {
                surfaceElement->properties.surface.terrain |= settings->water_level / 2;
            }
        }
    }

    // Smooth map
    if (settings->smooth)
    {
        // Keep smoothing the entire map until no tiles are changed anymore
        while (true)
        {
            uint32 numTilesChanged = 0;
            for (uint32 y = 1; y <= _heightMapData.height; y++)
            {
                for (uint32 x = 1; x <= _heightMapData.width; x++)
                {
                    numTilesChanged += tile_smooth(x, y);
                }
            }

            if (numTilesChanged == 0)
                break;
        }
    }

    // Clean up
    free(dest);
}
コード例 #6
0
ファイル: mapgen.c プロジェクト: trigger-death/OpenRCT2
bool mapgen_load_heightmap(const utf8 *path)
{
    const char* extension = path_get_extension(path);
    uint8 *pixels;
    size_t pitch;
    uint32 numChannels;
    uint32 width, height;

    if (strcicmp(extension, ".png") == 0) {
        if (!image_io_png_read(&pixels, &width, &height, path)) {
            log_warning("Error reading PNG");
            window_error_open(STR_HEIGHT_MAP_ERROR, STR_ERROR_READING_PNG);
            return false;
        }

        numChannels = 4;
        pitch = width * numChannels;
    }
    else if (strcicmp(extension, ".bmp") == 0) {
        if (!context_read_bmp((void *)&pixels, &width, &height, path)) {
            // ReadBMP contains window_error_open calls
            return false;
        }

        numChannels = 4;
        pitch = width * numChannels;
    }
    else
    {
        openrct2_assert(false, "A file with an invalid file extension was selected.");
        return false;
    }

    if (width != height) {
        window_error_open(STR_HEIGHT_MAP_ERROR, STR_ERROR_WIDTH_AND_HEIGHT_DO_NOT_MATCH);
        free(pixels);
        return false;
    }

    if (width > MAXIMUM_MAP_SIZE_PRACTICAL) {
        window_error_open(STR_HEIGHT_MAP_ERROR, STR_ERROR_HEIHGT_MAP_TOO_BIG);
        width = height = min(height, MAXIMUM_MAP_SIZE_PRACTICAL);
    }

    // Allocate memory for the height map values, one byte pixel
    free(_heightMapData.mono_bitmap);
    _heightMapData.mono_bitmap = (uint8*)malloc(width * height);
    _heightMapData.width = width;
    _heightMapData.height = height;

    // Copy average RGB value to mono bitmap
    for (uint32 x = 0; x < _heightMapData.width; x++)
    {
        for (uint32 y = 0; y < _heightMapData.height; y++)
        {
            const uint8 red = pixels[x * numChannels + y * pitch];
            const uint8 green = pixels[x * numChannels + y * pitch + 1];
            const uint8 blue = pixels[x * numChannels + y * pitch + 2];
            _heightMapData.mono_bitmap[x + y * _heightMapData.width] = (red + green + blue) / 3;
        }
    }

    free(pixels);
    return true;
}
コード例 #7
0
ファイル: Research.cpp プロジェクト: OpenRCT2/OpenRCT2
/**
 *
 *  rct2: 0x006848D4
 */
void research_finish_item(rct_research_item* researchItem)
{
    gResearchLastItem = *researchItem;
    research_invalidate_related_windows();

    if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE)
    {
        // Ride
        uint32_t base_ride_type = researchItem->baseRideType;
        int32_t rideEntryIndex = researchItem->entryIndex;
        rct_ride_entry* rideEntry = get_ride_entry(rideEntryIndex);

        if (rideEntry != nullptr && base_ride_type != RIDE_TYPE_NULL)
        {
            bool ride_group_was_invented_before = false;
            bool ride_type_was_invented_before = ride_type_is_invented(base_ride_type);
            rct_string_id availabilityString;

            // Determine if the ride group this entry belongs to was invented before.
            if (RideGroupManager::RideTypeHasRideGroups(base_ride_type))
            {
                const RideGroup* rideGroup = RideGroupManager::GetRideGroup(base_ride_type, rideEntry);

                if (rideGroup->IsInvented())
                {
                    ride_group_was_invented_before = true;
                }
            }

            ride_type_set_invented(base_ride_type);
            openrct2_assert(
                base_ride_type < std::size(RideTypePossibleTrackConfigurations), "Invalid base_ride_type = %d", base_ride_type);

            ride_entry_set_invented(rideEntryIndex);

            bool seenRideEntry[MAX_RIDE_OBJECTS]{};

            rct_research_item* researchItem2 = gResearchItems;
            for (; researchItem2->rawValue != RESEARCHED_ITEMS_END; researchItem2++)
            {
                if (researchItem2->rawValue != RESEARCHED_ITEMS_SEPARATOR && researchItem2->type == RESEARCH_ENTRY_TYPE_RIDE)
                {
                    uint8_t index = researchItem2->entryIndex;
                    seenRideEntry[index] = true;
                }
            }

            // RCT2 made non-separated vehicles available at once, by removing all but one from research.
            // To ensure old files keep working, look for ride entries not in research, and make them available as well.
            for (int32_t i = 0; i < MAX_RIDE_OBJECTS; i++)
            {
                if (!seenRideEntry[i])
                {
                    rct_ride_entry* rideEntry2 = get_ride_entry(i);
                    if (rideEntry2 != nullptr)
                    {
                        for (uint8_t j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++)
                        {
                            if (rideEntry2->ride_type[j] == base_ride_type)
                            {
                                ride_entry_set_invented(i);
                                break;
                            }
                        }
                    }
                }
            }

            // If a vehicle should be listed separately (maze, mini golf, flat rides, shops)
            if (RideGroupManager::RideTypeIsIndependent(base_ride_type))
            {
                availabilityString = STR_NEWS_ITEM_RESEARCH_NEW_RIDE_AVAILABLE;
                set_format_arg(0, rct_string_id, rideEntry->naming.name);
            }
            // If a vehicle is the first to be invented for its ride group, show the ride group name.
            else if (
                !ride_type_was_invented_before
                || (RideGroupManager::RideTypeHasRideGroups(base_ride_type) && !ride_group_was_invented_before))
            {
                rct_ride_name naming = get_ride_naming(base_ride_type, rideEntry);
                availabilityString = STR_NEWS_ITEM_RESEARCH_NEW_RIDE_AVAILABLE;
                set_format_arg(0, rct_string_id, naming.name);
            }
            // If the vehicle should not be listed separately and it isn't the first to be invented for its ride group,
            // report it as a new vehicle for the existing ride group.
            else
            {
                availabilityString = STR_NEWS_ITEM_RESEARCH_NEW_VEHICLE_AVAILABLE;
                rct_ride_name baseRideNaming = get_ride_naming(base_ride_type, rideEntry);

                set_format_arg(0, rct_string_id, baseRideNaming.name);
                set_format_arg(2, rct_string_id, rideEntry->naming.name);
            }

            if (!gSilentResearch)
            {
                if (gConfigNotifications.ride_researched)
                {
                    news_item_add_to_queue(NEWS_ITEM_RESEARCH, availabilityString, researchItem->rawValue);
                }
            }

            research_invalidate_related_windows();
        }
    }
    else
    {
        // Scenery
        rct_scenery_group_entry* sceneryGroupEntry = get_scenery_group_entry(researchItem->entryIndex);
        if (sceneryGroupEntry != nullptr)
        {
            scenery_group_set_invented(researchItem->entryIndex);

            set_format_arg(0, rct_string_id, sceneryGroupEntry->name);

            if (!gSilentResearch)
            {
                if (gConfigNotifications.ride_researched)
                {
                    news_item_add_to_queue(
                        NEWS_ITEM_RESEARCH, STR_NEWS_ITEM_RESEARCH_NEW_SCENERY_SET_AVAILABLE, researchItem->rawValue);
                }
            }

            research_invalidate_related_windows();
            init_scenery();
        }
    }
}