• Our friends from AlphaCentauri2.info are in need of technical assistance. If you have experience with the LAMP stack and some hours to spare, please help them out and post here.

Coding a Unit Limit: Land, Sea, & Air

Dylan Gubler

Chieftain
Joined
Aug 20, 2014
Messages
7
I enjoy playing LONG games of Civ, with High Tech/Civic Cost and Low Production/Growth Costs. I enjoy fighting multiple Wars/Era, I enjoy dealing with Civil Unrest, and I enjoy watching my Cities really evolve over time.

The only issue that I've found are Unit Carpets. If you think it's bad in Vanilla Civ, you should see some of my Modded Games. The World is just packed with Warriors by Mid-Classical Period.

I've tried manually increasing the costs of Military Units, but the AI runs out things to produce, and ultimately Carpets the map.

And so, I wanted to Mod a Unit Limit, preferably with the following Guidelines:

-

Each Empire can maintain a # of Military Units equal to:

Land Units: #Cities + #Encampments +#Encampment Buildings + #Palace [For that Early Game Slinger]

Sea Units: #Cities/2 + #Harbors + #Harbor Buildings

Air Units: #Cities/3 + #Aerodromes + #Aerodrome Buildings

Religious Units: #Holy Sites + #Holy Site Buildings

-

Now I'm a Game Design Student at the Art Institute of Vancouver, so I've done a lot of scripting in the past Year. Unfortunately, I'm just not very good at it.

I know how hard scripting is, and I have a rough understanding as to how hard this would be to code.

Even if someone could show me how to set a basic limit, it would be a huge help.

-

Thank you for taking the time to read this.
 
Well, I've yet to look into Lua, but in Civ 5, there was an event hook to check for whether a given thing could be chosen to be produced in a city (building, unit, etc); it would return true if it could be produced, false otherwise. If this hook also exists in Civ 6, you could hook a Lua function to it, check for if the thing is a unit, then manually implement your unit limit check, and return false if they'd hit it. Wouldn't stop new units from being added by, for example, scythia's double cavalry unit ability, or any sort of wonder or other kind of effect, but that should probably just be intentional. (If not, you could hook another function into the DoTurn or whatever event it is and delete units until they're back under the limit)
 
Here is a very basic implementation (more of sketch) of a very rudimentary version of the OP's ideas in LUA. It is anchored to a single integer (in this example--25) that limits the number of units (all units, of all domains, with the exception of DOMAIN_AIR). Any unit a player gets (by whatever means) in excess of that number is automatically destroyed. The only slightly more involved bells & whistles on this concept design is a limitation on the types of units that will be removed if the hard cap is exceeded. I made settlers, workers, traders, and the set from archaeologists to naturalists (including GPs and spies) exempt from the unit cap. So, there can be 50 civilians, but if the 51st unit is a military (non-Air) unit, it will be removed. When I first drafted this, on the quick, I missed your idea about having different caps for different domains, so that's the next item on my agenda. I am writing a few Listener functions to continually collate and update the variables you propose into a single unit cap for each specific Domain (let's see if that's even possible, who knows). I assume all civilian units are exempt from any cap, and so my other task is to segregate the exempt civilians from the rest of the units when determining whether the cap has been exceeded. Finally, I'll tie it all together, and if (or when) I am successful, I'll let you know. In the meantime, here is the fist version of the code, with extensive superfluous print statements peppered throughout :).

Code:
local sAllowedUnitCount = 20

function OnNewPlayerUnitAddedToMap( playerID : number, unitID : number )
    if iPlayer == 63 then
        print ("A unit has been created. But it appears that the unit is from a Barbarian tribe. Or is it AncientAliens™?")
        print ("We have no sway over these uncouth savages. They roam like the wind the vast emptiness of this domain and obey no laws.")
        print ("They will be the ruin of us all!")
        return
    end
    local pPlayer = Players[ playerID ]
    local pPlayerConfig = PlayerConfigurations[ playerID ]
    if pPlayer ~= nil then
        print ("A unit has been created.")
        print ("We must investigate whether there is cause for concern.")
        print ("Our justice shall be swift!")
        local iCurrentUnitCount = pPlayer:GetUnits():GetCount()
        if iCurrentUnitCount > sAllowedUnitCount then
            print ("ACHTUNG! A player has violated the limit - " .. sAllowedUnitCount .. " - on the number of units allowed!")
            print ("We must investigate and maintain law and order with extreme prejudice!")
            local pPlayerCivName = pPlayerConfig:GetCivilizationTypeName()
            print ("Player ID# = " .. playerID .. ", the pernicious " .. pPlayerCivName .. ", has")
            print ("exceeded the limit on units! We must prevent overcrowding.")
            print ("Determining: must the illegal unit be spared, or can it be removed?")
            local pUnit = pPlayer:GetUnits():FindID(unitID)
            if pUnit ~= nil then
                local pUnitType = pUnit:GetType()              
                if (pUnitType > 2 and pUnitType < 6) or (pUnitType > 17 and pUnitType ~= 88 and pUnitType ~= 89) then
                    pPlayer:GetUnits():Destroy(pUnit)
                    print ("Too many units! " .. pPlayerCivName .. "'s latest unit,")
                    print ("Unit ID# = " .. unitID .. ", a dastardly " .. GameInfo.Units[pUnitType].UnitType .. ", has been removed.")
                else
                    print ("The " .. pPlayerCivName .. "'s unit count has exceeded this player's allotment")
                    print ("as a result of a new unit appearing! But the new unit")
                    print ("(" .. GameInfo.Units[pUnitType].UnitType .. ") is of a type that is protected from removal.")
                    print ("It pains us, but we must spare it. Continuing to monitor. There is always the next time!")
                end
            else
                print ("Did the unit disappear on its own? Maybe it hates the Carpet of Doom as much as we do.")
                print ("Something went wrong it seems. Continuing to monitor with utmost vigilance!")
            end
        else
            print ("False alarm! Everything is in order, but we remain vigilant!")
        end
    else
        print ("A unit has been created. But the owner is unknown to us.")
        print ("Must be the Aliens. AncientAliens™")
        print ("It's always the Aliens. What if we are all Aliens?")
    end
end
Events.UnitAddedToMap.Add(OnNewPlayerUnitAddedToMap);

The code works successfully in the very rudimentary manner described above. Let's see if there is a next step up from there.

NOTE: I immediately see a very basic problem with this process, and it has to do with the so-called "AI". I am not sure there is any easy way to teach the AI this limitation, to make it consider whether building the next unit is a worthwhile investment. Maybe there is something in the XML behaviour/decision trees that can be tweaked to teach the AI to obey the unit cap. But I worry that we will run into a problem where the AI continues building units that continue being destroyed, wasting its time and resources.

Perhaps there is a way to disable units in the city production panel when the cap is reached, but I am not even sure whether this kind of largely-UI trick would work on the AI that does not use the UI built for human players. Besides, it might involve mixing UI and in game scripts, and that's not possible currently (or ever). Maybe I'll think of something else. We'll see.
 
Last edited:
Luei333:

I'm sorry to hear that this Solution is no longer available to us, and it sounds like a easiest solution. I really you replying so quickly to me. This is one of my very first posts on CivFanatics, and it's great to see that the Community is welcoming.

LeeS:

Well Damn! I'm no very familiar with Modding/Lua: Is there any chance that we'll gain access to this in the future?

Infixo:

^Ditto

Additionally, would you mind explaining explaining/linking what Hooks are? There may not be any in Civ 6, but it sounds like something I should now for the future.

Gleb Bazov:

Holy Cow Religion!

This is a fantastic first step Gleb. And you say that separating the domains is next on your agenda?

Well I'm giddy to see what you do next, please don't rush yourself. This is already so much, and I'm confident that it'll at least solve the problem that my games have been having.

In regards to disabling units in city production, Luei333 did mention a method in the Civ 5 Lua, but it seems to not be in Civ 6, which is a darn shame.

I'm going to look in as to how one takes this LUA Code and puts it into Civ 6. The only Scripting I've done has been with C# in Game Maker and Unity. The process of working with pre-written code is still very new to me.

Thanks so much for the Save, Gleb.
 
NOTE: I immediately see a very basic problem with this process, and it has to do with the so-called "AI". I am not sure there is any easy way to teach the AI this limitation, to make it consider whether building the next unit is a worthwhile investment. Maybe there is something in the XML behaviour/decision trees that can be tweaked to teach the AI to obey the unit cap. But I worry that we will run into a problem where the AI continues building units that continue being destroyed, wasting its time and resources.
AI will build them endlessly. We need access to game's source code (i.e. DLL from Civ5) to change this.
 
CIV 6 - LUA/SQL UNIT LIMIT ENFORCEMENT MOD
(AI friendly and fully functional (to the extent that I tested it))

Hey Dylan,

I finally found some free time and put together a functional Land/Air/Sea/Religious Unit Limit mod. The formulas for calculating the limit are as you described in the OP (at least I think so :)). The mod is actually entirely functional vis-a-vis the AI as well. The limit is enforced via a strategic dummy resource mechanism and LUA functions. So, once the AI hits its limit, it can't build anymore units, so there is no danger of it wasting its resource on useless production. Although the deletion of illegal units remains the last line of defence, in this new implementation of the mod the primary emphasis is on control through strategic resource requirements. Once you reach the limit, you simply can't build any more units. Feel free to play around with the formula. In my playthoughs, I gave myself 3 additional, "grandfathered" units, because having just two military units for the first little while was a bit disheartening.

Anyways, I've had very little time to do complete playthroughs with the mod. I primarily concentrated on cleaning up syntax, etc, so your testing and playthroughs would be much appreciated. Since I had a number of starts with the mod, there are at least three different coding approaches to the task in it, so it is by far not polished or finished. I will ultimately make the method uniform. However, the mod is fully functional in terms of what you asked for.

A minor caveat... I had a choice -- either remove all strategic resource requirements for all units in order to use my dummy regulator building and strat. resources in their place, or claw back on functional strategic resources once the limit is reached. I chose to retain functional strat. resources. However, this means that once you hit the limit, those resource are gone. Once you go back below the limit, they reappear. I'll probably find a more elegant way of doing this eventually, but this is it for now.

Have fun! :)
 

Attachments

Oh, yeah, one more PS. I haven't had any time to implement the tables of unit formation sets that I intended to have, and so I don't have any mechanism for retroactive "population control" yet (but that's probably going to be the very next thing I do). So, any units you get at the beginning are "grandfathered" by default. If you start (say, using LeeS' RASL mod) with 3 units, those three will stay, notwithstanding that your limit is 2. However, once you drop below 2 (and if your limit does not increase in the interim), you can't get it back. I don't mind it. I also suggest you think a bit more about the formula. I have a feeling that the numbers you picked might a bit tight. Of course, I play very large maps, so... but, even on small maps it's not a lot.

Cheers.
 
Oh, yeah, one more thing. Because the mod uses several dummy strat resources to regulate the limit on the different formation classes, the Top Panel menu and the Reports screen gets messy. However, I've modded the game's UI files to ignore the new strat resources, and they don't appear in my game (well, except a tooltip on the City Production Panel -- I'll get to that eventually too). If you need my modifications, let me know.
 
A minor caveat... I had a choice -- either remove all strategic resource requirements for all units in order to use my dummy regulator building and strat. resources in their place
Well, this was also the thing I decided to do this weekend.
Just logged in to prepare for posting my mods and seen an alert that you attached something to this thread. :high5: What a surprise!
And you made it far more elegant.
Attaching my work in case you would like to see how I implemented similar functionality with modifiers by XML and SQL only.
 

Attachments

Also note this is just an intro for resolving the problem: no differetiating for LAND/AIR/SEA was yet implemented.
 
It's actually quite impressive you managed to achieve this functionality with XML and SQL. I didn't even dare try going that route. :)
 
Hope this isn't considered necroing but this mod was a life saver for me and the carpet spam of the AI... I was wondering about something I noticed last night. I went to upgrade my warriors in to swordsman and they all disappeared!! My military strength score increased like they were still there, but the units were removed from the game. I had 4 sources of iron and upgraded 3 warriors. Any thoughts? Also noticed right away that the info of the unit limits on the top bar is all... scrunched together and overlaps. I use CQUI so that may the issue.

EDIT: Leaving this note for reference but I figured it out... I have the Combat Stacking and Overhaul mod. This changes ranged and siege weapons to a support class instead of normal land units. Your mod doesn't have that formation in it, so the AI wasn't restricted from spamming them. I just took out the code in the CSO mod that changed them and everything works now. ((Something seems to be broken for me. Now, the AI endlessly spams out archers. Example - France has 3 cities and no encampments. If I am looking at the code correctly, they should be limited to 4 or 5 units? They have about 30+ archers covering every tile. Only two warriors in their army. So seems to be reversed now lol! Instead of warrior spam, I have archer spam.))
 
Last edited:
Came across a new incompatibility yesterday. The Real Era Stop mod breaks the land unit count function... Somehow. The LUA console showed the breakdown on lines 210 and 421 of the code. I'm not a coder by any means and looking through the code for Real Era Stop I couldn't figure it out. I thought it was bc I had stopped the tech tree in the Industrial Era and the unit limit code was looking for aerodromes that don't exist at all, but testing with a stop on modern still broke it. Hopefully someone with some knowledge of coding can check into this... Doesn't look like Gleb is around anymore.
 
Hey everyone - this is a really great mod that fixes a critical deficiency in the game system of balance and playability. Big or long games are virtually unplayable due to the carpeting of units.

Is there anyone available to update or adapt this mod to the most recent updates or other major mods? Still testing it, but the fact that a city state doesnt have 20 units now makes it much, much more realistic.
 
Hi all, also being a huge map marathon player for a too long time, now with the warrior carpets it gets crazy.
What i have seen was a mod adding maintenance costs to the basic units already.

Pre-ancient units maintenance cost - that is the mode. And it helped a lot to limit the carpets.

Check it out. Possible better than a cap of any sort - and it gives a bonus to gold civs.
 
Back
Top Bottom