Location Based Settlement Names

whoward69

DLL Minion
Joined
May 30, 2011
Messages
8,728
Location
Near Portsmouth, UK
So you've created your new civ with a list of city names - Perth, Brisbane, Cairns, etc - but what if your civ is nomadic and a city list is inappropriate as the tribes named themselves after actions or their environment?

You could create a list of appropriate tribe names - Snake River, Rocky Pass, Soaring Eagle - and randomise them (see SQL at very end of post), but that could lead to weird naming circumstances - the Snake River Tribe settling nowhere near a river, or the Rocky Pass clan at the mouth of a river.

What we really want are semi-random names based on terrain/features/resources around the settlement tile.

We need to detect a new settlement being founded, and this can easily be achieved via the SetPopulation() GameEvent when the iOldPop parameter is zero.

Code:
function OnSetPopulation(iPlotX, iPlotY, iOldPop, iNewPop)
  -- Has this city just been founded
  if (iOldPop == 0) then
    local pCity = Map.GetPlot(iPlotX, iPlotY):GetPlotCity()

    if (IsMorindimPlayer(pCity:GetOwner()) and (Players[pCity:GetOwner()]:GetCapitalCity() ~= nil)) then
      SetClanName(pCity)
    end
  end
end
GameEvents.SetPopulation.Add(OnSetPopulation)

If this settlement has just been founded (iOldPop == 0) and it's for the required player (IsMorindimPlayer(pCity:GetOwner()) and it's not the "capital" (Players[pCity:GetOwner()]:GetCapitalCity() ~= nil) rename the city.
As the DLL will already have picked a name for the new settlement before this event is sent we still need a small list of city names for the civ, including our "capital".

Spoiler :

Code:
<GameData>
    <Civilization_CityNames>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_GREAT_SPIRIT</CityName>
        </Row>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_1</CityName>
        </Row>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_2</CityName>
        </Row>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_3</CityName>
        </Row>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_4</CityName>
        </Row>
    </Civilization_CityNames>

    <Language_en_US>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GREAT_SPIRIT">
            <Text>Great Spirit Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_1">
            <Text>Musk Ox Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_2">
            <Text>Moon Walkers Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_3">
            <Text>Cloud Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_4">
            <Text>Bear Clan</Text>
        </Row>
    </Language_en_US>
</GameData>


So how to pick a semi-random clan name based on local terrain/features?

Firstly we need to analyse the plots surrounding the settlement, both "near" (ring-1) and "far" (ring-2) - and for convience both ring-1 and ring-2 combined

Code:
local allPlots, ring1Plots, ring2Plots
local allTerrains, ring1Terrains, ring2Terrains
local allFeatures, ring1Features, ring2Features

function GetCount(array, index)
  return array[index] or 0
end

function IncCount(singleArray, combinedArray, index)
    singleArray[index] = (singleArray[index] or 0) + 1
    combinedArray[index] = (combinedArray[index] or 0) + 1
end

function AnalysePlots(pPlot)
  allPlots = {}
  ring1Plots = {}
  ring2Plots = {}

  allTerrains = {}
  ring1Terrains = {}
  ring2Terrains = {}

  allFeatures = {}
  ring1Features = {}
  ring2Features = {}

  for pRingPlot in PlotRingIterator(pPlot, 1) do
    IncCount(ring1Plots, allPlots, pRingPlot:GetPlotType())
    IncCount(ring1Terrains, allTerrains, pRingPlot:GetTerrainType())
    IncCount(ring1Features, allFeatures, pRingPlot:GetFeatureType())
  end

  for pRingPlot in PlotRingIterator(pPlot, 2) do
    IncCount(ring2Plots, allPlots, pRingPlot:GetPlotType())
    IncCount(ring2Terrains, allTerrains, pRingPlot:GetTerrainType())
    IncCount(ring2Features, allFeatures, pRingPlot:GetFeatureType())
  end
end

With the analysis complete, we can write some functions to determine if a feature/terrain type is present, eg for mountains we can check for both a range and an isolated peak

Code:
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (GetCount(allPlots, PlotTypes.PLOT_MOUNTAIN) >= 3) then
    sNameKey = "RANGE"
  elseif (GetCount(ring1Plots, PlotTypes.PLOT_MOUNTAIN) == 1) then
    sNameKey = "PEAK"
  end

  return sNameKey
end)

and for being on a river

Code:
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (pPlot:IsRiver()) then
    sNameKey = "RIVER"
  end

  return sNameKey
end)

or on/near a marsh

Code:
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Features, GameInfoTypes.FEATURE_MARSH) >= 1 or GetCount(ring2Features, GameInfoTypes.FEATURE_MARSH) >= 2) then
    sNameKey = "MARSH"
  end

  return sNameKey
end)

These anonymous functions are placed into the namingFunctions table (as we're about to randomise them) and return either a key - RANGE, PEAK, RIVER, MARSH - or nil.

If we checked the terrain/features in order, we would always pick a mountain name over a river name over a marsh name, so we need to randomise the order we check for terrain/features. By putting all of the check functions into a table we can simply randomise the table (via the GetShuffledCopyOfTable() MapmakerUtilities helper function) and then call the functions in their new order.

We also need some general "catch all" functions - for plains, grasslands and "any situation not covered"

Code:
-- Plains
function PlainsNames(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Terrains, GameInfoTypes.TERRAIN_PLAINS) >= 3) then
    sNameKey = "PLAINS"
  end

  return sNameKey
end

-- Grasslands
function GrassNames(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Terrains, GameInfoTypes.TERRAIN_GRASS) >= 3) then
    sNameKey = "GRASS"
  end

  return sNameKey
end

-- Generic
function GenericNames(pPlot)
  return "GENERIC"
end

which we will add to the table of functions after it has been randomised.

Code:
local namingFunctions = {}

-- Add name determining functions to the namingFunctions table here

function SetClanName(pClan)
  local pPlayer = Players[pClan:GetOwner()]
  local pPlot = pClan:Plot()
  local sKeyPrefix = "TXT_KEY_MORINDIM_CLAN_"

  AnalysePlots(pPlot)

  -- Randomise the order of looking for specific features/terrains
  local nameFunctions = GetShuffledCopyOfTable(namingFunctions)
  -- Add the "catch all" functions to the end of the table
  table.insert(nameFunctions, PlainsNames)
  table.insert(nameFunctions, GrassNames)
  table.insert(nameFunctions, GenericNames)

  -- Call each function in turn ...
  for _, fnNaming in ipairs(nameFunctions) do
    sNameKey = fnNaming(pPlot)

    -- ... did we get a possible name type, if so ...
    if (sNameKey) then
      -- ... find all possible settlement names from the key ...
      local sQuery = "SELECT Tag FROM Language_en_US WHERE Tag LIKE '" .. sKeyPrefix .. sNameKey .. "%' ORDER BY RANDOM();"

      -- ... for each possible settlement name ...
      for row in DB.Query(sQuery) do
        local sNewClanName = Locale.ConvertTextKey(row.Tag)

          -- ... if the name is available, use it
        if (pPlayer:IsCityNameValid(sNewClanName)) then
          pClan:SetName(row.Tag)
          return
        end
      end
    end
  end

  -- Just keep the game assigned name
end

The database entries for the settlement names look like

Code:
  <Row Tag="TXT_KEY_MORINDIM_CLAN_RANGE_1">
    <Text>Jagged Peaks Clan</Text>
  </Row>
  <Row Tag="TXT_KEY_MORINDIM_CLAN_RANGE_2">
    <Text>Snowy Ranges Clan</Text>
  </Row>
  <Row Tag="TXT_KEY_MORINDIM_CLAN_RANGE_3">
    <Text>Hidden Pass Clan</Text>
  </Row>
  <Row Tag="TXT_KEY_MORINDIM_CLAN_PEAK_1">
    <Text>Grey Mountain Clan</Text>
  </Row>
  <Row Tag="TXT_KEY_MORINDIM_CLAN_PEAK_2">
    <Text>Tooth Peak Clan</Text>
  </Row>

and we can add more simply by incrementing the final number, eg

Code:
  <Row Tag="TXT_KEY_MORINDIM_CLAN_PEAK_3">
    <Text>Spirit Top Clan</Text>
  </Row>

Note: pPlayer:IsCityNameValid(sNewName) is a Lua API extension in my DLL, it's effects can be duplicated in Lua by looping all the player's cities (for pCity in pPlayer:Cities() do ... end) and checking their name against sNewName (if (pCity:GetName() == sNewName) then return false end)

So why bother with "GENERIC", why not just keep any pre-assigned name from the DLL? We almost certainly need more than four settlement names for the "any other situation" cases, but if we put more than four plus the capital into the <Civilization_CityNames> table there is a chance that the Huns will "borrow" them (they only take from the sixth name onwards - hard-coded in the DLL) - and a Hunnic city called "Red Fox Clan" is probably immersion breaking!

As a working example, the complete Lua code and XML entries for the Morindim Clans follows
Spoiler :

Code:
--
-- Pick the name of the clan based on the surrounding terrain/features
--

include("MapmakerUtilities")
include("PlotIterators")
include("MorindimUtils")

local allPlots = {}
local ring1Plots = {}
local ring2Plots = {}

local allTerrains = {}
local ring1Terrains = {}
local ring2Terrains = {}

local allFeatures = {}
local ring1Features = {}
local ring2Features = {}

function GetCount(array, index)
  return array[index] or 0
end

function IncCount(singleArray, combinedArray, index)
    singleArray[index] = (singleArray[index] or 0) + 1
    combinedArray[index] = (combinedArray[index] or 0) + 1
end

local namingFunctions = {}

-- River
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (pPlot:IsRiver()) then
    sNameKey = "RIVER"
  end

  return sNameKey
end)

-- Lakes
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  for direction = 0, DirectionTypes.NUM_DIRECTION_TYPES - 1, 1 do
    local pAdjacentPlot = Map.PlotDirection(pPlot:GetX(), pPlot:GetY(), direction)

    if (pAdjacentPlot and pAdjacentPlot:IsLake()) then
      return "LAKE"
    end
  end

  return sNameKey
end)

-- Coast
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  for direction = 0, DirectionTypes.NUM_DIRECTION_TYPES - 1, 1 do
    local pAdjacentPlot = Map.PlotDirection(pPlot:GetX(), pPlot:GetY(), direction)

    if (pAdjacentPlot and pAdjacentPlot:IsWater() and not pAdjacentPlot:IsLake()) then
      return "COAST"
    end
  end

  return sNameKey
end)

-- Mountains
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (GetCount(allPlots, PlotTypes.PLOT_MOUNTAIN) >= 3) then
    sNameKey = "RANGE"
  elseif (GetCount(ring1Plots, PlotTypes.PLOT_MOUNTAIN) == 1) then
    sNameKey = "PEAK"
  end

  return sNameKey
end)

-- Hills
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Plots, PlotTypes.PLOT_HILLS) > 0) then
    if (GetCount(ring1Plots, PlotTypes.PLOT_HILLS) >= 3 or GetCount(ring2Plots, PlotTypes.PLOT_HILLS) >= 5) then
      sNameKey = "HILLS"
    end
  end

  return sNameKey
end)

-- Marsh
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Features, GameInfoTypes.FEATURE_MARSH) >= 1 or GetCount(ring2Features, GameInfoTypes.FEATURE_MARSH) >= 2) then
    sNameKey = "MARSH"
  end

  return sNameKey
end)

-- Tundra
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  -- Out of six ring1 plots need two or more, or from all 18 plots, need 6 or more
  if (GetCount(ring1Terrains, GameInfoTypes.TERRAIN_TUNDRA) >= 2 or GetCount(allTerrains, GameInfoTypes.TERRAIN_TUNDRA) >= 6) then
    sNameKey = "TUNDRA"
  end

  return sNameKey
end)

-- Snow/Ice
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  -- Out of six ring1 plots need two or more, or from all 18 plots, need 6 or more
  if ((GetCount(ring1Terrains, GameInfoTypes.TERRAIN_SNOW) + GetCount(ring1Features, GameInfoTypes.FEATURE_ICE)) >= 2
   or (GetCount(allTerrains, GameInfoTypes.TERRAIN_SNOW) + GetCount(allFeatures, GameInfoTypes.FEATURE_ICE)) >= 6) then
    sNameKey = "SNOW"
  end

  return sNameKey
end)

-- Forest
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Features, GameInfoTypes.FEATURE_FOREST) >= 2) then
    sNameKey = "FOREST"
  end

  return sNameKey
end)

-- Jungle
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Features, GameInfoTypes.FEATURE_JUNGLE) >= 3) then
    sNameKey = "JUNGLE"
  end

  return sNameKey
end)

-- Desert
table.insert(namingFunctions, function(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Terrains, GameInfoTypes.TERRAIN_DESERT) >= 3) then
    sNameKey = "DESERT"
  end

  return sNameKey
end)

-- Plains
function PlainsNames(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Terrains, GameInfoTypes.TERRAIN_PLAINS) >= 3) then
    sNameKey = "PLAINS"
  end

  return sNameKey
end

-- Grasslands
function GrassNames(pPlot)
  local sNameKey = nil

  if (GetCount(ring1Terrains, GameInfoTypes.TERRAIN_GRASS) >= 3) then
    sNameKey = "GRASS"
  end

  return sNameKey
end

-- Generic
function GenericNames(pPlot)
  return "GENERIC"
end


function AnalysePlots(pPlot)
  allPlots = {}
  ring1Plots = {}
  ring2Plots = {}

  allTerrains = {}
  ring1Terrains = {}
  ring2Terrains = {}

  allFeatures = {}
  ring1Features = {}
  ring2Features = {}

  for pRingPlot in PlotRingIterator(pPlot, 1) do
    IncCount(ring1Plots, allPlots, pRingPlot:GetPlotType())
    IncCount(ring1Terrains, allTerrains, pRingPlot:GetTerrainType())
    IncCount(ring1Features, allFeatures, pRingPlot:GetFeatureType())
  end

  for pRingPlot in PlotRingIterator(pPlot, 2) do
    IncCount(ring2Plots, allPlots, pRingPlot:GetPlotType())
    IncCount(ring2Terrains, allTerrains, pRingPlot:GetTerrainType())
    IncCount(ring2Features, allFeatures, pRingPlot:GetFeatureType())
  end
end

function SetClanName(pClan)
  local pPlayer = Players[pClan:GetOwner()]
  local pPlot = pClan:Plot()
  local sKeyPrefix = "TXT_KEY_MORINDIM_CLAN_"

  -- Handle Natural Wonders as a special case
  for pAreaPlot in PlotAreaSpiralIterator(pPlot, 2) do
    if (pAreaPlot:IsNaturalWonder()) then
      local sNwNameKey = sKeyPrefix .. string.sub(GameInfo.Features[pAreaPlot:GetFeatureType()].Type, 9)

      if (Locale.HasTextKey(sNwNameKey)) then
        local sNewClanName = Locale.ConvertTextKey(sNwNameKey)

        -- If the clan name is available, use it
        if (pPlayer:IsCityNameValid(sNewClanName)) then
          pClan:SetName(sNwNameKey)
          return
        end
      end

      -- Only going to be one natural wonder in range
      break
    end
  end

  -- Base the clan name on the terrain/features of surrounding plots
  AnalysePlots(pPlot)

  local nameFunctions = GetShuffledCopyOfTable(namingFunctions)
  table.insert(nameFunctions, PlainsNames)
  table.insert(nameFunctions, GrassNames)
  table.insert(nameFunctions, GenericNames)

  for _, fnNaming in ipairs(nameFunctions) do
    sNameKey = fnNaming(pPlot)

    if (sNameKey) then
      -- Find all possible clan names from the key
      local sQuery = "SELECT Tag FROM Language_en_US WHERE Tag LIKE '" .. sKeyPrefix .. sNameKey .. "%' ORDER BY RANDOM();"

      for row in DB.Query(sQuery) do
        local sNewClanName = Locale.ConvertTextKey(row.Tag)

          -- If the clan name is available, use it
        if (pPlayer:IsCityNameValid(sNewClanName)) then
          pClan:SetName(row.Tag)
          return
        end
      end
    end
  end

  -- Just keep the game assigned name
end

function OnSetPopulation(iPlotX, iPlotY, iOldPop, iNewPop)
  -- Has this city just been founded
  if (iOldPop == 0) then
    local pCity = Map.GetPlot(iPlotX, iPlotY):GetPlotCity()

    if (IsMorindimPlayer(pCity:GetOwner()) and (Players[pCity:GetOwner()]:GetCapitalCity() ~= nil)) then
      SetClanName(pCity)
    end
  end
end
GameEvents.SetPopulation.Add(OnSetPopulation)

Code:
<GameData>
    <Civilization_CityNames>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_GREAT_SPIRIT</CityName>
        </Row>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_1</CityName>
        </Row>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_2</CityName>
        </Row>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_3</CityName>
        </Row>
        <Row>
            <CivilizationType>CIVILIZATION_MORINDIM</CivilizationType>
            <CityName>TXT_KEY_MORINDIM_CLAN_4</CityName>
        </Row>
        <!-- Do NOT add any more clan names here, or the Huns will "borrow" them!  Instead add to the generic list below. -->
    </Civilization_CityNames>

    <Language_en_US>
        <!-- Spirit (special) clans -->
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GREAT_SPIRIT">
            <Text>Great Spirit Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_EARTH">
            <Text>Earth Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_SKY">
            <Text>Sky Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_WATER">
            <Text>Water Clan</Text>
        </Row>

        <!-- Clans named after local Natural Wonders -->
        <Row Tag="TXT_KEY_MORINDIM_CLAN_VOLCANO">
            <Text>Fire Mountain Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_ULURU">
            <Text>Uluru Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_CRATER">
            <Text>Crater Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_MESA">
            <Text>Flat Peak Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_REEF">
            <Text>White Water Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GEYSER">
            <Text>Smoking Water Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_POTOSI">
            <Text>Silver Mountain Clan</Text>
        </Row>

        <!-- Clans named after terrain/features -->
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_1">
            <Text>Salmon River Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_2">
            <Text>Foaming Water Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_3">
            <Text>Thundering Water Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_4">
            <Text>Yellow River Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_5">
            <Text>Forked River Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_6">
            <Text>Grey River Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_7">
            <Text>Beaver Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_8">
            <Text>Wild Rapids Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_9">
            <Text>Snake River Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_10">
            <Text>Water Mist Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RIVER_11">
            <Text>Red Gorge Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RANGE_1">
            <Text>Jagged Peaks Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RANGE_2">
            <Text>Snowy Ranges Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_RANGE_3">
            <Text>Hidden Pass Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_PEAK_1">
            <Text>Grey Mountain Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_PEAK_2">
            <Text>Tooth Peak Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_PEAK_3">
            <Text>Spirit Top Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_HILLS_1">
            <Text>Barren Hills Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_HILLS_2">
            <Text>Stone Hills Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_HILLS_3">
            <Text>Brown Goat Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_HILLS_4">
            <Text>Gold Hills Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_HILLS_5">
            <Text>Broken Pass Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_HILLS_6">
            <Text>Blue Cliffs Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_LAKE_1">
            <Text>Bear Lake Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_LAKE_2">
            <Text>Still Lake Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_LAKE_3">
            <Text>Trout Lake Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_LAKE_4">
            <Text>Black Lake Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_COAST_1">
            <Text>Endless Lake Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_COAST_2">
            <Text>Tall Dunes Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_COAST_3">
            <Text>Blue Kelp Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_COAST_4">
            <Text>Sea Otter Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_COAST_5">
            <Text>Red Crab Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_MARSH_1">
            <Text>Black Swamp Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_MARSH_2">
            <Text>Great Marsh Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_MARSH_3">
            <Text>Misty Marsh Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_MARSH_4">
            <Text>Caymen Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_MARSH_5">
            <Text>Rushes Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_FOREST_1">
            <Text>Tall Pines Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_FOREST_2">
            <Text>Dark Forest Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_FOREST_3">
            <Text>Tawny Owl Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_FOREST_4">
            <Text>Wolverine Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_FOREST_5">
            <Text>Mighty Redwood Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_FOREST_6">
            <Text>Copse Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_FOREST_7">
            <Text>Lone Tree Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_JUNGLE_1">
            <Text>Creeper Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_JUNGLE_2">
            <Text>Twisting Vine Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_JUNGLE_3">
            <Text>Panther Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_DESERT_1">
            <Text>Sidewinder Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_DESERT_2">
            <Text>Scorpion Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_TUNDRA_1">
            <Text>Moose Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_TUNDRA_2">
            <Text>North Slope Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_TUNDRA_3">
            <Text>Snow Fox Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_SNOW_1">
            <Text>Aurora Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_SNOW_2">
            <Text>Walrus Clan</Text>
        </Row>

        <!-- Plains/Grasslands clan names -->
        <Row Tag="TXT_KEY_MORINDIM_CLAN_PLAINS_1">
            <Text>Red Deer Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_PLAINS_2">
            <Text>Jumping Spider Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_PLAINS_3">
            <Text>Autumn Geese Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_PLAINS_4">
            <Text>Red Fox Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GRASS_1">
            <Text>Eagle Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GRASS_2">
            <Text>Wild Fire Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GRASS_3">
            <Text>Summer Swallow Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GRASS_4">
            <Text>Golden Grass Clan</Text>
        </Row>

        <!-- Generic clans -->
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GENERIC_1">
            <Text>Kestrel Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GENERIC_2">
            <Text>Night Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GENERIC_3">
            <Text>Elk Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GENERIC_4">
            <Text>Wolf Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GENERIC_5">
            <Text>Weasel Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GENERIC_6">
            <Text>Bison Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GENERIC_7">
            <Text>Whispering Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_GENERIC_8">
            <Text>Sabre Tooth Clan</Text>
        </Row>

        <!-- Random clans, very unlikely to ever appear! -->
        <Row Tag="TXT_KEY_MORINDIM_CLAN_1">
            <Text>Musk Ox Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_2">
            <Text>Moon Walkers Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_3">
            <Text>Cloud Clan</Text>
        </Row>
        <Row Tag="TXT_KEY_MORINDIM_CLAN_4">
            <Text>Bear Clan</Text>
        </Row>

        <!-- The clanless lands (used when a Magician appears not in a clan) -->
        <Row Tag="TXT_KEY_MORINDIM_BAD_LANDS">
            <Text>Bad Lands</Text>
        </Row>
    </Language_en_US>
</GameData>

And the SQL that randomises the 4 clan names in the Civilization_CityNames table - just for good measure!
Code:
-- Create a temp city name table keeping all the primary clan name
CREATE TABLE Civilization_CityNames_Morindim AS
SELECT * FROM Civilization_CityNames
  WHERE CityName='TXT_KEY_MORINDIM_CLAN_GREAT_SPIRIT'
  ORDER BY rowid DESC LIMIT 1;

-- Copy the remaining cities to the temp table in a random order  
INSERT INTO Civilization_CityNames_Morindim
SELECT * FROM Civilization_CityNames
  WHERE CivilizationType='CIVILIZATION_MORINDIM' AND CityName<>'TXT_KEY_MORINDIM_CLAN_GREAT_SPIRIT'
  ORDER BY RANDOM();

-- Copy everything back from the temp table, keeping the same order, and then tidy up after ourselves
DELETE FROM Civilization_CityNames WHERE CivilizationType='CIVILIZATION_MORINDIM';
INSERT INTO Civilization_CityNames SELECT * FROM Civilization_CityNames_Morindim ORDER BY rowid ASC;
DROP TABLE Civilization_CityNames_Morindim;
 
Is there any reason behind using SetPopulation event instead PlayerCityFounded?

I would even consider something like this for Sioux if I weren't so sentimental. Sweety Sugar. :crazyeye:
 
PlayerCityFounded() fires AFTER the log/notification messages so those will contain the default city name, not the location specific one
 
Sooo, I started wondering if it can be helpful on CityCapture.

We might hope that there is a matching event when the capture has been determined, but ownership not yet changed and buildings not yet destroyed, but have no information on this as yet.
Here it is, confirmed buildings, culture, old population, current production (I would bet that everything is available just like there is no capture):
Code:
function OnSetPopulation(iPlotX, iPlotY, iOldPop, iNewPop)
	print("MyLittleTesting", iPlotX, iPlotY, iOldPop, iNewPop)
	if iNewPop == 0 then
		local pCity = Map.GetPlot(iPlotX, iPlotY):GetPlotCity()
		CheckCity(pCity, iOldPop)
	end
end
GameEvents.SetPopulation.Add(OnSetPopulation)

function CheckCity(pCity, iOldPop)
	print(pCity:GetName(), iOldPop, pCity:GetNumBuildings(), pCity:GetJONSCulturePerTurn(), pCity:IsProductionBuilding(), pCity:IsProductionUnit())
end

Funny, I wanted this info almost one year ago.
Thanks for your wisdom. ;)

/Edit However, it may also trigger your code on liberation (since on CityCapture SetPopulation triggers 4 times. From CityPopulation to 0, then from 0 to NewCityPopulation, +2 times meaningless X to X. Maybe check city:GetGameTurnFounded()?
 
Back
Top Bottom