Results 1 to 1 of 1

Thread: How to make settlement populations migrate in and out of cities due to taxes, conflicts, capitals and plagues

  1. #1

    Icon11 How to make settlement populations migrate in and out of cities due to taxes, conflicts, capitals and plagues

    I love the population system from Total War Rome Remastered because in order to be able to recruit armies, you have to have enough people in your cities. However, the only way to lose population is to recruit units, to have a plague or to conquer and destroy the settlement.

    Thankfully, the scripting capabilities give us a great opportunity to introduce new mechanics into the game which we will implement in this tutorial:

    + Make settlements lose a random amount of population if taxes are high with a low probability
    + Make settlements lose a random amount of population if taxes are very high with a higher probability
    + Make settlements lose a random amount of population if they have a plague with a higher probability (additionally to the many people we lose to the plague)
    + Make settlements lose a random amount of population if there are riots with a low probability

    But not everything in life is bad, so we also want to do:

    + Make settlements gain a random amount of population if taxes are very low with high probability
    + Make settlements gain a random amount of population if it is the capital of the faction with a low probability

    What I like about this mechanics very much is that it forces the player to think whether he should do higher tax rates to get more money but at the same time risking not only riots from the taxed but also the fact that they could simply emigrate to another country. It also gives capitals another advantage other than being the only settlement with no capital distance malus for public order - it simply grows faster than the other cities simply because it is the center of your faction.

    A cool idea would be if sieges also would make the settlements population go down, but unfortunately I havent found a way how to implement that yet. The game doesnt seem to offer us a condition to check if a settlement is under siege.

    To implement this script, we are going to need a programming language like Python and a templating engine like Pythons quik in this example. Also, you have to have a list of all your RegionIds (Rome, Sparta, ...) of all the regions on your map. I use the modding build tool Atlas when modding Rome Remastered so I dont have to worry about that as I always have my data available during execution.

    Now, we only need two parts of code for this example. Part One triggers whether a settlement is going to gain or lose population in a round. Part two will react to the trigger and do two things: First it will randomize the amount of population that the settlement will gain or lose and secondly it will execute the population gain/loss and also display a message to the player.

    And here is the code (Python/quik templating) - of course you can use any other programming language and templating engine you wish, just adapt the logic to your particular language syntax and keywords.

    Part One (you can play around with the percentage probabilities in RandomPercent to see what makes more sense for you):

    Code:
    #for @Region in @Get.AllRegions():
        monitor_event SettlementTurnStart SettlementName @{Region.IdCity}
        and SettlementIsLocal
        and I_CompareCounter popPlus@{Region.UID} = 0
        and I_CompareCounter popMinus@{Region.UID} = 0
            if SettlementTaxLevel = tax_low
            and RandomPercent < 10
                console_command reseed_random
                set_counter popPlus@{Region.UID} 1
            end_if
            if IsCapital
            and RandomPercent < 5
                console_command reseed_random
                set_counter popPlus@{Region.UID} 1
            end_if
            if SettlementTaxLevel = tax_high
            and RandomPercent < 10
                console_command reseed_random
                set_counter popMinus@{Region.UID} 1
            end_if
            if SettlementTaxLevel = tax_extortionate
            and RandomPercent < 15
                console_command reseed_random
                set_counter popMinus@{Region.UID} 1
            end_if
            if SettlementHasPlague
            and RandomPercent < 5
                console_command reseed_random
                set_counter popMinus@{Region.UID} 1
            end_if
            if IsSettlementRioting
            and RandomPercent < 5
                console_command reseed_random
                set_counter popMinus@{Region.UID} 1
            end_if
        end_monitor
    #end
    And also finally Part Two:

    Code:
    monitor_event FactionTurnStart TrueCondition
    and FactionIsLocal
        #for @Region in @Get.AllRegions():
            monitor_conditions I_CompareCounter popPlus@{Region.UID} = 1
            #for @a in [2, 3, 4, 5, 6, 7, 8, 9, 10]:
                if RandomPercent < 10
                    inc_counter popPlus@{Region.UID} 1
                    console_command reseed_random
                end_if
            #end
            #for @a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
                if I_CompareCounter popPlus@{Region.UID} = @{a}
                    console_command add_population @Region.IdCity @{a}00
                    @Scripter.MessageInfo("Immigration to @{Region.NameCity}", "The region of @{Region.NameRegion} and especially the settlement of @{Region.NameCity} are currently experiencing a wave of immigration. @{a}00 new citizen have arrived. Migration is caused by low taxes and war.", "wonder_captured")
                end_if
            #end
            set_counter popPlus@{Region.UID} 0
            end_monitor
    
            monitor_conditions I_CompareCounter popMinus@{Region.UID} = 1
            #for @a in [2, 3, 4, 5, 6, 7, 8, 9, 10]:
                if RandomPercent < 10
                    inc_counter popMinus@{Region.UID} 1
                    console_command reseed_random
                end_if
            #end
            #for @a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
                if I_CompareCounter popMinus@{Region.UID} = @{a}
                    console_command add_population @Region.IdCity -@{a}00
                    @Scripter.MessageInfo("Emigration from @{Region.NameCity}", "The region of @{Region.NameRegion} and especially the settlement of @{Region.NameCity} are currently experiencing a wave of emigration. @{a}00 citizen have left into foreign lands. Migration is caused by low taxes and war.", "wonder_captured")
                end_if
            #end
            set_counter popMinus@{Region.UID} 0
            end_monitor
        #end
    end_monitor
    Note that I use a shorter Region UID for the counter names to make the size of the script smaller. However in my mod with 106 regions only, this script is just about 1 MB heavy so it is no big deal. Also, as I am working with Atlas, I dont have to worry about two things you have to worry about when you dont:

    -> Declaring counters at the top of the file
    -> Replacing @Scripter.MessageInfo() with the following snippet to generate a message to the player:

    Code:
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title x_TITLE
            body x_BODY
            image wonder_captured
            }
    Dont forget about that.

    The population migrations here range between 100 and 1000 people in case of a migration being triggered, however the most probable outcome is between 200 and 500 people.

    This is how it looks like in practice:



    Poor Cornith got taxed heavily so people decided to move out of it to the capital of Thessalonica and also to Larissa, where the taxes were set to very low. For demonstration purposes I set the probabilities of migration to 100% however, so in practice, there would not be migration for each turn immediately of course.

    This here is how the generated code looks like with the example of one region (Thermon):

    Part 1 Triggering the migration

    Code:
        monitor_event SettlementTurnStart SettlementName Thermon
        and SettlementIsLocal
        and I_CompareCounter popPlusRE0 = 0
        and I_CompareCounter popMinusRE0 = 0
            if SettlementTaxLevel = tax_low
            and RandomPercent < 100
                console_command reseed_random
                set_counter popPlusRE0 1
            end_if
            if IsCapital
            and RandomPercent < 100
                console_command reseed_random
                set_counter popPlusRE0 1
            end_if
            if SettlementTaxLevel = tax_high
            and RandomPercent < 100
                console_command reseed_random
                set_counter popMinusRE0 1
            end_if
            if SettlementTaxLevel = tax_extortionate
            and RandomPercent < 100
                console_command reseed_random
                set_counter popMinusRE0 1
            end_if
            if SettlementHasPlague
            and RandomPercent < 100
                console_command reseed_random
                set_counter popMinusRE0 1
            end_if
            if IsSettlementRioting
            and RandomPercent < 100
                console_command reseed_random
                set_counter popMinusRE0 1
            end_if
        end_monitor
    ...
    Part Two:

    Code:
    
    monitor_event FactionTurnStart TrueCondition
    and FactionIsLocal
        
            monitor_conditions I_CompareCounter popPlusRE0 = 1
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popPlusRE0 1
                    console_command reseed_random
                end_if
                    
                if I_CompareCounter popPlusRE0 = 1
                    console_command add_population Thermon 100
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 54AE7777557C2DEF703A8510171E54A0FC0674CB_TITLE
            body 54AE7777557C2DEF703A8510171E54A0FC0674CB_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 2
                    console_command add_population Thermon 200
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 67732C47F976551AD31E61988EB4CFCEFE4D0629_TITLE
            body 67732C47F976551AD31E61988EB4CFCEFE4D0629_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 3
                    console_command add_population Thermon 300
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 43251ADBE4E76E43519BA740E98D6E68B0F602EB_TITLE
            body 43251ADBE4E76E43519BA740E98D6E68B0F602EB_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 4
                    console_command add_population Thermon 400
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 8787C3D5950D248417D4AABE1237AEDA5077C92E_TITLE
            body 8787C3D5950D248417D4AABE1237AEDA5077C92E_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 5
                    console_command add_population Thermon 500
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 196E6B06A9E276AECC2E2753F9D285188B89AB2F_TITLE
            body 196E6B06A9E276AECC2E2753F9D285188B89AB2F_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 6
                    console_command add_population Thermon 600
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title C449F16ABCAA3CC8606B13689F2A967293B0F1F2_TITLE
            body C449F16ABCAA3CC8606B13689F2A967293B0F1F2_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 7
                    console_command add_population Thermon 700
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title C10A3379D7E2D3287E6D3EDC796662E485F930CB_TITLE
            body C10A3379D7E2D3287E6D3EDC796662E485F930CB_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 8
                    console_command add_population Thermon 800
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 95A5D08624D17698CBBCD08C0C01538A0FEAF312_TITLE
            body 95A5D08624D17698CBBCD08C0C01538A0FEAF312_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 9
                    console_command add_population Thermon 900
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 5066AF962940D18D43C6AA7CABDF114D1FD77BDC_TITLE
            body 5066AF962940D18D43C6AA7CABDF114D1FD77BDC_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popPlusRE0 = 10
                    console_command add_population Thermon 1000
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title D9EE8F3CEE9C2A2F304ABB84610AB0253D270287_TITLE
            body D9EE8F3CEE9C2A2F304ABB84610AB0253D270287_BODY
            image wonder_captured
            }
        
                end_if
                    set_counter popPlusRE0 0
            end_monitor
    
    
            monitor_conditions I_CompareCounter popMinusRE0 = 1
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
            
                if RandomPercent < 10
                    inc_counter popMinusRE0 1
                    console_command reseed_random
                end_if
                    
                if I_CompareCounter popMinusRE0 = 1
                    console_command add_population Thermon -100
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 170EB3073E6DB83C01147A7832F7C313262969D5_TITLE
            body 170EB3073E6DB83C01147A7832F7C313262969D5_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 2
                    console_command add_population Thermon -200
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title A9CF0BD078B44AE64ECE8DE9CD7966C8736B6AFB_TITLE
            body A9CF0BD078B44AE64ECE8DE9CD7966C8736B6AFB_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 3
                    console_command add_population Thermon -300
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 415C099937B4A58F6C9D07642ADB10A2C0F471B6_TITLE
            body 415C099937B4A58F6C9D07642ADB10A2C0F471B6_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 4
                    console_command add_population Thermon -400
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 1FDD6CA9611A81B44BBD7C79BAE28B04BDBB10F7_TITLE
            body 1FDD6CA9611A81B44BBD7C79BAE28B04BDBB10F7_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 5
                    console_command add_population Thermon -500
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 426E81EC88F349E6E55D98A1B263A274480076B9_TITLE
            body 426E81EC88F349E6E55D98A1B263A274480076B9_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 6
                    console_command add_population Thermon -600
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title A47BABFB1BDFEA76E78AC0D65DE5552E4B162153_TITLE
            body A47BABFB1BDFEA76E78AC0D65DE5552E4B162153_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 7
                    console_command add_population Thermon -700
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title C5D207EE0F51829987842FEBED12B6934155F936_TITLE
            body C5D207EE0F51829987842FEBED12B6934155F936_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 8
                    console_command add_population Thermon -800
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 91A6A34048338FAC32565060070385471033751B_TITLE
            body 91A6A34048338FAC32565060070385471033751B_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 9
                    console_command add_population Thermon -900
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title 180DE7E8747C5A4158C1AEBEA4EE52908A945309_TITLE
            body 180DE7E8747C5A4158C1AEBEA4EE52908A945309_BODY
            image wonder_captured
            }
        
                end_if
            
                if I_CompareCounter popMinusRE0 = 10
                    console_command add_population Thermon -1000
                    
        message_prompt
            {
            flag_counter dummy_f
            result_counter dummy_r
            title ACA88CAF47A1748EB7A83D65182E8052456063B0_TITLE
            body ACA88CAF47A1748EB7A83D65182E8052456063B0_BODY
            image wonder_captured
            }
        
                end_if
                    set_counter popMinusRE0 0
            end_monitor
        ...
    Notice how much shorter the python templating version is. Just the campaign script code for one single city is already 10x as long as the entire python templating code.
    Last edited by Ocyalos; January 29, 2022 at 03:23 PM.
    CPU: AMD Ryzen 5 5600X 4,6 Ghz AM4 | GPU: 2x NVIDIA GeForce RTX 3060Ti Gainward Ghost OC 8GB GDRR6 | RAM: Corsair Vengeance RGB PRO DDR4 3600 Mhz C18 16 GB | SSD: PNY XLR8 CS3030 4TB M.2 NVMe 3 GB/s | PSU: be quiet! Straight Power 11 Platinum 550 Watt | MB: Asus ROG Strix B550-F Gaming WiFi | Case: be quiet! Silent Base 801 Silver


    Long: New York Stock Exchange: MO, XOM, AAL, AMZN, FB, MSFT, GOOGL, AMD, CRM | Wiener Börse: POST, BG, ADKO, UBS | London Stock Exchange: BP, BATS | Hong Kong Stock Exchange: 3988, 601318 | Euronext Paris: ORA, FP | Bolsa de Madrid: ELE | Coinbase: BTC
    Short: -

Tags for this Thread

Posting Permissions

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