Results 1 to 16 of 16

Thread: Scripted buildings: create_building and destroy_buildings

  1. #1
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Scripted buildings: create_building and destroy_buildings

    Buildings can be instantly constructed and destroyed with script. The commands are probably well known to scripters but some of their peculiarities might not be...

    create_building

    Syntax: console_command create_building {settlement_name} {building_level_name}

    e.g. console_command create_building London town_watch

    There are no rules here regarding what can be built. If the settlement already has such a building then this script still works: two of those buildings will now exist there. Clearly that is undesirable in typical situations. Also, it can be used to build "castle" class buildings in "city" class settlements and vice versa. Again, you would probably not wish to do that.

    If your script is going to create a building then it would first need to check two things:
    1. That the building does not already exist in that settlement (unless your intention is to have two, of course).
    2. The class of the settlement - city or castle - to ensure that the correct tree is used. (Some building trees are for either/both - they have no "city" or "castle" qualifier - in which case the point is irrelevant.) And, of course, if the mod allows cities to convert to castles, and vice versa, then no assumption can be made by the script as to which class the settlement currently is. e.g. Want to build a barracks tree building in London? Is it currently a city ("barracks") or a castle ("castle_barracks") class? You'll need to find out with other script.


    destroy_buildings

    Syntax: destroy_buildings {faction_name} {building_tree_name} {true/false}

    e.g. destroy_buildings england barracks true

    This destroys all buildings of this building tree in the entire faction.

    Sadly, there is no way to destroy a particular building/tree in just one settlement.

    Actually, that's not quite true. One way would be to transfer ownership of the settlement to another faction (who does not have such a building/tree), use destroy_buildings on that other faction, then give the settlement back to the first faction. In the process it will kick out the occupant characters and units so in most cases it isn't a practical solution.

    The above example will destroy the "barracks" tree (building levels: town_watch, town_guard, city_watch, militia_drill_square, militia_barracks, army_barracks & royal_armoury) in every settlement that england currently owns. It won't, of course, also destroy any buildings from the related castle tree - "castle_barracks" - so to destroy all barracks-type buildings in the faction destroy_buildings will need to be called twice: once with "barracks" and once with "castle_barracks".

    The true/false indicates whether the faction should get money from the demolition(s), in the same way that the player gets money when using the "destroy building" button.

    It is still safe to use this command when the faction does not currently have any of that tree's buildings constructed; no resulting CTD or log errors.

    Hinterland buildings can be destroyed.

    If a settlement has more than one building of that tree constructed then destroy_buildings will only destroy one of them. To destroy them all destroy_buildings must be called multiple times, i.e. twice if there are two buildings, three times if there are three, and so on. It is not possible for the player or AI to construct multiple buildings of the same tree in the same settlement; this situation could only arise via create_building or descr_strat.txt (I assume that descr_strat does not prevent you from giving a settlement multiple buildings of the same tree).


    Recruitment

    If the building being created or destroyed has any recruitment capabilities then there are some things to be aware of.

    For example, say we have a building level named "my_building", in the building tree named "my_building_tree", and a recruitment capability of this:

    Code:
    recruit_pool "Peasants" 1 0.5 5 0
    It has a starting unit count of 1; immediately upon normal construction it would make 1 unit of Peasants available for recruitment. This also applies to create_building. Every time "create_building my_building" is called it adds 1 Peasant to the current recruitment pool level in that settlement.

    If the building is destroyed via destroy_buildings and then rebuilt using create_building then the pool resets - unless those two commands are used without any pause in between, i.e. in the same monitor without any wait, campaign_wait or while loop between them.

    In this example the pool grows by 0.5 every turn. After 4 turns the pool will be 3: 1 from the initial build and 4 x 0.5 = 2 from the replenishment rate.

    If at that time we did this...

    Code:
    monitor_event (whatever)
      destroy_buildings england my_building_tree false
      console_command create_building London my_building
    end_monitor
    ... then in London that pool level of 3 will not be lost. (Although, it will now be 4 because create_building adds 1 as explained above. For this reason it might be best if such a building - one that we are destroying and rebuilding on a regular basis - did not have any starting pool level points.)

    However, if we did this...

    Code:
    monitor_event (whatever)
      destroy_buildings england my_building_tree false
      campaign_wait 0.1
      console_command create_building London my_building
    end_monitor
    ...then the pool will be lost (reset back to 0, or 1 in this example again because of the create_building adding 1). Similarly if we did the destroy_buildings in one monitor and the create_building in another monitor (and therefore at a later time).

    destroy_buildings also removes its recruit_pool units from the recruitment queue, even if create_building is used immediately after it. That is, unless some other building remains in that settlement that also provides recruitment of that unit.

    In this example, if my_building was the only building in London that provided Peasants recruitment, and Peasants are currently in London's recruitment queue, then they will be automatically removed from the queue as soon as destroy_buildings is called. However, if Peasants are also provided by another building (e.g. barracks, which we are not destroying here) and that building exists in London then Peasants will not be removed from the queue.
    Last edited by Withwnar; September 18, 2014 at 03:42 AM.

  2. #2
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Re: Scripted buildings: create_building and destroy_buildings

    Part 2: dynamic creation example

    One application for these commands is to have a certain building auto-built and destroyed by script, such that it automatically only appears in settlements that meet certain conditions.

    This example is quite simple to keep it short: england gets an "english_france" building in whichever of these three settlements england currently owns: Paris, Rheims and Angers. Whenever england takes ownership of one of these regions script auto-builds the building there. Whenever they lose ownership of one of these regions script destroys the building there.

    The building cannot be built or destroyed by the player/AI. Furthermore, this one building is intended for both "city" and "castle" type settlements - only one tree is needed.

    This is the building in EDB:

    Code:
    building hinterland_english_france
    {
      levels english_france
      {
        english_france requires factions { }
        {
          capability
          {
          }
          material wooden
          construction 1 
          cost 0 
          settlement_min village
          upgrades
          {
          }
        }
      }
      plugins
      {
      }
    }
    • hinterland_ - to prevent destruction by player/AI
    • requires factions { } - to prevent construction by player/AI (note the space between the brackets!)
    • capability - some could be added if desired
    • cost 0 - no need for a cost. If it had a cost and "true" was used in destroy_buildings then england would get some money each time the building is destroyed - probably undesirable.
    • construction, settlement_min - irrelevant


    To destroy a building we can only destroy ALL such buildings in the faction. So the only way to implement this is:
    1) Destroy all english_france buildings (all hinterland_english_france trees)
    2) Build it only in those settlements owned by england
    i.e. Tear them all down and (re)build them only where they should now be.

    Here then is the basic script:

    Code:
    monitor_event FactionTurnStart FactionType england
    
      destroy_buildings england hinterland_english_france false
      
      if I_SettlementOwner Paris england
        console_command create_building Paris english_france
      end_if
      if I_SettlementOwner Rheims england
        console_command create_building Rheims english_france
      end_if
      if I_SettlementOwner Angers england
        console_command create_building Angers english_france
      end_if
    
    end_monitor
    It isn't complete because e.g. Paris might have had this building when france recaptures it. So we need to use destroy_buildings on france as well, and any other faction that could possibly take ownership of any of these settlements, i.e. all campaign factions.

    Code:
    monitor_event FactionTurnStart FactionType england
    
      destroy_buildings england hinterland_english_france false
      destroy_buildings france  hinterland_english_france false
      destroy_buildings hre     hinterland_english_france false
      destroy_buildings denmark hinterland_english_france false
      ...and so on for all other factions...
      
      if I_SettlementOwner Paris england
        console_command create_building Paris english_france
      end_if
      if I_SettlementOwner Rheims england
        console_command create_building Rheims english_france
      end_if
      if I_SettlementOwner Angers england
        console_command create_building Angers english_france
      end_if
    
    end_monitor
    So far the script only fires once per turn: england's turn start. When england captures Paris it would be better if the building appeared immediately, not during turn end. And if Paris was given to/from england via diplomacy then it would be better if the building presence/absence was updated immediately.

    This involves more events and therefore more monitors. To avoid duplication of the destroy and create script it can be done like this...

    Code:
    monitor_event FactionTurnEnd FactionType slave
      inc_event_counter english_france_update_now 1
    end_monitor
    
    monitor_event GeneralCaptureSettlement FactionIsLocal
      campaign_wait 0.1
      inc_event_counter english_france_update_now 1
    end_monitor
    
    monitor_event GiveSettlement
      inc_event_counter english_france_update_now 1
    end_monitor
    
    monitor_event BriberyMission FactionIsLocal
      and MissionSuccessLevel > not_successful
      inc_event_counter english_france_update_now 1
    end_monitor
    
    monitor_event EventCounter EventCounterType english_france_update_now
    
      destroy_buildings england hinterland_english_france false
      destroy_buildings france  hinterland_english_france false
      destroy_buildings hre     hinterland_english_france false
      destroy_buildings denmark hinterland_english_france false
      ...and so on for all other factions...
      
      if I_SettlementOwner Paris england
        console_command create_building Paris english_france
      end_if
      if I_SettlementOwner Rheims england
        console_command create_building Rheims english_france
      end_if
      if I_SettlementOwner Angers england
        console_command create_building Angers english_france
      end_if
    
    end_monitor
    Those first four monitors all trigger the last monitor. We really only need to be triggering on things that can happen during the player's turn, so that the buildings are updated as those things happen for the player to see immediately. Anything else, e.g. settlement captured by AI faction, is going to happen during the turn end sequence so the first monitor (slave turn end) is enough to handle those cases because the player is unlikely to see the building before it's their turn again anyway.

    However, there might be other script that can fire at some point within the turn end sequence that relies upon the building presence being up to date. If so then those monitor conditions should be adjusted to cater for that. e.g. Remove the FactionIsLocal from GeneralCaptureSettlement and BriberyMission. Just be aware that it takes time to destroy and create buildings so every unnecessary trigger of the last monitor is adding unnecessary lag to the turn end sequence.

    Note that the campaign_wait is needed in GeneralCaptureSettlement because at the time of that event triggering the settlement has not yet changed hands, so I_SettlementOwner (in the last monitor) would not give correct results.

    If the building should exist anywhere at campaign start, in this example because england owns any of those three settlements, then it can either be added to the settlement(s) in descr_strat.txt or just add this monitor...

    Code:
    monitor_event FactionTurnStart
      inc_event_counter english_france_update_now 1
      terminate_monitor
    end_monitor

    Recruitment Queue

    Now for the last trick. This is only needed if the building provides recruitment and we don't wish its units to be dropped from the queue each time the destroy-rebuild process happens (as mentioned in the first post).

    Let's say that our english_france building provides recruitment of Peasants. The player might have added some Peasants to the queue in Paris and Rheims, then in the same turn captured a settlement somewhere or used diplomacy to give/get some region; those Peasants are now auto-dropped from the queue and the player is likely unaware of it. "Why would capturing Inverness drop Peasants from the queue in Paris?" the player might rightly ask.

    The auto-dropping doesn't happen if there's another building in the settlement that provides the same unit.

    The solution is a bit of sleight of hand:
    1) Ensure that two of our buildings exist in any settlement that should have it
    2) Call destroy_buildings now instead of before the create_building calls of step 1

    It exploits the fact that one call of destroy_buildings only destroys one building from the tree in each settlement. If the settlement has two then after destroy_buildings one will still remain. Because the settlements that should now have the building were never in a state where they did not have this building (during this process) they still had a Peasant-giving building and therefore did not drop Peasants from their queue. For any settlement that currently has the building but should no longer have it (e.g. Paris given away) the extra building is not built there before the destroy_buildings call; the settlement only has one building and destroy_buildings will remove it.

    It needs one counter per settlement that the building may exist in. This counter indicates whether the settlement was left with the building after the last process run (1) or not (0). i.e. Whether this settlement currently has the building.

    Code:
    declare_counter english_france_Paris
    declare_counter english_france_Rheims
    declare_counter english_france_Angers
    
    monitor_event FactionTurnEnd FactionType slave
      inc_event_counter english_france_update_now 1
    end_monitor
    
    monitor_event GeneralCaptureSettlement FactionIsLocal
      campaign_wait 0.1
      inc_event_counter english_france_update_now 1
    end_monitor
    
    monitor_event GiveSettlement
      inc_event_counter english_france_update_now 1
    end_monitor
    
    monitor_event BriberyMission FactionIsLocal
      and MissionSuccessLevel > not_successful
      inc_event_counter english_france_update_now 1
    end_monitor
    
    monitor_event EventCounter EventCounterType english_france_update_now
    
      if I_SettlementOwner Paris england
        console_command create_building Paris english_france
        if I_CompareCounter english_france_Paris == 0
          console_command create_building Paris english_france
        end_if
        set_counter english_france_Paris 1
      end_if
    
      if I_SettlementOwner Rheims england
        console_command create_building Rheims english_france
        if I_CompareCounter english_france_Rheims == 0
          console_command create_building Rheims english_france
        end_if
        set_counter english_france_Rheims 1
      end_if
    
      if I_SettlementOwner Angers england
        console_command create_building Angers english_france
        if I_CompareCounter english_france_Angers == 0
          console_command create_building Angers english_france
        end_if
        set_counter english_france_Angers 1
      end_if
    
      destroy_buildings england hinterland_english_france false
      destroy_buildings france  hinterland_english_france false
      destroy_buildings hre     hinterland_english_france false
      destroy_buildings denmark hinterland_english_france false
      ...and so on for all other factions...
    
    end_monitor
    Only the last monitor has changed, plus the addition of the counters at the top.

    Be aware that all of this extra building creation and destruction adds further processing time. The more settlements involved the longer it will take.

    And a reminder from the first post: if adding recruitment to this building then it is probably best to give it 0 starting points in the recruit_pool. This auto-build process could happen multiple times in a turn and it is unlikely that you wish to be adding 1 (or anything) to the available pool every time it happens.
    Last edited by Withwnar; September 19, 2014 at 02:03 AM.

  3. #3
    Aikanár's Avatar no vaseline
    Join Date
    Mar 2009
    Location
    Sanctuary
    Posts
    12,516
    Blog Entries
    3

    Default Re: Scripted buildings: create_building and destroy_buildings

    I your tutorials


    Son of Louis Lux, brother of MaxMazi, father of Squeaks, Makrell, Kaiser Leonidas, Iskar, Neadal, Sheridan, Bercor and HigoChumbo, house of Siblesz

    Not everything that counts can be counted, and not everything that can be counted counts.

  4. #4
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Re: Scripted buildings: create_building and destroy_buildings

    Second post added. First post slightly elaborated.

    @Aik
    Thanks.

  5. #5

    Default Re: Scripted buildings: create_building and destroy_buildings

    Hello, I have a little question. If ypu destroy a building, can it be built again? I would like if it is possible to "disable" certain buildings, i.d. avoiding them to be built at all??

  6. #6
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Re: Scripted buildings: create_building and destroy_buildings

    You could make the building non-constructable (as explained in your thread) but still have some pre-built in descr_strat.txt. That way they exist at campaign start, can be destroyed, but new ones cannot be built anywhere.

    This isn't necessarily a question regarding scripted creation/destruction though, so if you wish to discuss further then please take it to another thread, e.g. yours.

  7. #7
    Polycarpe's Avatar Back into action!
    Join Date
    Feb 2010
    Location
    Quebec, Canada
    Posts
    3,338

    Default Re: Scripted buildings: create_building and destroy_buildings

    Withwnar, this tutorial is brillant. +rep

    I woud like to use the script in a special way:

    I created a building Tree called Granary; a building to stock food as well act as an emergency back-up in case of sieges.
    I don't know if its possible to apply the script during siege?
    But my idea is the granary building will be destroyed if the siege is holding for too long (lets say for 3 turns). In addition to this, I want to imitate the famine effect of a long-term siege and thus if the granary building is destroyed (either by the trigger siege OR by sabotage), a plague strikes the settlement.

    I know its challenging but I want to know if its possible.

    Thank you.
    Poly

  8. #8
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Re: Scripted buildings: create_building and destroy_buildings

    Thanks.

    Yes, create_building still works for besieged settlements.

    The granary building is possible but each settlement will need a counter and monitors to track how long it has been under siege. Then, when destroying it, script will also need to rebuild it in all settlements that should still have one. Doable but complicated, and no doubt a large script due to the number of settlements it must handle.

    Plague: someone was discussing that in a thread somewhere recently. Never used plague myself and it isn't really to do with buildings so would be off topic here.

  9. #9
    Polycarpe's Avatar Back into action!
    Join Date
    Feb 2010
    Location
    Quebec, Canada
    Posts
    3,338

    Default Re: Scripted buildings: create_building and destroy_buildings

    Quote Originally Posted by Withwnar View Post
    Thanks.

    Yes, create_building still works for besieged settlements.

    The granary building is possible but each settlement will need a counter and monitors to track how long it has been under siege. Then, when destroying it, script will also need to rebuild it in all settlements that should still have one. Doable but complicated, and no doubt a large script due to the number of settlements it must handle.

    Plague: someone was discussing that in a thread somewhere recently. Never used plague myself and it isn't really to do with buildings so would be off topic here.
    Ok thanks for the info, at least I know its possible. Guess I'll need to do some test regarding plagues then.

  10. #10

    Default Re: Scripted buildings: create_building and destroy_buildings

    Hi Withwnar, I've been trying to figure out how to make sacking settlements and exterminate the populace have long-term impacts (like a decrease in population growth for x years after). Do you think it would be possible to have a 'building' line created upon sacking or exterminating a populace that is destroyed (or changed to another 'building' within the building line) after a certain number of years? Thanks in advance

  11. #11
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Re: Scripted buildings: create_building and destroy_buildings

    I would say no, only because that the only way to check for sacking and exterminating is via the SackSettlement and ExterminatePopulation events which only fire on named characters. So if a capturing army did not have a named character commander, only a general (captain), then the events won't fire and so your script would have no way to trigger.

  12. #12

    Default Re: Scripted buildings: create_building and destroy_buildings

    Okay thanks for the reply Withwnar, saved me a lot of time trying to figure that out +rep

  13. #13

    Default Re: Scripted buildings: create_building and destroy_buildings

    would´t the scriptcommand
    console_command set_building_health (Settlement) (building) 0
    destroy non hinterlandbuildings?

  14. #14

    Default Re: Scripted buildings: create_building and destroy_buildings

    No, the building will just appear 100% damaged. The effect of set_building_health is very superficial. For example if a wall is breached and you use this command to repair it, then the building will appear repaired on the strat map, but there will still be a breach on the battle map.

  15. #15

    Default Re: Scripted buildings: create_building and destroy_buildings

    wall are hinterland building meaning there can´t be destroyed anyway

  16. #16
    Withwnar's Avatar Script To The Waist
    Join Date
    Oct 2008
    Location
    Earth
    Posts
    6,329

    Default Re: Scripted buildings: create_building and destroy_buildings

    Hinterland buildings can be destroyed by script. Not that you'd want to destroy a wall building though.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •