Ticket #3436: 3436_singMulti_filter_v6.1.patch

File 3436_singMulti_filter_v6.1.patch, 12.6 KB (added by elexis, 8 years ago)

The nonAIPlayers method of detecting singleplayer is not bad. It doesn't work with unassigned players, but that shouldn't be a problem and might change at some point (ticket somewhere) (also don't ask me how we should sort games which are played by exclusively AI). Fixed indentation in the xml and the second line of the if's. Added the replay.attribs.settings.GameType check.

  • binaries/data/mods/public/gui/replaymenu/replay_actions.js

    function createReplaySelectionData(selec  
    99    let mapNameFilter = Engine.GetGUIObjectByName("mapNameFilter");
    1010    let mapSizeFilter = Engine.GetGUIObjectByName("mapSizeFilter");
    1111    let populationFilter = Engine.GetGUIObjectByName("populationFilter");
    1212    let durationFilter = Engine.GetGUIObjectByName("durationFilter");
    1313    let compatibilityFilter = Engine.GetGUIObjectByName("compatibilityFilter");
     14    let singleplayerFilter = Engine.GetGUIObjectByName("singleplayerFilter");
     15    let victoryConFilter = Engine.GetGUIObjectByName("victoryConditionFilter");
     16    let ratedGamesFilter = Engine.GetGUIObjectByName("ratedGamesFilter");
    1417
    1518    return {
    1619        "directory": selectedDirectory,
    1720        "column": replaySelection.selected_column,
    1821        "columnOrder": replaySelection.selected_column_order,
    function createReplaySelectionData(selec  
    2124            "playernames": playersFilter.caption,
    2225            "mapName": mapNameFilter.list_data[mapNameFilter.selected],
    2326            "mapSize": mapSizeFilter.list_data[mapSizeFilter.selected],
    2427            "popCap": populationFilter.list_data[populationFilter.selected],
    2528            "duration": durationFilter.list_data[durationFilter.selected],
    26             "compatibility": compatibilityFilter.checked
     29            "compatibility": compatibilityFilter.checked,
     30            "singleplayer": singleplayerFilter.list_data[singleplayerFilter.selected],
     31            "victoryCondition": victoryConFilter.list_data[victoryConFilter.selected],
     32            "ratedGames": ratedGamesFilter.selected
    2733        }
    2834    };
    2935}
    3036
    3137/**
  • binaries/data/mods/public/gui/replaymenu/replay_filters.js

    function initFilters(filters)  
    3131    initDateFilter(filters && filters.date);
    3232    initMapSizeFilter(filters && filters.mapSize);
    3333    initMapNameFilter(filters && filters.mapName);
    3434    initPopCapFilter(filters && filters.popCap);
    3535    initDurationFilter(filters && filters.duration);
     36    initSingleplayerFilter(filters && filters.singleplayer);
     37    initVictoryConditionFilter(filters && filters.victoryCondition);
     38    initRatedGamesFilter(filters && filters.ratedGames);
    3639}
    3740
    3841/**
    3942 * Allow to filter by month. Uses g_Replays.
    4043 */
    function initDurationFilter(duration)  
    131134
    132135    if (durationFilter.selected == -1 || durationFilter.selected >= g_DurationFilterIntervals.length)
    133136        durationFilter.selected = 0;
    134137}
    135138
     139function initSingleplayerFilter(singleplayer)
     140{
     141    let singleplayerFilter = Engine.GetGUIObjectByName("singleplayerFilter");
     142    singleplayerFilter.list = [translateWithContext("gamemode", "Single- and multiplayer"), translate("Single Player"), translate("Multiplayer")];
     143    singleplayerFilter.list_data = ["", "Singleplayer", "Multiplayer"];
     144
     145    if (singleplayer)
     146        singleplayerFilter.selected = singleplayerFilter.list_data.indexOf(singleplayer);
     147
     148    if (singleplayerFilter.selected < 0 || singleplayerFilter.selected >= singleplayerFilter.list.length)
     149        singleplayerFilter.selected = 0;
     150}
     151
     152function initVictoryConditionFilter(victoryCondition)
     153{
     154    let victoryConditionFilter = Engine.GetGUIObjectByName("victoryConditionFilter");
     155    victoryConditionFilter.list = [translateWithContext("victory condition", "Any Gametype")].concat(g_VictoryConditions.map(victoryCondition => translateVictoryCondition(victoryCondition)));
     156    victoryConditionFilter.list_data = [""].concat(g_VictoryConditions);
     157
     158    if (victoryCondition)
     159        victoryConditionFilter.selected = victoryConditionFilter.list_data.indexOf(victoryCondition);
     160
     161    if (victoryConditionFilter.selected < 0 || victoryConditionFilter.selected >= victoryConditionFilter.list.length)
     162        victoryConditionFilter.selected = 0;
     163}
     164
     165function initRatedGamesFilter(ratedGames)
     166{
     167    let ratedGamesFilter = Engine.GetGUIObjectByName("ratedGamesFilter");
     168    ratedGamesFilter.list = [translateWithContext("rated game", "Rated and unrated games"), translate("Rated Games"), translate("Unrated Games")];
     169    ratedGamesFilter.list_data = ["", "rated", "not rated"];
     170
     171    if (ratedGames)
     172        ratedGamesFilter.selected = ratedGamesFilter.list_data.indexOf(ratedGames);
     173
     174    if (ratedGamesFilter.selected < 0 || ratedGamesFilter.selected >= ratedGamesFilter.list.length)
     175        ratedGamesFilter.selected = 0;
     176}
     177
    136178/**
    137179 * Initializes g_ReplaysFiltered with replays that are not filtered out and sort it.
    138180 */
    139181function filterReplays()
    140182{
    function filterReplay(replay)  
    191233    // Check for compatibility first (most likely to filter)
    192234    let compatibilityFilter = Engine.GetGUIObjectByName("compatibilityFilter");
    193235    if (compatibilityFilter.checked && !isReplayCompatible(replay))
    194236        return false;
    195237
     238    // Filter by multiplayer/singleplayer
     239    let singleplayerFilter = Engine.GetGUIObjectByName("singleplayerFilter");
     240    if (singleplayerFilter.selected == 1 && replay.isMultiplayer ||
     241        singleplayerFilter.selected == 2 && !replay.isMultiplayer)
     242        return false;
     243
     244    // Filter by victory condition
     245    let victoryConditionFilter = Engine.GetGUIObjectByName("victoryConditionFilter");
     246    if (victoryConditionFilter.selected > 0 && replay.attribs.settings.GameType != victoryConditionFilter.list_data[victoryConditionFilter.selected])
     247        return false;
     248
     249    // Filter by rating
     250    let ratedGamesFilter = Engine.GetGUIObjectByName("ratedGamesFilter");
     251    if (ratedGamesFilter.selected == 1 && !replay.attribs.settings.RatingEnabled ||
     252        ratedGamesFilter.selected == 2 && replay.attribs.settings.RatingEnabled)
     253        return false
     254
    196255    // Filter date/time (select a month)
    197     var dateTimeFilter = Engine.GetGUIObjectByName("dateTimeFilter");
     256    let dateTimeFilter = Engine.GetGUIObjectByName("dateTimeFilter");
    198257    if (dateTimeFilter.selected > 0 && getReplayMonth(replay) != dateTimeFilter.list_data[dateTimeFilter.selected])
    199258        return false;
    200259
    201260    // Filter by playernames
    202     var playersFilter = Engine.GetGUIObjectByName("playersFilter");
    203     var keywords = playersFilter.caption.toLowerCase().split(" ");
     261    let playersFilter = Engine.GetGUIObjectByName("playersFilter");
     262    let keywords = playersFilter.caption.toLowerCase().split(" ");
    204263    if (keywords.length)
    205264    {
    206265        // We just check if all typed words are somewhere in the playerlist of that replay
    207266        let playerList = replay.attribs.settings.PlayerData.map(player => player ? player.Name : "").join(" ").toLowerCase();
    208267        if (!keywords.every(keyword => playerList.indexOf(keyword) != -1))
    209268            return false;
    210269    }
    211270
    212271    // Filter by map name
    213     var mapNameFilter = Engine.GetGUIObjectByName("mapNameFilter");
     272    let mapNameFilter = Engine.GetGUIObjectByName("mapNameFilter");
    214273    if (mapNameFilter.selected > 0 && getReplayMapName(replay) != mapNameFilter.list_data[mapNameFilter.selected])
    215274        return false;
    216275
    217276    // Filter by map size
    218     var mapSizeFilter = Engine.GetGUIObjectByName("mapSizeFilter");
     277    let mapSizeFilter = Engine.GetGUIObjectByName("mapSizeFilter");
    219278    if (mapSizeFilter.selected > 0 && replay.attribs.settings.Size != mapSizeFilter.list_data[mapSizeFilter.selected])
    220279        return false;
    221280
    222281    // Filter by population capacity
    223     var populationFilter = Engine.GetGUIObjectByName("populationFilter");
     282    let populationFilter = Engine.GetGUIObjectByName("populationFilter");
    224283    if (populationFilter.selected > 0 && replay.attribs.settings.PopulationCap != populationFilter.list_data[populationFilter.selected])
    225284        return false;
    226285
    227286    // Filter by game duration
    228     var durationFilter = Engine.GetGUIObjectByName("durationFilter");
     287    let durationFilter = Engine.GetGUIObjectByName("durationFilter");
    229288    if (durationFilter.selected > 0)
    230289    {
    231290        let interval = g_DurationFilterIntervals[durationFilter.selected];
    232291
    233292        if ((interval.min > -1 && replay.duration < interval.min * 60) ||
  • binaries/data/mods/public/gui/replaymenu/replay_menu.js

    var g_Playernames = [];  
    3232 * Sorted list of unique maptitles. Used by mapfilter.
    3333 */
    3434var g_MapNames = [];
    3535
    3636/**
     37 * Sorted list of the victory conditions occuring in the replays
     38 */
     39var g_VictoryConditions = [];
     40
     41/**
    3742 * Directory name of the currently selected replay. Used to restore the selection after changing filters.
    3843 */
    3944var g_SelectedReplayDirectory = "";
    4045
    4146/**
    function init(data)  
    6065    displayReplayList();
    6166}
    6267
    6368/**
    6469 * Store the list of replays loaded in C++ in g_Replays.
    65  * Check timestamp and compatibility and extract g_Playernames, g_MapNames.
     70 * Check timestamp and compatibility and extract g_Playernames, g_MapNames, g_VictoryConditions.
    6671 * Restore selected filters and item.
    6772 */
    6873function loadReplays(replaySelectionData)
    6974{
    7075    g_Replays = Engine.GetReplays();
    function loadReplays(replaySelectionData  
    7378        return;
    7479
    7580    g_Playernames = [];
    7681    for (let replay of g_Replays)
    7782    {
     83        let nonAIPlayers = 0;
    7884        // Use time saved in file, otherwise file mod date
    7985        replay.timestamp = replay.attribs.timestamp ? +replay.attribs.timestamp : +replay.filemod_timestamp-replay.duration;
    8086
    8187        // Check replay for compatibility
    8288        replay.isCompatible = isReplayCompatible(replay);
    function loadReplays(replaySelectionData  
    8591
    8692        // Extract map names
    8793        if (g_MapNames.indexOf(replay.attribs.settings.Name) == -1 && replay.attribs.settings.Name != "")
    8894            g_MapNames.push(replay.attribs.settings.Name);
    8995
     96        // Extract victory conditions
     97        if (replay.attribs.settings.GameType && g_VictoryConditions.indexOf(replay.attribs.settings.GameType) == -1)
     98            g_VictoryConditions.push(replay.attribs.settings.GameType);
     99
    90100        // Extract playernames
    91101        for (let playerData of replay.attribs.settings.PlayerData)
    92102        {
    93103            if (!playerData || playerData.AI)
    94104                continue;
    function loadReplays(replaySelectionData  
    99109            if (ratingStart != -1)
    100110                playername = playername.substr(0, ratingStart);
    101111
    102112            if (g_Playernames.indexOf(playername) == -1)
    103113                g_Playernames.push(playername);
     114            ++nonAIPlayers;
    104115        }
     116        replay.isMultiplayer = nonAIPlayers > 1;
    105117    }
    106118    g_MapNames.sort();
     119    g_VictoryConditions.sort();
    107120
    108121    // Reload filters (since they depend on g_Replays and its derivatives)
    109122    initFilters(replaySelectionData && replaySelectionData.filters);
    110123
    111124    // Restore user selection
  • binaries/data/mods/public/gui/replaymenu/replay_menu.xml

     
    108108            <!-- Compatibility Filter Label -->
    109109            <object type="text" size="20 2 100% 100%" text_align="left" textcolor="white">
    110110                <translatableAttribute id="caption">Filter compatible replays</translatableAttribute>
    111111            </object>
    112112
     113            <!-- Singleplayer Multiplayer Filter -->
     114            <object name="singleplayerFilter" type="dropdown" style="ModernDropDown" size="0 30 100% 55" font="sans-bold-13">
     115                <action on="SelectionChange">displayReplayList();</action>
     116            </object>
     117
     118            <!-- Victory Condition Filter -->
     119            <object name="victoryConditionFilter" type="dropdown" style="ModernDropDown" size="0 60 100% 85" font="sans-bold-13">
     120                <action on="SelectionChange">displayReplayList();</action>
     121            </object>
     122
     123            <!-- Rated Games Filter -->
     124            <object name="ratedGamesFilter" type="dropdown" style="ModernDropDown" size="0 90 100% 115" font="sans-bold-13">
     125                <action on="SelectionChange">displayReplayList();</action>
     126            </object>
     127
    113128            <!-- Placeholder to show if no replay is selected -->
    114             <object name="replayInfoEmpty" size="0 30 100% 100%-60" type="image" sprite="ModernDarkBoxGold" hidden="false">
     129            <object name="replayInfoEmpty" size="0 120 100% 100%-60" type="image" sprite="ModernDarkBoxGold" hidden="false">
    115130                <object name="logo" size="50%-110 40 50%+110 140" type="image" sprite="logo"/>
    116131                <object name="subjectBox" type="image" sprite="ModernDarkBoxWhite" size="3% 180 97% 99%">
    117132                    <object name="subject" size="5 5 100%-5 100%-5" type="text" style="ModernText" text_align="center"/>
    118133                </object>
    119134            </object>
    120135
    121136            <!--  -->
    122             <object name="replayInfo" size="0 30 100% 100%-60" type="image" sprite="ModernDarkBoxGold" hidden="true">
     137            <object name="replayInfo" size="0 120 100% 100%-60" type="image" sprite="ModernDarkBoxGold" hidden="true">
    123138
    124139                <!-- Map Name Label -->
    125140                <object name="sgMapName" size="0 5 100% 20" type="text" style="ModernLabelText"/>
    126141
    127142                <!-- Map Preview Image -->