function OnStartButton()
-- <<<<< YNAMP
-- We can't have a nil Map Seed for the random selections
if not MapConfiguration.GetValue("RANDOM_SEED") then
print(MapConfiguration.GetValue("RANDOM_SEED"), GameConfiguration.GetValue("GAME_SYNC_RANDOM_SEED"))
local gameSeed = GameConfiguration.GetValue("GAME_SYNC_RANDOM_SEED")
GameConfiguration.RegenerateSeeds()
if gameSeed then
GameConfiguration.SetValue("GAME_SYNC_RANDOM_SEED", gameSeed)
end
print(MapConfiguration.GetValue("RANDOM_SEED"), GameConfiguration.GetValue("GAME_SYNC_RANDOM_SEED"))
end
-- hide the player section first to not show the mod selection for random slots
Controls.PlayersSection:SetHide(true)
-- output the last validation report to the log
print(Controls.WindowTitle:GetToolTipString())
---[[
local player_ids = GameConfiguration.GetParticipatingPlayerIDs();
local numPlayers = #player_ids
local numCS = GameConfiguration.GetValue("CITY_STATE_COUNT")
local newNumCS = numCS
local maxPlayer = 62 -- max is 64 but 1 slot is required for barbarian and 1 slot for free cities
local cityStateID = 0 -- Player slots IDs start at 0, Human is 0, so we should start at 1, but start at 0 in case some mod (spectator ?) change that
local maxCS = maxPlayer - numPlayers
local bSelectCS = MapConfiguration.GetValue("SelectCityStates") ~= "RANDOM"
local bBanListCS = MapConfiguration.GetValue("SelectCityStates") == "EXCLUSION"
local bBanLeaders = MapConfiguration.GetValue("BanLeaders")
local bOnlyTSL = MapConfiguration.GetValue("OnlyLeadersWithTSL")
local ruleset = GameConfiguration.GetValue("RULESET")
local playerDomain = ruleset and RulesetPlayerDomain[ruleset] or "Players:StandardPlayers"
local ruleset = GameConfiguration.GetValue("RULESET")
print("Active Ruleset = ", ruleset)
print("Player Domain = ", playerDomain)
-- Limit number of players for R&F and GS
print("------------------------------------------------------")
print("YnAMP checking for number of players limit on Start...")
print("num. players = ".. tostring(numPlayers) .. ", num. CS = ".. tostring(numCS), ", Selection type = ", MapConfiguration.GetValue("SelectCityStates"), ", Do selection =", bSelectCS)
if (GameConfiguration.GetValue("RULESET") == "RULESET_EXPANSION_1" or GameConfiguration.GetValue("RULESET") == "RULESET_EXPANSION_2") and numPlayers + numCS > maxPlayer then
newNumCS = maxCS
print("new num. CS = ".. tostring(newNumCS))
GameConfiguration.SetValue("CITY_STATE_COUNT", newNumCS)
end
if true then --bBanLeaders then -- I prefer the randomization of this function over the Core method (less duplicates when allowed, no duplicate when not), so make it default.
print("------------------------------------------------------")
print("Getting Leaders for Random slots...")
local IsUsedCiv = {}
local IsUsedLeader = {}
-- Taken from SetupParameters:Parameter_FilterValues
-- <<<
local unique_leaders = GameConfiguration.GetValue("NO_DUPLICATE_LEADERS");
local unique_civilizations = GameConfiguration.GetValue("NO_DUPLICATE_CIVILIZATIONS");
local leaders_in_use;
local civilizations_in_use;
local InsertIntoDuplicateBucket = function(map, key, other_key)
local bucketA = map[key];
local bucketB = map[other_key];
if(bucketA == nil and bucketB == nil) then
bucketA = {key, other_key};
map[key] = bucketA;
map[other_key] = bucketA;
elseif(bucketA == nil and bucketB ~= nil) then
table.insert(bucketB, key);
map[key] = bucketB;
elseif(bucketA ~= nil and bucketB == nil) then
table.insert(bucketA, other_key);
map[other_key] = bucketA;
elseif(bucketA ~= nil and bucketB ~= nil and bucketA ~= bucketB) then
-- consolidate buckets
-- if A is a dupe of B and B is a dupe of C, then A is a dupe of C.
for i,v in ipairs(bucketB) do
table.insert(bucketA, v);
map[v] = bucketA;
end
elseif(bucketA == bucketB) then
-- buckets are same, no need to do anything since they are already dupes of each other
end
end;
local duplicate_civilizations;
if(unique_civilizations) then
duplicate_civilizations = {};
for i, row in ipairs(CachedQuery("SELECT CivilizationType, OtherCivilizationType from DuplicateCivilizations where Domain = ?", playerDomain)) do
InsertIntoDuplicateBucket(duplicate_civilizations, row.CivilizationType, row.OtherCivilizationType);
end
end
local duplicate_leaders;
if(unique_leaders) then
duplicate_leaders = {};
for i, row in ipairs(CachedQuery("SELECT LeaderType, OtherLeaderType from DuplicateLeaders where Domain = ?", playerDomain)) do
InsertIntoDuplicateBucket(duplicate_leaders, row.LeaderType, row.OtherLeaderType);
end
end
-->>>
local function MarkUsedCiv(civilizationType)
IsUsedCiv[civilizationType] = true
local dupes = duplicate_civilizations and duplicate_civilizations[civilizationType]
if(dupes) then
for i,v in ipairs(dupes) do
IsUsedCiv[v] = true
end
end
end
local function MarkUsedLeader(leaderType)
IsUsedLeader[leaderType] = true
local dupes = duplicate_leaders and duplicate_leaders[leaderType]
if(dupes) then
for i,v in ipairs(dupes) do
IsUsedLeader[v] = true
end
end
end
-- Get Random slots and used leaders and Civs
local randomSlots = {}
for i, slotID in ipairs(player_ids) do
local playerConfig = PlayerConfigurations[slotID];
if playerConfig:GetSlotName() == "LOC_RANDOM_LEADER" then
table.insert(randomSlots, slotID)
else
local civilizationType = playerConfig:GetCivilizationTypeName()
local leaderType = playerConfig:GetLeaderTypeName()
MarkUsedCiv(civilizationType)
MarkUsedLeader(leaderType)
end
end
print("Random Leaders Slots = ", #randomSlots)
if #randomSlots > 0 then -- don't waste time if there are no random slots...
local filteredRandomLeaderList = {}
for leaderType, bValid in pairs(availableLeaderList) do
bValid = bValid and #CachedQuery("SELECT LeaderType from Players WHERE Domain = ? AND LeaderType = ?", playerDomain, leaderType)>0
if bValid then
table.insert(filteredRandomLeaderList, leaderType)
end
end
local shuffledList = GetShuffledCopyOfTable(filteredRandomLeaderList)
local listIndex = 1
-- Helper to get the CivilizationType of a LeaderType
local function GetPlayerCivilization(leaderType)
for i, row in ipairs(CachedQuery("SELECT CivilizationType from Players where LeaderType = ? LIMIT 1", leaderType)) do
return row.CivilizationType
end
end
--
local function GetLeaderName(leaderType)
for i, row in ipairs(CachedQuery("SELECT LeaderName from Players where LeaderType = ? LIMIT 1", leaderType)) do
return row.LeaderName
end
end
--
local function GetNextLeaderType(bSecondLoop)
local leaderType = shuffledList[listIndex]
local bNoDupeLeaders = unique_leaders or (not bSecondLoop) -- avoid duplicate leaders on first loop, even if allowed
local bNoDupeCivs = unique_civilizations or (not bSecondLoop) -- avoid duplicate civs on first loop, even if allowed
while(leaderType) do
if not MapConfiguration.GetValue(leaderType) then -- this leaderType is not banned
if (not IsUsedLeader[leaderType]) or (not bNoDupeLeaders) then
local civilizationType = GetPlayerCivilization(leaderType)
if civilizationType then
if (not IsUsedCiv[civilizationType]) or (not bNoDupeCivs) then
MarkUsedCiv(civilizationType)
MarkUsedLeader(leaderType)
listIndex = listIndex + 1
return leaderType
else
--print(" - Can't use leader because of duplicate Civilization : ", leaderType, civilizationType)
end
else
--print(" - WARNING: can't find civilizationType for : ", leaderType)
end
else
--print(" - Can't use duplicate leader : ", leaderType)
end
else
--print(" - Can't use banned leader : ", leaderType)
end
listIndex = listIndex + 1
leaderType = shuffledList[listIndex]
end
if not bSecondLoop then -- in case duplicates are allowed
print(" - Can't find next leader, trying second loop")
shuffledList = GetShuffledCopyOfTable(shuffledList)
listIndex = 1
if not unique_leaders then
IsUsedLeader = {}
end
if not unique_civilizations then
IsUsedCiv = {}
end
return GetNextLeaderType(true)
else
print(" - Can't find next leader after second loop")
end
end
print("Setting random slots...")
for i, slotID in ipairs(randomSlots) do
local playerConfig = PlayerConfigurations[slotID]
local leaderType = GetNextLeaderType()
if leaderType then
print("- Placing ", leaderType, " in slot#", slotID)
playerConfig:SetSlotStatus(SlotStatus.SS_COMPUTER)
playerConfig:SetLeaderName(GetLeaderName(leaderType))
playerConfig:SetLeaderTypeName(leaderType)
playerConfig:SetMajorCiv()
else
print("- No LeaderType available, clearing slot#", slotID)
playerConfig:SetLeaderTypeName(nil)
GameConfiguration.RemovePlayer(slotID)
end
end
end
end
-- Get available player slots list for CS
if (bSelectCS or bOnlyTSL) and (not ConfigYnAMP.IsDatabaseChanged) then
print("------------------------------------------------------")
print("Generate available slots list for CS...")
local CityStatesSlotsList = {}
while(cityStateID < maxPlayer) do
local playerConfig = PlayerConfigurations[cityStateID];
-- If we've reached the end of the line, exit.
if(playerConfig == nil) then
print("playerConfig is nil at cityStateID#", cityStateID)
--break;
end
-- Check for free slots to add to the CS list.
if (playerConfig:GetSlotStatus() == SlotStatus.SS_CLOSED) then
table.insert(CityStatesSlotsList, cityStateID)
end
-- Increment the AI, this assumes that either player config will hit nil
-- or we'll reach a suitable slot.
cityStateID = cityStateID + 1;
end
-- Get the City States list
local query = cityStatesQuery
local results = DB.ConfigurationQuery(query)
if(results and #results > 0) then
local filteredList = {}
local duplicate = {}
local mapName = MapConfiguration.GetValue("MapName")
for i, row in ipairs(results) do
local leaderType = row.ConfigurationId
local bValid = true
if bBanListCS then -- first check if the selection list is in "exclusion" mode
if MapConfiguration.GetValue(leaderType) then -- true if this CS was checked
bValid = false
end
end
if bValid and bOnlyTSL then -- filter CS list by TSL
local args = {}
args.leaderType = leaderType
args.civilizationType = LeadersCivilizations[leaderType]
args.mapName = mapName
if not HasTSL(args) then--(leaderType, mapName, playerDomain, civilizationType)
bValid = false
end
end
if bValid and not duplicate[leaderType] then
duplicate[leaderType] = true
table.insert(filteredList, {ConfigurationId = leaderType, Name = row.Name})
end
end
local bCapped = MapConfiguration.GetValue("SelectCityStates") == "SELECTION" or MapConfiguration.GetValue("SelectCityStates") == "EXCLUSION"
local bOnlySelection = MapConfiguration.GetValue("SelectCityStates") == "ONLY_SELECTION"
local cityStateSlots = (bCapped and numCS) or maxCS
local shuffledList = GetShuffledCopyOfTable(filteredList)
local randomList = {}
local slotListID = 1
print("------------------------------------------------------")
print("YnAMP setting specific CS slots...")
print("Trying to reserve slots for selected CS, available slots = "..tostring(#CityStatesSlotsList)..", maxCS = "..tostring(cityStateSlots).. ", bCapped = ", bCapped, " bOnlySelection = ", bOnlySelection)
for i, row in ipairs(shuffledList) do
--print(i)
--for k, v in pairs(row) do print(k, v) end
local leaderType = row.ConfigurationId
local leaderName = row.Name
if (not bBanListCS) and MapConfiguration.GetValue(leaderType) then -- true if this CS was checked and we're not in exclusion mode
if cityStateSlots > 0 then
local slotID = CityStatesSlotsList[slotListID]
if slotID then
print(" - Reserving player slot#"..tostring(slotID).." for ".. Locale.Lookup(leaderName) )
local playerConfig = PlayerConfigurations[slotID]
playerConfig:SetSlotStatus(SlotStatus.SS_COMPUTER)
playerConfig:SetLeaderName(leaderName)
playerConfig:SetLeaderTypeName(leaderType)
cityStateSlots = cityStateSlots - 1
slotListID = slotListID + 1
else
print(" - ERROR, No slots found for ".. Locale.Lookup(leaderName) .." at slotListID#"..tostring(slotListID).."/".. tostring(#CityStatesSlotsList) .." but calculated slots left = ".. tostring(cityStateSlots) )
end
else
print(" - Maximum #CS reached, can't set a slot for ".. Locale.Lookup(leaderName) .." at slotListID#"..tostring(slotListID).."/".. tostring(#CityStatesSlotsList) )
end
else -- add unselected CS to the random pool
table.insert(randomList, row)
end
end
local placedCS = slotListID - 1
local newNumCS = bOnlySelection and 0 or math.max(0, numCS - placedCS)
print("Unused slots left = ", cityStateSlots )
print("Setting Random CS to number of slots = ", newNumCS )
--GameConfiguration.SetValue("CITY_STATE_COUNT", newNumCS)
---[[
if newNumCS > 0 then
local nextIndex = 1
for slotListID = slotListID, slotListID + newNumCS - 1 do --cityStateSlots do
local slotID = CityStatesSlotsList[slotListID]
local playerConfig = PlayerConfigurations[slotID]
if playerConfig then
-- get next entry in the random pool
local row = randomList[nextIndex]
nextIndex = nextIndex + 1
if row then
local leaderType = row.ConfigurationId
local leaderName = row.Name
print(" - Reserving player slot#"..tostring(slotID).." for ".. Locale.Lookup(leaderName) )
playerConfig:SetSlotStatus(SlotStatus.SS_COMPUTER)
playerConfig:SetLeaderName(leaderName)
playerConfig:SetLeaderTypeName(leaderType)
else
print(" - No more CS in Random pool, can't set a CS at slotListID#"..tostring(slotListID).."/".. tostring(#CityStatesSlotsList) )
end
else
print(" - No more Slot available, can't set a CS at slotListID#"..tostring(slotListID).."/".. tostring(#CityStatesSlotsList) )
end
end
end
--]]
end
elseif ConfigYnAMP.IsDatabaseChanged then
print("------------------------------------------------------")
print("Database Changed, skipping CS selection...")
end
[...]