Help: AgentDrivenProperties (AI Combat Effectiveness)

Users who are viewing this thread

abc123456

Regular
I spent 2 days trying to reverse engineer the code handling the combat AI. I was able to make the AI parry around 95% of the time. However, the AI struggles to parry feints when you set AIAttackOnDecideChance to greater than 0.

It looks like the AI has problem parrying feinting attacks when they are attacking.
If you set AIParryOnDecideAbility = 100 and AIAttackOnDecideChance = 0, the AI does parry against feints well.

Does anyone know which properties to adjust to improve AI parry vs feinting attacks?
Or is the code handled elsewhere?

C#:
 float num3 = num + agent.Defensiveness;
            agentDrivenProperties.AiRangedHorsebackMissileRange = (float)(0.300000011920929 + 0.400000005960464 * (double)num2);
            agentDrivenProperties.AiFacingMissileWatch = (float)((double)num * 0.0599999986588955 - 0.959999978542328);
            agentDrivenProperties.AiFlyingMissileCheckRadius = (float)(8.0 - 6.0 * (double)num);
            agentDrivenProperties.AiShootFreq = (float)(0.300000011920929 + 0.699999988079071 * (double)num2);
            agentDrivenProperties.AiWaitBeforeShootFactor = (agent._propertyModifiers.resetAiWaitBeforeShootFactor ? 0f : ((float)(1.0 - 0.5 * (double)num2)));
            agentDrivenProperties.AIBlockOnDecideAbility = MBMath.Lerp(0.25f, 0.99f, MBMath.ClampFloat((float)Math.Pow((double)num, 1.0), 0f, 1f), 1E-05f);
            agentDrivenProperties.AIParryOnDecideAbility = MBMath.Lerp(0.01f, 0.95f, MBMath.ClampFloat((float)Math.Pow((double)num, 1.5), 0f, 1f), 1E-05f);
            agentDrivenProperties.AiTryChamberAttackOnDecide = (float)(((double)num - 0.150000005960464) * 0.100000001490116);
            agentDrivenProperties.AIAttackOnParryChance = (float)(0.300000011920929 - 0.100000001490116 * (double)agent.Defensiveness);
            agentDrivenProperties.AiAttackOnParryTiming = (float)(0.300000011920929 * (double)num - 0.200000002980232);
            agentDrivenProperties.AIDecideOnAttackChance = 0.15f * agent.Defensiveness;
            agentDrivenProperties.AIParryOnAttackAbility = MBMath.ClampFloat((float)Math.Pow((double)num, 3.0), 0f, 1f);
            agentDrivenProperties.AiKick = (float)((((double)num > 0.400000005960464) ? 0.400000005960464 : ((double)num)) - 0.100000001490116);
            agentDrivenProperties.AiAttackCalculationMaxTimeFactor = num;
            agentDrivenProperties.AiDecideOnAttackWhenReceiveHitTiming = (float)(-0.25 * (1.0 - (double)num));
            agentDrivenProperties.AiDecideOnAttackContinueAction = (float)(-0.5 * (1.0 - (double)num));
            agentDrivenProperties.AiDecideOnAttackingContinue = 0.1f * num;
            agentDrivenProperties.AIParryOnAttackingContinueAbility = MBMath.Lerp(0.05f, 0.95f, MBMath.ClampFloat((float)Math.Pow((double)num, 3.0), 0f, 1f), 1E-05f);
            agentDrivenProperties.AIDecideOnRealizeEnemyBlockingAttackAbility = 0.5f * MBMath.ClampFloat((float)Math.Pow((double)num, 2.5) - 0.1f, 0f, 1f);
            agentDrivenProperties.AIRealizeBlockingFromIncorrectSideAbility = 0.5f * MBMath.ClampFloat((float)Math.Pow((double)num, 2.5) - 0.1f, 0f, 1f);
            agentDrivenProperties.AiAttackingShieldDefenseChance = (float)(0.200000002980232 + 0.300000011920929 * (double)num);
            agentDrivenProperties.AiAttackingShieldDefenseTimer = (float)(0.300000011920929 * (double)num - 0.300000011920929);
            agentDrivenProperties.AiRandomizedDefendDirectionChance = (float)(1.0 - Math.Log((double)num * 7.0 + 1.0, 2.0) * 0.333330005407333);
            agentDrivenProperties.AISetNoAttackTimerAfterBeingHitAbility = MBMath.ClampFloat((float)Math.Pow((double)num, 2.0), 0.05f, 0.95f);
            agentDrivenProperties.AISetNoAttackTimerAfterBeingParriedAbility = MBMath.ClampFloat((float)Math.Pow((double)num, 2.0), 0.05f, 0.95f);
            agentDrivenProperties.AISetNoDefendTimerAfterHittingAbility = MBMath.ClampFloat((float)Math.Pow((double)num, 2.0), 0.05f, 0.95f);
            agentDrivenProperties.AISetNoDefendTimerAfterParryingAbility = MBMath.ClampFloat((float)Math.Pow((double)num, 2.0), 0.05f, 0.95f);
            agentDrivenProperties.AIEstimateStunDurationPrecision = 1f - MBMath.ClampFloat((float)Math.Pow((double)num, 2.0), 0.05f, 0.95f);
            agentDrivenProperties.AIHoldingReadyMaxDuration = MBMath.Lerp(0.25f, 0f, Math.Min(1f, num * 1.2f), 1E-05f);
            agentDrivenProperties.AIHoldingReadyVariationPercentage = num;
            agentDrivenProperties.AiRaiseShieldDelayTimeBase = (float)(0.5 * (double)num - 0.75);
            agentDrivenProperties.AiUseShieldAgainstEnemyMissileProbability = (float)(0.100000001490116 + (double)num * 0.600000023841858 + (double)num3 * 0.200000002980232);
            agentDrivenProperties.AiCheckMovementIntervalFactor = (float)(0.00499999988824129 * (1.10000002384186 - (double)num));
            agentDrivenProperties.AiMovemetDelayFactor = (float)(4.0 / (3.0 + (double)num2));
            agentDrivenProperties.AiParryDecisionChangeValue = (float)(0.0500000007450581 + 0.699999988079071 * (double)num);
            agentDrivenProperties.AiDefendWithShieldDecisionChanceValue = Math.Min(1f, (float)(0.200000002980232 + 0.5 * (double)num + 0.200000002980232 * (double)num3));
            agentDrivenProperties.AiMoveEnemySideTimeValue = (float)(0.5 * (double)num - 2.5);
            agentDrivenProperties.AiMinimumDistanceToContinueFactor = (float)(2.0 + 0.300000011920929 * (3.0 - (double)num));
            agentDrivenProperties.AiStandGroundTimerValue = (float)(0.5 * ((double)num - 1.0));
            agentDrivenProperties.AiStandGroundTimerMoveAlongValue = (float)(0.5 * (double)num - 1.0);
            agentDrivenProperties.AiHearingDistanceFactor = 1f + num;
            agentDrivenProperties.AiChargeHorsebackTargetDistFactor = (float)(1.5 * (3.0 - (double)num));
            agentDrivenProperties.AiWaitBeforeShootFactor = (agent._propertyModifiers.resetAiWaitBeforeShootFactor ? 0f : ((float)(1.0 - 0.5 * (double)num2)));
            float num4 = 1f - num2;
            agentDrivenProperties.AiRangerLeadErrorMin = (float)(-(float)((double)num4) * 0.349999994039536) + improvedCombatAI.RangedError;
            agentDrivenProperties.AiRangerLeadErrorMax = num4 * 0.2f + improvedCombatAI.RangedError;
            agentDrivenProperties.AiRangerVerticalErrorMultiplier = num4 * 0.1f;
            agentDrivenProperties.AiRangerHorizontalErrorMultiplier = num4 * 0.0349065848f;
            agentDrivenProperties.AIAttackOnDecideChance = MathF.Clamp((float)(0.230000004172325 * (double)base.CalculateAIAttackOnDecideMaxValue() * (3.0 - (double)agent.Defensiveness)), 0.05f, 1f);
            agentDrivenProperties.SetStat(DrivenProperty.UseRealisticBlocking, 1f);

EDIT: Just after posting this, I had an idea. If you set AIParryOnDecideAbility = 100 and AIAttackOnDecideChance = 0.1
The AI can now parry feints better.
It seems like the AI has poor defense if he is aggressive.

I guess posting in the forums helped my brain somehow!
 
Last edited:
I have been working on that piece of code a few hours too. But at the time it was located in another model.

Anyway, you want to consider that those abilities are, for an overwhelming part, between 0 and 1. Only the timers and some AI abilities that I might have missed do not fall into that range.

So setting 100 or everything like that seems pretty suspicious considering you want to reverse engineer the code. It also explains why you experienced troubles with the "decide -> attack" ability.

To be honest, I think this part of the code is handled properly by the developers and I think the combat AI is very convincing with the right values set. It is extremely easy to tweak as is the damage system. We just need a way now to control the formation and strategic AI and we will be able to build some great mods.
 
Upvote 0
I have been working on that piece of code a few hours too. But at the time it was located in another model.

Anyway, you want to consider that those abilities are, for an overwhelming part, between 0 and 1. Only the timers and some AI abilities that I might have missed do not fall into that range.

So setting 100 or everything like that seems pretty suspicious considering you want to reverse engineer the code. It also explains why you experienced troubles with the "decide -> attack" ability.

To be honest, I think this part of the code is handled properly by the developers and I think the combat AI is very convincing with the right values set. It is extremely easy to tweak as is the damage system. We just need a way now to control the formation and strategic AI and we will be able to build some great mods.

I worked it out and made a killer AI that feints and parry like crazy. Unfortunately I can cheese it by kick-attack. Do you know a way to control the AI distance? If I can make the AI keep a safe distance, then I can't kick it.

BTW, I think some of these code is unimplemented.

AIKick and AiTryChamberAttackOnDecide doesn't work. I think AI can't kick, bash or chamber.

Here is the updated code, try that and the AI will be insane. I am going to scale the abilities with melee skill, of course and remove the irrelevant ones.

BTW, the combat AI is actually very bad. For someone new or maybe never practiced much it's ok. But for experienced players it is way too easy, hence why I am doing this because the combat AI is the core for everything else. I want to make a better tournament mod, but that falls apart without a good 1v1 AI.


Code:
 agentDrivenProperties.AiParryDecisionChangeValue = 0;
            agentDrivenProperties.AiMovemetDelayFactor = 0;
            agentDrivenProperties.AiCheckMovementIntervalFactor = 0;
            agentDrivenProperties.AiAttackingShieldDefenseTimer = 0;
            agentDrivenProperties.AiAttackingShieldDefenseChance = 0;
            agentDrivenProperties.AIRealizeBlockingFromIncorrectSideAbility = 0;
            agentDrivenProperties.AIDecideOnRealizeEnemyBlockingAttackAbility = 100;
            agentDrivenProperties.AIParryOnAttackingContinueAbility = 100;
            agentDrivenProperties.AiDecideOnAttackingContinue = 100;
            agentDrivenProperties.AiDecideOnAttackContinueAction = 100;
            agentDrivenProperties.AiDecideOnAttackWhenReceiveHitTiming = 0;
            agentDrivenProperties.AiAttackCalculationMaxTimeFactor = 0;
            agentDrivenProperties.AiKick = 0;
            agentDrivenProperties.AIParryOnAttackAbility = 100;
            agentDrivenProperties.AIDecideOnAttackChance = 100;
            agentDrivenProperties.AiAttackOnParryTiming = 0;
            agentDrivenProperties.AIAttackOnParryChance = 0;
            agentDrivenProperties.AiDefendWithShieldDecisionChanceValue = 0;
            agentDrivenProperties.AiTryChamberAttackOnDecide = 0;
            agentDrivenProperties.AiMoveEnemySideTimeValue = 0;
            agentDrivenProperties.AiStandGroundTimerValue = 0;
            agentDrivenProperties.AIEstimateStunDurationPrecision = 0;
            agentDrivenProperties.AISetNoDefendTimerAfterParryingAbility = 0;
            agentDrivenProperties.AISetNoDefendTimerAfterHittingAbility = 0;
            agentDrivenProperties.AISetNoAttackTimerAfterBeingParriedAbility = 0;
            agentDrivenProperties.AISetNoAttackTimerAfterBeingHitAbility = 0;
            agentDrivenProperties.AiRandomizedDefendDirectionChance = 0;
            agentDrivenProperties.AiSpeciesIndex = 0;
            agentDrivenProperties.AiUseShieldAgainstEnemyMissileProbability = 0;
            agentDrivenProperties.AiRaiseShieldDelayTimeBase = 0;
            agentDrivenProperties.AIAttackOnDecideChance =0.9f;
            agentDrivenProperties.AiRangerHorizontalErrorMultiplier = 0;
            agentDrivenProperties.AiRangerVerticalErrorMultiplier = 0;
            agentDrivenProperties.AiRangerLeadErrorMax = 0;
            agentDrivenProperties.AiRangerLeadErrorMin = 0;
            agentDrivenProperties.AiChargeHorsebackTargetDistFactor = 0;
            agentDrivenProperties.AiHearingDistanceFactor = 0;
            agentDrivenProperties.AiStandGroundTimerMoveAlongValue = 0;
            agentDrivenProperties.AiMinimumDistanceToContinueFactor = 0;
            agentDrivenProperties.AIParryOnDecideAbility = 100;
            agentDrivenProperties.AIBlockOnDecideAbility = 0;
            agentDrivenProperties.AiWaitBeforeShootFactor = 0;
            //agentDrivenProperties.ArmorTorso = 0;
            //agentDrivenProperties.ArmorHead = 0;
            //agentDrivenProperties.WeaponsEncumbrance = 0;
            //agentDrivenProperties.ArmorEncumbrance = 0;
            //agentDrivenProperties.WeaponRotationalAccuracyPenaltyInRadians = 0;
            //agentDrivenProperties.WeaponUnsteadyEndTime = 0;
            //agentDrivenProperties.WeaponUnsteadyBeginTime = 0;
            //agentDrivenProperties.ArmorLegs = 0;
            //agentDrivenProperties.WeaponMaxUnsteadyAccuracyPenalty = 0;
            //agentDrivenProperties.WeaponStationaryAccuracyMultiplier = 0;
            //agentDrivenProperties.WeaponInaccuracy = 0;
            //agentDrivenProperties.ReloadSpeed = 0;
            //agentDrivenProperties.ThrustKnockBackChanceBonus = 0;
            //agentDrivenProperties.HandlingMultiplier = 0;
            //agentDrivenProperties.ThrustOrRangedReadySpeedMultiplier = 0;
            //agentDrivenProperties.SwingSpeedMultiplier = 1;
            //agentDrivenProperties.WeaponMaxMovementAccuracyPenalty = 0;
            agentDrivenProperties.AIHoldingReadyMaxDuration = 0;
            //agentDrivenProperties.ArmorArms = 0;
            //agentDrivenProperties.LongestRangedWeaponInaccuracy = 0;
            agentDrivenProperties.AiShootFreq = 0;
            agentDrivenProperties.AiFlyingMissileCheckRadius = 0;
            agentDrivenProperties.AiFacingMissileWatch = 0;
            agentDrivenProperties.AiRangedHorsebackMissileRange = 0;
            //agentDrivenProperties.MountDifficulty = 0;
            //agentDrivenProperties.MountChargeDamage = 0;
            //agentDrivenProperties.MountSpeed = 0;
            //agentDrivenProperties.LongestRangedWeaponSlotIndex = 0;
            //agentDrivenProperties.MountManeuver = 0;
            //agentDrivenProperties.AttributeHorseArchery = 0;
            //agentDrivenProperties.CombatMaxSpeedMultiplier = 100;
            //agentDrivenProperties.MaxSpeedMultiplier = 0;
            //agentDrivenProperties.TopSpeedReachDuration = 0; // crashses at 0
            //agentDrivenProperties.ShieldBashStunDurationMultiplier = 0;
            //agentDrivenProperties.AttributeShieldMissileCollisionBodySizeAdder = 0;
            //agentDrivenProperties.AttributeShield = 0;
            //agentDrivenProperties.AttributeRiding = 0;
            //agentDrivenProperties.AttributeCourage = 0;
            agentDrivenProperties.AIHoldingReadyVariationPercentage = 0;
 
Upvote 0
Yeah, I want to do exactly the same thing. I will try your setting soon.

It is right that some parts of the AI need a rework : the ability to kick and to avoid kicks is extremely important (it was extremely easy to implement in warband).

I think the AI is good -if modified.

Anyway, I'll probably do some testing soon.

There are two things that need to be fixed in priority :
-the AI must kick and avoid kicks;
-it should be impossible to cheese the AI by turning around it.

But I don't want Taleworlds to work on the AI abilities since it can be so easily modified. And this is why they did a great job on that. Of course, the default values are not suited to a veteran.

It is impossible for us to choose the spacing between units as far as I am aware, as well as it is yet impossible (or tedious to the point that you don't want to try it) to script their paths. It should be possible in the upcoming full game.

Apart from that, I think some of the values that you implemented can be modified to make the AI better. It is also likely that you will experience issues on a large battlefield with these values if I remrmber correctly.
 
Last edited:
Upvote 0
I tried your code and I'm not 100% convinced by it. Maybe it is the way I implemented it... Could you upload the file just so I can test ?
I found some exploits too. It seems like under some circumstances the AI dies easily despite being able to feint and parry very well. Frustrating.
Please TaleWorlds, just give Godlike AI difficulty so we can build fun mods around the AI system.
 
Upvote 0
Back
Top Bottom