The Hinge of Fate - Development Thread

I really like how you displayed "Fuel" and "Production" in your cities, and the unusual food one is nice too.

Why not figuring luxury as a propaganda form (newspapers, radio signals, etc) ?
 
upload_2022-2-2_23-13-20.png


This is fine?
 
@Prof. Garfield I'm getting this error when I make repeated attacks with aircraft at 202,192 - there are 2x air units in the tile and 3x ground units in the tile. The first time that a fighter attacks, it does not produce the error, however it produces the error every time after that. The combat takes place, and the air unit is not the first chosen defender, instead the ground units below are killed one by one.

This is the entirety of the error. Any thoughts?

Code:
error: bad return value #-1 from 'onChooseDefender' (civ.unit expected, got nil)
 

Attachments

  • 1Playtest.zip
    272.3 KB · Views: 18
@Prof. Garfield I'm getting this error when I make repeated attacks with aircraft at 202,192 - there are 2x air units in the tile and 3x ground units in the tile. The first time that a fighter attacks, it does not produce the error, however it produces the error every time after that. The combat takes place, and the air unit is not the first chosen defender, instead the ground units below are killed one by one.

This is the entirety of the error. Any thoughts?

I'm not getting the error, and I'm pretty sure the events I have are out of date. Please post you post your onChooseDefender code, so I can run it. It looks like the function registered in onChooseDefender does not always return a unit, so that must be fixed.
 
Here's what I have:

Code:
local function onChooseDefender(defaultFunction,tile,attacker,isCombat)
    -- compute the desired defender
    return desiredDefender
end

local function chooseDefender(defaultFunction,tile,attacker,isCombat)
    --transport.onChooseDefender(defaultFunction,tile,attacker,isCombat)
    local function hasAirGroundStack(tile)
        local groundOrSea = false
        local air = false
     
        if tile.city or gen.hasAirbase(tile) then
            return false
        end
 
        for unit in tile.units do
            if gen.isCarryAir(unit.type) then
                return false
            end
            if unit.type.domain ==1 and unit.type.range >= 2 then
                air = true
            else
                groundOrSea = true
            end
        end
        return air and groundOrSea
    end
    local function adjustedAttack(unit)
        local attack = unit.type.attack
        if unit.veteran then
            attack = attack*1.5
        end
        return attack
    end
 
    -- note: this doesn't factor in much,
    -- since air units don't gain terrain
    -- bonus, and don't have a vs air bonus
    local function adjustedDefense(airUnit)
        local defense = airUnit.type.defense
        if airUnit.veteran then
            defense = defense*1.5
        end
        return defense
    end
    local function defenseRating(airUnit)
        return adjustedDefense(airUnit)*(airUnit.hitpoints)//(airUnit.type.hitpoints)
    end
    local function selectAirDefender(tile)
        local unitChosen = nil
        local defensiveValue = 0
        for airUnit in tile.units do
            if airUnit.type.domain ==1 and airUnit.type.range >= 2 then
                local ad = defenseRating(airUnit)
                if ad > defensiveValue then
                    defensiveValue = ad
                    unitChosen = airUnit
                end
            end
        end
        return unitChosen
    end
    if gen.isAttackAir(attacker.type) and hasAirGroundStack(tile) then
        return selectAirDefender(tile)
    else
        return defaultFunction(tile,attacker)
    end
end
civ.scen.onChooseDefender(chooseDefender)
 
Try setting
Code:
local defensiveValue = -1

I think what is happening is that a severely damaged air unit will have a defenseRating of 0 (since the // form of division rounds down to nearest integer), but this update
Code:
               if ad > defensiveValue then
                    defensiveValue = ad
                    unitChosen = airUnit
                end
only happens if the new defensive value is strictly better than the current one.

A quick test suggests that this fix works, but let me know if you still have trouble.
 
I just realised you should probably replace

Code:
return selectAirDefender(tile)
with
Code:
return selectAirDefender(tile) or defaultFunction(tile,attacker)
That way, the code is failsafe. If selectAirDefender returns nil for some reason, the code will just fall back to the default function.
 
Turn 49...

We've survived our first Russian Winter, though the Soviets launched a minor counter offensive and pushed into Finland. They made it as far as Vipurri when I pushed them back. The plan for the Great Summer offensive of 1942 is to complete the conquest of Moscow with Army Group Center, which retained most of its strength over the winter. 6 Tiger I tanks are making their way to that front to break the deadlock. I'll also try and push back the Soviets in Finland and give Leningrad some space by capturing Tikhvin, Petrozavodsk and Sortavala.

upload_2022-2-3_17-46-32.png


In the south, my objective is to retake Odessa and hopefully push to Dnepropetrovsk and Kerch as good staging bases for a push towards Stalingrad and Baku to hopefully finish the war in the Summer of 1943.

upload_2022-2-3_17-49-13.png



In Africa, our fuel shortages, and inability to shut down Malta have left the Afrika Korps a mere shadow of itself. I'm trying to hold off 8th Army by Mersa Matruh. I don't think I'm going to be able to afford reinforcements and honestly the theater is likely lost due to this.

upload_2022-2-3_17-44-31.png
 
What I really like in these screenshots is, that there is a lot of place between the single cities, not only 1 or 2 tiles. In this scenario there is place for military operations! :)
 
Thanks Curt!

I badly mangled this playtest though trying and failing to win the Battle of Britain. I blew through almost half of my fuel in the first 10 turns. In my last playtest, I basically went "all in" on Russia first and used all that fuel to significantly boost my forces there.

upload_2022-2-4_7-6-21.png

Note that the Gefechtsverband give you a large aircraft boost at the cost of 5,000 fuel

I do think I will say this based on a few playtests... You have three main theaters (England, Russia, Africa) and it's in your very best interest to make sure that you are victorious in at least one of those theaters before the Americans can really get going. Winning Sea Lion early would take a ton of pressure off. But then so would defeating Russia before the USAAF gets activated. You've seen what RAF Bomber Command has done to my cities (happiness improvements). I'm not looking forward to seeing what the USAAF does to my industry and overall war effort.
 
And what does Gefechtsverband mean?

Near as I can tell, it was what the air wing equivalent of a "Kampfgruppe" would be. In this scenario, your 4 general units are able to hastily scrape together a group of ground forces or an air wing. It's expensive, given the 5,000 cost, but can help restore a situation or help prepare for an important operation. To use it, your general has to have full movement points and you need the available fuel. You also can't form one in England, Africa, or North America.

Interesting. Can you replenish your fuel supplies by capturing Baku and/or Iraqi cities?

Somewhat - you get a bonus for each one of the oil cities (Ploesti, Maikop, Grozny, Baku, Mosul) that you control. Right now it's only +100 for each though that could be subject to change. I do think for balance sake it's going to be important to give a pretty hefty fuel reward once either the UK or USSR are defeated.
 
29 turns into Barbarossa, Moscow is captured! We will mop up the NW as best we can this summer. In 1943, we will aim to end the Soviets.

upload_2022-2-4_17-55-44.png
 
Near as I can tell, it was what the air wing equivalent of a "Kampfgruppe" would be. In this scenario, your 4 general units are able to hastily scrape together a group of ground forces or an air wing. It's expensive, given the 5,000 cost, but can help restore a situation or help prepare for an important operation. To use it, your general has to have full movement points and you need the available fuel. You also can't form one in England, Africa, or North America.

The term "Gefechtsverband" is not usual for German airforces in WW 2. In some English sources one can find a "Gefechtsverband Rudel", but in reality this was the Stuka-Geschwader/Schlacht-Geschwader "Immelmann".

As far as I know, the Organization of the Luftwaffe was:

Luftflotte (=Air Army), in former times Fliegerdivision, in WW 2 mostly renamed to Fliegerkorps (= Air Corps), Geschwader (=Air Wing), Gruppe, Staffel, Schwarm, Kette, Rotte. For special operations, when the organization in Geschwader was not useful, even the term Kampfgruppe was used. As far as I know the bombers of the Legion Condor in the Spanish Civil war were named Kampfgruppe 88. Other terms were Küstenfliegergruppe (KüFlGr), Aufklärungsgruppe (AufklGr) und Nachtschlachtgruppe (NSG).

I think for this scenario may be the best term replacing "Gefechtsverband" would be Fliegerkorps.

https://en.wikipedia.org/wiki/Organization_of_the_Luftwaffe_(1933–1945)

The World War II German Luftwaffe Geschwader and Gruppe were similar to the wing and group of the United States Army Air Forces of the same era:
https://en.wikipedia.org/wiki/Wing_(military_unit)
 
Last edited:
I considered fliegerkorps, and don't have an issue changing it, really, but a fliegerkorps, in my understanding, was a fairly permanent structure? For example, Fliegerkorps X. is specifically featured in the scenario?

This is not really what this is meant to be. You aren't raising a new Geschwader or series of them - you're hypothetically just scraping together whatever planes you can come up with in the general area and throwing them together, much like many kampfgruppe (especially the paper tiger ones later in the war) would have been.

It takes its inspiration from this group that was hastily assembled to help Finland:

https://en.m.wikipedia.org/wiki/Detachment_Kuhlmey
 
Kalinin has exchanged hands - Moscow did not break the Soviets as I had hoped. We're going to have quite the fight on our hands to hold it.

upload_2022-2-4_23-7-47.png
 
Top Bottom