The Spanish Civil War v4 for ToT + ToTPP + Lua - Development Thread [ON HOLD]

It's awesome seeing you use it!
Yeah! And thanks to Lua I'm even saving more unit slots! I used to have a unit to represent the town of Guernika and trigger the bombing event "on unit killed"...now I can simply use Lua code to check the defender location and throw an event when the city of Guernika is bombed by German planes... :)

I'm back to Ireland and I brought with me the latest 2022 book releases related to the Spanish Civil War, and renewed energies to implement loads of stuff in the scenario :)
 
So far I'm implementing a quite complex and nice system to customize the combat based on the below premises:
  • Specific units are more suitable than others against enemy units (as shown above with my usage of the LST Traits module). Nothing new here.
  • There's a chance of specific Combat Events to trigger during combat: counterattack, encirclement, assault, etc which can modify the attacker/defender stats and even cause specific behaviours (troops fleeing or surrendering!). The better trained the units are (by tech), the more chance of these events triggering on their favour. This is innovative in a way that you need to train your troops (research specific techs) to improve your performance in combat and increase the chances to kick off one or more of these events.
  • Commander (Leader) units have specific traits that substantially alter the stats of the units under their command. If combat occurs on an adyacent tile, the fighting troops inherit the effects of these traits. For instance, a "fortress buster" commander will allow troops fighting "under their command" to be stronger when attacking units entrenched in fortifications. An "africanist" will be especially effective when commanding African colonial troops (legión, regulares). A "prince of terror" commander will have a chance to make the enemy withdraw from combat and flee from their positions even before fight starts, other traits will give bonuses when fighting on specific terrain, etc. Many cool combinations that I have implemented, and many more I can include!
I have finished implementing the mentioned combat mechanics (units, comba events, and commander bonuses), it's all working like a charm in all my tests. I found using the traits module for adding combat bonuses/penalties to unit types very easy and readable so I'm pasting some sample code in case somebody wants to give it a try:

In setTraits.lua I have all my traits assigned to the different unit type objects. For example:

SQL:
traits.assign(object.uGuardiaCivil,"infantry","police","ground_air_vulnerable")
traits.assign(object.uCarroVeloceCV33,"armoured","ground_air_vulnerable")

In combatSettings.lua I add a table where I set up different trait modifiers. The key is the attacker trait (see example for infantry units):

SQL:
local traitCombatBonusesTable = {
-- LAND COMBAT
-- Infantry particularly vulnerable attacking MG and armoured units.
["infantry"] = {tcbtDefenderTable={"mg","armoured"},tcbtAttackerBonusTable={0.8,1},tcbtDefenderBonusTable={1.5,1.75}}
}

Then still in combatSettings.lua I create a function which calculates if any of these combat modifiers need to apply:

SQL:
-- This function will return the specific bonuses if combat occurs between specific unit types as defined on traitCombatBonusesTable
local function getUnitTypeCombatModifiers(attacker, defender)

    local aCustomMult,dCustomMult = 1, 1
    -- Loop through the traitCombatBonusesTable table
    for attackerTrait,bonuses in pairs(traitCombatBonusesTable) do
        if traits.hasTrait(attacker.type,attackerTrait) then
            -- Loop through all defined defender traits
            for i,defenderTrait in pairs(bonuses.tcbtDefenderTable) do
                if traits.hasTrait(defender.type,defenderTrait) then
                    -- Combination found, retrieve modifiers
                    aCustomMult,dCustomMult = aCustomMult*bonuses.tcbtAttackerBonusTable[i],dCustomMult*bonuses.tcbtDefenderBonusTable[i]
                    -- civ.ui.text("getUnitTypeCombatModifiers added for attacker trait: "..attackerTrait.." and defenderTrait: "..defenderTrait)                   
                end
            end
        end
    end
    
    return aCustomMult,dCustomMult
    
end

And finally, still in the same module, I add a call to the function I created inside the body of computeCombatStatistics():

SQL:
-- Apply specific unit type combat modifier (traits)
local aUnitAtt, aUnitDef = getUnitTypeCombatModifiers(attacker, defender)

These values get added to the override table (combatModifierOverride), and that's all it needs :).

What's next? I'll still work in the combat, as i want to implement instances when combat is aborted after some fight but without total loss, and when defenders flee their positions moving to an adyacent tile instead of being killed.
 
I continue focused on basic game mechanics. This time, I've implemented some custom functionality for medium bombers when attacking cities.

If attacking a city, and not intercepted by either fighters or AA batteries, medium bombers will have a choice (actually the human player will, the AI will perform a random action) of air raid mission, with three different options for now. Light bombers and assault planes or CAS won't have this option and will perform standard civ2 combat.

See this quick test:

1) A He-111 flies over Santander and enters the city tile:

1664324085783.png

2) The human player gets the choice (texts are not final, I don't like the "strategic buildings" phrasing):

1664324626139.png


3) First option is standard civ 2 combat, with the additional bonuses, etc. Nothing new so I didn't take a screenshot.

4) If I choose the second option, there is a chance that a city improvement gets destroyed by the air raid. In this example the air raid was successful:
1664324937808.png


5) Sometimes bombers fail to hit their targets too, see this test bombing Bilbao:
1664325330000.png


Players will have the ability to "train" their air crews by researching technology which will increase the chances of successfully destroying city improvements. This is a functionality I'm implementing in general for ground, air and naval combat, as I will have specific "training/doctrine" techs that will make units stronger or last longer when engaging enemy units.

6) The third option, "terror bombing", targets the city population, and there is also a small chance to cause civil disorder in the bombed city.

Madrid, before this attack, was size 26:
1664325464352.png

During attack
1664325512639.png


After the attack is size 25 now, however, the civil disorder didn't trigger as the chance is very small
1664325561173.png


Please note these screenshots are using the Nationalist player just because it's the first to move and it's quicker for me to do tests, all functionality is available to both sides and texts change dinamically. The photo in the menu will also change and will likely display a picture of the attacking unit itself :)

As always, I'm open to suggestions and ideas.

Pablo
 
) If I choose the second option, there is a chance that a city improvement gets destroyed by the air raid. In this example the air raid was successful:
You could rename it "bombard city infrastructures" ?
And maybe specialize these in 3 options like "city defenses", "city industries" and "city civil infrastructures" ?

Whatever, it already looks great !
 
You could rename it "bombard city infrastructures" ?
And maybe specialize these in 3 options like "city defenses", "city industries" and "city civil infrastructures" ?

Whatever, it already looks great !

Merci @Dadais ! That's actually a great idea, You know what? I'll do the following inspired by your comments:

a) Allow CAS/Assault/Dive bombers to be able to target city defenses (vanilla improvements city walls, sam battery and coastal battery), since these planes are more suitable to target small and protected targets such as these. Medium bombers in carpet bombing are not effective against these.

b) Medium bombers will have two options to target improvements instead of one: "Industry" and "Civil Infrastructure". Also if successfully targeting industry, there will be a chance that also the city production is "sabotaged" (e.g., all shields gone of whatever was being produced in that city).

c) Light bombers will still only have the chance to engage enemy units.

Thanks,

Pablo
 
Done, thanks @Dadais for the suggestions.

A medium bomber has these options now:

1664360829391.png

I tried to target the industry, but failed:
1664360920982.png


Using the LST traits module again (soooo useful, thanks @Prof. Garfield !) I have categorised the city improvements in three, see sample:
1664360969083.png

Engaging a city with a dive bomber such as Stukas, the menu is different (please ignore the He 111 photo as for now it always displays the same picture):
1664361037147.png

I was lucky and the attack was successful:
1664361112778.png


It works really nicely as I also play specific sounds, the in-game experience is very satisfactory:
1664361213167.png

I will continue adding stuff such as this in the next couple of days, all related to base game mechanics.

Pablo
 
Very nice play on the strategic bombing mechanism! It certainly has some advantages over the one I've been using. Can you also tie it into changing some terrain to rubble? Not sure if your scenario has a terrain slot for that.
 
Very nice play on the strategic bombing mechanism! It certainly has some advantages over the one I've been using. Can you also tie it into changing some terrain to rubble? Not sure if your scenario has a terrain slot for that.
Thanks! Which advantages do you see?

Yeah I do have a "rubble" terrain for specific historical events as two cities might get totally wiped out from the map, but I didn't think about changing any terrain on the city suburbs or remove the outside industries (vanilla mines) when bombed by air, as I don't see suitable to "raze to the ground" entire 10 square kms of land (each tile is 10x10 km) by just a couple of bombers (each air unit represents 1 to 6 airplanes). However a couple of bombers can actually hit and destroy a specific building if they are accurate enough, which is what I am trying to simulate.

The actual unit ratio conversions are tight in my scenario to represent historical numbers and realism in combat, so i have to be careful to not to "overdo" :)
 
Thanks! Which advantages do you see?

-It saves unit slots
-In HoF sometimes the AI lingers near units but doesn't attack them; this seems to take that decision away from them once they go next to something, which they tend to do. Just one of those quirks of the AI you don't notice until you design something and tear your hair out over it!
-You can presumably modify the AI's chances of targeting a specific type of industry/housing based on different conditions such as turn, flag, counter, etc. etc. etc. (so, perhaps in a BoB type scenario, the Luftwaffe would be likely to switch over to hitting civilian targets at some point)
-It avoids terrain link issues if you aren't using that like in OTR/HoF.
-It could be used to avoid the need for multimaps, since you could have only certain units (strategic bombers) have this function, and presumably could also use this function to prevent them from hitting enemy units, though that might be a little trickier in situations where they encounter a unit in the field.

Very neat concept indeed!
 
-It saves unit slots

The strategic target module I made a while ago lets you use the same unit type for as many different targets as you like. You can even have no target unit if you want to tie a terrain type to a city improvement existing within the city. The LuaDocumentation folder has a file strategicTargetsDocumentation.txt with information about that module. The module has a lot of tools for building a custom strategic bombing system, but there is a "builder" function that will build one in targetSettings.lua if you provide a couple functions.

If you don't have an associated unit, the onCalculateCityYield event would be the place where the game would discover that the improvement is missing, and change the terrain. So, in @Pablostuka 's system, the following extra code would be needed to make the terrain change happen immediately:
Code:
for target in strat.iterateTargets(attackedCityObject) do
    strat.verifyTarget(target)
end
 
So, in @Pablostuka 's system, the following extra code would be needed to make the terrain change happen immediately:
Code:
for target in strat.iterateTargets(attackedCityObject) do
    strat.verifyTarget(target)
end
"My" system is not complicated at all as I don't want to link any improvements with terrains or special units. The LST strategicTargets module is very useful for a particular objective, but I developed something simpler to meet my own needs, which were just about diversifying the standard civ2 combat and basically reproduce the air raids in Spain 1936-1939, which most of the time were to just target enemy positions (city defenders - standard civ2 combat), but also some terror bombing (especially in cities such as Madrid and Barcelona) and some "more or less successful" strategic raids against specific industrial objectives. That's why I allow the human player to take a choice of possible actions, and the AI have different random actions, with most of the time performing standard civ2 combat.

Something I want to also implement with air units vs cities is the "psychological" warfare aspect. I already implemented it in plain ground combat (with the possibility of enemy troops surrendering), but against cities with planes it's different. In our war we had multiple air raids which instead of throwing bombs, they were throwing propaganda pamphlets to target the city morale and "invite" them to surrender. My own grandmother, who was a child living in a strategic town that saw heavy fighting, switched hands and even saw the last major Republican offensive of the war, told me stories on how all the kids ran away and hid shouting "que vienen las pavas!" (the "pavas" are coming!) when they saw formations of incoming nationalist planes throwing pamphlets. Later I learned that the "pava" was the nickname of the Heinkel He 46 used by the Condor Legion.

So in summary, I want to see how can I control the number of unhappy citizens with Lua. So far I know the LST generalLibrary allows me to set civil disorder (gen.setCivilDisorder(city)) and that I can play around with city.specialists and city.workers, but unfortunately city.numUnhappy cannot be set, it's a "read only" value. So I need to do tests and think about how can I mess around with that.

Pablo
 
So in summary, I want to see how can I control the number of unhappy citizens with Lua. So far I know the LST generalLibrary allows me to set civil disorder (gen.setCivilDisorder(city)) and that I can play around with city.specialists and city.workers, but unfortunately city.numUnhappy cannot be set, it's a "read only" value. So I need to do tests and think about how can I mess around with that.
I think you've run into one of the few major gaps in the TOTPP functionality, that we can't control happiness the same way we can control shield/trade/food production. I can think of a couple ideas.

1. Have an 'improvement' that represents city morale, and so is only bestowed and removed via events, rather than building and selling.

2. In the onCalculateCityYield event, modify cosmic.sizeUnhappiness so that you get the desired city happiness. I don't think anyone has done anything like this yet.

sizeUnhappiness (get/set - ephemeral)
cosmic.sizeUnhappiness -> integer

Returns the city size at which the first unhappy citizen appears at Chieftain difficulty.
 
2. In the onCalculateCityYield event, modify cosmic.sizeUnhappiness so that you get the desired city happiness. I don't think anyone has done anything like this yet.

sizeUnhappiness (get/set - ephemeral)
cosmic.sizeUnhappiness -> integer

Returns the city size at which the first unhappy citizen appears at Chieftain difficulty.
You must be right Prof !!

Placed at the beginning of civ.scen.onCalculateCityYield(function (city, food, shields, trade) with a city or city-owner or whichever checking to ajust its value, it shall help do the job !!
 
Thanks @Prof. Garfield , I'm not familiar with that Yield event so I'll investigate it further.

onCalculateCityYield (since 0.16)
civ.scen.onCalculateCityYield(function (city, food, shields, trade) -> (foodChange, shieldChangeBeforeWaste, shieldChangeAfterWaste, tradeChangeBeforeCorruption, tradeChangeAfterCorruption)) -> void

Registers a function to be called every time a city calculates its total resource yield. Input is the city, and the food, shields and trade of its tiles. Returns a 5-tuple of modifiers, food change, shield change before waste, shield change after waste, trade change before corruption, trade change after corruption. These modifiers are applied at the following points in the calculation:
  • Calculate yield from all worked tiles
  • Run onCalculateCityYield
  • Add foodChange, shieldChangeBeforeWaste and tradeChangeBeforeCorruption
  • Add changes from food trade routes
  • Add shields from improvements
  • Calculate and subtract waste
  • Calculate corruption and add changes from commodity trade routes
  • Calculate corruption again (now using the value after trade routes) and subtract.
  • Add shieldChangeAfterWaste and tradeChangeAfterCorruption
  • Calculate Tax/Lux/Sci

If it works as expected I'll make "light bombers" able to "throw pamphlets" since these were the type of planes used for the task.
 
Last edited:
Putting beautiful some combat events, so let me spoil you a bit :D These UI reports can be switched off in case players get annoyed by so many pop ups, but I like them... :)

The combat events I've implemented are very modularised and easy to configure. These have tribe independent chances to trigger and they have different effects applying to the attacker, the defender or both. Usually they modify the attacker or defender stats (attack, defense, firepower), depending on whom they trigger for, but also affect the way combat is sustained, allowing in some cases units fighting to death or retreating to safer positions, surrendering to the enemy, or simply fleeing in panic without a fight.

Example of assault (Nationalist human player is attacking):

1664550974420.png


Example of breakthrough (Republican human player is attacking):

1664551794757.png


If any nearby commander unit is present in combat, some of these combat events will have greater chances to trigger. Plus any applicable traits that these commanders possess, will also apply to the relevant fighting units, see below:

In this example, my Republican UGT militia is trying to attack an AI controlled enemy unit close to Zaragoza but a nearby enemy general located in the city is boosting the enemy's defense capabilities. As my militia is facing combat against Nationalist troops commanded by a "defense doctrine specialist" general, the defender's defense gets a small boost.

1664551941765.png


In this other example, the Nationalist human player is fighting the Republican AI in Sevilla's suburbs. Given a nearby general is a specialist in urban warfare, the troops under their command get a bonus on both attack and defence while fighting on urban soil:
1664553007477.png


This is a two-way system: both attackers and defenders have chances to trigger combat events in their favour, also can benefit by applicable traits if a nearby friendly commander is present. Not all commander traits will apply to all units so my UI reports show which actual trait is boosting which unit. Of course the system only applies the relevant events and bonuses to the correct units under the right domains.

Now I'll implement some air and naval combat events too. But for air/naval combat no leader bonuses/traits will apply, only specific events. Navy admirals and air generals are comfortable in their HQs and don't get close to combat! :D

I'm really enjoying what I can achieve with Lua!!
 
Last edited:
Forgot to say that the chances of these combat events to trigger can be increased by researching the appropriate technologies on the "military training" branch of the tech tree :) The more doctrines are researched, the better the troops will generally perform as they will have increased chances of triggering combat events in their favour.

Back in the MGE days this was completely unthinkable!
 
Forgot to say that the chances of these combat events to trigger can be increased by researching the appropriate technologies on the "military training" branch of the tech tree :) The more doctrines are researched, the better the troops will generally perform as they will have increased chances of triggering combat events in their favour.

Back in the MGE days this was completely unthinkable!
That's definitly something to developp ! Miam miam !
 
Top Bottom