Detecting city founding

Thalassicus

Bytes and Nibblers
Joined
Nov 9, 2005
Messages
11,057
Location
Texas
What's the simplest way to detect when a city is founded?

To detect new units and prevent repeats I gave them a "new unit" promotion... but I don't know of a comparable way to mark new cities.
 
I've always just used SerialEventCityCreated. I've never had a problem with it; it's not like SerialEventUnitCreated, which also triggers on embark/disembark actions and therefore requires a Rookie promotion to mark it, and unlike the SerialEventImprovementCreated function it does work for AI cities you can't see.
 
SerialEventCityCreated triggers for all cities each time a save is loaded. Since they use Lua mainly for graphics, I suspect those "created" events are when the graphical object is created, not the internal object. :think:

After thinking this over I figured out a straightforward solution. When the event runs, set a flag saying it's run. I don't know why I didn't think of this before...
PHP:
if not MapModData.VEM.CityFounded then
  MapModData.VEM.CityFounded = {}
  for playerID, player in pairs(Players) do
    MapModData.VEM.CityFounded[playerID] = {}
    for city in player:Cities() do
      MapModData.VEM.CityFounded[playerID][city:GetID()] = true
    end
  end
end

function OnNewCity(hexPos, playerID, cityID, cultureType, eraType, continent, populationSize, size, fowState)
  local player = Players[playerID]
    if not player or not player:IsAlive() then
    return
  end

  local city = Players[playerID]:GetCityByID(cityID)
  if (city == nil
      or MapModData.VEM.CityFounded[playerID][cityID]
      or city:GetGameTurnFounded() < Game.GetGameTurn()
    ) then
    return
  end
  
  MapModData.VEM.CityFounded[playerID][cityID] = true
  LuaEvents.CityFounded(hexPos, playerID, cityID, cultureType, eraType, continent, populationSize, size, fowState)
end
Replace "city" with "unit" and most of this also applies to units.
 
I just have this:

Code:
function OnEnterGame()   --Runs when Begin or Countinue Your Journey pressed
	print("Player entering game ...")
	RegisterOnSaveCallback()
	EA_GAME_INITIALIZED = true
end
Events.LoadScreenClose.Add(OnEnterGame)

then test EA_GAME_INITIALIZED in your SerialEventCityCreated function (and other event functions that try to run before the game actually starts).
 
Good idea, thanks! What's the role of RegisterOnSaveCallback?

So basically like this:

PHP:
function OnEnterGame()
  MapModData.VEM.Initialized = true
end
Events.LoadScreenClose.Add(OnEnterGame)

LuaEvents.CityFounded = LuaEvents.CityFounded or function(hexPos, playerID, cityID, cultureType, eraType, continent, populationSize, size, fowState) end
function OnNewCity(...)
  if MapModData.VEM.Initialized then
    LuaEvents.CityFounded(arg)
  end
end
Events.SerialEventCityCreated.Add(OnNewCity)

--------------------------------------------------

if not MapModData.VEM.UnitCreated then
  MapModData.VEM.UnitCreated = {}
  for playerID, player in pairs(Players) do
    MapModData.VEM.UnitCreated[playerID] = {}
    for unit in player:Units() do
      MapModData.VEM.UnitCreated[playerID][unit:GetID()] = true
    end
  end
end

LuaEvents.UnitSpawned = LuaEvents.UnitSpawned or function(playerID, unitID, hexVec, unitType, cultureType, civID, primaryColor, secondaryColor, unitFlagIndex, fogState, selected, military, notInvisible) end
function OnNewUnit(playerID, unitID, ...)
  if MapModData.VEM.Initialized then
    local unit = Players[playerID]:GetUnitByID(unitID)
    if not MapModData.VEM.UnitCreated[playerID][unitID] then
      MapModData.VEM.UnitCreated[playerID][unitID] = true
      LuaEvents.UnitSpawned(playerID, unitID, arg)
    end
  end
end
Events.SerialEventUnitCreated.Add(OnNewUnit)

_

SerialEventUnitCreated runs both when the game starts and when a unit embarks/disembarks/upgrades, so I think that one still needs a table storing which ones are new. I'm not sure how else the unit version could be simplified...
 
Sorry, the RegisterOnSaveCallback() line is unrelated to the question at hand. Didn't notice as I copied/pasted.

That's how I do SerialEventCityCreate anyway. Except I always use a bunch of

if <something> then return end

lines at the top of my functions, rather than nesting deeper and deeper in if blocks. But that's just personal preference.
 
Back
Top Bottom