Ejemplo n.º 1
0
    GameActionResult::Ptr Execute() const override
    {
        rct_banner* banner = &gBanners[_bannerIndex];

        utf8 *buffer = gCommonStringFormatBuffer;
        utf8 *dst = buffer;
        dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour);
        String::Set(dst, sizeof(gCommonStringFormatBuffer) - (dst - buffer), _name.c_str(), _name.size());

        rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
        if (string_id == 0)
        {
            return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT);
        }

        rct_string_id prev_string_id = banner->string_idx;
        banner->string_idx = string_id;
        user_string_free(prev_string_id);

        auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
        intent.putExtra(INTENT_EXTRA_BANNER_INDEX, _bannerIndex);
        context_broadcast_intent(&intent);

        return MakeResult();
    }
Ejemplo n.º 2
0
    GameActionResult::Ptr Query() const override
    {
        if (_bannerIndex >= MAX_BANNERS || _bannerIndex < 0)
        {
            log_warning("Invalid game command for setting banner name, banner id = %d", _bannerIndex);
            return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE);
        }

        // Ensure user string space.
        rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, _name.c_str());
        if (string_id != 0)
        {
            user_string_free(string_id);
        }
        else
        {
            return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT);
        }

        return MakeResult();
    }
Ejemplo n.º 3
0
void window_player_open(uint8 id)
{
	rct_window* window;

	int player = network_get_player_index(id);
	window = window_bring_to_front_by_number(WC_PLAYER, id);
	if (window == NULL) {
		window = window_create_auto_pos(240, 170, &window_player_overview_events, WC_PLAYER, WF_RESIZABLE);
		window->number = id;
		window->page = 0;
		window->viewport_focus_coordinates.y = 0;
		window->frame_no = 0;
		window->list_information_type = 0;
		window->picked_peep_frame = 0;
		window->highlighted_item = 0;
		window->min_width = 210;
		window->min_height = 134;
		window->max_width = 500;
		window->max_height = 450;
		window->no_list_items = 0;
		window->selected_list_item = -1;

		window->viewport_focus_coordinates.y = -1;
		window->error.var_480 = user_string_allocate(128, network_get_player_name(player)); // repurposing var_480 to store this
	}

	window->page = 0;
	window_invalidate(window);

	window->widgets = window_player_page_widgets[WINDOW_PLAYER_PAGE_OVERVIEW];
	window->enabled_widgets = window_player_page_enabled_widgets[WINDOW_PLAYER_PAGE_OVERVIEW];
	window->hold_down_widgets = 0;
	window->event_handlers = window_player_page_events[WINDOW_PLAYER_PAGE_OVERVIEW];
	window->pressed_widgets = 0;

	window_init_scroll_widgets(window);
	window_player_set_page(window, WINDOW_PLAYER_PAGE_OVERVIEW);
}
Ejemplo n.º 4
0
void fix_duplicated_banners()
{
    // For each banner in the map, check if the banner index is in use already, and if so, create a new entry for it
    bool               activeBanners[Util::CountOf(gBanners)]{};
    rct_tile_element * tileElement;
    for (int y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++)
    {
        for (int x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++)
        {
            tileElement = map_get_first_element_at(x, y);
            do
            {
                // TODO: Handle walls and large-scenery that use banner indices too. Large scenery can be tricky, as they occupy
                // multiple tiles that should both refer to the same banner index.
                if (tile_element_get_type(tileElement) == TILE_ELEMENT_TYPE_BANNER)
                {
                    uint8 bannerIndex = tileElement->properties.banner.index;
                    if (activeBanners[bannerIndex])
                    {
                        log_info(
                            "Duplicated banner with index %d found at x = %d, y = %d and z = %d.", bannerIndex, x, y,
                            tileElement->base_height);

                        // Banner index is already in use by another banner, so duplicate it
                        uint8 newBannerIndex = create_new_banner(GAME_COMMAND_FLAG_APPLY);
                        if (newBannerIndex == BANNER_NULL)
                        {
                            log_error("Failed to create new banner.");
                            continue;
                        }
                        Guard::Assert(activeBanners[newBannerIndex] == false);

                        // Copy over the original banner, but update the location
                        rct_banner & newBanner = gBanners[newBannerIndex];
                        newBanner              = gBanners[bannerIndex];
                        newBanner.x            = x;
                        newBanner.y            = y;

                        // Duplicate user string too
                        rct_string_id stringIdx = newBanner.string_idx;
                        if (is_user_string_id(stringIdx))
                        {
                            utf8 buffer[USER_STRING_MAX_LENGTH];
                            format_string(buffer, USER_STRING_MAX_LENGTH, stringIdx, nullptr);
                            rct_string_id newStringIdx = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
                            if (newStringIdx == 0)
                            {
                                log_error("Failed to allocate user string for banner");
                                continue;
                            }
                            newBanner.string_idx = newStringIdx;
                        }

                        tileElement->properties.banner.index = newBannerIndex;
                    }

                    // Mark banner index as in-use
                    activeBanners[bannerIndex] = true;
                }
            } while (!tile_element_is_last_for_tile(tileElement++));
        }
    }
}
Ejemplo n.º 5
0
static money32 BannerSetStyle(uint8 bannerIndex, uint8 colour, uint8 textColour, uint8 bannerFlags, uint8 flags)
{
    if (bannerIndex >= MAX_BANNERS)
    {
        gGameCommandErrorText = STR_INVALID_SELECTION_OF_OBJECTS;
        return MONEY32_UNDEFINED;
    }

    rct_banner* banner = &gBanners[bannerIndex];

    rct_tile_element* tileElement = banner_get_tile_element(bannerIndex);

    if (tileElement == nullptr)
    {
        return MONEY32_UNDEFINED;
    }

    if (!(flags & GAME_COMMAND_FLAG_APPLY))
    {
        return 0;
    }

    banner->colour = colour;
    banner->text_colour = textColour;
    banner->flags = bannerFlags;

    tileElement->properties.banner.flags = 0xFF;
    if (banner->flags & BANNER_FLAG_NO_ENTRY)
    {
        tileElement->properties.banner.flags &= ~(1 << tileElement->properties.banner.position);
    }

    sint32 colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour;

    utf8 buffer[256];
    format_string(buffer, 256, banner->string_idx, nullptr);
    sint32 firstCodepoint = utf8_get_next(buffer, nullptr);
    if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END)
    {
        utf8_write_codepoint(buffer, colourCodepoint);
    }
    else
    {
        utf8_insert_codepoint(buffer, colourCodepoint);
    }

    rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
    if (stringId != 0)
    {
        rct_string_id prevStringId = banner->string_idx;
        banner->string_idx = stringId;
        user_string_free(prevStringId);

        auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
        intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex);
        context_broadcast_intent(&intent);
    }
    else
    {
        gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
        return MONEY32_UNDEFINED;
    }

    return 0;
}
Ejemplo n.º 6
0
static money32 BannerSetName(uint8 bannerIndex,
    uint16 nameChunkIndex,
    uint32 nameChunk1,
    uint32 nameChunk2,
    uint32 nameChunk3,
    uint8 flags)
{
    static char newName[128];

    if (bannerIndex >= MAX_BANNERS)
    {
        log_warning("Invalid game command for setting banner name, banner id = %d", bannerIndex);
        return MONEY32_UNDEFINED;
    }
    rct_banner* banner = &gBanners[bannerIndex];

    gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS;
    size_t indexToOffset[3] = { 24, 0, 12 };

    if (nameChunkIndex > Util::CountOf(indexToOffset))
    {
        log_warning("Invalid chunk index for setting banner name, banner id = %d, index = %d", bannerIndex, nameChunkIndex);
        return MONEY32_UNDEFINED;
    }

    size_t nameChunkOffset = std::min<size_t>(indexToOffset[nameChunkIndex], Util::CountOf(newName) - 12);
    std::memcpy(&newName[0 + nameChunkOffset], &nameChunk1, sizeof(uint32));
    std::memcpy(&newName[4 + nameChunkOffset], &nameChunk2, sizeof(uint32));
    std::memcpy(&newName[8 + nameChunkOffset], &nameChunk3, sizeof(uint32));

    if (nameChunkIndex != 0)
    {
        return 0;
    }

    if (!(flags & GAME_COMMAND_FLAG_APPLY))
    {
        return 0;
    }

    utf8 *buffer = gCommonStringFormatBuffer;
    utf8 *dst = buffer;
    dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour);
    String::Set(dst, 256, newName, 32);

    rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
    if (stringId != 0)
    {
        rct_string_id prevStringId = banner->string_idx;
        banner->string_idx = stringId;
        user_string_free(prevStringId);

        auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
        intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex);
        context_broadcast_intent(&intent);
    }
    else
    {
        gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
        return MONEY32_UNDEFINED;
    }

    return 0;
}
Ejemplo n.º 7
0
static void twitch_parse_followers()
{
	struct AudienceMember {
		const char *name;
		bool isFollower;
		bool isInChat;
		bool isMod;
		bool exists;
		bool shouldTrack;
	};

	std::vector<AudienceMember> members;

	http_json_response *jsonResponse = _twitchJsonResponse;
	if (json_is_array(jsonResponse->root)) {
		int audienceCount = json_array_size(jsonResponse->root);
		for (int i = 0; i < audienceCount; i++) {
			json_t *audienceMember = json_array_get(jsonResponse->root, i);
			if (!json_is_object(audienceMember))
				continue;

			json_t *name = json_object_get(audienceMember, "name");
			json_t *isFollower = json_object_get(audienceMember, "isFollower");
			json_t *isInChat = json_object_get(audienceMember, "inChat");
			json_t *isMod = json_object_get(audienceMember, "isMod");

			AudienceMember member;
			member.name = json_string_value(name);
			member.isFollower = json_boolean_value(isFollower);
			member.isInChat = json_boolean_value(isInChat);
			member.isMod = json_boolean_value(isMod);
			member.exists = false;
			member.shouldTrack = false;

			if (member.name == NULL || member.name[0] == 0)
				continue;

			if (member.isInChat && gConfigTwitch.enable_chat_peep_tracking)
				member.shouldTrack = true;
			else if (member.isFollower && gConfigTwitch.enable_follower_peep_tracking)
				member.shouldTrack = true;

			if (gConfigTwitch.enable_chat_peep_names && member.isInChat)
				members.push_back(member);
			else if (gConfigTwitch.enable_follower_peep_names && member.isFollower)
				members.push_back(member);
		}

		uint16 spriteIndex;
		rct_peep *peep;
		char buffer[256];

		// Check what followers are already in the park
		FOR_ALL_GUESTS(spriteIndex, peep) {
			if (is_user_string_id(peep->name_string_idx)) {
				format_string(buffer, peep->name_string_idx, NULL);

				AudienceMember *member = NULL;
				for (size_t i = 0; i < members.size(); i++) {
					if (_strcmpi(buffer, members[i].name) == 0) {
						member = &members[i];
						members[i].exists = true;
						break;
					}
				}

				if (peep->peep_flags & PEEP_FLAGS_TWITCH) {
					if (member == NULL) {
						// Member no longer peep name worthy
						peep->peep_flags &= ~(PEEP_FLAGS_TRACKING | PEEP_FLAGS_TWITCH);

						// TODO set peep name back to number / real name
					} else {
						if (member->shouldTrack)
							peep->peep_flags |= (PEEP_FLAGS_TRACKING);
						else if (!member->shouldTrack)
							peep->peep_flags &= ~(PEEP_FLAGS_TRACKING);
					}
				} else if (member != NULL && !(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)) {
					// Peep with same name already exists but not twitch
					peep->peep_flags |= PEEP_FLAGS_TWITCH;
					if (member->shouldTrack)
						peep->peep_flags |= PEEP_FLAGS_TRACKING;
				}
			}
		}

		// Rename non-named peeps to followers that aren't currently in the park.
		if (members.size() > 0) {
			int memberIndex = -1;
			FOR_ALL_GUESTS(spriteIndex, peep) {
				int originalMemberIndex = memberIndex;
				for (size_t i = memberIndex + 1; i < members.size(); i++) {
					if (!members[i].exists) {
						memberIndex = i;
						break;
					}
				}
				if (originalMemberIndex == memberIndex)
					break;

				AudienceMember *member = &members[memberIndex];
				if (!is_user_string_id(peep->name_string_idx) && !(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)) {
					// Rename peep and add flags
					rct_string_id newStringId = user_string_allocate(4, member->name);
					if (newStringId != 0) {
						peep->name_string_idx = newStringId;
						peep->peep_flags |= PEEP_FLAGS_TWITCH;
						if (member->shouldTrack)
							peep->peep_flags |= PEEP_FLAGS_TRACKING;
					}
				} else {
					// Peep still yet to be found for member
					memberIndex--;
				}
			}