1. We have added the ability to collapse/expand forum categories and widgets on forum home.
    Dismiss Notice
  2. Photobucket has changed its policy concerning hotlinking images and now requires an account with a $399.00 annual fee to allow hotlink. More information is available at: this link.
    Dismiss Notice
  3. All Civ avatars are brought back and available for selection in the Avatar Gallery! There are 945 avatars total.
    Dismiss Notice
  4. To make the site more secure, we have installed SSL certificates and enabled HTTPS for both the main site and forums.
    Dismiss Notice
  5. Civ6 is released! Order now! (Amazon US | Amazon UK | Amazon CA | Amazon DE | Amazon FR)
    Dismiss Notice
  6. Dismiss Notice
  7. Forum account upgrades are available for ad-free browsing.
    Dismiss Notice

LeeS' Dummy Buildings Utilities

Discussion in 'Civ6 - Utilities, Code Snippets & Art Assets' started by LeeS, Apr 30, 2017.

  1. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    LeeS' Dummy Buildings Utilities

    Spoiler download :
    All the code for this utility is contained within the LeeS' Dummy Buildings Systems mod, which can be accessed and downloaded via dropbox here:
    LeeS' Dummy Buildings Systems (via Dropbox)

    1. The Utilities provided herein are in packaged into one mod, but it is not necessary for you to use any of the portions you do not want within your mod.
    2. You do not have to do anything to use one or more of the systems in the utility except:
      1. create a dependancy within your mod so that in order to use your mod a player needs to have downloaded and enabled this mod. See Adding the Dependancy to Your Mod
      2. use any desired game-tables added by this mod within the XML or SQl of your mod's files. See these descriptions of how to create the needed XML in your mod:
      3. add a <LoadOrder> designation somewhere between 1 and 150000 in the "action" that adds your XML/SQL files to the game's database. See Setting the Action <LoadOrder>
    3. Essentially, all you need to do is use any of the new game-tables within the code of your mod, and this utility-mod will implement the effects of your XML-commands via the lua files of the utility.
    4. You do not need to concern yourself with what happens if you only need to use one of the new XML-tables. Any that are not being used by your mod or some other mod will simply not activate themselves once a game is started or reloaded.
    5. So, you can use the part of the utility that hides dummy buildings without needing to use the other parts of the utility. In such cases your mod will contain all the code for what the game should do to add or remove such a dummy building to/from cities.
    Why Make the utility An Entirely Seperate Mod That A User Must Also Have Enabled?
    1. This cures a whole host of issues with regard to mod loading order, stability of mod-loading-order, and stability of file loading-order within a given mod
    2. This also ensures a simpler system for you the mod-maker to "hook up to" within your mod.
      • all you are doing is adding a dependancy within your mod
      • don't be freaked out by the length of the step-by-step instructions on what to do in modbuddy to add such a dependancy. It is actually far more work to show you which modbuddy menus must be used than it is to add the actual dependancy.
    3. It allows the system to be expanded to add new capabilities without in any way disturbing your mod
    4. It allows a far simpler method for updates and patches for any issues found than any other method. Everybody making use of this system is always working to the same "music sheet".
    Brief Description of Each of the Sub-Systems
    The utility provides implementations for the following:​
    1. A system to hide dummy buildings from the human player in the game's user interfaces.
      • This system merely requires that you add dummy buildings to your mod in the manner outlined. You don't need to edit or alter any code in the files of the utility.
      • Any Building which has the new column IsDummy set to "true" will be treated as a dummy building and will be hidden from the user (player) interfaces.
      • obviously if you are not using dummy buildings then there is no need to hide them from the human player, but in such a case you currently have no need of this utility.
    2. A system to add dummy buildings to a city based on whether the city has specified terrain, resources, feature, district, etc., pre-conditions met.
      • this part of the utility is based upon my older Buildings Require Local Resources Utility (Buildings Require Local Resources Utility)
      • this sytem is largely expanded, includes everything provided by the previous utility, and supercedes it entirely.
      • you can still use the older utility if you are currently using it, but you should adopt use of this expanded and more capable utility for any new mod.
      • this newer system does not in any way affect use of the older system. they can in fact be run together at the same time
    3. A system for implementing a city-by-city unit production modifier effect
    4. A system that allows specification that all buildings within a specific list must be present in a city in order to construct a wonder, national wonder, building, or unit. Firaxis only provides for a system where if any one building from a list is present, then another building can be constructed. This system will allow you to specify that a city must for example have both a Barracks and a Market in order for Wonder_X (or some other type of building) to be built in the city.
    More Details:​
    1. All of these sytems depend in one degree or another on dummy buildings.
    2. The dummy buildings system adds a column to the standard Firaxis <Buildings> table. This column is called IsDummy and is a boolean flag used by other parts of the systems to know whether a given building should be treated as a dummy building by the systems.
    3. The other systems add entirely new game-tables, and operate based on the data entered by you for your mod for these new game-tables.
    4. City Terrain Prerequisites: The system for city terrain-dependant effects provides for the following, among other effects:
      Spoiler utility capabilities :
      It will allow you to specify a city must have:
      1. a specific resource within its set of plots before a unit or building can be constructed in the city
      2. an improved copy of a specific resource within its set of plots before a unit or building can be constructed in the city
        • I have not yet found a reliable method to tell within a gameplay script whether an improvement is pillaged, so this part of the utility will be satisfied even if the plot has been pillaged. This is just one of the odd loopholes the the current implementation of Civ6 lua.
      3. a specific resource (improved or otherwise) within its set of plots as well as a specified building already constructed in the city before a unit or building can be constructed in the city
      4. all of a list of buildings existing within the city before a building (or wonder) can be constructed. This is not supported by the standard <BuildingPrereqs> table.
      5. a specific type of terrain the city is constructed on before a unit or building can be constructed in the city
      6. a specific type of terrain the city is constructed on or adjacent to before a unit or building can be constructed in the city
      7. a specific type of terrain must be present in a tile owned by the city and within its 3-tile working radius before a unit or building to be constructed in the city
      8. that a terrain must not be a lake (for the case of TERRAIN_COAST)
      9. the city center is adjacent to a mountain, or a lake, or a river in order for a unit or building to be constructed in the city. You will also be able to specify combinations of lake and river, but this part of the utility does not support complex combinations such as Mountain+River or River+Lake but not Mountain.
      10. a minimum number of mountain tiles within the plots the city owns in order for a unit or building to be constructed in the city
      11. the city is adjacent to a specific feature in order for a unit or building to be constructed in the city
      12. a specific type of feature must be present in a tile owned by the city and within its 3-tile working radius before a unit or building to be constructed in the city
      13. a minimum number of tiles with the feature within the plots the city owns in order for a unit or building to be constructed in the city
      14. in the case of features specification can be made whether the plot can have an improvement or not
      15. the city is adjacent to a specific terrain improvement in order for a unit or building to be constructed in the city
      16. a specific type of terrain improvement must be present in a tile owned by the city and within its 3-tile working radius in order for a unit or building to be constructed in the city
      17. in the case of terrain improvements specification can be made whether the plot can have a feature (such as a Floodplain on a tile with a Farm) and the number of specified terrain improvements that the city must have can be specified.
      18. that a specified type of city district owned by the city meet a specified condition in order for a unit or building to be constructed in the city:
        1. the district must be placed adjacent to a mountain
        2. the district must be placed adjacent to a river
        3. the district must have a minimum number of adjacent mountains
        4. the district must be placed adjacent to another type of district
        5. the district must be placed adjacent to a specific type of resource
        6. the district must be placed adjacent to a specific type of feature
        7. the district must be the specific type of district and cannot be a unique replacement type of district (unique replacements are otherwise auto-included)
        8. the district must be placed adjacent to a hill
        9. the district must be placed on or adjacent to a hill
        10. the district must be placed adjacent to a Natural Wonder
        11. the district must be placed adjacent to a World Wonder
      19. for districts, you can also specify that the city itself must have specific number of mountain tiles that it owns
      • A dummy building that you specify will be added to the city when a condition you specify is met
      • You must use this dummy building only as an unlocker for constructing a "real" building/wonder in a city, or as an unlocker for constructing a unit.
      • You should not give this dummy building direct effects such as a modifier or a <Building_YieldChanges> effect.
      • One dummy building can be used to unlock multiple "real" buildings or units, but one "real" bulding can only ever have one dummy building as its prerequisite in table <BuildingPrereqs>
      • Having more than one dummy building (or other type of building) as a unit's prerequisite in <Unit_BuildingPrereqs> may or may not have undesirable effects. I have not tested for this instance.
        • The dummy building is always shown as the PrereqBuilding in table <BuildingPrereqs>
        • The "real" building is always shown as the Building in table <BuildingPrereqs>
        • The dummy building is always shown as the PrereqBuilding in table <Unit_BuildingPrereqs>
          • note that attempting to use column NumSupported in table <Unit_BuildingPrereqs> for any unit other than the Archaeologist has bizarre results. these are not caused by this mod: they are caused by Firaxis' implementation of the table.
      • The system is built as an "ORS" system. This means if you give multiple resource requirements, the code only requires any one of these resources to be present within a city's set of map-tiles in order for the dummy building to be added to the city.
      • dummy buildings are always added to the city center district. the code is written to require and expect this. a building does not have to be located within the same district to act as a prerequisite for another building.
    5. Individualized City Unit Production Modifier Buildings: The system for City-Specific Unit-Production Modifiers is a system wherein if a city has a specified building:
      1. Production of specified units is increased (or decreased) by a percentage.
      2. The Units to be affected can be specified as:
        1. individual specific units
        2. individual specific units and any unique replacement units for them
        3. units of a given domain-type
        4. units of a given formation-type
        5. units of a given promotion-class
      3. The building that gives the affect can be a specific building, or all unique replacements for that type of building can be included.
    6. PreRequisite Buildings ANDS:
      1. Provides a tool that requires a city have all the "real" buildings within a list before a second "real" building is unlocked within that city.
      2. The tool automatically adds and accounts for all unique replacements and the "standard" building from within a "group" of buildings regardless of whether a unique is stated as a prerequisite, or the standard building is so stated.
      3. When a city has all the requisite buildings from within a list (or their unique replacement versions), then a specified dummy building is added to the city, and this acts as the prerequisite the game sees for the building we really want to have a "must have all these buildings" requirement.

    Utility Sub-Systems Menu
    (clicking on the topic link will take you directly to the instructions for that part of the utility)​
    1. Jump to the Utility Sub-System: Creating and Hiding Dummy Buildings
    2. Jump to the Utility Sub-System: City-Terrain Building Prereqs (terrains, resources, improvments, terrain-features, districts adjacencies, etc.)
    3. Jump to the Utility Sub-System: Individualized City Unit Production Modifier Buildings
    4. Jump to the Utility Sub-System: PreRequisite Buildings ANDS System
    5. Jump to the Utility Sub-System: Pre-Packaged Misc Modifier Code
    6. Jump to the Utility Sub-System: Miscellaneous Snippets of Lua Code
      • when looking through the lua code of the mod's files for useful snippets of code, you should refer here first and use the versions presented here in preference to any snippets of code from the mods files for any snippetes or functions that look useful.
    7. Jump to the Utility Sub-System: Topic6 (just a placeholder at the moment)
    8. Jump to the Utility Sub-System: Topic7 (just a placeholder at the moment)
    9. ModBuddy Instructions for Setting Up Your mod to use one or more of the systems:
      • Adding the Dependancy to Your Mod
        • This sets up the requirement within your mod that the user needs this utility mod enabled in their list of mods
      • Setting the Action <LoadOrder>
        • This controls the order in which the game adds mod files. You need this to ensure that your mod's files load into the game after the utility sets up the needed tables and before the final "clean-up" actions the utility makes for all buildings defined into the game database as dummy buildings.
      • Adding a File-Loading Priority to Your Mod's Files
        • This controls the order in which files within a single mod "action" load into the game.
        • This really only applies to actions that are "UpdateDatabase" type.
        • File Priority has no effect on file-loading order for files not within the same "action".

    FAQ
    Spoiler :
    1. [Q]:Multiplayer Compatibility ?
      [A]: I have no idea if or how well this mod and its systems will run in Multiplayer.
    2. [Q]: Mod Compatibility?
      [A]: UI mods:
      • The mod will at the moment be incompatible to almost all if not all the mods that provide a custom UI, since part of what this mod does is re-write several of the UI files to hide the dummy builings added by this mod from human-view.
      • The changes to the UI files made by this mod should be relatively easy for inclusion in other mods that re-write the same files, but whether the makers of such mods are willing to provide compatibility on their end or whether I will have to try to provide compatibility "fixer" files for each such mod is a question I cannot answer yet.
      [A]: Other types of mods:
      • there are some issues still existing in the game's method for reloading mods when a saved game is loaded that might cause issues between this mod and some other mod. I am not sure the one bug has been fixed by Firaxis where mods would load in one order when a game was started but would load in another order when a saved game was reloaded. I am hoping ( and testing seems to indicate) these issues are resolved by making the utility a required mod for other mods via the dependancy.
    3. [Q]: DLC Requirements?
      [A]: The utility does not depend on you having any DLC. Currently I do not have anything except the Aztec civ "DLC", so I am building the mod to be free of such dependancies.
    4. [Q]: What happens if some other mod over-writes the changes you are making to the UI files, and this utility's changes are no longer applied to those UI pop-up panels?
      [A]: Then you will be able to see the various dummy buildngs other mods add to the game, both in the civilopedia and in the various city-views and mouse tool-tips. There is no other actual effect than a bit more clutter in the mouse tips, the civilopedia, etc.



    Future Expansion of the Systems
    1. Any future expansion to add more capability will be performed as stand-alone additional "systems", but will be rolled into the utility mod. New exapansions of the system will not therefore affect your mod in any way. This approach must be used in order to not create compatibility issues with existing mods that are using the current systems
    2. Updates to the current systems will only be made to cure any bugs or incorrect performances discovered within the existing systems.
    Credits
    credit where credit is due. I just have to work up who to credit at the moment​
    1. q/ @notque for help with the AI favored items code.
    2. @Magil (I think) for advice on using a DistrictModifier to create a city production effect when a city has a particular building.
    A Few Notes on Code Examples
    1. I've generally used code examples taken directly from the Buildings Are Fun mod, but the way the files are structured within the mod are not always reflected by the way I show the examples in this thread.
    2. What makes sense in my head for organizing the xml files within a mod is not the same as what makes sense for demonstrating the same code as an example of how to code something.
    Posting Comments Re: the Modifier System provided by Firaxis
    1. The Dynamic Modifiers and the Game Effects as created for Civ6 can do a lot. They cannot however do much if any of this.
    2. This is well-hackneyed territory already explored in other civ6 modding threads.
    3. Please refrain from adding comments to the thread about how a modifier can do all this. They are neither productive to the intent of this utility, nor helpful to other modders who are interested in the effects this utility and its systems can provide.

    Moderator Action: Moved to Civ 6 - Utilities Forum.
    --Ozbenno
     
    Last edited: Aug 23, 2017
  2. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    • ModBuddy Users:
      1. Open ModBuddy and your mod's project.
      2. Change to the Mod's "Properties" view if not already there.
        • Right-Click on your mod's Name, and then select "Properties" from the drop-down menu
        Spoiler Change to Properties :
      3. ModBuddy should now look like this (note that this is an example mod, and that I have changed from the standard dark color-scheme of ModBuddy)
        Spoiler Open Mod With Properties Selected :
      4. Click "Associations":
        Spoiler Associations Tab :
      5. In the top section called "Dependancies", click on the "Add Mod...." button:
        Spoiler Dependancies Add Mod button :
      6. Clicking the "Add Mod...." button brings up this Pop-up Menu:
        Spoiler Pop Up Menu :
      7. Type or Paste in the name of the mod.
        • You want the name of the mod to be as close as possible to that used by the original mod-maker so that it is easier for you to understand what mod is being set-up as a dependancy.
        • Aside from this, the name of the mod is not important because the game does not actually use the name of the mod.
        • For this system, always copy/paste LeeS' Dummy Buildings Systems into this field.
        Spoiler Mod Title :
      8. Copy/Paste the ID of the mod.
        • This is the actual part that is important. Civ6 Identifies mods by their ID.
        • For this system, always copy/paste 88ccd553-d804-48ff-a83c-55a43ab2b323 into this field.
        Spoiler Mod ID :
      9. Click "OK" in the Pop-Up Menu to accept the dependancy.
        Spoiler OK :
      10. After clicking "OK" in the pop-up, the Assocciations page of the mod should look like this:
        Spoiler :
      11. Once the dependancy is created you cannot directly edit it. All you can do is delete it via the "Remove" button and start over if you have made a mistake.
      12. The resulting output in the modinfo file once the mod is built:
        Spoiler :
        Code:
        <?xml version="1.0" encoding="utf-8"?>
        <Mod id="0f20dda6-5a1c-4a18-b092-3163d473b6ea" version="1">
          <Properties>
            <Name>TestImports</Name>
            <Description>Test Lua Replacement files without IsDummy column</Description>
            <Teaser>Test Lua Replacement files without IsDummy column</Teaser>
            <Authors>LeeS</Authors>
          </Properties>
          <Dependencies>
            <Mod id="88ccd553-d804-48ff-a83c-55a43ab2b323" title="LeeS' Dummy Buildings Systems" />
          </Dependencies>
          <InGameActions>
            ...snipped
          </InGameActions>
          <Files>
            ...snipped
          </Files>
        </Mod>
    • Others:
      • If you do not use ModBuddy to create your mods for you, then all you need to do is add these lines exactly as shown to your modinfo file directly under the "<Properties>" section:
        Code:
          <Dependencies>
            <Mod id="88ccd553-d804-48ff-a83c-55a43ab2b323" title="LeeS' Dummy Buildings Systems" />
          </Dependencies>
    Return to the Utility "Main" Menu

    1. An Action's <LoadOrder> setting applies across all mods and across all actions within all currently-enabled mods.
    2. Lower-Numbered <LoadOrder> settings cause the files within the action to be loaded earlier than files within actions that have a higher-numbered <LoadOrder> setting
    3. Plus and minus values (+/-) do apply but you only need to specify negative (minus (-)) values because positive (plus (+)) values are assumed.
    4. From what I have seen so far actions with the same <LoadOrder> settings load before any other action(s) with a higher setting, but rules of enable-order and Mod Id# begin to apply to determine which action will be loaded first from a group of actions with the same <LoadOrder> setting when such multiple actions exist within the list of all enabled mods.
    5. All that is important for purposes of hooking your mod into this utility is that your action's <LoadOrder> setting is a positive value less than "150000"
    • ModBuddy Users:
      1. Open ModBuddy and your mod's project.
      2. Change to the Mod's "Properties" view if not already there.
        • Right-Click on your mod's Name, and then select "Properties" from the drop-down menu
        Spoiler Change to Properties :
      3. ModBuddy should now look like this (note that this is an example mod, and that I have changed from the standard dark color-scheme of ModBuddy)
        Spoiler Open Mod With Properties Selected :
      4. Select the In-Game Tab
        Spoiler Select In-Game Tab :
      5. Look for the "Add Action" button
        Spoiler Add Action Button :
      6. New Action Added
        • ModBuddy should now look something close to the image shown at this point
        • You may or may not have additional actions already added to your mod
        Spoiler New Action Added :
      7. Click on the New Action
        Spoiler Click New Action :
      8. Changing the Action Type from UpdateDatabase
        • This will not be necessary for hooking your mod up to this utility
        • It is shown for general reference purposes
        Spoiler Changing Action Type :
      9. Click the "Custom Properties" arrow for the action
        • This alters the action's menu and brings up this view
        Spoiler Click Custom Properties :
      10. Click on the Custom Properties "Add" button
        Spoiler Custom Properties Add Button :
      11. Clicking on the Custom Properties "Add" button bring up this pop-up menu
        • You can add various property "Names" and "Values"
        • For the purposes of this utility we want to use LoadOrder and 100 (see the next image)
        Spoiler Add Property Pop-Up :
      12. Type in the text of the settings needed.
        • There are no drop-downs for either of these fields. You have to know what you want to specify.
        • For the purposes of this utility, an example of 100 for the LoadOrder will be used. (This is in fact the value I have used in my own mod that makes use of this Modding Utility).
        Spoiler LoadOrder of 100 :
      13. Click the OK button on the pop-up
        Spoiler Click OK :
      14. After you click OK the pop-up will close and you will see this in your action:
        Spoiler OK Clicked :
      15. Click the Custom Properties arrow again to close the Action's Custom Properties view and return to where you can add new files to the action.
        Spoiler Click Action Custom Properties Again :
      16. The resulting output in the modinfo file for the action once the mod is built:
        Spoiler :
        Code:
          <InGameActions>
            <UpdateDatabase id="Example_UpdateInGameDatabase">
              <Properties>
                <LoadOrder>100</LoadOrder>
              </Properties>
              ....snipped lines.....usually your filenames are here
            </UpdateDatabase>
          </InGameActions>
    • Others:
      • If you do not use ModBuddy to create your mods for you, then all you need to do is add these lines exactly as shown to your action:
        Code:
              <Properties>
                <LoadOrder>100</LoadOrder>
              </Properties>
    Return to the Utility "Main" Menu


    • ModBuddy Users:
      1. Open ModBuddy and your mod's project.
      2. Change to the Mod's "Properties" view if not already there.
        • Right-Click on your mod's Name, and then select "Properties" from the drop-down menu
        Spoiler Change to Properties :
      3. ModBuddy should now look like this (note that this is an example mod, and that I have changed from the standard dark color-scheme of ModBuddy)
        Spoiler Open Mod With Properties Selected :
      4. Select the In-Game Tab
        Spoiler Select In-Game Tab :
      5. Once you are in the "In-Game" tab you can select an existing action or create a new action
      6. Click on the Action (whether new or existing does not matter)
        Spoiler Click New Action :
      7. Once at the Action, you can add new files for the action to load.
        • Setting of the File Priority is done in the same pop-up as selecting the file to be added to the action.
        • Higher numbers for Priority load before files with lower numbers but only so long as both files are within the same action.
        • You cannot edit an existing file "spec" so you need to figure out all files that are to be added to the same action and the priority each file needs before you begin adding the files to the action.
          • I agree this is a bit PITA but I can only show you how to do it, I cannot change the way it works.
        • For this example I have given the file a priority of "2", meaning it will be the first loaded of the two files loaded I want for the action
        Spoiler Priority of 2 Set :
      8. After I click "OK" in the pop-up, my view of the action changes to this:
        • note thsat I cannot now see the assigned priority anywhere
        Spoiler OK clicked :
      9. Here I have added the second of the two files I want the action to load, and I have assigned a lower priority number than the previous file.
        Spoiler Priority of 1 Set :
      10. The resulting output in the modinfo file for the action once the mod is built:
        Spoiler :
        Code:
          <InGameActions>
            <UpdateDatabase id="Example_UpdateInGameDatabase">
              <File priority="2">XML/GameData2.xml</File>
              <File priority="1">XML/GameData1.xml</File>
            </UpdateDatabase>
          </InGameActions>
    • Others:
      • If you do not use ModBuddy to create your mods for you, then all you need to do is add these lines exactly as shown to your modinfo file directly under the "<Properties>" section:
        Code:
          <InGameActions>
            <UpdateDatabase id="Example_UpdateInGameDatabase">
              <File priority="2">XML/GameData2.xml</File>
              <File priority="1">XML/GameData1.xml</File>
            </UpdateDatabase>
          </InGameActions>
    Return to the Utility "Main" Menu
     
    Last edited: May 26, 2017
  3. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA

    General Description
    1. This Creating and Hiding Dummy Buildings system can be used whether or not you as a mod-maker need or are interested in any of the other systems within this utility
    2. The system presents a slightly different method of defining a dummy building than has previously been advocated by me (or others, I think) in terms of prerequisites techs (etc.) for a dummy building
    3. The system adds a new column to the Buildings table that is used as a boolean flag for the remainder of the system (and for the other systems of the utility) to directly identify that a specific building is in fact a dummy building (IsDummy="true").
    4. A belts and suspenders approach is used to keep the AI (and the human) from selecting a dummy building as a construction project within a city.
    5. Dummy Buildings are given a PrereqTech of "TECH_NUCLEAR_FUSION". In and of itself this keeps the AI and the Human from even being able to try to construct a dummy building for the vast majority of any single game. Future Tech is not used in order to avoid any possible issues related to Future Tech being a "repeatable" research item.
    6. Dummy Buildings are given a Cost of "10000". This keeps the AI from being able to insta-build (or 1-turn build) a dummy building: this affords the other parts of the system an opportunity to detect an attempt to construct a dummy building, remove it from the AI (or human player's) city qeue, and thereby avoid a situation wherein an AI is uselessly spending time constructing a building that will likely be removed from the city next turn anyway.
    7. Dummy Buildings are not given a PurchaseYield designation
    8. As Fail-Safe measures, Dummy Buildings are given valid designations for Name and Description
    9. Dummy Buildings are always given a PrereqDistrict of "DISTRICT_CITY_CENTER"
    10. An lua file is included that keeps any building defined as IsDummy="true" from being added as a city's selected construction item.
    11. A further file is included that creates code in the game's database that tends to make the AI players not value dummy buildings as anything to construct within a city.
    12. The other files included as part of the system are all for the "hiding from human view" part of the system.

    Defining A Dummy Building
    This definition does not in any way instruct the game on how to use this dummy building. It is what we need to merely add the dummy to the game's database.

    1. The definition of a dummy building example is thus as:
      Code:
      <GameInfo>
      	<Types>
      		<Row Type="BUILDING_EXAMPLE_DUMMY"
      			Kind="KIND_BUILDING" />
      	</Types>
      	<Buildings>
      		<Row BuildingType="BUILDING_EXAMPLE_DUMMY"
      			Name="LOC_BUILDING_EXAMPLE_DUMMY_NAME"
      			Description="LOC_BUILDING_EXAMPLE_DUMMY_DESCRIPTION"
      			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000"
      			PrereqTech="TECH_NUCLEAR_FUSION" IsDummy="true" />
      	</Buildings>
      </GameInfo>
    2. To keep a dummy building from showing in the civilopedia, we add to this definition:
      Code:
      <GameInfo>
      	<Types>
      		<Row Type="BUILDING_EXAMPLE_DUMMY"
      			Kind="KIND_BUILDING" />
      	</Types>
      	<Buildings>
      		<Row BuildingType="BUILDING_EXAMPLE_DUMMY"
      			Name="LOC_BUILDING_EXAMPLE_DUMMY_NAME"
      			Description="LOC_BUILDING_EXAMPLE_DUMMY_DESCRIPTION"
      			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000"
      			PrereqTech="TECH_NUCLEAR_FUSION" IsDummy="true" />
      	</Buildings>
      	<CivilopediaPageExcludes>
      		<Row SectionId="BUILDINGS" PageId="BUILDING_EXAMPLE_DUMMY"/>
      	</CivilopediaPageExcludes>
      </GameInfo>
    3. It is also necessary to follow-through and assign an Icon in the IconDefinitions and to give a valid setting for "LOC_BUILDING_EXAMPLE_DUMMY_NAME" and "LOC_BUILDING_EXAMPLE_DUMMY_DESCRIPTION" in the localized text. We do this because we cannot control whether some other mod will wipe our changes to the various UI files, and so this acts to give a clue to the user what in the world this dummy is for and why it is showing up in-game.
      Spoiler :
      • Definition of the Dummy Building's Icon.
        Code:
        <GameData>
        	<IconDefinitions>
        		<Row Name="ICON_BUILDING_EXAMPLE_DUMMY" Atlas="ICON_ATLAS_BUILDINGS" Index="0"/>
        		<Row Name="ICON_BUILDING_EXAMPLE_DUMMY_FOW" Atlas="ICON_ATLAS_BUILDINGS_FOW" Index="0"/>
        	</IconDefinitions>
        </GameData>
      • Definition of the Dummy Building's In-Game Text:
        Code:
        <GameData>
        	<LocalizedText>
        		<Row Tag="LOC_BUILDING_EXAMPLE_DUMMY_NAME" Language="en_US">
        			<Text>Example Dummy</Text>
        		</Row>
        		<Row Tag="LOC_BUILDING_EXAMPLE_DUMMY_DESCRIPTION" Language="en_US">
        			<Text>This is an example dummy building. If there are no conflicts between mods, you will not usually see this.</Text>
        		</Row>
        	</LocalizedText>
        </GameData>
    Return to the Utility "Main" Menu


    Utility Sub-System: City-Terrain Building Prereqs
    (terrains, resources, improvments, terrain-features, districts adjacencies, etc.)​

    General Description
    You can skip this if all you want is to get to the meat of how to use this city-terrain-requirements method, but bear in mind that if you deviate from the notes made here you will probably see erratic performances from the code​
    1. In all the descriptions for this sub-system of the utility, the phrase real building refers to one or more buildings that a player (human or AI) actually sees in their city build qeues and that a player is intended to construct or purchase within their cities.
    2. This sub-system of the utility provides the ability to create terrain-related prerequisites as to whether a city can construct a given real building or unit. The terrain-releated prerequisites can be actual terrain is needed, or a terrain-feature (such as Flood Plains) must be present near the city, or a specific resource is required, or a specific terrain-improvement, etc.
    3. In all cases the code only concerns itself with plots that a given city "owns" in the sense that it was the city that originally acquired the map-plot for the city-owner.
    4. Plots that do not belong to the city-owner or that are not "owned" by the city are ignored and cannot satisfy the requirements you specify.
    5. With one exception which will be specifically noted to you in these instructions, all of game-tables added to the game by this sub-system act as logical "ORS" tables. This means that if you specify a city needs four resources in order for a specified dummy to be added to a city, what you are really telling the code is that any one of the four resources will do. This principle applies regardless of whether you are stating the city needs specific map resources, or specific map terrains, or whatever else: so long as any one condition you make is satisfied, the lua code will add the specified dummy building to the city.
    6. The system uses dummy buildngs that act as the one and only prerequisite structure for a unit or real building. The unit or real building may also have a civic or technology prerequisite.
    7. The system is constructed to expect that what is being implemented by the code is placement of a dummy building into a city where the dummy building has no other game-effect than to act as a prerequisite "unlocker" for a real building or for a unit.
    8. The system is coded under the assumption that while a single dummy building can act as the unlocker for multiple real buildings or units, each unit or real building will only have one dummy building as a prerequisite and that no other building prerequisites are used for the same real building or unit.
    9. Dummy buildngs should not be coded in a "string-of-dependancies" wherein one dummy building is attempting to act as a prerequisite to another dummy building.
    10. Dummy buildings are always added to the City Center District. This vastly simplifies the lua code needed, and also does not detrimentally affect the ability of the dummy building acting as a prerequisite to a building that is only constructable in for example an Encampment District.
    11. For tables <BuildingPrereqs> and <Unit_BuildingPrereqs> the game does not actually pay attention to which district the PrereqBuilding is placed within. The game only cares whether or not the city has the PrereqBuilding.



    New Game-Tables Used By the Terrains Sub-System
    • in all these tables you specify the dummy building to be added to a city as column DummyBuildingType
    • in the short descriptions of the tables, the phrase dummy building means whatever building you have specified in a given row for that table as DummyBuildingType
    • in the short descriptions of the tables, the phrase "real" building refers to one or more buildings that a player (human or AI) actually sees in their city build qeues and that a player is intended to construct or purchase within their cities.
    • all of these tables only control the conditions under which a dummy building is added to a city. you still need to set-up the dummy building as a prerequisite for the real building the player would construct or purchase in their cities.
    1. DummyUnlocker_CityLocalResources
    2. DummyUnlocker_CityImprovedLocalResources
    3. DummyUnlocker_CityRequiresBuildingPreReqORS
    4. DummyUnlocker_CityRequiresBuildingPreReqANDS
      • Allows you to specify that a city must also have all buildings within a given list of "real" buildings before a dummy building can be added to the city.
      • This is the only xml-table added to the game by this sub-system that acts as a logical "ANDS" table.
      • Every PrereqBuilding listed for a single dummy building must be present in the city in order for the dummy building to be added to the city.
      • Unique replacement buildings are automatically accounted for and treated the same as the standard building they replace. You should always state the standard building from the group rather than the unique replacement:
        • "BUILDING_BROADCAST_CENTER", "BUILDING_UNIVERSITY", "BUILDING_TEMPLE", and "BUILDING_FACTORY" are all good and will account for "BUILDING_FILM_STUDIO", "BUILDING_MADRASA", "BUILDING_STAVE_CHURCH", and "BUILDING_ELECTRONICS_FACTORY", as well as any additional replacement buildings added by your or some other mod.
        • "BUILDING_FILM_STUDIO", "BUILDING_MADRASA", "BUILDING_STAVE_CHURCH", and "BUILDING_ELECTRONICS_FACTORY" will cause the code to account for "BUILDING_BROADCAST_CENTER", "BUILDING_UNIVERSITY", "BUILDING_TEMPLE", and "BUILDING_FACTORY" but no other unique replacement building from within these "groups" would be accounted for. The reason is the logic required to handle this is far more complicated than necessary especially when just stating the standard building is simpler and can easily be programmed to account for all occurances within table <BuildingReplaces>.
      • Jump to Column Definitions and Usage Examples for DummyUnlocker_CityRequiresBuildingPreReqANDS
    5. DummyUnlocker_CityTerrainRequirements
      • Allows you to specify terrain-types that must be near the city in order for a dummy building to be placed in the city
      • the terrain specifications can be stated as the city must be placed on the given terrain, or must be on or adjacent to the given terrain, or that the city must have the given terrain present within its set of owned map-plots.
      • This table also provides ability to specify that the city must be adjacent to a mountain, lake, river, river or lake, or that the city must own a certain number of mountain tiles
      • Jump to Column Definitions and Usage Examples for DummyUnlocker_CityTerrainRequirements
    6. DummyUnlocker_CityFeatureRequirements
      • Allow specification that a given terrain-feature (such as a Flood Plains or an Oasis) must be owned by the city in order for a dummy building to placed within the city.
      • Allows specification that the terrain-feature must be adjacent to the city-center, or merely owned by the city in its set of map-plots.
      • Allows specification that the city must "own" a given number of map-plots with the specified feature.
      • Allows specification whether or not the feature can have a terrain improvement.
      • Jump to Column Definitions and Usage Examples for DummyUnlocker_CityFeatureRequirements
    7. DummyUnlocker_CityImprovementRequirements
      • Allow specification that a given terrain-improvement (such as a Farm) must be owned by the city in order for a dummy building to placed within the city.
      • Allows specification that the terrain-improvement must be adjacent to the city-center, or merely owned by the city in its set of map-plots.
      • Allows specification that the city must "own" a given number of map-plots with the specified improvement.
      • Allows specification whether or not the improvement can be on a plot with a terrain-feature (so you could disallow farms placed on Flood Plains, for example).
      • Jump to Column Definitions and Usage Examples for DummyUnlocker_CityImprovementRequirements
    8. DummyUnlocker_CityDistrictRequirements
      • This table is meant for Districts other than the city center district. Attempts to use the City-Center district for this table are completely ignored by the lua code.
      • All of the following should be interpretted as requiring that the city "own" the plots mentioned.
      • Allows you to specify terrain-features or terrain-resources that must be adjacent to the specified district in order for a dummy building to be placed in the city
      • Allows you to specify other district-types that must be adjacent to the specified district in order for a dummy building to be placed in the city
      • Allows you to specify that the specified district must be adjacent to a mountain, or a river, or a nautral wonder, or a world wonder in order for a dummy building to be placed in the city
      • Allows you to specify that the specified district must be adjacent to a minimum number of mountain tiles in order for a dummy building to be placed in the city
      • Allows you to specify that the city must "own" a minimum number of mountain tiles (regardless of where the mountains are placed in relation to the district) in order for a dummy building to be placed in the city
      • Allows you to specify that the district must be the exact type of district specified and not a unique replacement or the "standard" district in order for a dummy building to be placed in the city. This allows you to create an additional special buff to a civilization-unique district.
      • Allows you to specify that the specified district must be adjacent-to but not located on a hill tile in order for a dummy building to be placed in the city
      • Allows you to specify that the specified district must be adjacent-to or located on a hill tile in order for a dummy building to be placed in the city
      • Jump to Column Definitions and Usage Examples for DummyUnlocker_CityDistrictRequirements



    DummyUnlocker_CityLocalResources
    1. The definition of the new table is as this (sql version):
      Code:
      CREATE TABLE IF NOT EXISTS 
      	DummyUnlocker_CityLocalResources (
      	DummyBuildingType	text		REFERENCES Buildings(BuildingType)		default null,
      	ResourceType		text		REFERENCES Resources(ResourceType)		default null,
      	CustomModId		text);
    2. The columns thus require:
      Spoiler column requirements :
      • DummyBuildingType: This is the name of your dummy building, exactly as you entered it for column BuildingType in table Buildings.
      • ResourceType: This is the name of the desired resource exactly as it is shown for column ResourceType in table Resources. Do not under any circumstances state either of the "artifact" resources.
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing ResourceType designations.
      • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
    3. For this table, the specified resources do not have to be improved with an appropriate terrain-improvement. This table only requires that the city own a tile that has the specified resource.
    4. The player must also have the required technology that reveals the resource and makes the player able to use the resource.
    5. You should not use this table and table DummyUnlocker_CityImprovedLocalResources for the same dummy building.
    6. Example:
      • Assume I want to place a dummy building in a city if the city has either a Cow or a Horse resource, but I do not want to require that the plot with either of these resources is improved with a pasture.
      • Calling my Dummy Building "BUILDING_TANNERY_LRS_UNLOCKER", I then do as follows:
        Code:
        <GameInfo>
        	<DummyUnlocker_CityLocalResources>
        		<Row DummyBuildingType="BUILDING_TANNERY_LRS_UNLOCKER" ResourceType="RESOURCE_CATTLE" />
        		<Row DummyBuildingType="BUILDING_TANNERY_LRS_UNLOCKER" ResourceType="RESOURCE_HORSES" />
        	</DummyUnlocker_CityLocalResources>
        </GameInfo>
        Showing the rest of the code I would use to create a dummy building called "BUILDING_TANNERY_LRS_UNLOCKER", and set it up in this table, I would have:
        Spoiler :
        Code:
        <GameInfo>
        	<Types>
        		<Row Type="BUILDING_TANNERY_LRS_UNLOCKER" Kind="KIND_BUILDING" />
        	</Types>
        	<Buildings>
        		<Row BuildingType="BUILDING_TANNERY_LRS_UNLOCKER" Name="LOC_BUILDING_TANNERY_LRS_UNLOCKER_NAME"
        			Description="LOC_BUILDING_TANNERY_LRS_UNLOCKER_DESCRIPTION"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        	</Buildings>
        	<CivilopediaPageExcludes>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_TANNERY_LRS_UNLOCKER"/>
        	</CivilopediaPageExcludes>
        	<DummyUnlocker_CityLocalResources>
        		<Row DummyBuildingType="BUILDING_TANNERY_LRS_UNLOCKER" ResourceType="RESOURCE_CATTLE" />
        		<Row DummyBuildingType="BUILDING_TANNERY_LRS_UNLOCKER" ResourceType="RESOURCE_HORSES" />
        	</DummyUnlocker_CityLocalResources>
        </GameInfo>
      • This causes the lua code of the utility to place the dummy building "BUILDING_TANNERY_LRS_UNLOCKER" into the city when the proper conditions are met. As yet this does not affect anything else in the game.
    7. Hooking the Example Dummy Building to a "Real" Building:
      • To make this dummy building act as a prerequisite for a "BUILDING_TANNERY_LRS" I would need to create a valid definition for a building called "BUILDING_TANNERY_LRS", and then I would add the following to my code:
        Code:
        <GameInfo>
        	<BuildingPrereqs>
        		<Row Building="BUILDING_TANNERY_LRS" PrereqBuilding="BUILDING_TANNERY_LRS_UNLOCKER"/>
        	</BuildingPrereqs>
        </GameInfo>
      • This makes my dummy building act as the prerequisite to construction of the real building "BUILDING_TANNERY_LRS".
      • I could just as easily make this dummy a prerequisite to a Unit by stating as:
        Code:
        <GameInfo>
        	<Unit_BuildingPrereqs>
        		<Row Unit="UNIT_TANNERY_GUY" PrereqBuilding="BUILDING_TANNERY_LRS_UNLOCKER"/>
        	</Unit_BuildingPrereqs>
        </GameInfo>
    8. What effect the real building has or the unit has in-game is not really the concern of this utility, and for the sake of simplicity I will not add more to these instructions by diverging off into what a "Real" Building called a "Tannery" ought to do in-game once it is unlocked for construction.
      • both "BUILDING_TANNERY_LRS_UNLOCKER" and "BUILDING_TANNERY_LRS" are used in the LeeS' Buildings Are Fun mod so you can look in the files therein (LeeS_BuildingsAreFun\XML\RealBuildings/Resource_Dependant_Buildings.xml has the code for "BUILDING_TANNERY_LRS" and LeeS_BuildingsAreFun\XML\DummyBuildings/DummyResourceUnlockerBuildings.xml has the code for the "BUILDING_TANNERY_LRS_UNLOCKER" dummy building)
    Return to the list of New Game-Tables Used By the Terrains Sub-System
    Return to the Utility "Main" Menu
     
    Last edited: May 29, 2017
  4. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    DummyUnlocker_CityImprovedLocalResources
    1. The definition of the new table is as this (sql version):
      Code:
      CREATE TABLE IF NOT EXISTS 
      	DummyUnlocker_CityImprovedLocalResources (
      	DummyBuildingType	text		REFERENCES Buildings(BuildingType)		default null,
      	ResourceType		text		REFERENCES Resources(ResourceType)		default null,
      	CustomModId		text);
    2. The columns thus require:
      Spoiler column requirements :
      • DummyBuildingType: This is the name of your dummy building, exactly as you entered it for column BuildingType in table Buildings.
      • ResourceType: This is the name of the desired resource exactly as it is shown for column ResourceType in table Resources. Do not under any circumstances state either of the "artifact" resources.
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing ResourceType designations.
      • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
    3. For this table, the specified resources have to be improved with an appropriate terrain-improvement.
    4. The player must also have the required technology that reveals the resource and makes the player able to use the resource.
    5. You should not use this table and table DummyUnlocker_CityLocalResources for the same dummy building.
    6. Example:
      • Assume I want to place a dummy building in a city if the city has either an improved Stone or an improved Marble resource.
      • Calling my Dummy Building "BUILDING_STONEWORKS_LRS_UNLOCKER", I then do as follows:
        Code:
        <GameInfo>
        	<DummyUnlocker_CityImprovedLocalResources>
        		<Row DummyBuildingType="BUILDING_STONEWORKS_LRS_UNLOCKER" ResourceType="RESOURCE_MARBLE" />
        		<Row DummyBuildingType="BUILDING_STONEWORKS_LRS_UNLOCKER" ResourceType="RESOURCE_STONE" />
        	</DummyUnlocker_CityImprovedLocalResources>
        </GameInfo>
        Showing the rest of the code I would use to create a dummy building called "BUILDING_STONEWORKS_LRS_UNLOCKER", and set it up in this table, I would have:
        Spoiler :
        Code:
        <GameInfo>
        	<Types>
        		<Row Type="BUILDING_STONEWORKS_LRS_UNLOCKER" Kind="KIND_BUILDING" />
        	</Types>
        	<Buildings>
        		<Row BuildingType="BUILDING_STONEWORKS_LRS_UNLOCKER" Name="LOC_BUILDING_STONEWORKS_LRS_UNLOCKER_NAME"
        			Description="LOC_BUILDING_STONEWORKS_LRS_UNLOCKER_DESCRIPTION"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        	</Buildings>
        	<CivilopediaPageExcludes>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_STONEWORKS_LRS_UNLOCKER"/>
        	</CivilopediaPageExcludes>
        	<DummyUnlocker_CityImprovedLocalResources>
        		<Row DummyBuildingType="BUILDING_STONEWORKS_LRS_UNLOCKER" ResourceType="RESOURCE_MARBLE" />
        		<Row DummyBuildingType="BUILDING_STONEWORKS_LRS_UNLOCKER" ResourceType="RESOURCE_STONE" />
        	</DummyUnlocker_CityImprovedLocalResources>
        </GameInfo>
      • This causes the lua code of the utility to place the dummy building "BUILDING_STONEWORKS_LRS_UNLOCKER" into the city when the proper conditions are met. As yet this does not affect anything else in the game.
    7. Hooking the Example Dummy Building to a "Real" Building:
      • To make this dummy building act as a prerequisite for a "BUILDING_STONEWORKS_LRS" I would need to create a valid definition for a building called "BUILDING_STONEWORKS_LRS", and then I would add the following to my code:
        Code:
        <GameInfo>
        	<BuildingPrereqs>
        		<Row Building="BUILDING_STONEWORKS_LRS" PrereqBuilding="BUILDING_STONEWORKS_LRS_UNLOCKER"/>
        	</BuildingPrereqs>
        </GameInfo>
      • This makes my dummy building act as the prerequisite to construction of the real building "BUILDING_STONEWORKS_LRS".
      • I could just as easily make this dummy a prerequisite to a Unit by stating as:
        Code:
        <GameInfo>
        	<Unit_BuildingPrereqs>
        		<Row Unit="UNIT_STONEWORKS_GUY" PrereqBuilding="BUILDING_STONEWORKS_LRS_UNLOCKER"/>
        	</Unit_BuildingPrereqs>
        </GameInfo>
    8. What effect the real building has or the unit has in-game is not really the concern of this utility, and for the sake of simplicity I will not add more to these instructions by diverging off into what a "Real" Building called a "Tannery" ought to do in-game once it is unlocked for construction.
      • both "BUILDING_STONEWORKS_LRS_UNLOCKER" and "BUILDING_STONEWORKS_LRS" are used in the LeeS' Buildings Are Fun mod so you can look in the files therein (LeeS_BuildingsAreFun\XML\RealBuildings/Resource_Dependant_Buildings.xml has the code for "BUILDING_STONEWORKS_LRS" and LeeS_BuildingsAreFun\XML\DummyBuildings/DummyResourceUnlockerBuildings.xml has the code for the "BUILDING_STONEWORKS_LRS_UNLOCKER" dummy building)
    9. Example 2: Only One Resource Requirement:
      • Assume I want to place a dummy building in a city only if the city has an improved Tea resource.
      • Calling my Dummy Building "BUILDING_TEA_HOUSE_LRS_UNLOCKER", I then do as follows:
        Code:
        <GameInfo>
        	<DummyUnlocker_CityImprovedLocalResources>
        		<Row DummyBuildingType="BUILDING_TEA_HOUSE_LRS_UNLOCKER" ResourceType="RESOURCE_TEA" />
        	</DummyUnlocker_CityImprovedLocalResources>
        </GameInfo>
        Showing the rest of the code I would use to create a dummy building called "BUILDING_TEA_HOUSE_LRS_UNLOCKER", and set it up in this table, I would have:
        Spoiler :
        Code:
        <GameInfo>
        	<Types>
        		<Row Type="BUILDING_TEA_HOUSE_LRS_UNLOCKER" Kind="KIND_BUILDING" />
        	</Types>
        	<Buildings>
        		<Row BuildingType="BUILDING_TEA_HOUSE_LRS_UNLOCKER" Name="LOC_BUILDING_TEA_HOUSE_LRS_UNLOCKER_NAME"
        			Description="LOC_BUILDING_TEA_HOUSE_LRS_UNLOCKER_DESCRIPTION"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        	</Buildings>
        	<CivilopediaPageExcludes>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_TEA_HOUSE_LRS_UNLOCKER"/>
        	</CivilopediaPageExcludes>
        	<DummyUnlocker_CityImprovedLocalResources>
        		<Row DummyBuildingType="BUILDING_TEA_HOUSE_LRS_UNLOCKER" ResourceType="RESOURCE_TEA" />
        	</DummyUnlocker_CityImprovedLocalResources>
        </GameInfo>
      Return to the list of New Game-Tables Used By the Terrains Sub-System
      Return to the Utility "Main" Menu



      DummyUnlocker_CityRequiresBuildingPreReqORS
      1. The definition of the new table is as this (sql version):
        Code:
        CREATE TABLE IF NOT EXISTS 
        	DummyUnlocker_CityRequiresBuildingPreReqORS (
        	DummyBuildingType	text		REFERENCES Buildings(BuildingType)		default null,
        	PrereqBuilding		text		REFERENCES Buildings(BuildingType)		default null,
        	CustomModId		text);
      2. The columns thus require:
        Spoiler column requirements :
        • DummyBuildingType: This is the name of your dummy building, exactly as you entered it for column BuildingType in table Buildings.
        • PrereqBuilding: This is the name of a "Real" Building that must exist in a city in order for the DummyBuildingType building to be added to the city.
          • Since this is a logical "ORS" table, if multiple rows exist within the table for the same DummyBuildingType, any one such listed building will satisy the prereq condition for a given city.
          • You should state the "Standard" building from within a group of buildings (ie, BUILDING_TEMPLE instead of BUILDING_STAVE_CHURCH). Stating BUILDING_STAVE_CHURCH but not stating BUILDING_TEMPLE will cause the code to auto-include BUILDING_TEMPLE, but any other unique replacement buildings for BUILDING_TEMPLE added by other mods will not be auto-included.
          • All Unique replacement buildings are automatically included and accounted for when a standard building from within a group is stated.
            ]/list]
          • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
        • You should use table DummyUnlocker_CityRequiresBuildingPreReqORS when only one PrereqBuilding is desired. You should not in this case use table DummyUnlocker_CityRequiresBuildingPreReqANDS
        • You must never state the same DummyBuildingType in both table DummyUnlocker_CityRequiresBuildingPreReqORS and table DummyUnlocker_CityRequiresBuildingPreReqANDS. The code is written to ignore such entries into table DummyUnlocker_CityRequiresBuildingPreReqANDS when the same DummyBuildingType has been registered into table DummyUnlocker_CityRequiresBuildingPreReqORS.
        • Example:
          • Assume I want to make a condition wherein a city must already have a "BUILDING_TEMPLE" (or "BUILDING_STAVE_CHURCH") before a dummy building called "BUILDING_RELIGIOUS_LRS_UNLOCKER" can be added to the city.
          • I can create such an additional prerequisite condition by this code:
            Code:
            <GameInfo>
            	<DummyUnlocker_CityRequiresBuildingPreReqORS>
            		<Row DummyBuildingType="BUILDING_RELIGIOUS_LRS_UNLOCKER" PrereqBuilding="BUILDING_TEMPLE"/>
            	</DummyUnlocker_CityRequiresBuildingPreReqORS>
            </GameInfo>
            Because the lua code that implements this table's effects automatically accounts for unique replacement versions of "standard" buildings, I do not need a second row designating the Stave Church.
          • If I want to I can alter the example and include a row for the Stave Church:
            Code:
            <GameInfo>
            	<DummyUnlocker_CityRequiresBuildingPreReqORS>
            		<Row DummyBuildingType="BUILDING_RELIGIOUS_LRS_UNLOCKER" PrereqBuilding="BUILDING_TEMPLE"/>
            		<Row DummyBuildingType="BUILDING_RELIGIOUS_LRS_UNLOCKER" PrereqBuilding="BUILDING_STAVE_CHURCH"/>
            	</DummyUnlocker_CityRequiresBuildingPreReqORS>
            </GameInfo>
            The effect in-game of either of these two example is identical.
        • Example 2:
          • Assume I want to make a condition wherein a city must already have either a "BUILDING_FACTORY" or a "BUILDING_BROADCAST_CENTER" before a dummy building called "BUILDING_MODERNITY_LRS_UNLOCKER" can be added to the city.
          • I can create such an additional prerequisite condition by this code:
            Code:
            <GameInfo>
            	<DummyUnlocker_CityRequiresBuildingPreReqORS>
            		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_FACTORY"/>
            		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_BROADCAST_CENTER"/>
            	</DummyUnlocker_CityRequiresBuildingPreReqORS>
            </GameInfo>
            Because the lua code that implements this table's effects automatically accounts for unique replacement versions of "standard" buildings, I do not need a additional rows designating the Film Studio or the Electronics Factory. Nor do I need additional rows for any mod-added buildings that also are unique replacements for the Factory or Broadcast Center. Stating the table as I have in this example has the same effect as if I had stated
            Code:
            <GameInfo>
            	<DummyUnlocker_CityRequiresBuildingPreReqORS>
            		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_FACTORY"/>
            		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_ELECTRONICS_FACTORY"/>
            		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_BROADCAST_CENTER"/>
            		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_FILM_STUDIO"/>
            	</DummyUnlocker_CityRequiresBuildingPreReqORS>
            </GameInfo>
        Return to the list of New Game-Tables Used By the Terrains Sub-System
        Return to the Utility "Main" Menu



        DummyUnlocker_CityRequiresBuildingPreReqANDS
        1. The definition of the new table is as this (sql version):
          Code:
          CREATE TABLE IF NOT EXISTS 
          	DummyUnlocker_CityRequiresBuildingPreReqANDS (
          	DummyBuildingType	text		REFERENCES Buildings(BuildingType)		default null,
          	PrereqBuilding		text		REFERENCES Buildings(BuildingType)		default null,
          	CustomModId		text);
        2. The columns thus require:
          Spoiler column requirements :
          • DummyBuildingType: This is the name of your dummy building, exactly as you entered it for column BuildingType in table Buildings.
          • PrereqBuilding: This is the name of a "Real" Building that must exist in a city in order for the DummyBuildingType building to be added to the city.
            • Since this is a logical "ANDS" table, if multiple rows exist within the table for the same DummyBuildingType, all such listed buildings must be present in the city in order for the prereq condition to be met.
            • You should state the "Standard" building from within a group of buildings (ie, BUILDING_TEMPLE instead of BUILDING_STAVE_CHURCH). The code for this table will account for all unique replacement versions of standard buildings regardless of which you state (the standard or a unique replacement) but processing is reduced and simplified when you state the Standard building from within a group.
            • The code automatically accounts for the fact that no city can have both a BUILDING_TEMPLE and a BUILDING_STAVE_CHURCH, so the code automatically ferrets out these equivalencies and accepts either BUILDING_STAVE_CHURCH or BUILDING_TEMPLE as satisfying a requirement for BUILDING_TEMPLE.
              ]/list]
            • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
          • You should use table DummyUnlocker_CityRequiresBuildingPreReqORS when only one PrereqBuilding is desired. You should not in this case use table DummyUnlocker_CityRequiresBuildingPreReqANDS
          • You must never state the same DummyBuildingType in both table DummyUnlocker_CityRequiresBuildingPreReqORS and table DummyUnlocker_CityRequiresBuildingPreReqANDS. The code is written to ignore such entries into table DummyUnlocker_CityRequiresBuildingPreReqANDS when the same DummyBuildingType has been registered into table DummyUnlocker_CityRequiresBuildingPreReqORS.
          • Example:
            • Assume I want to make a condition wherein a city must already have both a "BUILDING_FACTORY" and a "BUILDING_BROADCAST_CENTER" before a dummy building called "BUILDING_MODERNITY_LRS_UNLOCKER" can be added to the city.
            • I can create such an additional prerequisite condition by this code:
              Code:
              <GameInfo>
              	<DummyUnlocker_CityRequiresBuildingPreReqANDS>
              		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_FACTORY"/>
              		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_BROADCAST_CENTER"/>
              	</DummyUnlocker_CityRequiresBuildingPreReqANDS>
              </GameInfo>
              Because the lua code that implements this table's effects automatically accounts for unique replacement versions of "standard" buildings, I do not need a additional rows designating the Film Studio or the Electronics Factory. Nor do I need additional rows for any mod-added buildings that also are unique replacements for the Factory or Broadcast Center. Stating the table as I have in this example has the same effect as if I had stated
              Code:
              <GameInfo>
              	<DummyUnlocker_CityRequiresBuildingPreReqANDS>
              		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_FACTORY"/>
              		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_ELECTRONICS_FACTORY"/>
              		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_BROADCAST_CENTER"/>
              		<Row DummyBuildingType="BUILDING_MODERNITY_LRS_UNLOCKER" PrereqBuilding="BUILDING_FILM_STUDIO"/>
              	</DummyUnlocker_CityRequiresBuildingPreReqANDS>
              </GameInfo>
          Return to the list of New Game-Tables Used By the Terrains Sub-System
          Return to the Utility "Main" Menu
     
  5. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    DummyUnlocker_CityTerrainRequirements
    1. The definition of the new table is as this (sql version):
      Code:
      CREATE TABLE IF NOT EXISTS 
      	DummyUnlocker_CityTerrainRequirements (
      	DummyBuildingType			text		REFERENCES Buildings(BuildingType)				default null,
      	CityPlotTerrainType			text		REFERENCES Terrains(TerrainType)				default null,
      	CityOnOrAdjacentTerrainType		text		REFERENCES Terrains(TerrainType)				default null,
      	CityNearbyTerrainType			text		REFERENCES Terrains(TerrainType)				default null,
      		--means within the city working radius and 'owned' by the city
      	CityAdjacentMountainRequired		boolean		NOT NULL CHECK (CityAdjacentMountainRequired IN (0,1))		default 0,
      	CityAdjacentRiverRequired		boolean		NOT NULL CHECK (CityAdjacentRiverRequired IN (0,1))		default 0,
      	CityAdjacentLakeRequired		boolean		NOT NULL CHECK (CityAdjacentLakeRequired IN (0,1))		default 0,
      	CityAdjacentLakeOrRiverRequired		boolean		NOT NULL CHECK (CityAdjacentLakeOrRiverRequired IN (0,1))	default 0,
      	SpecifiedTerrainsMustNotBeLake		boolean		NOT NULL CHECK (SpecifiedTerrainsMustNotBeLake IN (0,1))	default 1,
      	NumberCityOwnedMountains		integer										default 0,
      	CustomModId				text);
      
    2. The columns thus require:
      Spoiler column requirements :
      • DummyBuildingType: This is the name of your dummy building, exactly as you entered it for column BuildingType in table Buildings.
      • CityPlotTerrainType: This is the name of a Terrain-Type, such as "TERRAIN_GRASS", that the city center must be placed on in order for the DummyBuildingType to be added to the city.
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing CityPlotTerrainType designations. Too many such rows however would effectively be the same as no such requirement for the city center plot.
      • CityOnOrAdjacentTerrainType: This is the name of a Terrain-Type, such as "TERRAIN_GRASS", that the city center must be placed on or adjacent to in order for the DummyBuildingType to be added to the city.
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing CityOnOrAdjacentTerrainType designations. Too many such rows however would effectively be the same as no such requirement for the city center plot.
      • CityNearbyTerrainType: This is the name of a Terrain-Type, such as "TERRAIN_GRASS", that must be present within the set of plots the city owns in order for the DummyBuildingType to be added to the city.
        • The city center does not have to be on or adjacent to this type of terrain. This city just has to "own" at least one tile of the specified Terrain-Type.
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing CityNearbyTerrainType designations. Too many such rows however would effectively be the same as no such requirement for the city center plot.
      • CityAdjacentMountainRequired: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the city center must be placed adjacent to at least one mountain in order for the dummy building to be added to the city.
        • The default value for this column is "false".
      • CityAdjacentRiverRequired: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the city center must be placed adjacent to at least one river tile in order for the dummy building to be added to the city.
        • The default value for this column is "false".
      • CityAdjacentLakeRequired: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the city center must be placed adjacent to at least one lake tile in order for the dummy building to be added to the city.
      • CityAdjacentLakeOrRiverRequired: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the city center must be placed adjacent to at least one lake or river tile in order for the dummy building to be added to the city.
        • The default value for this column is "false".
      • SpecifiedTerrainsMustNotBeLake: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the terrain designated for either column CityOnOrAdjacentTerrainType or CityNearbyTerrainType cannot be a lake tile in order for the dummy building to be added to the city.
        • This is needed because "TERRAIN_COAST" applies to both lakes and actual "coastal" sea tiles.
        • The default value for this column is "true".
      • NumberCityOwnedMountains: This is an integer (number) column.
        • It specifies the number of mountain tiles a city must "own" in order for the dummy building to be added to the city.
        • Adjacency does not matter for this column. All that matters is that the city "owns" the specified number of mountain tiles.
        • The default value for this column is "0".
      • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
    3. Note on "stacking-up" of boolean or other requirements:
      • One DummyBuildingType can have multiple rows added within the table, and multiple of the boolean conditions can be stated within the same row of the table, but this does not cause a "stacking effect" of the requirements stated. So long as the city meets at least one of the requirements given the dummy building will be added to the city.
    4. Any column you do not wish to use can be omitted except the DummyBuildingType column.
      • omitting this column does not cause a game crash or return to the game main menu, but would be pointless.
    5. Besides column DummyBuildingType you need to give at least one condition to be met for each row you add to the table.
      • failing to do so will not cause a game crash or return to the game main menu, but again would be pointless.
    6. Example:
      • Here is an example of using this table to specify that a city must "own" at least one Coastal tile:
        Code:
        <GameData>
        	<DummyUnlocker_CityTerrainRequirements>
        		<Row DummyBuildingType="BUILDING_COASTAL_CITY_LRS_UNLOCKER" CityNearbyTerrainType="TERRAIN_COAST" />
        	</DummyUnlocker_CityTerrainRequirements>
        </GameData>
        Since SpecifiedTerrainsMustNotBeLake defaults to boolean "true" I do not need to state anything more in the table in order to require that the coastal tile must actually be part of an ocean mass and not part of a lake mass.
      • This same dummy building is then used to "unlock" multiple "real" buildings:
        Code:
        <GameData>
        	<BuildingPrereqs>
        		<Row Building="BUILDING_LRS_COASTAL0" PrereqBuilding="BUILDING_COASTAL_CITY_LRS_UNLOCKER"/>
        		<Row Building="BUILDING_LRS_COASTAL1" PrereqBuilding="BUILDING_COASTAL_CITY_LRS_UNLOCKER"/>
        		<Row Building="BUILDING_LRS_COASTAL2" PrereqBuilding="BUILDING_COASTAL_CITY_LRS_UNLOCKER"/>
        		<Row Building="BUILDING_LRS_COASTAL3" PrereqBuilding="BUILDING_COASTAL_CITY_LRS_UNLOCKER"/>
        		<Row Building="BUILDING_LRS_COASTAL4" PrereqBuilding="BUILDING_COASTAL_CITY_LRS_UNLOCKER"/>
        		<Row Building="BUILDING_LRS_COASTAL5" PrereqBuilding="BUILDING_COASTAL_CITY_LRS_UNLOCKER"/>
        		<Row Building="BUILDING_LRS_COASTAL6" PrereqBuilding="BUILDING_COASTAL_CITY_LRS_UNLOCKER"/>
        		<Row Building="BUILDING_LRS_COASTAL7" PrereqBuilding="BUILDING_COASTAL_CITY_LRS_UNLOCKER"/>
        	</BuildingPrereqs>
        </GameData>
      • This enables these buildings for construction or purchase within the city so long as all the other prerequisites (such as a required civic or technology) are satisfied for these "real" buildings and so long as one or more of these buildings is not locked out of the city by some other restriction, such as a mutually-exclusive building is already present in the city.
    7. Example 2:
      • Here is an example of using this table to specify that a city must be adjacent to at least one mountain tile:
        Code:
        <GameData>
        	<DummyUnlocker_CityTerrainRequirements>
        		<Row DummyBuildingType="BUILDING_LRS_OBSERVATORY_UNLOCKER" CityAdjacentMountainRequired="true" CityAdjacentRiverRequired="false"
        			CityAdjacentLakeRequired="false" CityAdjacentLakeOrRiverRequired="false" />
        	</DummyUnlocker_CityTerrainRequirements>
        </GameData>
        Since the columns for CityAdjacentRiverRequired, CityAdjacentLakeRequired, and CityAdjacentLakeOrRiverRequired default to boolean "false" I do not need to state anything for them and I can simplify the row to:
        Code:
        <GameData>
        	<DummyUnlocker_CityTerrainRequirements>
        		<Row DummyBuildingType="BUILDING_LRS_OBSERVATORY_UNLOCKER" CityAdjacentMountainRequired="true" />
        	</DummyUnlocker_CityTerrainRequirements>
        </GameData>
        The two methods for showing the row in the table will function identically.
      • This dummy building is then used to "unlock" a "real" building called "BUILDING_LRS_OBSERVATORY":
        Code:
        <GameData>
        	<BuildingPrereqs>
        		<Row Building="BUILDING_LRS_OBSERVATORY" PrereqBuilding="BUILDING_LRS_OBSERVATORY_UNLOCKER"/>
        	</BuildingPrereqs>
        </GameData>
      • Cities that are founded adjacent to a mountain can construct or purchase "BUILDING_LRS_OBSERVATORY" if the player has the required technology or civic prerequisite for "BUILDING_LRS_OBSERVATORY" and so long as "BUILDING_LRS_OBSERVATORY" is not locked out of the city by some other restriction, such as a mutually-exclusive building is already present in the city.
    Return to the list of New Game-Tables Used By the Terrains Sub-System
    Return to the Utility "Main" Menu


    DummyUnlocker_CityFeatureRequirements
    1. The definition of the new table is as this (sql version):
      Code:
      CREATE TABLE IF NOT EXISTS 
      	DummyUnlocker_CityFeatureRequirements (
      	DummyBuildingType			text		REFERENCES Buildings(BuildingType)			default null,
      	CityAdjacentFeatureType			text		REFERENCES Features(FeatureType)			default null,
      	CityNearbyFeatureType			text		REFERENCES Features(FeatureType)			default null,
      		--means within the city working radius and 'owned' by the city
      	FeatureMustNotBeImproved		boolean		NOT NULL CHECK (FeatureMustNotBeImproved IN (0,1))	default 1,
      	NumberCityOwnedFeatureRequired		integer									default 0,
      	CustomModId				text);
    2. The columns thus require:
      Spoiler column requirements :
      • DummyBuildingType: This is the name of your dummy building, exactly as you entered it for column BuildingType in table Buildings.
      • CityAdjacentFeatureType: This is the name of a feature type as stated in column FeatureType from the game's <Features> table, such as "FEATURE_FLOODPLAINS".
        • This specifies that the city center must be adjacent to a tile with the feature mentioned.
      • CityNearbyFeatureType: This is the name of a feature type as stated in column FeatureType from the game's <Features> table, such as "FEATURE_FLOODPLAINS".
        • This specifies that the city must "own" at least one tile with the feature mentioned.
        • You can pair-up with column with column NumberCityOwnedFeatureRequired to designate that a city have a minimum number of tiles with the feature. So, for excample, you could create a requirement that a city "own" at least three Floodplain tiles in order for the dummy building to be placed within the city.
      • FeatureMustNotBeImproved: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the feature stated in either column CityAdjacentFeatureType or column CityNearbyFeatureType cannot have a terrain improvement.
        • The default value for this column is "true".
      • NumberCityOwnedFeatureRequired: This is an integer (number) column.
        • It specifies the number of tiles a city must "own" with the feature-type stated in column CityNearbyFeatureType in order for the dummy building to be added to the city.
        • Adjacency does not matter for this column. All that matters is that the city "owns" the specified number of tiles.
        • The default value for this column is "0".
      • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
    3. Like with the previous tables, you can "stack" conditions in multiple rows for the same dummy building, but these do not create an accumulated total requirement. So long as any one requirement set is satisfied, the dummy building will be added to a city.
    4. Example:
      • This is an example of stating that a city must have at least four unimproved "woods" (ie, "FEATURE_FOREST") before the dummy building "BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER" is placed within a city.
        Code:
        <GameData>
        	<DummyUnlocker_CityFeatureRequirements>
        		<Row DummyBuildingType="BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER" NumberCityOwnedFeatureRequired="4"
        			CityNearbyFeatureType="FEATURE_FOREST" FeatureMustNotBeImproved="true" />
        	</DummyUnlocker_CityFeatureRequirements>
        </GameData>
      • This dummy building can then act as the prerequisite unlocker building for a World Wonder called a Forestry Service:
        Code:
        <GameData>
        	<BuildingPrereqs>
        		<Row Building="BUILDING_FORESTRY_SERVICE_LRS" PrereqBuilding="BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER"/>
        	</BuildingPrereqs>
        </GameData>
      • Since I cannot into 3d modelling, this world wonder is just added to a city center when completed, but here is the xml-code full example of the world wonder with a dummy acting as its "building prerequisite". The wonder adds 2 Culture to all unimproved forest tiles worked by the city that constructs the wonder, and 1 Production to all unimproved forest tiles anywhere in the player's empire:
        Spoiler :
        [/code]<GameData>
        <Types>
        <Row Type="BUILDING_FORESTRY_SERVICE_LRS" Kind="KIND_BUILDING"/>
        <Row Type="BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER" Kind="KIND_BUILDING"/>
        </Types>
        <Buildings>
        <Row BuildingType="BUILDING_FORESTRY_SERVICE_LRS" Name="LOC_BUILDING_FORESTRY_SERVICE_LRS_NAME"
        Description="LOC_BUILDING_FORESTRY_SERVICE_LRS_DESCRIPTION" PrereqCivic="CIVIC_CIVIL_ENGINEERING"
        MaxWorldInstances="1" IsWonder="true" AdvisorType="ADVISOR_GENERIC" Housing="1" Entertainment="1"
        Cost="1200" Quote="LOC_BUILDING_FORESTRY_SERVICE_LRS_QUOTE" QuoteAudio="NULL" />
        <Row BuildingType="BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER" Name="LOC_BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER_NAME"
        Description="LOC_BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER_DESCRIPTION"
        PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        </Buildings>
        <BuildingPrereqs>
        <Row Building="BUILDING_FORESTRY_SERVICE_LRS" PrereqBuilding="BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER"/>
        </BuildingPrereqs>
        <CivilopediaPageExcludes>
        <Row SectionId="BUILDINGS" PageId="BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER"/>
        </CivilopediaPageExcludes>
        <DummyUnlocker_CityFeatureRequirements>
        <Row DummyBuildingType="BUILDING_FORESTRY_SERVICE_LRS_UNLOCKER" NumberCityOwnedFeatureRequired="4"
        CityNearbyFeatureType="FEATURE_FOREST" FeatureMustNotBeImproved="true"
        CustomModId="46f68baa-7457-4c80-b88d-53da67a4b38d" />
        </DummyUnlocker_CityFeatureRequirements>
        <Building_YieldChanges>
        <Row BuildingType="BUILDING_FORESTRY_SERVICE_LRS" YieldType="YIELD_CULTURE" YieldChange="1"/>
        <Row BuildingType="BUILDING_FORESTRY_SERVICE_LRS" YieldType="YIELD_SCIENCE" YieldChange="1"/>
        </Building_YieldChanges>
        <Modifiers>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_CULTURE</ModifierId>
        <ModifierType>MODIFIER_ALL_CITIES_ATTACH_MODIFIER</ModifierType>
        <SubjectRequirementSetId>CITY_HAS_FORESTRY_SERVICE_LRS_REQUIREMENTS</SubjectRequirementSetId>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_CULTURE_MODIFIER</ModifierId>
        <ModifierType>MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD</ModifierType>
        <SubjectRequirementSetId>PLOT_HAS_FOREST_REQUIREMENTS_LRS</SubjectRequirementSetId>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_PRODUCTION</ModifierId>
        <ModifierType>MODIFIER_ALL_CITIES_ATTACH_MODIFIER</ModifierType>
        <!--<SubjectRequirementSetId>CITY_HAS_FORESTRY_SERVICE_LRS_REQUIREMENTS</SubjectRequirementSetId>-->
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_PRODUCTION_MODIFIER</ModifierId>
        <ModifierType>MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD</ModifierType>
        <SubjectRequirementSetId>PLOT_HAS_FOREST_REQUIREMENTS_LRS</SubjectRequirementSetId>
        </Row>
        <Row>
        <ModifierId>LRS_FORESTRY_SERVICE_UNOMPROVED_FOREST_MODIFIER</ModifierId>
        <ModifierType>MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD</ModifierType>
        <SubjectRequirementSetId>LRS_PLOT_HAS_NO_IMPROVEMENT_REQUIREMENTS</SubjectRequirementSetId>
        </Row>
        </Modifiers>
        <ModifierArguments>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_CULTURE</ModifierId>
        <Name>ModifierId</Name>
        <Value>FORESTRY_SERVICE_LRS_FOREST_CULTURE_MODIFIER</Value>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_CULTURE_MODIFIER</ModifierId>
        <Name>ModifierId</Name>
        <Value>LRS_FORESTRY_SERVICE_UNOMPROVED_FOREST_MODIFIER</Value>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_CULTURE_MODIFIER</ModifierId>
        <Name>YieldType</Name>
        <Value>YIELD_CULTURE</Value>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_CULTURE_MODIFIER</ModifierId>
        <Name>Amount</Name>
        <Value>2</Value>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_PRODUCTION</ModifierId>
        <Name>ModifierId</Name>
        <Value>FORESTRY_SERVICE_LRS_FOREST_PRODUCTION_MODIFIER</Value>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_PRODUCTION_MODIFIER</ModifierId>
        <Name>ModifierId</Name>
        <Value>LRS_FORESTRY_SERVICE_UNOMPROVED_FOREST_MODIFIER</Value>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_PRODUCTION_MODIFIER</ModifierId>
        <Name>YieldType</Name>
        <Value>YIELD_PRODUCTION</Value>
        </Row>
        <Row>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_PRODUCTION_MODIFIER</ModifierId>
        <Name>Amount</Name>
        <Value>1</Value>
        </Row>
        </ModifierArguments>
        <BuildingModifiers>
        <Row>
        <BuildingType>BUILDING_FORESTRY_SERVICE_LRS</BuildingType>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_CULTURE</ModifierId>
        </Row>
        <Row>
        <BuildingType>BUILDING_FORESTRY_SERVICE_LRS</BuildingType>
        <ModifierId>FORESTRY_SERVICE_LRS_FOREST_PRODUCTION</ModifierId>
        </Row>
        </BuildingModifiers>
        <Requirements>
        <Row>
        <RequirementId>LRS_REQUIRES_PLOT_HAS_NO_IMPROVEMENT</RequirementId>
        <RequirementType>REQUIREMENT_PLOT_HAS_ANY_IMPROVEMENT</RequirementType>
        <Inverse>true</Inverse>
        </Row>
        <Row>
        <RequirementId>REQUIRES_CITY_HAS_FORESTRY_SERVICE_LRS</RequirementId>
        <RequirementType>REQUIREMENT_CITY_HAS_BUILDING</RequirementType>
        </Row>
        <Row>
        <RequirementId>REQUIRES_PLOT_HAS_FOREST_LRS</RequirementId>
        <RequirementType>REQUIREMENT_PLOT_FEATURE_TYPE_MATCHES</RequirementType>
        </Row>
        </Requirements>
        <RequirementArguments>
        <Row>
        <RequirementId>REQUIRES_CITY_HAS_FORESTRY_SERVICE_LRS</RequirementId>
        <Name>BuildingType</Name>
        <Value>BUILDING_FORESTRY_SERVICE_LRS</Value>
        </Row>
        <Row>
        <RequirementId>REQUIRES_PLOT_HAS_FOREST_LRS</RequirementId>
        <Name>FeatureType</Name>
        <Value>FEATURE_FOREST</Value>
        </Row>
        </RequirementArguments>
        <RequirementSets>
        <Row>
        <RequirementSetId>LRS_PLOT_HAS_NO_IMPROVEMENT_REQUIREMENTS</RequirementSetId>
        <RequirementSetType>REQUIREMENTSET_TEST_ALL</RequirementSetType>
        </Row>
        <Row>
        <RequirementSetId>CITY_HAS_FORESTRY_SERVICE_LRS_REQUIREMENTS</RequirementSetId>
        <RequirementSetType>REQUIREMENTSET_TEST_ALL</RequirementSetType>
        </Row>
        <Row>
        <RequirementSetId>PLOT_HAS_FOREST_REQUIREMENTS_LRS</RequirementSetId>
        <RequirementSetType>REQUIREMENTSET_TEST_ALL</RequirementSetType>
        </Row>
        </RequirementSets>
        <RequirementSetRequirements>
        <Row>
        <RequirementSetId>LRS_PLOT_HAS_NO_IMPROVEMENT_REQUIREMENTS</RequirementSetId>
        <RequirementId>LRS_REQUIRES_PLOT_HAS_NO_IMPROVEMENT</RequirementId>
        </Row>
        <Row>
        <RequirementSetId>PLOT_HAS_FOREST_REQUIREMENTS_LRS</RequirementSetId>
        <RequirementId>REQUIRES_PLOT_HAS_FOREST_LRS</RequirementId>
        </Row>
        <Row>
        <RequirementSetId>CITY_HAS_FORESTRY_SERVICE_LRS_REQUIREMENTS</RequirementSetId>
        <RequirementId>REQUIRES_CITY_HAS_FORESTRY_SERVICE_LRS</RequirementId>
        </Row>
        </RequirementSetRequirements>
        </GameData>[/code]
    Return to the list of New Game-Tables Used By the Terrains Sub-System
    Return to the Utility "Main" Menu
     
  6. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    DummyUnlocker_CityImprovementRequirements
    1. The definition of the new table is as this (sql version):
      Code:
      CREATE TABLE IF NOT EXISTS 
      	DummyUnlocker_CityImprovementRequirements (
      	DummyBuildingType			text		REFERENCES Buildings(BuildingType)			default null,
      	CityAdjacentImprovementType		text		REFERENCES Improvements(ImprovementType)		default null,
      	CityNearbyImprovementType		text		REFERENCES Improvements(ImprovementType)		default null,
      		--means within the city working radius and 'owned' by the city
      	ImprovementMustNotBeOnFeature		boolean		NOT NULL CHECK (ImprovementMustNotBeOnFeature IN (0,1))	default 0,
      	NumberCityOwnedImprovementRequired	integer									default 0,
      	CustomModId				text);
    2. The columns thus require:
      Spoiler column requirments :
      • DummyBuildingType: This is the name of your dummy building, exactly as you entered it for column BuildingType in table Buildings.
      • CityAdjacentImprovementType: This is the name of an improvement type as stated in column ImprovementType from the game's <Improvements> table, such as "IMPROVEMENT_FARM".
        • This specifies that the city center must be adjacent to a tile with the improvement mentioned.
      • CityNearbyImprovementType: This is the name of a improvement type as stated in column ImprovementType from the game's <Improvements> table, such as "IMPROVEMENT_FARM".
        • This specifies that the city must "own" at least one tile with the improvement mentioned.
        • You can pair-up with column with column NumberCityOwnedImprovementRequired to designate that a city have a minimum number of tiles with the improvement. So, for excample, you could create a requirement that a city "own" at least three Farm tiles in order for the dummy building to be placed within the city.
      • ImprovementMustNotBeOnFeature: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the improvement stated in either column CityNearbyImprovementType or column CityAdjacentImprovementType cannot have a terrain feature such as a Floodplains.
        • The default value for this column is "false".
      • NumberCityOwnedImprovementRequired: This is an integer (number) column.
        • It specifies the number of tiles a city must "own" with the improvement-type stated in column CityNearbyImprovementType in order for the dummy building to be added to the city.
        • Adjacency does not matter for this column. All that matters is that the city "owns" the specified number of tiles.
        • The default value for this column is "0".
      • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
    3. Like with the previous tables, you can "stack" conditions in multiple rows for the same dummy building, but these do not create an accumulated total requirement. So long as any one requirement set is satisfied, the dummy building will be added to a city.
    4. Any column you do not wish to use can be omitted except the DummyBuildingType column.
      • omitting this column does not cause a game crash or return to the game main menu, but would be pointless.
    5. Besides column DummyBuildingType you need to give at least one condition to be met for each row you add to the table.
      • failing to do so will not cause a game crash or return to the game main menu, but again would be pointless.
    6. Example:
      • If I want to create a condition wherein a dummy building called a "BUILDING_LUMBERYARD_UNLOCKER" will be added to city that has at least three Sawmill (lumber mill) improvements within the city's territory, I would make a designation in the table like this:
        Code:
        <GameData>
        	<DummyUnlocker_CityImprovementRequirements>
        		<Row DummyBuildingType="BUILDING_LUMBERYARD_UNLOCKER"
        			CityNearbyImprovementType="IMPROVEMENT_LUMBER_MILL"
        			NumberCityOwnedImprovementRequired="3"
        			ImprovementMustNotBeOnFeature="false" />
        	</DummyUnlocker_CityImprovementRequirements>
        </GameData>
        Because column ImprovementMustNotBeOnFeature defaults to boolean "false" I could omit that column in the example.
    Return to the list of New Game-Tables Used By the Terrains Sub-System
    Return to the Utility "Main" Menu



    DummyUnlocker_CityDistrictRequirements
    1. The definition of the new table is as this (sql version):
      Code:
      CREATE TABLE IF NOT EXISTS 
      	DummyUnlocker_CityDistrictRequirements (
      	DummyBuildingType			text		REFERENCES Buildings(BuildingType)				default null,
      	CityDistrictType			text		REFERENCES Districts(DistrictType)				default null,
      	DistrictMustBeAdjacentToMountain	boolean		NOT NULL CHECK (DistrictMustBeAdjacentToMountain IN (0,1))	default 0,
      	DistrictMustBeAdjacentToRiver		boolean		NOT NULL CHECK (DistrictMustBeAdjacentToRiver IN (0,1))		default 0,
      	NumberAdjacentMountain			integer										default 0,
      	NumberCityOwnedMountains		integer										default 0,
      	AdjacentRequiredDistrictType		text		REFERENCES Districts(DistrictType)				default null,
      	AdjacentRequiredResourceType		text		REFERENCES Resources(ResourceType)				default null,
      	AdjacentRequiredFeatureType		text		REFERENCES Features(FeatureType)				default null,
      	AdjacentRequiredImprovementType		text		REFERENCES Improvements(ImprovementType)			default null,
      	MustBeSpecifiedCityDistrictType		boolean		NOT NULL CHECK (MustBeSpecifiedCityDistrictType IN (0,1))	default 0,
      	DistrictMustBeAdjacentToHill		boolean		NOT NULL CHECK (DistrictMustBeAdjacentToHill IN (0,1))		default 0,
      	DistrictMustBeOnOrNextToHill		boolean		NOT NULL CHECK (DistrictMustBeOnOrNextToHill IN (0,1))		default 0,
      	DistrictMustBeAdjacentToNaturalWonder	boolean		NOT NULL CHECK (DistrictMustBeAdjacentToNaturalWonder IN (0,1))	default 0,
      	DistrictMustBeAdjacentToWorldWonder	boolean		NOT NULL CHECK (DistrictMustBeAdjacentToWorldWonder IN (0,1))	default 0,
      	CustomModId				text);
    2. The columns thus require:
      Spoiler column requirments :
      • DummyBuildingType: This is the name of your dummy building, exactly as you entered it for column BuildingType in table Buildings.
      • CityDistrictType: This is the name of a district type as stated in column DistrictType from the game's <Districts> table, such as "DISTRICT_CAMPUS".
        • This specifies the city district type for which the rest of the row's settings will apply when and if the city has the specified district.
        • "DISTRICT_CITY_CENTER" should never be stated in this column nor should you attempt to manipulate this table to try to apply its affects to the City Center District.
        • Attempts to use "DISTRICT_CITY_CENTER" for this column are completely ignored by the lua-code that implements this table's affects.
      • DistrictMustBeAdjacentToMountain: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the CityDistrictType must be placed adjacent to a mountain in order for the DummyBuildingType to be added to the city.
        • The default value for this column is "false".
      • DistrictMustBeAdjacentToRiver: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the CityDistrictType must be placed adjacent to a river tile in order for the DummyBuildingType to be added to the city.
        • The default value for this column is "false".
      • NumberAdjacentMountain: This is an integer (number) column.
        • It specifies the number of tiles adjacent to the CityDistrictType that must be mountains in order for the DummyBuildingType to be added to the city.
        • The default value for this column is "0".
      • NumberCityOwnedMountains: This is an integer (number) column.
        • It specifies the number of tiles a city must "own" that are mountain tiles in order for the DummyBuildingType to be added to the city.
        • Adjacency does not matter for this column. All that matters is that the city "owns" the specified number of tiles.
        • The default value for this column is "0".
      • AdjacentRequiredDistrictType: This is the name of a district type as stated in column DistrictType from the game's <Districts> table, such as "DISTRICT_HARBOR".
        • Unlike column CityDistrictType, you can specify "DISTRICT_CITY_CENTER" for AdjacentRequiredDistrictType.
      • AdjacentRequiredResourceType: This is the name of a resource type as stated in column ResourceType from the game's <Resourcess> table, such as "RESOURCE_BANANAS".
        • This specifies that the city must "own" at least one tile adjacent to the district with the resource mentioned.
      • AdjacentRequiredFeatureType: This is the name of a feature type as stated in column FeatureType from the game's <Features> table, such as "FEATURE_FLOODPLAINS".
        • This specifies that the city must "own" at least one tile adjacent to the district with the feature mentioned.
      • AdjacentRequiredImprovementType: This is the name of an improvement type as stated in column ImprovementType from the game's <Improvements> table, such as "IMPROVEMENT_FARM".
        • This specifies that the city must "own" at least one tile adjacent to the district with the improvement mentioned.
      • MustBeSpecifiedCityDistrictType: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the CityDistrictType stated is the only one for which the requirements will apply. Unique Replacements that are not this specific CityDistrictType and "standard" Districts that are not the specifiec district stated will not have the effect applied to them.
        • The default value for this column is "false".
      • DistrictMustBeAdjacentToHill: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the stated CityDistrictType must be adjacent to a hill tile that the city owns in order for the DummyBuildingType to be added to the city.
        • The default value for this column is "false".
      • DistrictMustBeOnOrNextToHill: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the stated CityDistrictType must be on or adjacent to a hill tile that the city owns in order for the DummyBuildingType to be added to the city.
        • The default value for this column is "false".
      • DistrictMustBeAdjacentToNaturalWonder: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the stated CityDistrictType must be adjacent to a Natural Wonder tile that the city owns in order for the DummyBuildingType to be added to the city.
        • The default value for this column is "false".
      • DistrictMustBeAdjacentToWorldWonder: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the stated CityDistrictType must be adjacent to a World Wonder tile that the city owns in order for the DummyBuildingType to be added to the city.
        • The default value for this column is "false".
      • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
    3. Like with the previous tables, you can "stack" conditions in multiple rows for the same dummy building, but these do not create an accumulated total requirement. So long as any one requirement set is satisfied, the dummy building will be added to a city.
    4. Any column you do not wish to use can be omitted except the DummyBuildingType and CityDistrictType columns.
      • omitting these columns does not cause a game crash or return to the game main menu, but would be pointless.
    5. Besides columns DummyBuildingType and CityDistrictType you need to give a valid designation for at least one condition to be met for each row you add to the table.
      • failing to do so will not cause a game crash or return to the game main menu, but again would be pointless.
    6. Example:
      • If I want to specify that a Campus District be placed adjacent to two mountain tiles that the city owns in order for a "BUILDING_CAMPUS_OBSERVATORY_LRS_UNLOCKER" to be added to a city, I do as follows with this table:
        Code:
        <GameData>
        	<DummyUnlocker_CityDistrictRequirements>
        		<Row DummyBuildingType="BUILDING_CAMPUS_OBSERVATORY_LRS_UNLOCKER"
        			CityDistrictType="DISTRICT_CAMPUS" NumberAdjacentMountain="2" />
        	</DummyUnlocker_CityDistrictRequirements>
        </GameData>
      • Column NumberAdjacentMountain would conflict with column DistrictMustBeAdjacentToMountain, so only NumberAdjacentMountain is used.
    7. Example 2:
      • If I want to specify that a City have an Encampment District and the city itself must own at least 4 mountain tiles in order for a "BUILDING_ALPINE_ACADEMY_LRS_UNLOCKER" to be added to a city, I do as follows with this table:
        Code:
        <GameData>
        	<DummyUnlocker_CityDistrictRequirements>
        		<Row DummyBuildingType="BUILDING_ALPINE_ACADEMY_LRS_UNLOCKER"
        			CityDistrictType="DISTRICT_ENCAMPMENT" NumberCityOwnedMountains="4" />
        	</DummyUnlocker_CityDistrictRequirements>
        </GameData>
      • Column NumberCityOwnedMountains would conflict with both column DistrictMustBeAdjacentToMountain and column NumberAdjacentMountain, so only NumberCityOwnedMountains is used.
      • 4 mountain tiles within the "ownership" of one city is not terribly difficult to accomplish in-game, but 4 mountain tiles adjacent to any specific district might be a fairly rare occurance to the point of nearly creating an unachievable condition.
    8. Example 3:
      • If I want to specify that a City have an Entertainment Complex District that is adjacent to at least on mountain tile the city owns in order for a "BUILDING_SKI_RESORT_LRS_UNLOCKER" to be added to a city, I do as follows with this table:
        Code:
        <GameData>
        	<DummyUnlocker_CityDistrictRequirements>
        		<Row DummyBuildingType="BUILDING_SKI_RESORT_LRS_UNLOCKER"
        			CityDistrictType="DISTRICT_ENTERTAINMENT_COMPLEX"
        			DistrictMustBeAdjacentToMountain="true" />
        	</DummyUnlocker_CityDistrictRequirements>
        </GameData>
      • Column DistrictMustBeAdjacentToMountain is thus my preferred column to use.
    Return to the list of New Game-Tables Used By the Terrains Sub-System
    Return to the Utility "Main" Menu
     
  7. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA


    General Description
    1. If a city has a specified building:
      1. Production of specified units is increased (or decreased) by a percentage.
      2. The Units to be affected can be specified as:
        1. individual specific units
        2. individual specific units and any unique replacement units for them
        3. units of a given domain-type
        4. units of a given formation-type
        5. units of a given promotion-class
      3. The building that gives the affect can be a specific building, or all unique replacements for that type of building can be included.
    2. There is no built-in restriction in the code to keep city-states from taking advantage of any effect created by this system.
    3. In order to restrict the effect to a specific civilization you would need to make the "real" building one that is only available to a specific civilization/leader via a trait
    4. Major civilizations have a special trait different from that applied to city-states and barbarians, so to restrict the effect to only major civilizations you would need to add a building-trait to "TRAIT_LEADER_MAJOR_CIV" since this is the common trait all major players in the game share.



    New Game-Table Used By the Building_UnitProductionModifier Sub-System: Building_UnitProductionModifierDummyBuildings
    1. The definition of the new table is as this (sql version):
      Code:
      CREATE TABLE IF NOT EXISTS 
      	Building_UnitProductionModifierDummyBuildings (
      	BuildingType			TEXT NOT NULL	REFERENCES Buildings(BuildingType),
      	DummyBuildingType		TEXT NOT NULL	REFERENCES Buildings(BuildingType),
      	ReverseDummyBuildingType	TEXT		REFERENCES Buildings(BuildingType),
      	ApplyBy				text									default null,
      	PromotionClass			text		REFERENCES UnitPromotionClasses(PromotionClassType)	default null,
      	FormationClass			text		REFERENCES UnitFormationClasses(FormationClassType)	default null,
      	DomainType			text									default null,
      	UnitType			text		REFERENCES Units(UnitType)				default null,
      	ApplyToBuildingTypeReplaces	boolean		NOT NULL CHECK (ApplyToBuildingTypeReplaces IN (0,1))	default 0,
      	ApplyToUnitTypeReplaces		boolean		NOT NULL CHECK (ApplyToUnitTypeReplaces IN (0,1))	default 0,
      	MustNotBeCivilian		boolean		NOT NULL CHECK (MustNotBeCivilian IN (0,1))		default 1,
      	CustomModId			text);
    2. The columns thus require:
      Spoiler column requirments :
      • BuildingType: This is the name of the real building players will construct in thier cities, stated exactly as you entered it for column BuildingType in table Buildings. This is the building whose presence in a city causes specified units to be produced faster (or slower if desired).
        • An individual real building can be specified in multiple rows of the table, but if doing so as a general rule all the units thus added to the building's effects should be added by the same ApplyBy method.
      • DummyBuildingType: This is the name of a dummy building that is linked by this table to the real building specified as BuildingType, exactly as you entered it for column BuildingType in table Buildings.
        • this dummy bulding gets added to a city when one of the applicable units is being produced in the city that has the defined BuildingType, and gets taken away when the city is no longer constructing one of the applicable units.
        • you need to use care when entering multiple rows with the same designation for DummyBuildingType because you can create a condition where what you wanted was a 20% increase in unit production, but you only see a 10% increase. Remember that in civ6 there can only be one copy of a building in the same city, so you cannot add multlple copies of the same building to the same city and thereby create a "stacking" effect.
      • ReverseDummyBuildingType: This is the name of a dummy building that is added to a city when the city is not producing one of the applicable units, state the name of the dummy building exactly as you entered it for column BuildingType in table Buildings.
        • I will describe how this column and its associated building can be used if desired but for the most part you will normally not state anything for ReverseDummyBuildingType in this table, and you will not need to create a dummy building to act as the ReverseDummyBuildingType.
      • ApplyBy: This is a test string you enter that designates how the code should interpret the units to be applied to the stated BuildingType. This column is required and must be one of the following and only one of the following:
        • "Domain"
        • "Unit"
        • "Formation"
        • "Promotion"
      • PromotionClass: This is the name of the desired unit PromotionClass exactly as it is shown for column PromotionClassType in table UnitPromotionClasses.
        • This column is only used when column ApplyBy is set to a value of "Promotion"
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing PromotionClassType designations.
      • FormationClass: This is the name of the desired unit FormationClass exactly as it is shown for column FormationClassType in table UnitFormationClasses.
        • This column is only used when column ApplyBy is set to a value of "Formation"
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing FormationClass designations.
      • DomainType: This is the name of the desired unit Domain. Unit Domains don't actually have a table where they are defined: this is all just an internal mecahnism of the game executing software.
        • This column is only used when column ApplyBy is set to a value of "Domain"
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing DomainType designations.
        • The allowed settings for DomainType are:
          • "DOMAIN_LAND"
          • "DOMAIN_SEA"
          • "DOMAIN_AIR"
          Anything else will be ignored.
      • UnitType: This is the name of the desired unit PromotionClass exactly as it is shown for column UnitType in table Units.
        • This column is only used when column ApplyBy is set to a value of "Unit"
        • Note that you can add multiple rows to the table with the same DummyBuildingType but differing UnitType designations.
      • ApplyToBuildingTypeReplaces: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the code should apply the affect to any unique replacement building that is a replacement for the BuildingType given.
        • The default value for this column is "false".
        • by giving "false" for this column and giving the name of a unique replacement building for BuildingType you can create a unique effect for a specific unique replacement building.
      • ApplyToUnitTypeReplaces: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies that the effect should be applied to unique replacement units for the stated UnitType.
        • This column only has an affect if the setting of ApplyBy is "Unit" and the stated UnitType is not a unique replacement unit.
        • The default value for this column is "false".
      • MustNotBeCivilian: This is a logical boolean column for which you specify true or false (1 or 0 if programming in SQL).
        • It specifies whether or not civilian units are to be included.
        • This column only has an affect when ApplyBy is "Unit" or "Domain".
          • civilian units don't have PromotionClass (except for the Spy Unit), and their FormationClass is "FORMATION_CLASS_CIVILIAN".
          • the code sorts based solely on whether a unit has "FORMATION_CLASS_CIVILIAN" to determine if it is a civilian unit. Support units therefore are excluded from being considered "civilians.
          • Religious units have a PromotionClass, but they have to be purchased, so modification of their "rate of construction" would never occur anyway.
          • Spy Units (any unit that has PromotionClass="PROMOTION_CLASS_SPY") are exempted from beig considered civilians by a Special Rule of the code.
          • Regardless of the setting for MustNotBeCivilian, when specification is being made by column UnitType, then the specific unit listed as UnitType is always included in the effects.
        • The default value for this column is "true".
      • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
    3. Examples: There are two methods for implementing this system:
      • Using <DistrictModifiers> to create the actual effect, in which case only a DummyBuildingType is required.
        • In this method the DummyBuildingType is merely a marker to the game's executing dll to implement the effect in the city.
      • Using both a DummyBuildingType and a ReverseDummyBuildingType to create and cancel the effect within a given city as needed.
        • In this method the effects are tied directly to the DummyBuildingType and its matching opposite ReverseDummyBuildingType as <BuildingModifiers> that create or take away the production yield % affect.
    4. Example 1: Using the <DistrictModifiers> Approach:
      • <DistrictModifiers> should always be attached to the City Center District when using this approach, like as this:
        Code:
        <DistrictModifiers>
        		<Row DistrictType="DISTRICT_CITY_CENTER" ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" />
        </DistrictModifiers>
      • It does not matter if the Real Building the player buys or constructs is placed into the city center district or not.
      1. We need to create the "Real" bulding we are going to use. This is the building the player buys or constructs in cities:
        Code:
        <GameData>
        	<Types>
        		<Row Type="BUILDING_LRS_COASTAL0" Kind="KIND_BUILDING"/>
        	</Types>
        	<Buildings>
        		<!-- Ancient Era-->
        		<Row BuildingType="BUILDING_LRS_COASTAL0" Name="LOC_BUILDING_LRS_COASTAL0_NAME" Description="LOC_BUILDING_LRS_COASTAL0_DESCRIPTION"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="65" PurchaseYield="YIELD_GOLD" AdvisorType="ADVISOR_CONQUEST" ObsoleteEra="ERA_CLASSICAL" />
        	</Buildings>
        </GameData>
      2. We need to create the dummy bulding we are going to use:
        Code:
        <GameData>
        	<Types>
        		<Row Type="BUILDING_COASTAL0_DUMMY_LRS" Kind="KIND_BUILDING"/>
        	</Types>
        	<Buildings>
        		<Row BuildingType="BUILDING_COASTAL0_DUMMY_LRS" Name="LOC_BUILDING_COASTAL0_DUMMY_LRS"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        	</Buildings>
        	<CivilopediaPageExcludes>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_COASTAL0_DUMMY_LRS"/>
        	</CivilopediaPageExcludes>
        </GameData>
      3. Next we need to code to implement the Building_UnitProductionModifierDummyBuildings table:
        Code:
        <GameData>
        	<Building_UnitProductionModifierDummyBuildings>
        		<Row BuildingType="BUILDING_LRS_COASTAL0" DummyBuildingType="BUILDING_COASTAL0_DUMMY_LRS"
        			MustNotBeCivilian="true" ApplyBy="Formation" FormationClass="FORMATION_CLASS_NAVAL" CustomModId="Hamburgers" />
        	</Building_UnitProductionModifierDummyBuildings>
        </GameData>
        In this example we are applying the effect are creating to all units constructed in the city which are of "FORMATION_CLASS_NAVAL", ie, Sea Combat Units.
      4. Now we need to create a District Modifier that will be applied to a city when the city has "BUILDING_COASTAL0_DUMMY_LRS" present in the city. The lua code of the utility handles placement and removal of this dummy building from the city as required based on:
        • 1) Does the city have "BUILDING_LRS_COASTAL0" ?
        • 2) Is the city producing a unit that conforms to "FORMATION_CLASS_NAVAL" as its current production item ?
        • If both conditions #1 and #2 are satisfied, then dummy building "BUILDING_COASTAL0_DUMMY_LRS" is added to the city. Otherwise, dummy building "BUILDING_COASTAL0_DUMMY_LRS" is removed from the city if it has previously been placed there.
        • The game's standard executing-software-level systems then handle to enactment of the production % modifier we will define.
      5. Our modifier is thus defined as
        Code:
        <GameData>
        	<Modifiers>
        		<Row ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER"
        			SubjectRequirementSetId="LRS_CITY_HAS_COASTAL0_DUMMY_REQUIREMENTS" />
        	</Modifiers>
        	<ModifierArguments>
        		<Row ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" Name="Amount" Value="5" />
        		<Row ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" Name="YieldType" Value="YIELD_PRODUCTION" />
        	</ModifierArguments>
        	<RequirementSets>
        		<Row RequirementSetId="LRS_CITY_HAS_COASTAL0_DUMMY_REQUIREMENTS" RequirementSetType="REQUIREMENTSET_TEST_ALL" />
        	</RequirementSets>
        	<RequirementSetRequirements>
        		<Row RequirementSetId="LRS_CITY_HAS_COASTAL0_DUMMY_REQUIREMENTS" RequirementId="LRS_REQUIRES_CITY_HAS_COASTAL0_DUMMY" />
        	</RequirementSetRequirements>
        	<Requirements>
        		<Row RequirementId="LRS_REQUIRES_CITY_HAS_COASTAL0_DUMMY" RequirementType="REQUIREMENT_CITY_HAS_BUILDING" />
        	</Requirements>  
        	<RequirementArguments>
        		<Row RequirementId="LRS_REQUIRES_CITY_HAS_COASTAL0_DUMMY" Name="BuildingType" Value="BUILDING_COASTAL0_DUMMY_LRS" />
        	</RequirementArguments>
        	<DistrictModifiers>
        		<Row DistrictType="DISTRICT_CITY_CENTER" ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" />
        	</DistrictModifiers>
        </GameData>
        This gives us a 5% increase in production in the city when it is producing naval combat units.
      6. The entire code for this effect would be:
        Spoiler :
        Code:
        <GameData>
        	<Types>
        		<Row Type="BUILDING_COASTAL0_DUMMY_LRS" Kind="KIND_BUILDING"/>
        		<Row Type="BUILDING_LRS_COASTAL0" Kind="KIND_BUILDING"/>
        	</Types>
        	<Buildings>
        		<!-- Ancient Era-->
        		<Row BuildingType="BUILDING_LRS_COASTAL0" Name="LOC_BUILDING_LRS_COASTAL0_NAME" Description="LOC_BUILDING_LRS_COASTAL0_DESCRIPTION"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="65" PurchaseYield="YIELD_GOLD" AdvisorType="ADVISOR_CONQUEST" ObsoleteEra="ERA_CLASSICAL" />
        		<Row BuildingType="BUILDING_COASTAL0_DUMMY_LRS" Name="LOC_BUILDING_COASTAL0_DUMMY_LRS"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        	</Buildings>
        	<CivilopediaPageExcludes>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_COASTAL0_DUMMY_LRS"/>
        	</CivilopediaPageExcludes>
        	<Building_UnitProductionModifierDummyBuildings>
        		<Row BuildingType="BUILDING_LRS_COASTAL0" DummyBuildingType="BUILDING_COASTAL0_DUMMY_LRS"
        			MustNotBeCivilian="true" ApplyBy="Formation" FormationClass="FORMATION_CLASS_NAVAL" CustomModId="Hamburgers" />
        	</Building_UnitProductionModifierDummyBuildings>
        	<Modifiers>
        		<Row ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER"
        			SubjectRequirementSetId="LRS_CITY_HAS_COASTAL0_DUMMY_REQUIREMENTS" />
        	</Modifiers>
        	<ModifierArguments>
        		<Row ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" Name="Amount" Value="5" />
        		<Row ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" Name="YieldType" Value="YIELD_PRODUCTION" />
        	</ModifierArguments>
        	<RequirementSets>
        		<Row RequirementSetId="LRS_CITY_HAS_COASTAL0_DUMMY_REQUIREMENTS" RequirementSetType="REQUIREMENTSET_TEST_ALL" />
        	</RequirementSets>
        	<RequirementSetRequirements>
        		<Row RequirementSetId="LRS_CITY_HAS_COASTAL0_DUMMY_REQUIREMENTS" RequirementId="LRS_REQUIRES_CITY_HAS_COASTAL0_DUMMY" />
        	</RequirementSetRequirements>
        	<Requirements>
        		<Row RequirementId="LRS_REQUIRES_CITY_HAS_COASTAL0_DUMMY" RequirementType="REQUIREMENT_CITY_HAS_BUILDING" />
        	</Requirements>  
        	<RequirementArguments>
        		<Row RequirementId="LRS_REQUIRES_CITY_HAS_COASTAL0_DUMMY" Name="BuildingType" Value="BUILDING_COASTAL0_DUMMY_LRS" />
        	</RequirementArguments>
        	<DistrictModifiers>
        		<Row DistrictType="DISTRICT_CITY_CENTER" ModifierId="LRS_COASTAL0_DUMMY_PRODUCTION" />
        	</DistrictModifiers>
        </GameData>
      • We could alter this so that only if the city is producing one of a few select naval units does the effect apply:
        Code:
        <GameData>
        	<Building_UnitProductionModifierDummyBuildings>
        		<Row BuildingType="BUILDING_LRS_COASTAL0" DummyBuildingType="BUILDING_COASTAL0_DUMMY_LRS"
        			MustNotBeCivilian="true" ApplyBy="Unit" UnitType="UNIT_GALLEY" ApplyToUnitTypeReplaces="true" CustomModId="Hamburgers" />
        		<Row BuildingType="BUILDING_LRS_COASTAL0" DummyBuildingType="BUILDING_COASTAL0_DUMMY_LRS"
        			MustNotBeCivilian="true" ApplyBy="Unit" UnitType="UNIT_QUADRIREME" ApplyToUnitTypeReplaces="true" CustomModId="Hamburgers" />
        	</Building_UnitProductionModifierDummyBuildings>
        </GameData>
      • This would make the effect apply to only Galleys and Quedriremes and their Unique Replacement versions, which would tends to be more realistic for a building available in the Ancient Era of the game.
    5. (continued in next post)
    Return to the Utility "Main" Menu
     
    Last edited: May 26, 2017
  8. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    Utility Sub-System: Individualized City Unit Production Modifier Buildings (continued)

    New Game-Table Used By the Building_UnitProductionModifier Sub-System: Building_UnitProductionModifierDummyBuildings
    (continued)
    1. Example 2: Using BuildingModifiers Directly Attached to the DummyBuildingType and its matching opposite ReverseDummyBuildingType:
      • This method requires one building give the city a positive total produciton yield percentage modifier, and the other building to give a balanced and opposing negative total produciton yield percentage modifier.
      • The reason for this is that percentage yield modifiers applied by buildings to a city are permanent, and stack. If the same building with a +5% total modifier to city production is added repetatively added to a city, each time this is done the net effect is an additional and accumulating percentage yield modification.
      • Not only does the same modifier thus applied to the same city stack for that city, but removal from the city of the building that added the modifier does not remove the modification -- the modification to % total city yield is permanent.
      • So in using this method you need to give the modifier when the city is constructing one of the units you are allowing production modification of, and then you need to remove the percentage city production modifier when the city is no longer constructing one of the applicable units. Hence why in this method it is necessary to have both a "Positive" and a "Negative" building.
      • Definition of the "Positive" Building: DummyBuildingType
        Code:
        <GameData>
        	<Types>
        		<Row Type="BUILDING_COASTAL0_DUMMY_LRS" Kind="KIND_BUILDING"/>
        	</Types>
        	<Buildings>
        		<Row BuildingType="BUILDING_COASTAL0_DUMMY_LRS" Name="LOC_BUILDING_COASTAL0_DUMMY_LRS"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        	</Buildings>
        	<CivilopediaPageExcludes>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_COASTAL0_DUMMY_LRS"/>
        	</CivilopediaPageExcludes>
        	<Modifiers>
        		<!--Adjust City Yield PRODUCTION %-->
        		<Replace ModifierId="LRS_BUILDING_ADD_PRODUCTION_YIELD_PERCENT_005" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	</Modifiers>
        	<ModifierArguments>
        		<!--Adjust City Yield %-->
        		<Replace ModifierId="LRS_BUILDING_ADD_PRODUCTION_YIELD_PERCENT_005" Name="Amount" Value="5" />
        		<Replace ModifierId="LRS_BUILDING_ADD_PRODUCTION_YIELD_PERCENT_005" Name="YieldType" Value="YIELD_PRODUCTION" />
        	</ModifierArguments>
        	<BuildingModifiers>
        		<!-- BUILDING_COASTAL0_DUMMY_LRS gives a total of +5% YIELD_PRODUCTION -->
        		<Row BuildingType="BUILDING_COASTAL0_DUMMY_LRS" ModifierId="LRS_BUILDING_ADD_PRODUCTION_YIELD_PERCENT_005" />
        	</BuildingModifiers>
        </GameData>
      • Definition of the "Negative" Building: ReverseDummyBuildingType
        Code:
        <GameData>
        	<Types>
        		<Row Type="BUILDING_COASTAL0_ANTI_DUMMY_LRS" Kind="KIND_BUILDING"/>
        	</Types>
        	<Buildings>
        		<Row BuildingType="BUILDING_COASTAL0_ANTI_DUMMY_LRS" Name="LOC_BUILDING_COASTAL0_ANTI_DUMMY_LRS"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        	</Buildings>
        	<CivilopediaPageExcludes>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_COASTAL0_ANTI_DUMMY_LRS"/>
        	</CivilopediaPageExcludes>
        	<Modifiers>
        		<!--Adjust City Yield PRODUCTION %-->
        		<Replace ModifierId="LRS_BUILDING_SUBTRACT_PRODUCTION_YIELD_PERCENT_005" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	</Modifiers>
        	<ModifierArguments>
        		<!--Adjust City Yield %-->
        		<Replace ModifierId="LRS_BUILDING_SUBTRACT_PRODUCTION_YIELD_PERCENT_005" Name="Amount" Value="-5" />
        		<Replace ModifierId="LRS_BUILDING_SUBTRACT_PRODUCTION_YIELD_PERCENT_005" Name="YieldType" Value="YIELD_PRODUCTION" />
        	</ModifierArguments>
        	<BuildingModifiers>
        		<!-- BUILDING_COASTAL0_ANTI_DUMMY_LRS gives a total of -5% YIELD_PRODUCTION -->
        		<Row BuildingType="BUILDING_COASTAL0_ANTI_DUMMY_LRS" ModifierId="LRS_BUILDING_SUBTRACT_PRODUCTION_YIELD_PERCENT_005" />
        	</BuildingModifiers>
        </GameData>
      • With the set-up of these two dummy buildings we can add and then take away the 5% extra total city production as needed based upon what the city is producing when the city has the real building defined as BuildingType:
        Code:
        <GameData>
        	<Building_UnitProductionModifierDummyBuildings>
        		<Row BuildingType="BUILDING_LRS_COASTAL0" DummyBuildingType="BUILDING_COASTAL0_DUMMY_LRS" ReverseDummyBuildingType="BUILDING_COASTAL0_ANTI_DUMMY_LRS"
        			MustNotBeCivilian="true" ApplyBy="Unit" UnitType="UNIT_GALLEY" ApplyToUnitTypeReplaces="true" CustomModId="Hamburgers" />
        		<Row BuildingType="BUILDING_LRS_COASTAL0" DummyBuildingType="BUILDING_COASTAL0_DUMMY_LRS" ReverseDummyBuildingType="BUILDING_COASTAL0_ANTI_DUMMY_LRS"
        			MustNotBeCivilian="true" ApplyBy="Unit" UnitType="UNIT_QUADRIREME" ApplyToUnitTypeReplaces="true" CustomModId="Hamburgers" />
        	</Building_UnitProductionModifierDummyBuildings>
        </GameData>
      • We do not need the set-up for the district modifier used in the other method, so including our "Real" Building, the code is:
        Spoiler :
        Code:
        <GameData>
        	<Types>
        		<Row Type="BUILDING_COASTAL0_DUMMY_LRS" Kind="KIND_BUILDING"/>
        		<Row Type="BUILDING_COASTAL0_ANTI_DUMMY_LRS" Kind="KIND_BUILDING"/>
        		<Row Type="BUILDING_LRS_COASTAL0" Kind="KIND_BUILDING"/>
        	</Types>
        	<Buildings>
        		<!-- Ancient Era-->
        		<Row BuildingType="BUILDING_LRS_COASTAL0" Name="LOC_BUILDING_LRS_COASTAL0_NAME" Description="LOC_BUILDING_LRS_COASTAL0_DESCRIPTION"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="65" PurchaseYield="YIELD_GOLD" AdvisorType="ADVISOR_CONQUEST" ObsoleteEra="ERA_CLASSICAL" />
        		<Row BuildingType="BUILDING_COASTAL0_DUMMY_LRS" Name="LOC_BUILDING_COASTAL0_DUMMY_LRS"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        		<Row BuildingType="BUILDING_COASTAL0_ANTI_DUMMY_LRS" Name="LOC_BUILDING_COASTAL0_ANTI_DUMMY_LRS"
        			PrereqDistrict="DISTRICT_CITY_CENTER" Cost="10000" PrereqTech="TECH_FUTURE_TECH" IsDummy="true" />
        	</Buildings>
        	<CivilopediaPageExcludes>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_COASTAL0_DUMMY_LRS"/>
        		<Row SectionId="BUILDINGS" PageId="BUILDING_COASTAL0_ANTI_DUMMY_LRS"/>
        	</CivilopediaPageExcludes>
        	<Modifiers>
        		<!--Adjust City Yield PRODUCTION %-->
        		<Replace ModifierId="LRS_BUILDING_ADD_PRODUCTION_YIELD_PERCENT_005" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        		<Replace ModifierId="LRS_BUILDING_SUBTRACT_PRODUCTION_YIELD_PERCENT_005" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	</Modifiers>
        	<ModifierArguments>
        		<!--Adjust City Yield %-->
        		<Replace ModifierId="LRS_BUILDING_ADD_PRODUCTION_YIELD_PERCENT_005" Name="Amount" Value="5" />
        		<Replace ModifierId="LRS_BUILDING_ADD_PRODUCTION_YIELD_PERCENT_005" Name="YieldType" Value="YIELD_PRODUCTION" />
        		<Replace ModifierId="LRS_BUILDING_SUBTRACT_PRODUCTION_YIELD_PERCENT_005" Name="Amount" Value="-5" />
        		<Replace ModifierId="LRS_BUILDING_SUBTRACT_PRODUCTION_YIELD_PERCENT_005" Name="YieldType" Value="YIELD_PRODUCTION" />
        	</ModifierArguments>
        	<BuildingModifiers>
        		<!-- BUILDING_COASTAL0_DUMMY_LRS gives a total of +5% YIELD_PRODUCTION -->
        		<Row BuildingType="BUILDING_COASTAL0_DUMMY_LRS" ModifierId="LRS_BUILDING_ADD_PRODUCTION_YIELD_PERCENT_005" />
        		<!-- BUILDING_COASTAL0_ANTI_DUMMY_LRS gives a total of -5% YIELD_PRODUCTION -->
        		<Row BuildingType="BUILDING_COASTAL0_ANTI_DUMMY_LRS" ModifierId="LRS_BUILDING_SUBTRACT_PRODUCTION_YIELD_PERCENT_005" />
        	</BuildingModifiers>
        	<Building_UnitProductionModifierDummyBuildings>
        		<Row BuildingType="BUILDING_LRS_COASTAL0" DummyBuildingType="BUILDING_COASTAL0_DUMMY_LRS" ReverseDummyBuildingType="BUILDING_COASTAL0_ANTI_DUMMY_LRS"
        			MustNotBeCivilian="true" ApplyBy="Unit" UnitType="UNIT_GALLEY" ApplyToUnitTypeReplaces="true" CustomModId="Hamburgers" />
        		<Row BuildingType="BUILDING_LRS_COASTAL0" DummyBuildingType="BUILDING_COASTAL0_DUMMY_LRS" ReverseDummyBuildingType="BUILDING_COASTAL0_ANTI_DUMMY_LRS"
        			MustNotBeCivilian="true" ApplyBy="Unit" UnitType="UNIT_QUADRIREME" ApplyToUnitTypeReplaces="true" CustomModId="Hamburgers" />
        	</Building_UnitProductionModifierDummyBuildings>
        </GameData>
    2. The relative advantage of the District Modifiers method is that it requires fewer dummy buildings, so if you intend to add a series of these types of modifiers to the game, you should probably adopt this method
    3. If you are only adding one or two such unit production modifier "set-ups" then it is probably moot which of the two methods you employ. The amount of code required is about the same.
    4. The lua code that implements table <Building_UnitProductionModifierDummyBuildings> accounts for either of the two methods in terms of placing or not placing the correct dummy and anti-dummy in a city.
    Return to the Utility "Main" Menu



    General Description
    1. Provides a tool that requires a city have all the "real" buildings within a list before a second "real" building is unlocked within that city.
    2. The tool automatically adds and accounts for all unique replacements and the "standard" building from within a "group" of buildings regardless of whether a unique is stated as a prerequisite, or the standard building is so stated.
    3. When a city has all the requisite buildings from within a list (or their unique replacement versions), then a specified dummy building is added to the city, and this acts as the prerequisite the game sees for the building we really want to have a "must have all these buildings" requirement.

    New Game-Tables Used By the Sub-System
    1. The definition of the new table is as this (sql version):
      Code:
      CREATE TABLE IF NOT EXISTS 
      	Building_PreReqBuildingANDS (
      	RealBuildingType		text		REFERENCES Buildings(BuildingType)		default null,
      	PrereqRealBuildingType		text		REFERENCES Buildings(BuildingType)		default null,
      	DummyBuildingType		text		REFERENCES Buildings(BuildingType)		default null,
      	CustomModId		text);
    2. The columns thus require:
      Spoiler column requirements :
      • RealBuildingType: This is the name of the real building players will construct in thier cities, stated exactly as you entered it for column BuildingType in table Buildings. This is the building for which this list of prerequisite real buildings is being created.
      • PrereqRealBuildingType: This is the name of a prerequisite real building players will construct in thier cities, stated exactly as it appears for column BuildingType in table Buildings.
        • You should state the "standard" building from within a group rather than a unique replacement building from within a group. Unique replacement buildings are automatically accounted for by the code.
        • If you state a uniguq replacement building for this column, the lua code will seek out and add both the "standard" building for a such a unique replacement as well as all other unique replacements for the "standard" building.
        • You will have multiple rows within the table wherein PrereqRealBuildingType changes for each row you enter, but the other columns have the same values.
      • DummyBuildingType: This is the name of a dummy building that is linked by this table to the real building specified as RealBuildingType, exactly as you entered it for column BuildingType in table Buildings.
        • this dummy bulding gets added to a city when the city has all the requisite buildings in the list
      • CustomModId: This is the customized mod ID designation you use as discussed earlier. You do not need to state this in the rows you add to the table since the file UpdateNewMapResourceTables.sql will do this for you if you have correctly added it to your mod and updated it as shown.
    3. Example:
      • If I want to create a condition wherein a wonder called "BUILDING_WONDEROUS" can only be constructed in a city that has a Workshop, Market, and Temple, then I can implement such an effect using a dummy building called "BUILDING_WONDEROUS_UNLOCKER" and the folowing two tables (aside from the required definitions of these new buildings):
        Code:
        <GameData>
        	<Building_PreReqBuildingANDS>
        		<Row DummyBuildingType="BUILDING_WONDEROUS_UNLOCKER" RealBuildingType="BUILDING_WONDEROUS" PrereqRealBuildingType="BUILDING_TEMPLE" CustomModId="Hamburgers"/>
        		<Row DummyBuildingType="BUILDING_WONDEROUS_UNLOCKER" RealBuildingType="BUILDING_WONDEROUS" PrereqRealBuildingType="BUILDING_WORKSHOP" CustomModId="Hamburgers"/>
        		<Row DummyBuildingType="BUILDING_WONDEROUS_UNLOCKER" RealBuildingType="BUILDING_WONDEROUS" PrereqRealBuildingType="BUILDING_MARKET" CustomModId="Hamburgers"/>
        	</Building_PreReqBuildingANDS>
        	<BuildingPrereqs>
        		<Row Building="BUILDING_WONDEROUS" PrereqBuilding="BUILDING_WONDEROUS_UNLOCKER"/>
        	</BuildingPrereqs>
        </GameData>
    Return to the Utility "Main" Menu




    General Description
    1. The LeeS' Dummy Buildings Systems utility contains three utility xml-files in the mod's XML/ folder.
    2. All these files can be added to your mods and set to load into the game via an InGameActions UpdateDatabase type of action.
      • This will be unecessary if you are making your mod dependant on the utility. The code within the files will be loaded into the game's database before any code in your xml files.
    3. You can use the code in these files as desired within your mods, or not.
    4. You can copy the original files into your mods and you can add more code to these files, but you must not change any of the exiting code within the files. My mod(s) are expecting these pre-created modifiers and etc to be exactly as they are currently written, and will possibly malfunction if you change the effect of say BUILDING_LRS_ADD_STONE_PRODUCTION_1.
    5. Since all the game tables these files have code for are structured to have unique constraint requirements, I have used <Replace> instead of <Row>. With <Replace> it does not matter how may different files add the same code, you do not get database and fatal file errors for defining something already in the game's database.
    Utility Files
    1. BuildingModifiers.xml:
      • Contains the code to create many resource-related building-modifiers (as well as a few selected others) that you might want to add to a building. This file contains as an example a premade modifier you can "call" in the <BuildingModifiers> table to add +1 Production to all Stone Plots worked by a city when a city has a specified building. The modiifier already created in the file for this is called BUILDING_LRS_ADD_STONE_PRODUCTION_1. So your code for a new building would only need this to call and make use of this premade modifier:
        Code:
        <GameData>
        	<BuildingModifiers>
        		<Row>
        			<BuildingType>BUILDING_STONEWORKS_LRS</BuildingType>
        			<ModifierId>BUILDING_LRS_ADD_STONE_PRODUCTION_1</ModifierId>
        		</Row>
        	</BuildingModifiers>
        </GameData>
        Both the modifier and all its needed arguments to apply +1 production to all stone plots worked by the city is contained within the pre-packaged files.
      • BuildingModifiers.xml also contains all the code needed to apply a series of percentage total city yield modifiers for all the yield types. These are organized as a "bit" system, so that 10 total modifiers can grant any % yield increase to a city from 1% to 1023%, as like these for science yield modifiers:
        Code:
        <Modifiers>
        	<!--Adjust City Yield %-->
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_001" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_002" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_004" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_008" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_016" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_032" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_064" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_128" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_256" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        	<Replace ModifierId="LRS_BUILDING_ADD_SCIENCE_YIELD_PERCENT_512" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_CITY_YIELD_MODIFIER" />
        </Modifiers>
    2. CityYieldAntiModifiers.xml:
      • This file contains all the code needed to create negative city % yield modifiers.
      • I make use these in the LeeS' Buildings Are Fun mod to create trade-off systems where a production building adds production as a % but takes away food as a %, for example.
    3. PlotResourceRequirementSets.xml:
      • Contains the code to create all the <Requirements>, <RequirementArguments>, <RequirementSets>, and <RequirementSetRequirements> to define a "Plot Must Have Resource-X" set-up for every resource used by the base game.
      • So, for example, you can use RESOURCE_IS_STONE_LRS like this in a modifier:
        Code:
        <GameData>
        	<Modifiers>
        		<!--Adjust Plot Yield-->
        		<Replace>
        			<ModifierId>BUILDING_LRS_ADD_STONE_PRODUCTION_1</ModifierId>
        			<ModifierType>MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD</ModifierType>
        			<SubjectRequirementSetId>RESOURCE_IS_STONE_LRS</SubjectRequirementSetId>
        		</Replace>
        	</Modifiers>
        </GameData>
    4. The files should be loaded into the game in this order to not get missing reference errors:
      Code:
          <UpdateDatabase id="Utility_PlotResources">
            <File>XML/UtilityCode/PlotResourceRequirementSets.xml</File>
          </UpdateDatabase>
          <UpdateDatabase id="Utility_BuildingModifiers">
            <File>XML/UtilityCode/BuildingModifiers.xml</File>
          </UpdateDatabase>
          <UpdateDatabase id="Utility_AntiCityYieldModifiers">
            <File>XML/UtilityCode/CityYieldAntiModifiers.xml</File>
          </UpdateDatabase>
      
      These activations also need to occur before any code in which you are using the modifiers, etc. in these files. If you are using the utility mod rather than copying these files into your mod, the load order issues are already handled for you.
    Return to the Utility "Main" Menu
     
    Last edited: May 26, 2017
  9. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    • If you are not writing you own lua code-scripts for your mods, you can just skip all this. It would only confuse you and be of no value to you.
    General Description
    1. These are not files that you need to copy from the mod, these are snippets of lua code you can use in your own lua gameplay scripts.
    2. All these snippets of code need to run from lua files that are set up as like this in the modinfo file:
      Code:
        <InGameActions>
          <AddGameplayScripts id="LUA_Gameplay_AI_CannotBuildDummies">
            <File>LUA/UtilityImplementationScripts/KeepAIFromBuildingDummies.lua</File>
          </AddGameplayScripts>
        </InGameActions>
      
    3. You simply copy the snippet from here, paste it into your own lua file, and call it like in the examples shown.
    4. There are few of these code-snippets for which I have not added an example of using it. I intend to go back through the posts and add examples where they are missing. Also I intend to look for typos in the descriptions. The code itself has all been directly copied from functioning lua-scripts so should not have any copy-paste errors.
    Return to the Utility "Main" Menu

    PlaceBuildingInCityCenter
    1. You should use this version instead of any version you might find in the Buildings Are Fun mod, because those used within the lua files of the mod are in most case custom-configured to the needs of that particular sub-system even though the function-names used are the same in differing files.
    2. Code:
      Code:
      function PlaceBuildingInCityCenter(pCity, iBuilding)
      	local iCityPlotIndex = Map.GetPlot(pCity:GetX(), pCity:GetY()):GetIndex()
      	if not pCity:GetBuildings():HasBuilding(iBuilding) then
      		pCity:GetBuildQueue():CreateIncompleteBuilding(iBuilding, iCityPlotIndex, 100);
      	else
      		if pCity:GetBuildings():IsPillaged(iBuilding) then
      			pCity:GetBuildings():SetPillaged(iBuilding, false)
      		end
      	end
      end
    3. This function does not return any data to you. It implements placing the specified building into the city center district of the specified city.
    4. If the city already has the building then the code checks whther the building has been "pillaged", and if so removes the building and then re-places it into the city
    5. This routine as-written is only meant to implement placement of dummy or "marker" buildings that themselves have no direct game effects such as YieldChanges or BuildingModifiers.
    6. You can still use it for example to fix the fact that Trajan's "Free Building" effect ceases after the Medieval Era for new cities:
      Spoiler :
      Code:
      local iFreeMonumentBuilding = GameInfo.Buildings["BUILDING_MONUMENT"].Index
      function PlaceBuildingInCityCenter(pCity, iBuilding)
      	local iCityPlotIndex = Map.GetPlot(pCity:GetX(), pCity:GetY()):GetIndex()
      	if not pCity:GetBuildings():HasBuilding(iBuilding) then
      		pCity:GetBuildQueue():CreateIncompleteBuilding(iBuilding, iCityPlotIndex, 100);
      	else
      		if pCity:GetBuildings():IsPillaged(iBuilding) then
      			pCity:GetBuildings():RemoveBuilding(iBuilding);
      			pCity:GetBuildQueue():CreateIncompleteBuilding(iBuilding, iCityPlotIndex, 100);
      		end
      	end
      end
      function CityFoundedMonumentFix(iPlayer, iCityID)
      	if (PlayerConfigurations[iPlayer]:GetCivilizationTypeName() == "CIVILIZATION_ROME") then
      		local pPlayer = Players[iPlayer];
      		local pCity = pPlayer:GetCities():FindID(iCityID)
      		if not pCity:GetBuildings():HasBuilding(iFreeMonumentBuilding) then
      			PlaceBuildingInCityCenter(pCity, iFreeMonumentBuilding)
      		end
      	end
      end
      Events.CityInitialized.Add(CityFoundedMonumentFix)
    7. You must pass the data to the function for the following arguments:
      • pCity is an object reference to the city. You have to get the city's object reference and pass this data in the argument position for pCity.
      • iBuilding is the numerical Index # for the desired building.
    Return to the Utility "Main" Menu

    RemoveBuildingFromCityCenter
    1. You should use this version instead of any version you might find in the Buildings Are Fun mod, because those used within the lua files of the mod are in most case custom-configured to the needs of that particular sub-system even though the function-names used are the same in differing files.
    2. Code:
      Code:
      function RemoveBuildingFromCityCenter(pCity, iBuilding)
      	local iCityPlotIndex = Map.GetPlot(pCity:GetX(), pCity:GetY()):GetIndex()
      	if pCity:GetBuildings():HasBuilding(iBuilding) then
      		pCity:GetBuildings():RemoveBuilding(iBuilding);
      	end
      end
    3. This function does not return any data to you. It implements removing the specified building from the city center district of the specified city.
    4. If the city already has the building then the code checks whther the building has been "pillaged", and if so removes the building and then re-places it into the city
    5. This routine as-written is only meant to implement removal of dummy or "marker" buildings that themselves have no direct game effects such as YieldChanges or BuildingModifiers.
    6. The print commands for dubugging purposes have been turned into comments by use of the double-dash symbols (--) in front of the command "print"
    7. You must pass the data to the function for the following arguments:
      • pCity is an object reference to the city. You have to get the city's object reference and pass this data in the argument position for pCity.
      • iBuilding is the numerical Index # for the desired building.
    Return to the Utility "Main" Menu

    UnitIsDeadToPlayer
    1. When iterating through a list of player's units using
      Code:
      local pPlayerUnits = pPlayer:GetUnits()
      for i, pUnit in pPlayerUnits:Members() do
      	--something for each unit
      end
      Dead units still show in the list of a player's unit "members". This function can be used to sort for that so that you do not attempt to perform an lua "action" on a non-existant unit.
    2. Code:
      Code:
      function UnitIsDeadToPlayer(pUnit, iPlayer)
      	if pUnit then
      		if (pUnit:GetX() == nil) or (pUnit:GetX() < 0) or (pUnit:GetY() == nil) or (pUnit:GetY() < 0) or (pUnit:GetOwner() ~= iPlayer) then
      			return true
      		end
      	else
      		--the pUnit data is nil, assume the unit is ded
      		return true
      	end
      	--safety valve point: assume the unit is not ded if we get here
      	return false
      end
    3. I would use this as like this, since the function returns true/false as to whether the unit is dead:
      Code:
      local pPlayer = Players[iPlayer]
      local pPlayerUnits = pPlayer:GetUnits()
      for i, pUnit in pPlayerUnits:Members() do
      	if not UnitIsDeadToPlayer(pUnit, iPlayer) then
      		--do something for units that are not dead
      	end
      end
    4. You must pass the data to the function for the following arguments:
      • pUnit is an argument that expects the unit's object
      • iPlayer is an argument that expects the player's ID #
    Return to the Utility "Main" Menu

    IsUniqueReplacement
    1. Code:
      Code:
      function IsUniqueReplacement(sData)
      	if GameInfo.Buildings[sData] ~= nil then
      		for ReplacementBuilding in GameInfo.BuildingReplaces() do
      			if ReplacementBuilding.CivUniqueBuildingType == sData then
      				return true
      			end
      		end
      	elseif GameInfo.Districts[sData] ~= nil then
      		for ReplacementDistrict in GameInfo.DistrictReplaces() do
      			if ReplacementDistrict.CivUniqueDistrictType == sData then
      				return true
      			end
      		end
      	elseif GameInfo.Units[sData] ~= nil then
      		for ReplacementUnit in GameInfo.UnitReplaces() do
      			if ReplacementUnit.CivUniqueUnitType == sData then
      				return true
      			end
      		end
      	end
      	return false
      end
    2. Returns true/false as to whether an item is a unique replacement
    3. The code automatically recognizes the difference between a unit, building, or district, and discards (ie, returns false) for anything that is not a valid unit, district, or building in the game's database.
    4. You must pass the data to the function for the following arguments:
      • sData is a text string. You pass information to this argument as either a variable or as direct text such as "BUILDING_BROADWAY", "DISTRICT_MBANZA", or "UNIT_ARABIAN_MAMLUK"
    Return to the Utility "Main" Menu

    GetReplacementsPrimaryItem
    1. Code:
      Code:
      function GetReplacementsPrimaryItem(sData)
      	if GameInfo.Buildings[sData] ~= nil then
      		for ReplacementBuilding in GameInfo.BuildingReplaces() do
      			if ReplacementBuilding.CivUniqueBuildingType == sData then
      				return ReplacementBuilding.ReplacesBuildingType
      			end
      		end
      	elseif GameInfo.Districts[sData] ~= nil then
      		for ReplacementDistrict in GameInfo.DistrictReplaces() do
      			if ReplacementDistrict.CivUniqueDistrictType == sData then
      				return ReplacementDistrict.ReplacesDistrictType
      			end
      		end
      	elseif GameInfo.Units[sData] ~= nil then
      		for ReplacementUnit in GameInfo.UnitReplaces() do
      			if ReplacementUnit.CivUniqueUnitType == sData then
      				return ReplacementUnit.ReplacesUnitType
      			end
      		end
      	end
      	return nil
      end
    2. Returns the text name of the District, Unit, or Buildings for the "standard" unit, building, or district a unique replacement is the replacement for.
      • so if I do this
        Code:
        print(GetReplacementsPrimaryItem("DISTRICT_MBANZA"))
        I will get "DISTRICT_NEIGHBORHOOD" printed into the game's lua.log file
    3. The code automatically recognizes the difference between a unit, building, or district, and discards (ie, returns nil) for anything that is not a valid unit, district, or building in the game's database.
    4. The code also returns nil if you send the name of a unit, district, or building that is not a unique replacement.
    5. You want to use this function and the previous one in a "set", as like this:
      Code:
      local sDistrictName = "DISTRICT_MBANZA"
      if IsUniqueReplacement(sDistrictName) then
      	print(GetReplacementsPrimaryItem(sDistrictName))
      else
      	print(sDistrictName .. " is not a unique replacement for anything")
      end
    6. You must pass the data to the function for the following arguments:
      • sData is a text string. You pass information to this argument as either a variable or as direct text such as "BUILDING_BROADWAY", "DISTRICT_MBANZA", or "UNIT_ARABIAN_MAMLUK"
    Return to the Utility "Main" Menu

    HasUniqueReplacements
    1. Code:
      Code:
      function HasUniqueReplacements(sData)
      	if GameInfo.Buildings[sData] ~= nil then
      		for ReplacesBuilding in GameInfo.BuildingReplaces() do
      			if ReplacesBuilding.ReplacesBuildingType == sData then
      				return true
      			end
      		end
      	elseif GameInfo.Districts[sData] ~= nil then
      		for ReplacesDistrict in GameInfo.DistrictReplaces() do
      			if ReplacesDistrict.ReplacesDistrictType == sData then
      				return true
      			end
      		end
      	elseif GameInfo.Units[sData] ~= nil then
      		for ReplacesUnit in GameInfo.UnitReplaces() do
      			if ReplacesUnit.ReplacesUnitType == sData then
      				return true
      			end
      		end
      	end
      	return false
      end
    2. Returns true/false as to whether the item-data passed is the "standard" item for which there are unique replacements.
    3. The code automatically recognizes the difference between a unit, building, or district, and discards (ie, returns false) for anything that is not a valid unit, district, or building in the game's database.
    4. You must pass the data to the function for the following arguments:
      • sData is a text string. You pass information to this argument as either a variable or as direct text such as "BUILDING_BROADWAY", "DISTRICT_MBANZA", or "UNIT_ARABIAN_MAMLUK"
    Return to the Utility "Main" Menu

    IsUniqueReplacementBuilding
    1. Code:
      Code:
      function IsUniqueReplacementBuilding(sData)
      	if GameInfo.Buildings[sData] ~= nil then
      		for ReplacementBuilding in GameInfo.BuildingReplaces() do
      			if ReplacementBuilding.CivUniqueBuildingType == sData then
      				return true
      			end
      		end
      	end
      	return false
      end
    2. Returns true/false as to whether the item-data passed is a unique replacement building.
    3. The code automatically recognizes the difference a valid building, and discards (ie, returns false) for anything that is not a valid building in the game's database.
    4. You must pass the data to the function for the following arguments:
      • sData is a text string. You pass information to this argument as either a variable or as direct text such as "BUILDING_STAVE_CHURCH".
    Return to the Utility "Main" Menu

    IsPrimaryBuilding
    1. Code:
      Code:
      function IsPrimaryBuilding(sData)
      	if GameInfo.Buildings[sData] ~= nil then
      		for PrimaryBuilding in GameInfo.BuildingReplaces() do
      			if PrimaryBuilding.ReplacesBuildingType == sData then
      				return true
      			end
      		end
      	end
      	return false
      end
    2. Returns true/false as to whether the item-data passed is the standard of "primary" building for which there are unique replacement buildings.
    3. The code automatically recognizes the difference a valid building, and discards (ie, returns false) for anything that is not a valid building in the game's database.
    4. You must pass the data to the function for the following arguments:
      • sData is a text string. You pass information to this argument as either a variable or as direct text such as "BUILDING_TEMPLE".
    Return to the Utility "Main" Menu

    CityHasUniqueReplacementForPrimaryBuilding
    1. Code:
      Code:
      function CityHasUniqueReplacementForPrimaryBuilding(pCity, sPrimaryBuildingName)
      	if GameInfo.Buildings[sPrimaryBuildingName] ~= nil then
      		for PrimaryBuilding in GameInfo.BuildingReplaces() do
      			if PrimaryBuilding.ReplacesBuildingType == sPrimaryBuildingName then
      				if pCity:GetBuildings():HasBuilding(GameInfo.Buildings[PrimaryBuilding.CivUniqueBuildingType].Index) then
      					return true
      				end
      			end
      		end
      	end
      	return false
      end
    2. Returns true/false as to whether the city passed as argument pCity has a unique replacement building for the item-data passed as argument sPrimaryBuildingName
    3. If the city has the actual "primary" building, you will get false because the primary is not a unique replacement building. So, running the function as this
      Code:
      CityHasUniqueReplacementForPrimaryBuilding(pCity, "BUILDING_TEMPLE")
      will give the following results:
      • If the city has a Stave Church you will get boolean true
      • If the city has a Temple you will get boolean false
    4. The code automatically recognizes a valid building, and discards (ie, returns false) for anything that is not a valid building in the game's database.
    5. You must pass the data to the function for the following arguments:
      • sPrimaryBuildingName is a text string. You pass information to this argument as either a variable or as direct text such as "BUILDING_TEMPLE".
      • pCity is an object reference to the city. You have to get the city's object reference and pass this data in the argument position for pCity.
    Return to the Utility "Main" Menu

    GetReplacementsPrimaryBuildingIndex
    1. Code:
      Code:
      function GetReplacementsPrimaryBuildingIndex(sData)
      	if GameInfo.Buildings[sData] ~= nil then
      		for ReplacementBuilding in GameInfo.BuildingReplaces() do
      			if ReplacementBuilding.CivUniqueBuildingType == sData then
      				return GameInfo.Buildings[ReplacementBuilding.ReplacesBuildingType].Index
      			end
      		end
      	end
      	return -1
      end
    2. Returns the integer Index # for the Building the Unique Replacment Building replaces
    3. If you pass "BUILDING_STAVE_CHURCH" as argument sData you will get the Index # for "BUILDING_TEMPLE"
    4. If the data you pass as sData is neither a valid building nor a unique replacement building, you will get -1.
    5. Example: the following would cause "12" to be printed into the game's lua.log file because "BUILDING_TEMPLE" is the building that "BUILDING_STAVE_CHURCH" replaces and "BUILDING_TEMPLE" is at Index position #12 in table <Buildings>:
      Code:
      print(GetReplacementsPrimaryBuildingIndex("BUILDING_STAVE_CHURCH"))
      "BUILDING_MONUMENT" is at Index position "0" in table <Buildings>, "BUILDING_PALACE" is at Index Position "1".
    6. Example: the following would cause "-1" to be printed into the game's lua.log file because "BUILDING_TEMPLE" is not a unique replacement building:
      Code:
      print(GetReplacementsPrimaryBuildingIndex("BUILDING_TEMPLE"))
    7. Example: the following would cause "-1" to be printed into the game's lua.log file because "BUILDING_LAMBS_EAT_OATSES" is not a valid building:
      Code:
      print(GetReplacementsPrimaryBuildingIndex("BUILDING_LAMBS_EAT_OATSES"))
    8. You must pass the data to the function for the following arguments:
      • sData is a text string. You pass information to this argument as either a variable or as direct text such as "BUILDING_STAVE_CHURCH".
    Return to the Utility "Main" Menu

    ResourceIsRevealedToPlayer
    1. Code:
      Code:
      function ResourceIsRevealedToPlayer(iPlayer, iResource)
      	local pPlayer = Players[iPlayer]
      	local tResourceData = GameInfo.Resources[iResource]
      	if tResourceData ~= nil then
      		local sTech = tResourceData.PrereqTech
      		if (sTech ~= nil) and (sTech ~= -1) and (sTech ~= "NONE") and (sTech ~= "NULL") and (sTech ~= "null") then
      			local iTech = GetTechID(sTech)
      			if iTech >= 0 then
      				return PlayerHasTech(pPlayer, iTech)
      			else
      				--print("ResourceIsRevealedToPlayer: invalid technology prereq data for resource Index # " .. tostring(iResource) .. ", returning false")
      			end
      		else
      			return true
      		end
      	else
      		--print("ResourceIsRevealedToPlayer: invalid resource data for resource Index # " .. tostring(iResource) .. ", returning false")
      	end
      	return false
      end
    2. Returns true/false as to whether a given player can see (use) the specified resource.
    3. The code automatically recognizes a valid resource, and discards (ie, returns false) for anything that is not a valid resource in the game's database.
    4. Example: If I want to know whether a player can see "Iron" I might so this as part of a code that would run every turn for every player:
      Code:
      local iResourceIron = GameInfo.Resources["RESOURCE_IRON"].Index
      function ResourceIsRevealedToPlayer(iPlayer, iResource)
      	local pPlayer = Players[iPlayer]
      	local tResourceData = GameInfo.Resources[iResource]
      	if tResourceData ~= nil then
      		local sTech = tResourceData.PrereqTech
      		if (sTech ~= nil) and (sTech ~= -1) and (sTech ~= "NONE") and (sTech ~= "NULL") and (sTech ~= "null") then
      			local iTech = GetTechID(sTech)
      			if iTech >= 0 then
      				return PlayerHasTech(pPlayer, iTech)
      			else
      				--print("ResourceIsRevealedToPlayer: invalid technology prereq data for resource Index # " .. tostring(iResource) .. ", returning false")
      			end
      		else
      			return true
      		end
      	else
      		--print("ResourceIsRevealedToPlayer: invalid resource data for resource Index # " .. tostring(iResource) .. ", returning false")
      	end
      	return false
      end
      function PrintCanSeeIron(iPlayer, bIsFirstTime)
      	if Players[iPlayer]:IsMajor() then
      		local sPlayerCivName = PlayerConfigurations[iPlayer]:GetCivilizationTypeName()
      		local sPlayerLeaderName = PlayerConfigurations[iPlayer]:GetLeaderTypeName()
      		if ResourceIsRevealedToPlayer(iPlayer, iResourceIron) then
      			print("[PrintCanSeeIron] Player # " .. iPlayer .. " is being used as " .. sPlayerCivName .. " with leader of " .. sPlayerLeaderName .. " and can see Iron")
      		else
      			print("[PrintCanSeeIron] Player # " .. iPlayer .. " is being used as " .. sPlayerCivName .. " with leader of " .. sPlayerLeaderName .. " and cannot currently see Iron")
      		end
      	end
      end
      Events.PlayerTurnActivated.Add(PrintCanSeeIron)
    5. You must pass the data to the function for the following arguments:
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • iResource this is the resource's Index #
    Return to the Utility "Main" Menu

    GetCityPlots
    1. Code:
      Code:
      function GetCityPlots(pCity)
      	local iCityRadius = 3
      	local tTempTable = {}
      	if pCity ~= nil then
      		local iCityOwner = pCity:GetOwner()
      		local iCityX, iCityY = pCity:GetX(), pCity:GetY()
      		for dx = (iCityRadius * -1), iCityRadius do
      			for dy = (iCityRadius * -1), iCityRadius do
      				local pPlotNearCity = Map.GetPlotXYWithRangeCheck(iCityX, iCityY, dx, dy, iCityRadius);
      				if pPlotNearCity and (pPlotNearCity:GetOwner() == iCityOwner) and (pCity == Cities.GetPlotPurchaseCity(pPlotNearCity:GetIndex())) then
      					table.insert(tTempTable, pPlotNearCity)
      					--print("[GetCityPlots] plot object added to City Plots table tTempTable with X,Y values of X" .. pPlotNearCity:GetX() .. ", Y" .. pPlotNearCity:GetY() .. " (dx = " .. dx .. ", dy = " .. dy .. ")")
      				end
      			end
      		end
      	end
      	return tTempTable
      end
    2. Returns an lua-table of plots that belong to the city in a form where all the table "v" values are actually plot objects.
    3. Example: If I want to print "The City Has a Mountain" for each mountain that belongs to a given city:
      Code:
      for i,pPlot in pairs(GetCityPlots(pCity)) do
      	if pPlot:IsMountain() then
      		print("The City Has a Mountain")
      	end
      end
      Or I can do the same code as this:
      Code:
      local tCityPlots = GetCityPlots(pCity)
      for i,pPlot in pairs(tCityPlots) do
      	if pPlot:IsMountain() then
      		print("The City Has a Mountain")
      	end
      end
    4. You must pass the data to the function for the following arguments:
      • pCity is an object reference to the city. You have to get the city's object reference and pass this data in the argument position for pCity.
    Return to the Utility "Main" Menu

    GetValidPlotsInRadiusR
    1. Code:
      Code:
      function GetValidPlotsInRadiusR(pPlot, iRadius)
      	local tTempTable = {}
      	if pPlot ~= nil then
      		local iPlotX, iPlotY = pPlot:GetX(), pPlot:GetY()
      		for dx = (iRadius * -1), iRadius do
      			for dy = (iRadius * -1), iRadius do
      				local pNearPlot = Map.GetPlotXYWithRangeCheck(iPlotX, iPlotY, dx, dy, iRadius);
      				if pNearPlot and (pNearPlot ~= pPlot) then
      					table.insert(tTempTable, pNearPlot)
      				end
      			end
      		end
      	end
      	return tTempTable
      end
    2. Returns an lua-table of valid plots that are within the specified radius of the origin plot, with the returned table in a form where all the table "v" values are actually plot objects.
    3. Example: If I want to print "We have found a Natural Wonder" for each Natural Wonder found within a range of 4 tiles of a central plot:
      Code:
      for i,pNearbyPlot in pairs(GetValidPlotsInRadiusR(pPlot, 4)) do
      	if pNearbyPlot:IsNaturalWonder() then
      		print("We have found a Natural Wonder")
      	end
      end
      Or I can do the same code as this:
      Code:
      local tNearbyPlots = GetValidPlotsInRadiusR(pPlot, 4)
      for i,pNearbyPlot in pairs(tNearbyPlots) do
      	if pNearbyPlot:IsNaturalWonder() then
      		print(""We have found a Natural Wonder")
      	end
      end
      The presumption is being made that the code has already retrieved the plot object for the center plot.
    4. The original center-plot of the search will never be included in the table of plots returned by the function.
    5. If you want the center-plot included in whatever other code you are executing on the resulting table of plots, simply do as this:
      Code:
      local tNearbyPlots = GetValidPlotsInRadiusR(pPlot, 4)
      table.insert(tNearbyPlots, pPlot)
      for i,pNearbyPlot in pairs(tNearbyPlots) do
      	if pNearbyPlot:IsNaturalWonder() then
      		print(""We have found a Natural Wonder")
      	end
      end
    6. You must pass the data to the function for the following arguments:
      • pPlot is an object reference to the center plot for the search. You have to get the plot's object reference and pass this data in the argument position for pPlot.
      • iRadius is an intenger value you set for the radius out from the center pPlot that the code should grab information for. All plots within this radius of the center pPlot will be added to the table of plots you get from running this function.
    Return to the Utility "Main" Menu

    CivicHasPreReq
    1. Code:
      Code:
      function CivicHasPreReq(sCivic)
      	for Row in GameInfo.CivicPrereqs() do
      		if Row.Civic == sCivic then
      			return true
      		end
      	end
      	return false
      end
    2. Returns boolean true/false so to whether or not a specified civi has a prerequisite in table <CivicPrereqs>
    3. You must pass the data to the function for the following arguments:
      • sCivic is a text string. You pass information to this argument as either a variable or as direct text such as "CIVIC_CRAFTSMANSHIP".
    Return to the Utility "Main" Menu

    GetCivicPreReqs
    1. Code:
      Code:
      function GetCivicPreReqs(sCivic)
      	local tTable = {}
      	for Row in GameInfo.CivicPrereqs() do
      		if Row.Civic == sCivic then
      			table.insert(tTable, Row.PrereqCivic)
      		end
      	end
      	return tTable
      end
    2. Returns an lua-table of all Civics that are listed as direct prerequisites in table <CivicPrereqs> for the specified Civic
    3. The resulting table will be in a form wherein all the "v" values are the names of Civics as in "CIVIC_CODE_OF_LAWS".
    4. An lua-table is used as the "return" value because some civics have multiple prerequisite civics and others have only one or none at all.
    5. "CIVIC_CODE_OF_LAWS" has no prerequisites listed in table <CivicPrereqs> so doing this will not cause an error but neither will anything be printed:
      Code:
      for i,sPrereqCivic in pairs(GetCivicPreReqs("CIVIC_CODE_OF_LAWS")) do
      	print("CIVIC_CODE_OF_LAWS has a prerequisite civic of " .. sPrereqCivic)
      end
    6. You must pass the data to the function for the following arguments:
      • sCivic is a text string. You pass information to this argument as either a variable or as direct text such as "CIVIC_CRAFTSMANSHIP".
    Return to the Utility "Main" Menu
     
    Last edited: Aug 5, 2017
  10. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    Utility Sub-System: Miscellaneous Snippets of Lua Code (continued)

    GetTechID
    1. Code:
      Code:
      function GetTechID(sTech)
      	local tTechData = GameInfo.Technologies[sTech]
      	if tTechData == nil then
      		--print("GetTechID: invalid sTech, returning -1")
      		return -1
      	end
      	return tTechData.Index
      end
    2. Returns the Index # from table <Technologies> for the technology you specify. If you send the name of a technology that does not exist within the game's database, the code returns -1.
    3. Since there is no direct GameInfoTypes equivalent in Civ6, we cannot rely on grabbing a tech's GameInfoType nor rely on this being -1 is a tech does not exist because we typed the name wrong or some other mod removed the tech from the game.
    4. The DB.MakeHash() that works for Civics, as in:
      Code:
      local iCivic = DB.MakeHash(sCivic)
      Did not work reliably for technologies when the game was originally released so I avoided attempting that method except in the few tables wherein I had already verified the code was hooked properly for the given table to the "Hash" system.
    5. You can use this function as a template for any other table that does not seem to give reliable results when you attempt:
      Code:
      local iData = DB.MakeHash(sNameOfItem)
    6. You must pass the data to the function for the following arguments:
      • sTech is a text string. You pass information to this argument as either a variable or as direct text such as "TECH_CHEMISTRY".
    Return to the Utility "Main" Menu

    PlayerHasTech
    1. Code:
      Code:
      function PlayerHasTech(pPlayer, iTech)
      	if iTech >= 0 then
      		local pPlayerTechs = pPlayer:GetTechs()
      		if pPlayerTechs ~= nil then
      			return pPlayerTechs:HasTech(iTech)
      		else
      			--print("PlayerHasTech: invalid player techs table for player, returning false")
      		end
      	end
      	return false
      end
    2. Returns boolean true/false as to whether the specified player has the specified technology.
    3. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iTech is an intenger value that will be the Index # from table <Technologies> for the technology you wish to verify a player has. You can use function GetTechID(sTech) to get this info, like this:
        Code:
        local sTechForCheck = "HAPPY_BOATS"
        if GetTechID(sTechForCheck) == -1 then
        	print("The game has no technology called " .. sTechForCheck)
        else
        	if PlayerHasTech(pPlayer, GetTechID(sTechForCheck)) then
        		print("The player has the technology " .. sTechForCheck)
        	else
        		print("The player does not have the technology " .. sTechForCheck)
        	end
        end
    Return to the Utility "Main" Menu

    GetPlayersTechCost
    1. Code:
      Code:
      function GetPlayersTechCost(sTech, pPlayer, iPlayer)
      	local pPlayerTechs = pPlayer:GetTechs()
      	if pPlayerTechs ~= nil then
      		local iTech = GetTechID(sTech)
      		if iTech >= 0 then
      			return pPlayerTechs:GetResearchCost(iTech)
      		end
      	else
      		--print("GetPlayersTechCost: invalid player techs table for player # " .. iPlayer .. ", returning nil")
      	end
      	return nil
      end
    2. This function needs the GetTechID(sTech) function presented earlier to be available within and placed higher-up within the same lua file
    3. Returns the tech cost in number of beakers of the tech for the specified player. This accounts for adjustments made to the "standard" cost of the tech by difficulty settings, game speed, etc.
    4. If the tech name passed to the function is invalid or the code cannot calculate the tech cost for some other reason, the function returns boolean nil
    5. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • sTech is a text string. You pass information to this argument as either a variable or as direct text such as "TECH_CHEMISTRY".
    Return to the Utility "Main" Menu

    FinishCurrentTechResearch
    1. Code:
      Code:
      function FinishCurrentTechResearch(pPlayer, iPlayer)
      	local pPlayerTechs = pPlayer:GetTechs()
      	if pPlayerTechs ~= nil then
      		local iTech = pPlayerTechs:GetResearchingTech()
      		if iTech > -1 then
      			local iTechCost = pPlayerTechs:GetResearchCost(iTech)
      			if (iTechCost ~= nil) and (iTechCost > 0) then
      				pPlayerTechs:SetResearchProgress(iTech, iTechCost)
      				return true
      			end
      		end
      	else
      		--print("FinishCurrentTechResearch: invalid player techs table for player # " .. iPlayer .. ", returning nil")
      	end
      	return nil
      end
    2. Completes the research on the technology the player is currently researching.
    3. The function returns boolean true when it succeeds in finishing the player's current research tech.
    4. If the player is not currently researching anything or the code cannot finish the player's current research for some other reason, the function returns boolean nil
    5. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
    Return to the Utility "Main" Menu

    FinishTech
    1. Code:
      Code:
      function FinishTech(sTech, pPlayer, iPlayer)
      	local iTech = GetTechID(sTech)
      	if iTech >= 0 then
      		local pPlayerTechs = pPlayer:GetTechs()
      		if pPlayerTechs ~= nil then
      			local iTechCost = pPlayerTechs:GetResearchCost(iTech)
      			if (iTechCost ~= nil) and (iTechCost > 0) then
      				pPlayerTechs:SetResearchProgress(iTech, iTechCost)
      				return true
      			end
      		else
      			--print("FinishTech: invalid player techs table for player # " .. iPlayer .. ", returning nil")
      		end
      	end
      	return nil
      end
    2. This function needs the GetTechID(sTech) function presented earlier to be available within and placed higher-up within the same lua file
    3. Finishes research for the player for the specific technology stated.
    4. The function returns boolean true when it succeeds in finishing the player's research on the specified tech.
    5. If the code cannot finish the research on the specified tech for any reason, the function returns boolean nil
    6. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • sTech is a text string. You pass information to this argument as either a variable or as direct text such as "TECH_CHEMISTRY".
    Return to the Utility "Main" Menu

    SetTechResearchProgress
    1. Code:
      Code:
      function SetTechResearchProgress(sTech, iValue, pPlayer, iPlayer)
      	local iTech = GetTechID(sTech)
      	if iTech >= 0 then
      		local pPlayerTechs = pPlayer:GetTechs()
      		if pPlayerTechs ~= nil then
      			pPlayerTechs:SetResearchProgress(iTech, iValue)
      			return true
      		else
      			--print("SetTechResearchProgress: invalid player techs table for player # " .. iPlayer .. ", returning nil")
      		end
      	end
      	return nil
      end
    2. This function needs the GetTechID(sTech) function presented earlier to be available within and placed higher-up within the same lua file
    3. Sets a completion amount in number of beakers for research on a given technology for a given player.
    4. The function returns boolean true when it succeeds in setting the player's research completion amount on the specified tech.
    5. If the code cannot set the research completion amount on the specified tech for any reason, the function returns boolean nil
    6. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • sTech is a text string. You pass information to this argument as either a variable or as direct text such as "TECH_CHEMISTRY".
      • iValue is an integer value to set the player's reseach progress to on the given technology. This will be the total number of beakers the play will have toward completion of the tech.
    Return to the Utility "Main" Menu

    ChangeCurrentTechProgress
    1. Code:
      Code:
      function ChangeCurrentTechProgress(iChange, pPlayer, iPlayer)
      	local pPlayerTechs = pPlayer:GetTechs()
      	if pPlayerTechs ~= nil then
      		pPlayerTechs:ChangeCurrentResearchProgress(iChange)
      		return true
      	else
      		--print("ChangeCurrentTechProgress: invalid player culture table for player # " .. iPlayer .. ", returning nil")
      	end
      	return nil
      end
    2. NOTE THAT I DO NOT NOW REMEEMBER WHETHER I VERIFIED THIS ACTUALLY WORKS
      • I wrote many helper routines for Really Advanced Setup Lite when the game was first released, but as I fine-tuned the code of Really Advanced Setup Lite I eliminated use of some that were redundant. And I cannot now remember which I verified work properly in some cases.
    3. Changes the progress on the current Technology the Player is 'Researching'
    4. The function returns boolean true when it succeeds in changing the player's research completion amount on the specified tech.
    5. If the code cannot change the research completion amount on the currently researching tech for any reason, the function returns boolean nil
    6. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • iChange is an integer amount to change the current research progress by. It is a number of beakers to add to the current progress.
    Return to the Utility "Main" Menu

    SetCurrentlyResearchingTech
    1. Code:
      Code:
      function SetCurrentlyResearchingTech(sTech, pPlayer, iPlayer)
      	local iTech = GetTechID(sTech)
      	if iTech >= 0 then
      		local pPlayerTechs = pPlayer:GetTechs()
      		if pPlayerTechs ~= nil then
      			pPlayerTechs:SetResearchingTech(iTech)
      			return true
      		else
      			--print("SetCurrentlyResearchingTech: invalid player techs table for player # " .. iPlayer .. ", returning nil")
      		end
      	end
      	return nil
      end
    2. This function needs the GetTechID(sTech) function presented earlier to be available within and placed higher-up within the same lua file
    3. Sets the Technology the Player is 'Currently Researching'
    4. The function returns boolean true when it succeeds in setting the player's research tech.
    5. If the code cannot set the research tech for any reason, the function returns boolean nil
    6. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • sTech is a text string. You pass information to this argument as either a variable or as direct text such as "TECH_CHEMISTRY".
    Return to the Utility "Main" Menu

    GetCurrentlyResearchingTech
    1. Code:
      Code:
      function GetCurrentlyResearchingTech(pPlayer, iPlayer)
      	local pPlayerTechs = pPlayer:GetTechs()
      	if pPlayerTechs ~= nil then
      		return pPlayerTechs:GetResearchingTech()
      	else
      		--print("GetCurrentlyResearchingTech: invalid player techs table for player # " .. iPlayer .. ", returning nil")
      	end
      	return nil
      end
    2. Returns the Index # of the tech the player is currently researching.
    3. If the code cannot figure out and return the Index # for the currenntly being researched tech for any reason, the function returns boolean nil
    4. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
    Return to the Utility "Main" Menu

    GetPlayersTechProgress
    1. Code:
      Code:
      function GetPlayersTechProgress(sTech, pPlayer, iPlayer)
      	local iTech = GetTechID(sTech)
      	if iTech >= 0 then
      		local pPlayerTechs = pPlayer:GetTechs()
      		if pPlayerTechs ~= nil then
      			return pPlayerTechs:GetResearchProgress(iTech)
      		else
      			--print("GetPlayersTechProgress: invalid player techs table for player # " .. iPlayer .. ", returning nil")
      		end
      	end
      	return nil
      end
    2. This function needs the GetTechID(sTech) function presented earlier to be available within and placed higher-up within the same lua file
    3. Returns the Progress in numerical beakers the Player has toward the specified technology. The game keeps account of this data with decimal extensions applied so you can get results such as "10", "15.4765325", "20", etc.
      • you may want to apply either "math.floor()" or "math.ceil()" to the result you get after checking that the result was not nil
    4. The player does not have to be actively researching the specified technology to get valid results. If a tech has been boosted but the player is not currently researching the specified tech, you will get the data for how much total boost has been applied. If some other lua code adds beakers toward completion of a tech, this also will be reflected in the total number returned for the specified technology.
    5. The function does not report whether or not the player has completed research on the technology.
    6. If no progress has been made on a specified tech, the result will be numerical 0 instead of boolean nil so long as the code is able to acquire a reading for the specified tech (ie, the tech name is valid).
    7. If the code cannot calculate the research completion amount on the specified tech for any reason, the function returns boolean nil
    8. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • sTech is a text string. You pass information to this argument as either a variable or as direct text such as "TECH_CHEMISTRY".
    Return to the Utility "Main" Menu

    FinishCivic
    1. Code:
      Code:
      function FinishCivic(sCivic, pPlayer, iPlayer)
      	local iCivic = DB.MakeHash(sCivic)
      	if iCivic ~= nil then
      		local pCulture = pPlayer:GetCulture()
      		if pCulture ~= nil then
      			local iCivicCost = pCulture:GetCultureCost(iCivic)
      			pCulture:SetCulturalProgress(iCivic, iCivicCost)
      			return true
      		else
      			--print("FinishCivic: invalid player civics table for player # " .. iPlayer .. ", returning nil")
      		end
      	else
      		--print("FinishCivic: invalid civic hash")
      	end
      	return nil
      end
    2. "Finishes" the specified civic for the player. Even if the player is not "working on researching" the specified civic, the function completes it for the player.
    3. The function returns boolean true when it succeeds in finishing the the civic for the player.
    4. If the code cannot finish the civic for the player for any reason, the function returns boolean nil
    5. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • sCivic is a text string. You pass information to this argument as either a variable or as direct text such as "CIVIC_CRAFTSMANSHIP".
    Return to the Utility "Main" Menu

    SetCivicProgress
    1. Code:
      Code:
      function SetCivicProgress(sCivic, iIntChange, pPlayer, iPlayer)
      	local pCulture = pPlayer:GetCulture()
      	if pCulture ~= nil then
      		local iCivic = DB.MakeHash(sCivic)
      		if iCivic ~= nil then
      			pCulture:SetCulturalProgress(iCivic, iIntChange)
      			return true
      		else
      			--print("SetCivicProgress: invalid civic hash, returning nil")
      		end
      	else
      		--print("SetCivicProgress: invalid player civics table for player # " .. iPlayer .. ", returning nil")
      	end
      	return nil
      end
    2. Set the player 'research' progress for the given civic, in culture-points.
    3. The function returns boolean true when it succeeds in setting the player's 'research' completion amount on the specified civic.
    4. If the code cannot set the research completion amount on the specified tech for any reason, the function returns boolean nil
    5. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • sCivic is a text string. You pass information to this argument as either a variable or as direct text such as "CIVIC_CRAFTSMANSHIP".
      • iIntChang is an integer value in terms of number of culture points to add or subtract.
    Return to the Utility "Main" Menu

    SetResearchingCivic
    1. Code:
      Code:
      function SetResearchingCivic(sCivic, pPlayer, iPlayer)
      	local pCulture = pPlayer:GetCulture()
      	if pCulture ~= nil then
      		local iCivic = DB.MakeHash(sCivic)
      		if iCivic ~= nil then
      			pCulture:SetCivic(iCivic)
      			return true
      		else
      			--print("SetResearchingCivic: invalid civic hash, returning nil")
      		end
      	else
      		--print("SetResearchingCivic: invalid player civics table for player # " .. iPlayer .. ", returning nil")
      	end
      	return nil
      end
    2. NOTE THAT I DO NOT NOW REMEEMBER WHETHER I VERIFIED THIS ACTUALLY WORKS
      • I wrote many helper routines for Really Advanced Setup Lite when the game was first released, but as I fine-tuned the code of Really Advanced Setup Lite I eliminated use of some that were redundant. And I cannot now remember which I verified work properly in some cases.
    3. Sets the civic the player is currently 'researching'.
    4. The function returns boolean true when it succeeds in setting the player's current civic 'research' project to the specified civic.
    5. If the code cannot set the current civic 'research' project to the specified civic for any reason, the function returns boolean nil
    6. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • sCivic is a text string. You pass information to this argument as either a variable or as direct text such as "CIVIC_CRAFTSMANSHIP".
    Return to the Utility "Main" Menu
     
  11. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    Utility Sub-System: Miscellaneous Snippets of Lua Code (continued)

    ChangeCurrentCivicProgress
    1. Code:
      Code:
      function ChangeCurrentCivicProgress(iIntChange, pPlayer, iPlayer)
      	local pCulture = pPlayer:GetCulture()
      	if pCulture ~= nil then
      		pCulture:ChangeCurrentCulturalProgress(iIntChange)
      		return true
      	else
      		--print("ChangeCurrentCivicProgress: invalid player culture table for player # " .. iPlayer .. ", returning nil")
      	end
      	return nil
      end
    2. NOTE THAT I DO NOT NOW REMEEMBER WHETHER I VERIFIED THIS ACTUALLY WORKS
      • I wrote many helper routines for Really Advanced Setup Lite when the game was first released, but as I fine-tuned the code of Really Advanced Setup Lite I eliminated use of some that were redundant. And I cannot now remember which I verified work properly in some cases.
    3. Changes the progress on the current Civic the Player is 'Researching'
    4. The function returns boolean true when it succeed.
    5. If the code fails for any reason, the function returns boolean nil
    6. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
      • iIntChange is an integer amount in culture-points to add or subtract to the progress
    Return to the Utility "Main" Menu

    FinishCurrentCivicProgress
    1. Code:
      Code:
      -function FinishCurrentCivicProgress(pPlayer, iPlayer)
      	local pCulture = pPlayer:GetCulture()
      	if pCulture ~= nil then
      		local iCurrentCivicID = pCulture:GetProgressingCivic();
      		if (iCurrentCivicID ~= nil) and (iCurrentCivicID >= 0) then
      			local iCivicCost = pCulture:GetCultureCost(iCurrentCivicID)
      			pCulture:SetCulturalProgress(iCurrentCivicID, iCivicCost)
      			return true
      		else
      			--print("FinishCurrentCivicProgress: cannot access the current civic research item, returning nil")
      		end
      	else
      		--print("FinishCurrentCivicProgress: invalid player culture table for player # " .. iPlayer .. ", returning nil")
      	end
      	return nil
      end
    2. NOTE THAT I DO NOT NOW REMEEMBER WHETHER I VERIFIED THIS ACTUALLY WORKS
      • I wrote many helper routines for Really Advanced Setup Lite when the game was first released, but as I fine-tuned the code of Really Advanced Setup Lite I eliminated use of some that were redundant. And I cannot now remember which I verified work properly in some cases.
    3. Finishes the 'research' on whichever civic the player is currently 'researching'.
    4. The function returns boolean true when it succeeds.
    5. If the code cannot complete 'research' on the the specified civic for any reason, the function returns boolean nil
    6. You must pass the data to the function for the following arguments:
      • pPlayer is an object reference to the player. You have to get the player's object reference and pass this data in the argument position for pPlayer, like this
        Code:
        local pPlayer = Players[iPlayer]
        iPlayer is the player # from the list of in-game active players, and is sent to you from the game's core operating system when most lua "events" fire.
      • iPlayer this is the player # from the list of players in the current game. Nearly all lua core game "hook events" will give you this data.
    Return to the Utility "Main" Menu


    Utility Sub-System: Topic6
    (just a placeholder at the moment)​
    Return to the Utility "Main" Menu

    Utility Sub-System: Topic7
    (just a placeholder at the moment)​
    Return to the Utility "Main" Menu
     
  12. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
  13. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
  14. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    The system has been re-structured into a stand-alone mod that is now a prerequisite mod that a user downloads and enables. You just need to create a dependancy to the prerequisite mod within your mod. I have covered in detail the needed modbuddy menu clicks to add this dependancy.

    Please be a little patient with questions and the like over the weekend while I update the Buildings Are Fun mod and look back through the thread ofr confusing or left-over contradictory instructions.

    Feel free to ask away just have a littel patience on the time it takes for me to repsond with answers.
     
  15. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
  16. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    The summer patch broke the code I was using to hide dummy buildings and otherwise de-kludge the city production panel from showing 8 bajillion buildngs you could not produce at the moment.

    I have fixes worked out but I am holding off at least for a few days on an update because some people are experiencing certain things that the Summer Patch broke in the base game and this may mean a hotfix will be coming soon to cure the ills introduced into even un-modded games by this most recent patch.

    Part of this update will be more reliable methods within this utility to keep AI and humans from attempting to construct dummy buildings, and as part of this a streamlining of the code you as a mod-maker need to include for "locking" a dummy building. You will essentially have to do nothing as a mod-maker to lock out a dummy building: the utility will do all of it.
     
  17. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    I've updated the download and provided links to a dropbox where you can download the updated version that is compat with the most recent (Summer '17) patch. If you go to the CFC resource page for the utility I am directing you to the dropbox where the updates will be "housed" hereinafter.

    I cannot seem to get the CFC resource system to accept an update to the pre-provided download button, it just wants to stay stuck on the original version I uploaded to the resource system. So I've placeed a giant red warning message on the CFC Resource page to just use the dopbox link and ignore the button that the forum wants to use.

    I'll be updating instructions on how to set-up dummy buildings with this more-streamlined method. Hint: you as a mod-maker will have to do much less.

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

    Update description from the resource page:

    Spoiler :
    See: CFC Resource Page

    This update simplifies and enhances the systems.

    The simplifications are in making the system auto-handle issues with creating a "lock-out" for dummy buildings, so that mod-makers no longer have to concern themselves with such issues.

    I will update the mod-maker instructions in the next couple of days

    Since we can now "include" custom lua files within other lua files, I have also added my three "toolkit" lua files to the mod and are making the mod send them to the VFS system so that other lua mod-makers can use those "toolkit" files via a simple set of commands within their lua gameplay script files by placing these statements near the top of their file:
    Code:
    include("LeeS_PlotToolkitRoutines.lua")
    include("LeeS_CityToolKitRoutines.lua")
    include("LeeS_PlayerToolkitRoutines.lua")
     
    Last edited: Aug 23, 2017
  18. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,149
    Location:
    Illinois, USA
    Seems I was a bit remiss in getting around to updating the instructions here. Given there appears to be (if rumor is more than mere rumor) a DLC dropping within the next week or so I am going to wait until after working through any changes the DLC and/or patch will require to these systems before issuing an update to the code or the instructions for how to use the systems.
     

Share This Page