Ticket #1834: gamesetup_playerCapsForRms.diff

File gamesetup_playerCapsForRms.diff, 36.4 KB (added by FeXoR, 11 years ago)

SVN diff

  • binaries/data/mods/public/gui/gamesetup/gamesetup.js

     
    1515const STARTING_RESOURCES_DEFAULTIDX = 1;
    1616// Max number of players for any map
    1717const MAX_PLAYERS = 8;
     18// The default upper player limit for random maps by map size:
     19// [Tiny, Small, Medium, Normal, Large, Very Large, Giant]
     20// Ignored if explicitely defined in the RMS json
     21// Still capped at MAX_PLAYERS if excessing it in getPlayersCapRMS().
     22const MAX_PLAYERS_BY_MAP_SIZE_RMS = [4, 6, 8, 8, 8, 8, 8];
     23// The default upper player limit for random maps
     24// Ignored if explicitely defined in the RMS json
     25const MIN_PLAYERS_RMS = 1;
     26// The default number of player for random maps
     27const DEFAULT_NUM_PLAYERS_RMS = 2;
    1828
    1929////////////////////////////////////////////////////////////////////////////////////////////////
    2030
     
    8696{
    8797    // Load AI list and hide deprecated AIs
    8898    g_AIs = Engine.GetAIs();
    89 
     99   
    90100    // Sort AIs by displayed name
    91101    g_AIs.sort(function (a, b) {
    92102        return a.data.name < b.data.name ? -1 : b.data.name < a.data.name ? +1 : 0;
    93103    });
    94 
     104   
    95105    // Get default player data - remove gaia
    96106    g_DefaultPlayerData = initPlayerDefaults();
    97107    g_DefaultPlayerData.shift();
     
    99109        g_DefaultPlayerData[i].Civ = "random";
    100110   
    101111    g_MapSizes = initMapSizes();
    102 
     112   
    103113    // Init civs
    104114    initCivNameList();
    105 
     115   
    106116    // Init map types
    107117    var mapTypes = getGUIObjectByName("mapTypeSelection");
    108118    mapTypes.list = ["Scenario","Random"];
    109119    mapTypes.list_data = ["scenario","random"];
    110 
     120   
    111121    // Setup map filters - will appear in order they are added
    112122    addFilter("Default", function(settings) { return settings && !keywordTestOR(settings.Keywords, ["naval", "demo", "hidden"]); });
    113123    addFilter("Naval Maps", function(settings) { return settings && keywordTestAND(settings.Keywords, ["naval"]); });
    114124    addFilter("Demo Maps", function(settings) { return settings && keywordTestAND(settings.Keywords, ["demo"]); });
    115125    addFilter("Old Maps", function(settings) { return !settings; });
    116126    addFilter("All Maps", function(settings) { return true; });
    117 
     127   
    118128    // Populate map filters dropdown
    119129    var mapFilters = getGUIObjectByName("mapFilterSelection");
    120130    mapFilters.list = getFilters();
    121131    g_GameAttributes.mapFilter = "Default";
    122 
     132   
    123133    // Setup controls for host only
    124134    if (g_IsController)
    125135    {
    126136        mapTypes.selected = 0;
    127137        mapFilters.selected = 0;
    128 
     138       
    129139        initMapNameList();
    130 
     140       
    131141        var numPlayersSelection = getGUIObjectByName("numPlayersSelection");
    132142        var players = [];
    133143        for (var i = 1; i <= MAX_PLAYERS; ++i)
    134144            players.push(i);
    135145        numPlayersSelection.list = players;
    136146        numPlayersSelection.list_data = players;
    137         numPlayersSelection.selected = MAX_PLAYERS - 1;
    138 
     147        numPlayersSelection.selected = DEFAULT_NUM_PLAYERS_RMS - players[0];
     148       
    139149        var populationCaps = getGUIObjectByName("populationCap");
    140150        populationCaps.list = POPULATION_CAP;
    141151        populationCaps.list_data = POPULATION_CAP_DATA;
     
    179189            {
    180190                g_GameAttributes.settings.GameType = VICTORY_DATA[this.selected];
    181191            }
    182 
     192           
    183193            if (!g_IsInGuiUpdate)
    184194            {
    185195                updateGameAttributes();
    186196            }
    187197        };
    188198        victoryConditions.selected = VICTORY_DEFAULTIDX;
    189 
     199       
    190200        var mapSize = getGUIObjectByName("mapSize");
    191201        mapSize.list = g_MapSizes.names;
    192202        mapSize.list_data = g_MapSizes.tiles;
     
    196206            {
    197207                g_GameAttributes.settings.Size = g_MapSizes.tiles[this.selected];
    198208            }
    199 
     209            changeNumPlayersCaps();
     210           
    200211            if (!g_IsInGuiUpdate)
    201212            {
    202213                updateGameAttributes();
    203214            }
    204215        };
    205 
     216       
    206217        getGUIObjectByName("revealMap").onPress = function()
    207218        {   // Update attributes so other players can see change
    208219            g_GameAttributes.settings.RevealMap = this.checked;
    209 
     220           
    210221            if (!g_IsInGuiUpdate)
    211222            {
    212223                updateGameAttributes();
    213224            }
    214225        };
    215 
     226       
    216227        getGUIObjectByName("lockTeams").onPress = function()
    217228        {   // Update attributes so other players can see change
    218229            g_GameAttributes.settings.LockTeams = this.checked;
    219 
     230           
    220231            if (!g_IsInGuiUpdate)
    221232            {
    222233                updateGameAttributes();
     
    226237        getGUIObjectByName("enableCheats").onPress = function()
    227238        {   // Update attributes so other players can see change
    228239            g_GameAttributes.settings.CheatsEnabled = this.checked;
    229 
     240           
    230241            if (!g_IsInGuiUpdate)
    231242            {
    232243                updateGameAttributes();
     
    254265            getGUIObjectByName("playerCiv["+i+"]").hidden = true;
    255266            getGUIObjectByName("playerTeam["+i+"]").hidden = true;
    256267        }
    257 
     268       
    258269        getGUIObjectByName("numPlayersSelection").hidden = true;
    259270    }
    260 
     271   
    261272    // Set up multiplayer/singleplayer bits:
    262273    if (!g_IsNetworked)
    263274    {
     
    279290            getGUIObjectByName("enableCheatsText").hidden = false;
    280291        }
    281292    }
    282 
     293   
    283294    // Settings for all possible player slots
    284295    var boxSpacing = 32;
    285296    for (var i = 0; i < MAX_PLAYERS; ++i)
     
    291302        boxSize.top = i * boxSpacing;
    292303        boxSize.bottom = i * boxSpacing + h;
    293304        box.size = boxSize;
    294 
     305       
    295306        // Populate team dropdowns
    296307        var team = getGUIObjectByName("playerTeam["+i+"]");
    297308        team.list = ["None", "1", "2", "3", "4"];
    298309        team.list_data = [-1, 0, 1, 2, 3];
    299310        team.selected = 0;
    300 
     311       
    301312        let playerSlot = i; // declare for inner function use
    302313        team.onSelectionChange = function()
    303314        {   // Update team
     
    305316            {
    306317                g_GameAttributes.settings.PlayerData[playerSlot].Team = this.selected - 1;
    307318            }
    308 
     319           
    309320            if (!g_IsInGuiUpdate)
    310321            {
    311322                updateGameAttributes();
    312323            }
    313324        };
    314325       
    315 
     326       
    316327        // Set events
    317328        var civ = getGUIObjectByName("playerCiv["+i+"]");
    318329        civ.onSelectionChange = function()
     
    321332            {
    322333                g_GameAttributes.settings.PlayerData[playerSlot].Civ = this.list_data[this.selected];
    323334            }
    324 
     335           
    325336            if (!g_IsInGuiUpdate)
    326337            {
    327338                updateGameAttributes();
    328339            }
    329340        };
    330341    }
    331 
     342   
    332343    if (g_IsNetworked)
    333344    {
    334345        // For multiplayer, focus the chat input box by default
     
    345356function handleNetMessage(message)
    346357{
    347358    log("Net message: "+uneval(message));
    348 
     359   
    349360    switch (message.type)
    350361    {
    351362    case "netstatus":
     
    356367            Engine.PopGuiPage();
    357368            reportDisconnect(message.reason);
    358369            break;
    359 
     370       
    360371        default:
    361372            error("Unrecognised netstatus type "+message.status);
    362373            break;
    363374        }
    364375        break;
    365 
     376   
    366377    case "gamesetup":
    367378        if (message.data) // (the host gets undefined data on first connect, so skip that)
    368379        {
     
    371382
    372383        onGameAttributesChange();
    373384        break;
    374 
     385   
    375386    case "players":
    376387        // Find and report all joinings/leavings
    377388        for (var host in message.hosts)
     
    392403        g_PlayerAssignments = message.hosts;
    393404        updatePlayerList();
    394405        break;
    395 
     406   
    396407    case "start":
    397408        Engine.SwitchGuiPage("page_loading.xml", {
    398409            "attribs": g_GameAttributes,
     
    400411            "playerAssignments": g_PlayerAssignments
    401412        });
    402413        break;
    403 
     414   
    404415    case "chat":
    405416        addChatMessage({ "type": "message", "guid": message.guid, "text": message.text });
    406417        break;
    407 
     418   
    408419    default:
    409420        error("Unrecognised net message type "+message.type);
    410421    }
     
    414425function getMapDisplayName(map)
    415426{
    416427    var mapData = loadMapData(map);
    417 
     428   
    418429    if (!mapData || !mapData.settings || !mapData.settings.Name)
    419430    {   // Give some msg that map format is unsupported
    420431        log("Map data missing in scenario '"+map+"' - likely unsupported format");
    421432        return map;
    422433    }
    423 
     434   
    424435    return mapData.settings.Name;
    425436}
    426437
     
    428439function getMapPreview(map)
    429440{
    430441    var mapData = loadMapData(map);
    431 
     442   
    432443    if (!mapData || !mapData.settings || !mapData.settings.Preview)
    433444    {   // Give some msg that map format is unsupported
    434445        return "nopreview.png";
    435446    }
    436 
     447   
    437448    return mapData.settings.Preview;
    438449}
    439450
     
    444455    {
    445456        return settings[property];
    446457    }
    447 
     458   
    448459    // Use defaults
    449460    if (defaults && (property in defaults))
    450461    {
    451462        return defaults[property];
    452463    }
    453 
     464   
    454465    return undefined;
    455466}
    456467
     468// Get the possible number of players for this random map ny map size
     469function getPlayersCapRMS(mapName, mapSize, maxPlayersByMapSizeRMS, minPlayersRMS)
     470{
     471    // Get map name
     472    mapName = (mapName || g_GameAttributes.map);
     473    // Get map size
     474    if (mapSize || g_GameAttributes.settings.Size)
     475        mapSize = (mapSize || g_GameAttributes.settings.Size);
     476    else
     477    {
     478        // Only a log to not show up at gui initialization
     479        log("getPlayersCapRMS: g_GameAttributes.settings.Size is undefined! Returning MAX_PLAYERS = " + MAX_PLAYERS);
     480        return {"min" : MIN_PLAYERS_RMS, "max" : MAX_PLAYERS};
     481    }
     482    // Get maximum numbers of players by map size array
     483    if (g_MapData[mapName] && g_MapData[mapName].settings && g_MapData[mapName].settings.MaximumPlayersByMapSize)
     484        maxPlayersByMapSizeRMS = (maxPlayersByMapSizeRMS || g_MapData[mapName].settings.MaximumPlayersByMapSize);
     485    else
     486        maxPlayersByMapSizeRMS = (maxPlayersByMapSizeRMS || MAX_PLAYERS_BY_MAP_SIZE_RMS);
     487   
     488    // Get minimum numbers of players by map size
     489    if (g_MapData[mapName] && g_MapData[mapName].settings && g_MapData[mapName].settings.MinimumPlayers)
     490        minPlayersRMS = (minPlayersRMS || g_MapData[mapName].settings.MinimumPlayers);
     491    else
     492        minPlayersRMS = (minPlayersRMS || MIN_PLAYERS_RMS);
     493   
     494    // Setting upper player cap
     495    var maxPlayers = Math.min(maxPlayersByMapSizeRMS[Math.round(mapSize/64 - 2)], MAX_PLAYERS);
     496    if (maxPlayers < 2)
     497    {
     498        warn("getPlayersCapRMS: Maximum number of players should at least be 2 but is " + maxPlayers + "! Setting it to 2.");
     499        maxPlayers = 2;
     500    }
     501   
     502    // Setting lower players cap
     503    var minPlayers = minPlayersRMS;
     504    if (minPlayers > maxPlayers)
     505    {
     506        warn("getPlayersCapRMS: minPlayers > maxPlayers! Lowering minPlayers (" + minPlayers + ") to maxPlayers (" + maxPlayers + ").");
     507        minPlayers = maxPlayers;
     508    }
     509   
     510    return {"min" : minPlayers, "max" : maxPlayers};
     511}
     512
     513// Change player number combobox content and update number of players combobox
     514function changeNumPlayersCaps(playerCaps)
     515{
     516    playerCaps = (playerCaps || getPlayersCapRMS());
     517    var numPlayersSelection = getGUIObjectByName("numPlayersSelection");
     518    var selectedNumPlayers = parseInt(numPlayersSelection.list_data[numPlayersSelection.selected]);
     519    var pList = [];
     520    for (var i = playerCaps.min; i <= playerCaps.max; ++i)
     521        pList.push(i);
     522    numPlayersSelection.list = pList;
     523    numPlayersSelection.list_data = pList;
     524    if (!selectedNumPlayers)
     525    {
     526        if (pList.indexOf(DEFAULT_NUM_PLAYERS_RMS) !== -1)
     527            numPlayersSelection.selected = pList.indexOf(DEFAULT_NUM_PLAYERS_RMS);
     528        else if (DEFAULT_NUM_PLAYERS_RMS > pList[pList.length - 1])
     529            numPlayersSelection.selected = pList.length - 1;
     530        else
     531            numPlayersSelection.selected = 0;
     532    }
     533    else if (pList.indexOf(selectedNumPlayers) !== -1)
     534        numPlayersSelection.selected = pList.indexOf(selectedNumPlayers);
     535    else if (selectedNumPlayers < pList[0])
     536        numPlayersSelection.selected = 0;
     537    else if (selectedNumPlayers > pList[pList.length - 1])
     538        numPlayersSelection.selected = pList.length - 1;
     539    else
     540        warn("changeNumPlayersCaps: Selected number of players could not be set properly on player cap change!");
     541    selectNumPlayers(pList[numPlayersSelection.selected]);
     542}
     543
    457544// Initialize the dropdowns containing all the available civs
    458545function initCivNameList()
    459546{
     
    470557   
    471558    // Alphabetically sort the list, ignoring case
    472559    civList.sort(sortNameIgnoreCase);
    473 
     560   
    474561    var civListNames = [ civ.name for each (civ in civList) ];
    475562    var civListCodes = [ civ.code for each (civ in civList) ];
    476 
     563   
    477564    //  Add random civ to beginning of list
    478565    civListNames.unshift("[color=\"orange\"]Random");
    479566    civListCodes.unshift("random");
     
    495582    // TODO: Should verify these are valid maps before adding to list
    496583    var mapSelectionBox = getGUIObjectByName("mapSelection")
    497584    var mapFiles;
    498 
     585   
    499586    switch (g_GameAttributes.mapType)
    500587    {
    501588    case "scenario":
    502589        mapFiles = getXMLFileList(g_GameAttributes.mapPath);
    503590        break;
    504 
     591   
    505592    case "random":
    506593        mapFiles = getJSONFileList(g_GameAttributes.mapPath);
    507594        break;
    508 
     595   
    509596    default:
    510597        error("initMapNameList: Unexpected map type '"+g_GameAttributes.mapType+"'");
    511598        return;
    512599    }
    513 
     600   
    514601    // Apply map filter, if any defined
    515602    var mapList = [];
    516603    for (var i = 0; i < mapFiles.length; ++i)
     
    523610            mapList.push({ "name": getMapDisplayName(file), "file": file });
    524611        }
    525612    }
    526 
     613   
    527614    // Alphabetically sort the list, ignoring case
    528615    mapList.sort(sortNameIgnoreCase);
    529616    if (g_GameAttributes.mapType == "random")
     
    531618   
    532619    var mapListNames = [ map.name for each (map in mapList) ];
    533620    var mapListFiles = [ map.file for each (map in mapList) ];
    534 
     621   
    535622    // Select the default map
    536623    var selected = mapListFiles.indexOf(g_GameAttributes.map);
    537624    // Default to the first element if list is not empty and we can't find the one we searched for
     
    539626    {
    540627        selected = 0;
    541628    }
    542 
     629   
    543630    // Update the list control
    544631    mapSelectionBox.list = mapListNames;
    545632    mapSelectionBox.list_data = mapListFiles;
     
    558645        g_MapData[name] = {settings : {"Name" : "Random", "Description" : "Randomly selects a map from the list"}};
    559646        return g_MapData[name];
    560647    }
    561 
     648   
    562649    if (!g_MapData[name])
    563650    {
    564651        switch (g_GameAttributes.mapType)
     
    566653        case "scenario":
    567654            g_MapData[name] = Engine.LoadMapSettings(g_GameAttributes.mapPath+name);
    568655            break;
    569 
     656       
    570657        case "random":
    571658            g_MapData[name] = parseJSONData(g_GameAttributes.mapPath+name+".json");
    572659            break;
    573 
     660       
    574661        default:
    575662            error("loadMapData: Unexpected map type '"+g_GameAttributes.mapType+"'");
    576663            return undefined;
    577664        }
    578665    }
    579 
     666   
    580667    return g_MapData[name];
    581668}
    582669
     
    624711    {
    625712        return;
    626713    }
    627 
     714   
    628715    // Network clients can't change number of players
    629716    if (g_IsNetworked && !g_IsController)
    630717    {
    631718        return;
    632719    }
    633 
     720   
    634721    // Only meaningful for random maps
    635722    if (g_GameAttributes.mapType != "random")
    636723    {
    637724        return;
    638725    }
    639 
     726   
    640727    // Update player data
    641728    var pData = g_GameAttributes.settings.PlayerData;
    642729    if (pData && num < pData.length)
     
    652739            g_GameAttributes.settings.PlayerData.push(g_DefaultPlayerData[i]);
    653740        }
    654741    }
    655 
     742   
    656743    // Some players may have lost their assigned slot
    657744    for (var guid in g_PlayerAssignments)
    658745    {
     
    665752                g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1} };
    666753        }
    667754    }
    668 
     755   
    669756    updateGameAttributes();
    670757}
    671758
     
    677764    {
    678765        return;
    679766    }
    680 
     767   
    681768    // Network clients can't change map type
    682769    if (g_IsNetworked && !g_IsController)
    683770    {
    684771        return;
    685772    }
    686 
     773   
    687774    // Reset game attributes
    688775    g_GameAttributes.map = "";
    689776    g_GameAttributes.mapType = type;
    690 
     777   
    691778    // Clear old map data
    692779    g_MapData = {};
    693 
     780   
    694781    // Select correct path
    695782    switch (g_GameAttributes.mapType)
    696783    {
     
    700787        g_GameAttributes.map = (g_IsNetworked ? DEFAULT_NETWORKED_MAP : DEFAULT_OFFLINE_MAP);
    701788        g_GameAttributes.mapPath = "maps/scenarios/";
    702789        break;
    703 
     790   
    704791    case "random":
     792        var playerCaps = getPlayersCapRMS();
    705793        g_GameAttributes.mapPath = "maps/random/";
    706794        g_GameAttributes.settings = {
    707             PlayerData: g_DefaultPlayerData.slice(0, 4),
     795            PlayerData: g_DefaultPlayerData.slice(0, Math.max(Math.min(DEFAULT_NUM_PLAYERS_RMS, playerCaps.max), playerCaps.min)),
    708796            Seed: Math.floor(Math.random() * 65536),
    709797            CheatsEnabled: g_GameAttributes.settings.CheatsEnabled
    710798        };
    711799        break;
    712 
     800   
    713801    default:
    714802        error("selectMapType: Unexpected map type '"+g_GameAttributes.mapType+"'");
    715803        return;
    716804    }
    717 
     805   
    718806    initMapNameList();
    719 
     807   
    720808    updateGameAttributes();
     809   
     810    changeNumPlayersCaps();
    721811}
    722812
    723813function selectMapFilter(filterName)
     
    727817    {
    728818        return;
    729819    }
    730 
     820   
    731821    // Network clients can't change map filter
    732822    if (g_IsNetworked && !g_IsController)
    733823    {
    734824        return;
    735825    }
    736 
     826   
    737827    g_GameAttributes.mapFilter = filterName;
    738 
     828   
    739829    initMapNameList();
    740 
     830   
    741831    updateGameAttributes();
    742832}
    743833
     
    749839    {
    750840        return;
    751841    }
    752 
     842   
    753843    // Network clients can't change map
    754844    if (g_IsNetworked && !g_IsController)
    755845    {
    756846        return;
    757847    }
    758 
     848   
    759849    // Return if we have no map
    760850    if (!name)
    761851    {
    762852        return;
    763853    }
    764 
     854   
    765855    var mapData = loadMapData(name);
    766856    var mapSettings = (mapData && mapData.settings ? deepcopy(mapData.settings) : {});
    767 
     857   
    768858    // Copy any new settings
    769859    g_GameAttributes.map = name;
    770860    g_GameAttributes.script = mapSettings.Script;
     
    800890            }
    801891        }
    802892    }
    803 
     893   
    804894    updateGameAttributes();
     895   
     896    changeNumPlayersCaps();
    805897}
    806898
    807899function launchGame()
     
    811903        error("Only host can start game");
    812904        return;
    813905    }
    814 
     906   
    815907    // Check that we have a map
    816908    if (!g_GameAttributes.map)
    817909    {
     
    821913    if (g_GameAttributes.map == "random")
    822914        selectMap(getGUIObjectByName("mapSelection").list_data[Math.floor(Math.random() *
    823915            (getGUIObjectByName("mapSelection").list.length - 1)) + 1]);
    824 
     916   
    825917    g_GameAttributes.settings.mapType = g_GameAttributes.mapType;
    826918    var numPlayers = g_GameAttributes.settings.PlayerData.length;
    827919    // Assign random civilizations to players with that choice
     
    894986        }
    895987        // Remove extra player data
    896988        g_GameAttributes.settings.PlayerData = g_GameAttributes.settings.PlayerData.slice(0, numPlayers);
    897 
     989       
    898990        Engine.StartGame(g_GameAttributes, playerID);
    899991        Engine.SwitchGuiPage("page_loading.xml", {
    900992            "attribs": g_GameAttributes,
     
    9091001function onGameAttributesChange()
    9101002{
    9111003    g_IsInGuiUpdate = true;
    912 
     1004   
    9131005    // Don't set any attributes here, just show the changes in GUI
    914 
     1006   
    9151007    var mapName = g_GameAttributes.map || "";
    9161008    var mapSettings = g_GameAttributes.settings;
    9171009    var numPlayers = (mapSettings.PlayerData ? mapSettings.PlayerData.length : MAX_PLAYERS);
    918 
     1010   
    9191011    // Update some controls for clients
    9201012    if (!g_IsController)
    9211013    {
     
    9321024        startingResourcesBox.selected = startingResourcesBox.list_data.indexOf(mapSettings.StartingResources);
    9331025        initMapNameList();
    9341026    }
    935 
     1027   
    9361028    // Controls common to all map types
    9371029    var numPlayersSelection = getGUIObjectByName("numPlayersSelection");
     1030    var minNumPlayers = numPlayersSelection.list_data[0];
    9381031    var revealMap = getGUIObjectByName("revealMap");
    9391032    var victoryCondition = getGUIObjectByName("victoryCondition");
    9401033    var lockTeams = getGUIObjectByName("lockTeams");
     
    9661059    case "random":
    9671060        if (g_IsController)
    9681061        {   //Host
    969             numPlayersSelection.selected = numPlayers - 1;
     1062            numPlayersSelection.selected = numPlayers - minNumPlayers;
    9701063            numPlayersSelection.hidden = false;
    9711064            mapSize.hidden = false;
    9721065            revealMap.hidden = false;
     
    10171110            victoryConditionText.caption = VICTORY_TEXT[victoryIdx];
    10181111            lockTeamsText.caption = (mapSettings.LockTeams ? "Yes" : "No");
    10191112        }
    1020 
     1113       
    10211114        break;
    1022 
     1115   
    10231116    case "scenario":
    10241117        // For scenario just reflect settings for the current map
    10251118        numPlayersSelection.hidden = true;
     
    10451138        victoryConditionText.caption = VICTORY_TEXT[victoryIdx];
    10461139        lockTeamsText.caption = (mapSettings.LockTeams ? "Yes" : "No");
    10471140        getGUIObjectByName("populationCap").selected = POPULATION_CAP_DEFAULTIDX;
    1048 
     1141       
    10491142        break;
    1050 
     1143   
    10511144    default:
    10521145        error("onGameAttributesChange: Unexpected map type '"+g_GameAttributes.mapType+"'");
    10531146        return;
    10541147    }
    1055 
     1148   
    10561149    // Display map name
    10571150    getGUIObjectByName("mapInfoName").caption = getMapDisplayName(mapName);
    10581151   
    10591152    // Load the description from the map file, if there is one
    10601153    var description = mapSettings.Description || "Sorry, no description available.";
    1061 
     1154    // Adding player caps to the map description
     1155    if (g_GameAttributes.mapType == "random")
     1156    {
     1157        if (g_MapData[mapName] && g_MapData[mapName].settings && g_MapData[mapName].settings.MinimumPlayers)
     1158            description += "\n\nMinimum number of players: " + g_MapData[mapName].settings.MinimumPlayers;
     1159        else
     1160            description += "\n";
     1161        description += "\nMaximum numbers of players (by map size):";
     1162        if (g_MapData[mapName] && g_MapData[mapName].settings && g_MapData[mapName].settings.MaximumPlayersByMapSize)
     1163            description += "\nTiny: " + g_MapData[mapName].settings.MaximumPlayersByMapSize.toString().replace(/,/g, "-").replace("-", ", Small: ").replace("-", ", Medium: ").replace("-", ", Normal: ").replace("-", ", Large: ").replace("-", ", Very Large: ").replace("-", ", Giant: ");
     1164        else
     1165            description += "\nTiny: " + MAX_PLAYERS_BY_MAP_SIZE_RMS.toString().replace(/,/g, "-").replace("-", ", Small: ").replace("-", ", Medium: ").replace("-", ", Normal: ").replace("-", ", Large: ").replace("-", ", Very Large: ").replace("-", ", Giant: ");
     1166    }
     1167    // Add naval warning to the map description
    10621168    if (g_GameAttributes.mapFilter == "Naval Maps")
    10631169        description += g_NavalWarning;
    1064 
     1170   
    10651171    // Describe the number of players
    10661172    var playerString = numPlayers + " " + (numPlayers == 1 ? "player" : "players") + ". ";
    1067 
     1173   
    10681174    for (var i = 0; i < MAX_PLAYERS; ++i)
    10691175    {
    10701176        // Show only needed player slots
    10711177        getGUIObjectByName("playerBox["+i+"]").hidden = (i >= numPlayers);
    1072 
     1178       
    10731179        // Show player data or defaults as necessary
    10741180        if (i < numPlayers)
    10751181        {
     
    10831189            // Player data / defaults
    10841190            var pData = mapSettings.PlayerData ? mapSettings.PlayerData[i] : {};
    10851191            var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[i] : {};
    1086 
     1192           
    10871193            // Common to all game types
    10881194            var color = iColorToString(getSetting(pData, pDefs, "Colour"));
    10891195            pColor.sprite = "colour:"+color+" 100";
    10901196            pName.caption = getSetting(pData, pDefs, "Name");
    1091 
     1197           
    10921198            var team = getSetting(pData, pDefs, "Team");
    10931199            var civ = getSetting(pData, pDefs, "Civ");
    10941200           
     
    11241230    }
    11251231
    11261232    getGUIObjectByName("mapInfoDescription").caption = playerString + description;
    1127 
     1233   
    11281234    g_IsInGuiUpdate = false;
    1129 
     1235   
    11301236    // Game attributes include AI settings, so update the player list
    11311237    updatePlayerList();
    11321238}
     
    11461252function updatePlayerList()
    11471253{
    11481254    g_IsInGuiUpdate = true;
    1149 
     1255   
    11501256    var hostNameList = [];
    11511257    var hostGuidList = [];
    11521258    var assignments = [];
    11531259    var aiAssignments = {};
    11541260    var noAssignment;
    11551261    var assignedCount = 0;
    1156 
     1262   
    11571263    for (var guid in g_PlayerAssignments)
    11581264    {
    11591265        var name = g_PlayerAssignments[guid].name;
    11601266        var hostID = hostNameList.length;
    11611267        var player = g_PlayerAssignments[guid].player;
    1162 
     1268       
    11631269        hostNameList.push(name);
    11641270        hostGuidList.push(guid);
    11651271        assignments[player] = hostID;
    1166 
     1272       
    11671273        if (player != 255)
    11681274            assignedCount++;
    11691275    }
    1170 
     1276   
    11711277    // Only enable start button if we have enough assigned players
    11721278    if (g_IsController)
    11731279        getGUIObjectByName("startGame").enabled = (assignedCount > 0);
    1174 
     1280   
    11751281    for each (var ai in g_AIs)
    11761282    {
    11771283        if (ai.data.hidden)
     
    11951301        hostNameList.push("[color=\"70 150 70 255\"]AI: " + ai.data.name);
    11961302        hostGuidList.push("ai:" + ai.id);
    11971303    }
    1198 
     1304   
    11991305    noAssignment = hostNameList.length;
    12001306    hostNameList.push("[color=\"140 140 140 255\"]Unassigned");
    12011307    hostGuidList.push("");
    1202 
     1308   
    12031309    for (var i = 0; i < MAX_PLAYERS; ++i)
    12041310    {
    12051311        let playerSlot = i;
    12061312        let playerID = i+1; // we don't show Gaia, so first slot is ID 1
    1207 
     1313       
    12081314        var selection = assignments[playerID];
    1209 
     1315       
    12101316        var configButton = getGUIObjectByName("playerConfig["+i+"]");
    12111317        configButton.hidden = true;
    1212 
     1318       
    12131319        // Look for valid player slots
    12141320        if (playerSlot < g_GameAttributes.settings.PlayerData.length)
    12151321        {
     
    12251331                    else
    12261332                        warn("AI \""+aiId+"\" not present. Defaulting to unassigned.");
    12271333                }
    1228 
     1334               
    12291335                if (!selection)
    12301336                    selection = noAssignment;
    1231 
     1337               
    12321338                // Since no human is assigned, show the AI config button
    12331339                if (g_IsController)
    12341340                {
     
    12401346                            id: g_GameAttributes.settings.PlayerData[playerSlot].AI,
    12411347                            callback: function(ai) {
    12421348                                g_GameAttributes.settings.PlayerData[playerSlot].AI = ai.id;
    1243 
     1349                               
    12441350                                if (g_IsNetworked)
    12451351                                {
    12461352                                    Engine.SetNetworkGameAttributes(g_GameAttributes);
     
    12671373                    }
    12681374                }
    12691375            }
    1270 
     1376           
    12711377            var assignBox = getGUIObjectByName("playerAssignment["+i+"]");
    12721378            assignBox.list = hostNameList;
    12731379            assignBox.list_data = hostGuidList;
     
    12751381            {
    12761382                assignBox.selected = selection;
    12771383            }
    1278 
     1384           
    12791385            if (g_IsNetworked && g_IsController)
    12801386            {
    12811387                assignBox.onselectionchange = function ()
     
    12991405                        }
    13001406                        else
    13011407                            swapPlayers(guid, playerSlot);
    1302 
     1408                       
    13031409                        Engine.SetNetworkGameAttributes(g_GameAttributes);
    13041410                    }
    13051411                };
     
    13231429                        }
    13241430                        else
    13251431                            swapPlayers(guid, playerSlot);
    1326 
     1432                       
    13271433                        updatePlayerList();
    13281434                    }
    13291435                };
    13301436            }
    13311437        }
    13321438    }
    1333 
     1439   
    13341440    g_IsInGuiUpdate = false;
    13351441}
    13361442
     
    13391445    // Player slots are indexed from 0 as Gaia is omitted.
    13401446    var newPlayerID = newSlot + 1;
    13411447    var playerID = g_PlayerAssignments[guid].player;
    1342 
     1448   
    13431449    // Attempt to swap the player or AI occupying the target slot,
    13441450    // if any, into the slot this player is currently in.
    13451451    if (playerID != 255)
     
    13561462                break;
    13571463            }
    13581464        }
    1359 
     1465       
    13601466        // Transfer the AI from the target slot to the current slot.
    13611467        g_GameAttributes.settings.PlayerData[playerID - 1].AI = g_GameAttributes.settings.PlayerData[newSlot].AI;
    13621468    }
    1363 
     1469   
    13641470    if (g_IsNetworked)
    13651471        Engine.AssignNetworkPlayer(newPlayerID, guid);
    13661472    else
    13671473        g_PlayerAssignments[guid].player = newPlayerID;
    1368 
     1474   
    13691475    // Remove AI from this player slot
    13701476    g_GameAttributes.settings.PlayerData[newSlot].AI = "";
    13711477}
     
    13851491{
    13861492    var username = escapeText(msg.username || g_PlayerAssignments[msg.guid].name);
    13871493    var message = escapeText(msg.text);
    1388 
     1494   
    13891495    // TODO: Maybe host should have distinct font/color?
    13901496    var color = "white";
    1391 
     1497   
    13921498    if (g_PlayerAssignments[msg.guid] && g_PlayerAssignments[msg.guid].player != 255)
    13931499    {   // Valid player who has been assigned - get player colour
    13941500        var player = g_PlayerAssignments[msg.guid].player - 1;
     
    13971503        var mapSettings = (mapData && mapData.settings ? mapData.settings : {});
    13981504        var pData = mapSettings.PlayerData ? mapSettings.PlayerData[player] : {};
    13991505        var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[player] : {};
    1400 
     1506       
    14011507        color = iColorToString(getSetting(pData, pDefs, "Colour"));
    14021508    }
    1403 
     1509   
    14041510    var formatted;
    14051511    switch (msg.type)
    14061512    {
    14071513    case "connect":
    14081514        formatted = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font] [color="gold"]has joined[/color]';
    14091515        break;
    1410 
     1516   
    14111517    case "disconnect":
    14121518        formatted = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font] [color="gold"]has left[/color]';
    14131519        break;
    1414 
     1520   
    14151521    case "message":
    14161522        formatted = '[font="serif-bold-13"]<[color="'+ color +'"]' + username + '[/color]>[/font] ' + message;
    14171523        break;
    1418 
     1524   
    14191525    default:
    14201526        error("Invalid chat message '" + uneval(msg) + "'");
    14211527        return;
    14221528    }
    1423 
     1529   
    14241530    g_ChatMessages.push(formatted);
    1425 
     1531   
    14261532    getGUIObjectByName("chatText").caption = g_ChatMessages.join("\n");
    14271533}
    14281534
     
    14421548        var newFilter = {};
    14431549        newFilter.name = name;
    14441550        newFilter.filter = filterFunc;
    1445 
     1551       
    14461552        g_MapFilters.push(newFilter);
    14471553    }
    14481554    else
     
    14591565    {
    14601566        filters.push(g_MapFilters[i].name);
    14611567    }
    1462 
     1568   
    14631569    return filters;
    14641570}
    14651571
     
    14731579            return g_MapFilters[i].filter(mapSettings);
    14741580        }
    14751581    }
    1476 
     1582   
    14771583    error("Invalid map filter: "+name);
    14781584    return false;
    14791585}
     
    14851591    {
    14861592        return false;
    14871593    }
    1488 
     1594   
    14891595    for (var m = 0; m < matches.length; ++m)
    14901596    {   // Fail on not match
    14911597        if (keywords.indexOf(matches[m]) == -1)
     
    15031609    {
    15041610        return false;
    15051611    }
    1506 
     1612   
    15071613    for (var m = 0; m < matches.length; ++m)
    15081614    {   // Success on match
    15091615        if (keywords.indexOf(matches[m]) != -1)
  • binaries/data/mods/public/maps/random/archipelago.json

     
    88        "Keywords": ["naval"],
    99        "Preview" : "archipelago.png",
    1010        "CircularMap" : true,
     11        "MaximumPlayersByMapSize" : [3, 6, 8, 8, 8, 8, 8],
    1112        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1213    }
    1314}
  • binaries/data/mods/public/maps/random/belgian_uplands.json

     
    22    "settings" : {
    33        "Name" : "Belgian Uplands",
    44        "Script" : "belgian_uplands.js",
     5        "Preview" : "belgian_uplands.png",
    56        "Description" : "An experimental map with its hightmap generated by erosion to look more natural. Not all seeds will be fair though! Tiny maps with 8 players may take a while to generate.",
    67        "CircularMap" : false,
     8        "MaximumPlayersByMapSize" : [2, 4, 6, 8, 8, 8, 8],
    79        "BaseTerrain" : ["temp_grass", "temp_grass_b", "temp_grass_c", "temp_grass_d", "temp_grass_long_b", "temp_grass_clovers_2", "temp_grass_mossy", "temp_grass_plants"],
    810        "BaseHeight" : 0,
    9         "Preview" : "belgian_uplands.png",
    1011        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1112    }
    1213}
  • binaries/data/mods/public/maps/random/canyon.json

     
    77        "BaseHeight" : 30,
    88        "Preview" : "canyon.png",
    99        "CircularMap" : true,
     10        "MinimumPlayers" : 2,
     11        "MaximumPlayersByMapSize" : [3, 6, 8, 8, 8, 8, 8],
    1012        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1113    }
    1214}
     15 No newline at end of file
  • binaries/data/mods/public/maps/random/corsica.json

     
    88        "Keywords": ["naval"],
    99        "Preview" : "corsica.png",
    1010        "CircularMap" : false,
     11        "MaximumPlayersByMapSize" : [2, 4, 6, 8, 8, 8, 8],
    1112        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1213    }
    1314}
     15 No newline at end of file
  • binaries/data/mods/public/maps/random/deep_forest.json

     
    77        "BaseHeight" : 0,
    88        "Preview" : "deep_forest.png",
    99        "CircularMap" : true,
     10        "MaximumPlayersByMapSize" : [3, 6, 8, 8, 8, 8, 8],
    1011        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1112    }
    1213}
  • binaries/data/mods/public/maps/random/guadalquivir_river.js

     
    142142    createArea(placer, painter, null);
    143143   
    144144    // create starting units
    145     placeCivDefaultEntities(fx, fz, id, BUILDING_ANGlE);
     145    placeCivDefaultEntities(fx, fz, id, BUILDING_ANGlE, (mapSize/64 - 3 < 1) ? {"iberWall" : false} : undefined);
    146146   
    147147    // create animals
    148148    for (var j = 0; j < 2; ++j)
  • binaries/data/mods/public/maps/random/guadalquivir_river.json

     
    77        "BaseHeight" : -5,
    88        "Preview" : "guadalquivir_river.png",
    99        "CircularMap" : true,
     10        "MaximumPlayersByMapSize" : [2, 4, 6, 6, 8, 8, 8],
    1011        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1112    }
    1213}
  • binaries/data/mods/public/maps/random/gulf_of_bothnia.json

     
    77        "BaseHeight" : 3,
    88        "Preview" : "gulf_of_bothnia.png",
    99        "CircularMap" : true,
     10        "MinimumPlayers" : 2,
    1011        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1112    }
    1213}
     14 No newline at end of file
  • binaries/data/mods/public/maps/random/islands.json

     
    88        "Keywords": ["naval"],
    99        "Preview" : "islands.png",
    1010        "CircularMap" : true,
     11        "MaximumPlayersByMapSize" : [2, 4, 6, 8, 8, 8, 8],
    1112        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1213    }
    1314}
  • binaries/data/mods/public/maps/random/migration.json

     
    88        "Keywords": ["naval"],
    99        "Preview" : "migration.png",
    1010        "CircularMap" : true,
     11        "MaximumPlayersByMapSize" : [2, 3, 5, 5, 6, 7, 8],
    1112        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1213    }
    1314}
  • binaries/data/mods/public/maps/random/pheonician_levant.json

     
    77        "BaseHeight" : 1,
    88        "Preview" : "phoenician_levant.png",
    99        "CircularMap" : false,
     10        "MaximumPlayersByMapSize" : [4, 4, 8, 8, 8, 8, 8],
    1011        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1112    }
    1213}
     14 No newline at end of file
  • binaries/data/mods/public/maps/random/pyrenean_sierra.js

     
    351351    createArea(placer, painter, null);
    352352   
    353353    // create starting units
    354     placeCivDefaultEntities(fx, fz, id, BUILDING_ANGlE);
     354    placeCivDefaultEntities(fx, fz, id, BUILDING_ANGlE, (round(mapSize/64) - 2 == 1) ? {"iberWall" : "towers"} : undefined);
    355355   
    356356    // create animals
    357357    for (var j = 0; j < 2; ++j)
  • binaries/data/mods/public/maps/random/pyrenean_sierra.json

     
    77        "BaseHeight" : -100,
    88        "Preview" : "pyrenean_sierra.png",
    99        "CircularMap" : true,
     10        "MinimumPlayers" : 2,
    1011        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1112    }
    1213}
     14 No newline at end of file
  • binaries/data/mods/public/maps/random/snowflake_searocks.json

     
    77        "BaseHeight" : -5,
    88        "Preview" : "snowflake_searocks.png",
    99        "CircularMap" : true,
     10        "MinimumPlayers" : 2,
     11        "MaximumPlayersByMapSize" : [3, 4, 8, 8, 8, 8, 8],
    1012        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1113    }
    1214}
  • binaries/data/mods/public/maps/random/unknown.json

     
    77        "BaseHeight" : -5,
    88        "Preview" : "unknown.png",
    99        "CircularMap" : true,
     10        "MinimumPlayers" : 2,
     11        "MaximumPlayersByMapSize" : [2, 4, 6, 8, 8, 8, 8],
    1012        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1113    }
    1214}
  • binaries/data/mods/public/maps/random/unknown_land.json

     
    77        "BaseHeight" : -5,
    88        "Preview" : "unknown.png",
    99        "CircularMap" : true,
     10        "MinimumPlayers" : 2,
     11        "MaximumPlayersByMapSize" : [2, 4, 6, 8, 8, 8, 8],
    1012        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1113    }
    1214}
  • binaries/data/mods/public/maps/random/unknown_nomad.json

     
    88        "Preview" : "unknown.png",
    99        "Keywords": ["demo"],
    1010        "CircularMap" : true,
     11        "MinimumPlayers" : 2,
     12        "MaximumPlayersByMapSize" : [2, 4, 6, 8, 8, 8, 8],
    1113        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
    1214    }
    1315}