Extracting a Civ's unique building (class) in Lua

bootrecords

Chieftain
Joined
Aug 14, 2015
Messages
16
Location
Disordered States of Europe
For a mod that I am currently working on, on acquisition of a social policy I want to add a hidden building to cities that already have a museum-class building at that time. Importantly, I also want to add this hidden building to cities that belong to civs that potentially replaced BUILDING_MUSEUM with a unique building of BUILDINGCLASS_MUSEUM.

Accordingly, I have been wondering whether there is a simple way to extract the ID of the building from BUILDINGCLASS_MUSEUM that a player uses. Does anyone know of an according function that achieves this?

Alternatively, if no such function exists, can anyone think of an approach that is at least more convenient than crawling all the Civilization_BuildingClassOverrides entries and checking whether any entry is of BUILDINGCLASS_MUSEUM and, if there is one, if the according CivilizationType matches the current player's? Granted, the aforementioned crawling could probably be reduced to one iteration in the beginning that stores all pairs of CivilizationTypes and BuildingTypes matching the BUILDINGCLASS_MUSEUM in a static or global table, but if there was a way to go without, I'd sure like to know.
 
There are several ways of doing this, although I don't believe there exists any way of doing so directly.

One method, as you described, is to simply scan the database as your script loads for all valid Museum replacements and store them in a table for later use. If you will be scanning often, this may be the best way to go, as you would effectively cache the entries into a Lua table, which can be accessed much more quickly than a database query.

Alternatively, you can use the information from the building to scan the Buildings database and look for matches for BuildingClass Museum there.
 
JFD has used several times a function highly akin to this except for UUs. So I stole that function and changed the word "unit" to "building", and we'll just say JFD wrote this function :p.
Code:
function JFD_GetUniqueBuilding(player, buildingClass)
  local buildingType = nil
  local civType = GameInfo.Civilizations[player:GetCivilizationType()].Type

  for uniqueBuilding in GameInfo.Civilization_BuildingClassOverrides{CivilizationType = civType, BuildingClassType = buildingClass} do
    buildingType = uniqueBuilding.BuildingType
    break
  end

  if (buildingType == nil) then
    buildingType = GameInfo.BuildingClasses[buildingClass].DefaultBuilding
  end

  return buildingType
end
Or maybe he really did write that function and I just don't know where.
 
Yeah, at its core, that function simply scans the BuildingClassOverrides table for matches and returns them. JFD simply wrapped it up in its own little abstracted sub-function for easier calling on-demand.
 
JFD has used several times a function highly akin to this except for UUs. So I stole that function and changed the word "unit" to "building", and we'll just say JFD wrote this function :p.
Code:
function JFD_GetUniqueBuilding(player, buildingClass)
  local buildingType = nil
  local civType = GameInfo.Civilizations[player:GetCivilizationType()].Type

  for uniqueBuilding in GameInfo.Civilization_BuildingClassOverrides{CivilizationType = civType, BuildingClassType = buildingClass} do
    buildingType = uniqueBuilding.BuildingType
    break
  end

  if (buildingType == nil) then
    buildingType = GameInfo.BuildingClasses[buildingClass].DefaultBuilding
  end

  return buildingType
end
Or maybe he really did write that function and I just don't know where.

Hm, yeah, my thoughts went in a very similar direction... this is basically that database crawling I referred to. Although I have to say that the notation
GameInfo.Civilization_BuildingClassOverrides{CivilizationType = civType, BuildingClassType = buildingClass}
is pretty elegant, actually. Didn't realise that DB queries could relatively efficiently be formulated like this in Lua. Thanks for bringing that up!

EDIT: BTW, when a civ with a unique building replacement captures a city with the default (or another unique replacement) building of that class, that building, if not destroyed, is transformed into the capturing civ's unique, right? Or is it destroyed by default? Does this also happen when the captured city is puppeted?
 
I always revert to a bit of gifted wisdom when I have it available:
Code:
------------------------------------------------------------
---- Whoward69' BuildingClass in a city check
------------------------------------------------------------

function HasBuildingClass(pCity, sBuildingClass)
  for building in GameInfo.Buildings("BuildingClass='" .. sBuildingClass .. "'") do
    if (pCity:IsHasBuilding(building.ID)) then
      return true
    end
  end
  
  return false
end

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

edit --> and you would want to state sBuildingClass as a string: ie, "BUILDINGCLASS_MUSEUM"
 
EDIT: BTW, when a civ with a unique building replacement captures a city with the default (or another unique replacement) building of that class, that building, if not destroyed, is transformed into the capturing civ's unique, right? Or is it destroyed by default? Does this also happen when the captured city is puppeted?

If I recall correctly, unique buildings will always be destroyed when the City is captured -- even if you set it explicitly to have a 100% chance of capture. All other normal buildings I believe have a chance of surviving a City capture, at which point if it does survive and the conquering Civ has a unique version of that building, the game will swap the basic building for the unique building. I believe it makes no difference whether you puppet it or not, because the game has to update the City's buildings once it has transferred over to your control to await your decision on what to do with it.

With that said, both AW's posted JFD code and LeeS' posted whoward code will work fine for most scenarios. I personally use a variant of whoward's code because it suits my needs better. JFD's code works well for whatever situation he's coded it for, but while it will generally work as expected, his code will fail to catch some corner cases, of which my Civ would be one of.

My Civ doesn't do anything with Museums specifically, but it does have two unique Shrine replacement buildings. Unfortunately, the game doesn't like the idea of anyone having multiple uniques within the same building class, so it freaks out if I handle it normally. I ended up having to write a bunch of Lua to handle it the way I needed it to, and as a result, my Civ uses two unique buildings from the Shrine buildingclass, but only one of which is actually defined as a unique building. JFD's code would not be able to catch my second unique Shrine, and once my code swaps it in, his code will 'miss' it. I bring this up because it could potentially be applied to a Civ which wanted to have multiple Museums.

In my case, I used the variant of whoward's code so that I could simply check that I had one of the buildings within the Shrine buildingclass in my Cities.
 
I always revert to a bit of gifted wisdom when I have it available:
Code:
------------------------------------------------------------
---- Whoward69' BuildingClass in a city check
------------------------------------------------------------

function HasBuildingClass(pCity, sBuildingClass)
  for building in GameInfo.Buildings("BuildingClass='" .. sBuildingClass .. "'") do
    if (pCity:IsHasBuilding(building.ID)) then
      return true
    end
  end
  
  return false
end

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

edit --> and you would want to state sBuildingClass as a string: ie, "BUILDINGCLASS_MUSEUM"

Yes! So much this! THANK YOU, LeeS! :goodjob:


If I recall correctly, unique buildings will always be destroyed when the City is captured -- even if you set it explicitly to have a 100% chance of capture. All other normal buildings I believe have a chance of surviving a City capture, at which point if it does survive and the conquering Civ has a unique version of that building, the game will swap the basic building for the unique building. I believe it makes no difference whether you puppet it or not, because the game has to update the City's buildings once it has transferred over to your control to await your decision on what to do with it.

Good to know - that probably spares me the trouble of having to implement manual checks on most of these conditions. Thanks a lot for the help. :)
 
Top Bottom