Jump to content

R&D AI Improvements


Amineri

Recommended Posts

I'm more than happy for people to consolidate my mods and post them up on Nexus. The primary reason I don't do so myself is that providing support for 20 or so mods would be pretty time-consuming (and take time away from actually modding ;) ).

 

As regarding the Bug Fixes mod I'm not planning on updating it until after EW comes out and we know which bugs the official patch and expansion resolve.

Link to comment
Share on other sites

  • Replies 144
  • Created
  • Last Reply

Top Posters In This Topic

Just ran into a strange bug with Bug Fixes + AI Improvements. Applying both consistently freezes the game for me on aliens turn. Last change in Bug Fixes is the reason:

UPK_FILE=XComGame.upk
OFFSET=8272039
[MODDED_HEX]
{ hex offset 7E38A7 }
{ Fix AI so it doesn't skip turns when aliens are flanked and overwatched }
{ before: }
{ UNINSTALL }
{ 07 F6 01 9A 19 00 BA 88 00 00 0A 00 1C 7C 00 00 00 1B 1E 35 00 00 00 00 00 00 16 26 16 07 F6 01 82 81 19 01 B0 88 00 00 0A 00 C2 8A 00 00 00 2D 01 C2 8A 00 00 16 18 23 00 97 36 19 01 B1 88 00 00 09 00 77 BB 00 00 00 01 77 BB 00 00 25 16 16 B6 00 B8 88 00 00 AC 1E 9A 99 99 3E 38 3F 19 01 B0 88 00 00 09 00 8C 8A 00 00 00 01 8C 8A 00 00 16 16 04 00 B8 88 00 00 04 3A B9 88 00 00 53  }
{ after: }
{ INSTALL }
07 F7 01 9A 19 00 BA 88 00 00 0A 00 1C 7C 00 00 00 1B 1E 35 00 00 00 00 00 00 16 26 16 07 F7 01 82 81 19 01 B0 88 00 00 0A 00 C2 8A 00 00 00 2D 01 C2 8A 00 00 16 18 23 00 97 36 19 01 B2 88 00 00 09 00 91 30 00 00 00 01 91 30 00 00 25 16 16 B6 00 B8 88 00 00 AC 1E 9A 99 99 3E 38 3F 36 19 01 B2 88 00 00 09 00 91 30 00 00 00 01 91 30 00 00 16 16 04 00 B8 88 00 00 00 B8 88 00 00 53 
If I apply only Bug Fixes — game works perfectly. Same with only IA Improvements. Both (AI Improvements after Bug Fixes) cause consistent freeze. Removing AI-turn-skipping thing from Bug Fixes and applying AI Improvements after this eliminates the problem.

 

Are those changes truly incompatible or am I doing something wrong? So far I haven't received any similar bugreports from other players using this with Larger Pods, but for me it's pretty consistent.

 

Turns out, I never used Bug Fixes Installer before: I applied code from forum topics myself and omitted this last change, because as I understood AI Improvements already include this fix. And I had no overwatch-freeze bug with AI Improvements only.

 

PS With this two conflicting changes I had not only this bug, but all other sorts of bugs, like pods activating while still in the fow, laser overwatch crash, support supression crash. After removing conflicting change those bugs have disappeared too.

Edited by wghost81
Link to comment
Share on other sites

Sorry this got a little mixed up. I went through my notes and tried to trace out just what happened.

 

So the bug comes about because in the vanilla code the function XGAIAbilityDM.AI_GetScoreModifier is the code:

	if(kAbility.GetType() == 1)
	{
		// End:0x1f6 Loop:False
		if(!m_kBehavior.m_bIgnoreOverwatchers && (m_kPlayer.m_arrEnemiesInOverwatch.Length > 0))
		{
			fModifier *= 0.30 / float(m_kBehavior.m_iOverwatchDangerZone);
		}
	}

The issue is that the condition is checking to see if there are any enemies overwatching, while the divisor is the OverwatchDangerZone. Due to a variety of conditions this can result in a DIVIDE-BY-ZERO, screwing up the priority calculation for the move ability. This results in the move ability being filtered out. However since the unit is flanked all non-move abilities are also filtered out, leaving an empty ability list for the unit, resulting in the turn-skipping.

 

My first attempt at a fix revised the code to :

if(kAbility.GetType() == 1)
07 F7 01 9A 19 00 BA 88 00 00 0A 00 1C 7C 00 00 00 1B 1E 35 00 00 00 00 00 00 16 26 16 

    if(!m_kBehavior.m_bIgnoreOverwatchers && m_kPlayer.m_arrEnemiesInOverwatch.Length > 0)
    07 F7 01 82 81 19 01 B0 88 00 00 0A 00 C2 8A 00 00 00 2D 01 C2 8A 00 00 16 18 23 00 97 36 19 01 B2 88 00 00 09 00 91 30 00 00 00 01 91 30 00 00 25 16 16 

	fModifier *= (0.30 / float(m_kUnit.m_arrFlankingUnits.Length));
	B6 00 B8 88 00 00 AC 1E 9A 99 99 3E 38 3F 36 19 01 B2 88 00 00 09 00 91 30 00 00 00 01 91 30 00 00 16 16 

This removed the turn-skipping but wasn't really ideal in terms of the resultant AI behavior. The above code reflects the before/after hex changes that you posted.

 

Subsequently I came up with a better alternative :

    if(kAbility.GetType() == 1)
    {
        // End:0x1F6
        if(!m_kBehavior.m_bIgnoreOverwatchers && m_kBehavior.m_iOverwatchDangerZone > 0)
        {            
            fModifier *= (0.30 / float(m_kBehavior.m_iOverwatchDangerZone));
        }
    }

This code explicitly checks that the OverwatchDangerZone value is positive before performing the division, so it's impossible to generate Divide-by-zero errors.

 

This change is implemented via the following hex change:

XGAIAbilityDM.AI_GetScoreModifier
	
original hex:
07 F6 01 82 81 19 01 B0 88 00 00 0A 00 C2 8A 00 00 00 2D 01 C2 8A 00 00 16 18 23 00 97 36 19 01 B1 88 00 00 09 00 77 BB 00 00 00 01 77 BB 00 00 25 16 16 B6 00 B8 88 00 00 AC 1E 9A 99 99 3E 38 3F 19 01 B0 88 00 00 09 00 8C 8A 00 00 00 01 8C 8A 00 00 16 16 

new hex:
07 F6 01 82 81 19 01 B0 88 00 00 0A 00 C2 8A 00 00 00 2D 01 C2 8A 00 00 16 18 22 00 97 19 01 B0 88 00 00 09 00 8C 8A 00 00 00 01 8C 8A 00 00 25 16 16 0B B6 00 B8 88 00 00 AC 1E 9A 99 99 3E 38 3F 19 01 B0 88 00 00 09 00 8C 8A 00 00 00 01 8C 8A 00 00 16 16 

This is currently what is running in Long War, and should be compatible with the AI changes (particularly the ones that adjust how the OverwatchDangerZone value is computed).

Edited by Amineri
Link to comment
Share on other sites

New vanilla EW code that fixes this bug:

    if(kAbility.GetType() == 1)
    {
        if((!m_kBehavior.m_bIgnoreOverwatchers && m_kPlayer.m_arrEnemiesInOverwatch.Length > 0) && m_kBehavior.m_iOverwatchDangerZone > 0)
        {
            fModifier *= (0.30 / float(m_kBehavior.m_iOverwatchDangerZone));
        }
    }

Looks pretty similar to my unofficial patch, but Firaxis retained the m_kPlayer.m_arrEnemiesInOverwatch.Length > 0, which doesn't actually do anything because m_iOverwatchDangerZone can only be positive if there are overwatchers.

 

Anyhow, this particular bug fix isn't needed for EW.

Link to comment
Share on other sites

Shame they didn't make this change to EU.

 

Like most things it's both good and bad...

 

The bad is that the bug wasn't fixed, but the good part is that with fewer changes to EU it will be easier and quicker to adapt existing mods to the (minimally) patched EU.

 

It also looks like they locked down the EU patch much earlier : final version for EU patch 5 was July 11, 2013.

 

EW however wasn't locked down until October 1, 2013. So about 2 1/2 months more development on EW.

Link to comment
Share on other sites

I've played about 3 game months and I can say: AI is definitely better in EW. I've seen Thinman Hunker Down twice, I've seen enemies trying to run being overwatched and/or supressed (capturing aliens can be a real pain now) and I've seen patrols coming towards me more often (as if they finally learned to hear sounds as XCOM soldiers do).

 

Flank+overwatch freeze has been removed, but aliens sometimes freeze when supressed or even overwatched, but not flanked. I've seen this with Thinman and Mutons. With EU if you supress a Muton you can be sure he'll throw a grenade, but now he could just skip his turn (Impossible difficulty). Amineri, you were able to fix supressed aliens turn skip bug for EU, may be you cold do this for EW as well?

 

And, sadly, aliens still teleport from/inside my LOS. :sad: It's rare (I've seen it twice), but it happens.

 

On a side note. It seems, they reduced panic effects. I've never seen my soldier panic when Muton uses his Intimidate ability. And I still take my starting team on missions: 60-70 Will max. One reason less to use SHIVs.

Edited by wghost81
Link to comment
Share on other sites

  • 2 weeks later...

I was thinking about new EW pod activation options: ranged units, which can't take cover, go on overwatch on reveal. It's implemented in XComAlienPod:

 

 

if(((((XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.m_kPodMgr.m_bPodRevealAttack && !m_bAttacked) && !m_kActiveUnit.CanUseCover()) && !m_kActiveUnit.IsMeleeOnly()) && m_kActiveUnit.GetCharType() != 23) && !m_bSkipActivateMatinee)
{
    m_eWaitStatus = 14;
    J0x1165:
    // End:0x11CE [Loop If]
    if(m_kEnemy.IsMoving() && !m_kEnemy.m_kCurrAction.IsA('XGAction_EndMove'))
    {
        Sleep(0.10);
        // [Loop Continue]
        goto J0x1165;
    }
    // End:0x1474
    if((m_kActiveUnit.m_arrVisibleEnemies.Length > 0) && m_kActiveUnit.GetCharType() != 16)
    {
        // End:0x130A
        if(XComGameReplicationInfo(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kGameCore.IsOptionEnabled(14))
        {
            XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.m_kPodMgr.m_iAttackChance = 50;
        }
        // End:0x1388
        else
        {
            XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.m_kPodMgr.m_iAttackChance = 0;
        }
        // End:0x1474
        if(class'XComEngine'.static.SyncRand(100, (string(Name) @ string(GetStateName())) @ string(GetFuncName())) < XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.m_kPodMgr.m_iAttackChance)
        {
            m_bAttacked = m_kActiveUnit.FireAtEnemy();
        }
    }
    // End:0x14BD
    if(m_bAttacked && m_bCoordinatedMovement)
    {
        CoverGoToPoints.Remove(0, CoverGoToPoints.Length);
        m_kActiveCover = none;
        m_bCoordinatedMovement = false;
    }
    // End:0x15A9
    if(!m_bAttacked)
    {
        // End:0x1530
        if((m_kActiveUnit.GetCharType() == 12) || m_kActiveUnit.GetCharType() == 19)
        {
            MoveToCover(m_kActiveCover);
        }
        // End:0x15A9
        else
        {
            // End:0x1569
            if(m_kActiveUnit.GetCharType() == 8)
            {
                OpenCyberdisc(m_kActiveUnit);
            }
            m_kActiveUnit.m_kBehavior.DoOverwatch();
            m_bAttacked = true;
        }
    }
}
// End:0x1667
else
{
    // End:0x1654
    if(m_kActiveUnit.GetCharType() == 23)
    {
        // End:0x1651
        if(m_kActiveUnit.IsVisible())
        {
            m_kActiveUnit.ResetMoves();
            m_kActiveUnit.ResetUseAbilities();
            m_kActiveUnit.DoStealthAbility();
        }
    }
    // End:0x1667
    else
    {
        MoveToCover(m_kActiveCover);
    }
}

 

I was just wondering if this code could be rewritten to allow ALL ranged units move to cover (if they can) and then go on overwatch or fire at player unit.

Edited by wghost81
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...