public BLTAgentStatCalculateModel(AgentStatCalculateModel previousModel) { this.previousModel = previousModel; CampaignEvents.OnMissionEndedEvent.AddNonSerializedListener(this, _ => { activeModifiers.Clear(); }); Current = this; }
private static bool CalculateAILevelPrefix(AgentStatCalculateModel __instance, ref float __result, int relevantSkillLevel) { if (ModSettings.Settings.LogarithmicAICombatDifficulty.Enabled && relevantSkillLevel > 1) { var instanceType = __instance.GetType(); var difficultyModifier = (float)instanceType.GetMethod("GetDifficultyModifier", BindingFlags.Instance | BindingFlags.Public).Invoke(__instance, null); var level = (float)Math.Pow(Math.Log(relevantSkillLevel, 350), 2) * difficultyModifier; __result = level < 0 ? 0f : level > 1 ? 1f : level; return(false); } else { return(true); } }
static void Postfix(Agent agent, ref AgentDrivenProperties agentDrivenProperties, WeaponComponentData equippedItem, WeaponComponentData secondaryItem, AgentStatCalculateModel __instance) { MethodInfo method = typeof(AgentStatCalculateModel).GetMethod("GetMeleeSkill", BindingFlags.NonPublic | BindingFlags.Instance); method.DeclaringType.GetMethod("GetMeleeSkill"); //int meleeSkill = Utilities.GetMeleeSkill(agent, equippedItem, secondaryItem); //int effectiveSkill = Utilities.GetEffectiveSkill(agent.Character, agent.Origin, agent.Formation, skill); SkillObject skill = (equippedItem == null) ? DefaultSkills.Athletics : equippedItem.RelevantSkill; int meleeSkill = (int)method.Invoke(__instance, new object[] { agent, equippedItem, secondaryItem }); int effectiveSkill = __instance.GetEffectiveSkill(agent.Character, agent.Origin, agent.Formation, skill); float meleeLevel = Utilities.CalculateAILevel(agent, meleeSkill); //num float effectiveSkillLevel = Utilities.CalculateAILevel(agent, effectiveSkill); //num2 float meleeDefensivness = meleeLevel + agent.Defensiveness; //num3 agentDrivenProperties.AiChargeHorsebackTargetDistFactor = 8f; agentDrivenProperties.AIBlockOnDecideAbility = MBMath.ClampFloat(0.1f + meleeLevel * 0.6f, 0.2f, 0.45f); // chance for directed blocking agentDrivenProperties.AIParryOnDecideAbility = MBMath.ClampFloat((meleeLevel * 0.30f) + 0.15f, 0.1f, 0.45f); agentDrivenProperties.AIRealizeBlockingFromIncorrectSideAbility = MBMath.ClampFloat((meleeLevel * 0.3f) - 0.05f, 0.01f, 0.25f); agentDrivenProperties.AIDecideOnAttackChance = MBMath.ClampFloat(meleeLevel + 0.1f, 0f, 0.95f); agentDrivenProperties.AIDecideOnRealizeEnemyBlockingAttackAbility = MBMath.ClampFloat(meleeLevel + 0.1f, 0f, 0.95f); agentDrivenProperties.AiRangedHorsebackMissileRange = 0.5f; agentDrivenProperties.AiUseShieldAgainstEnemyMissileProbability = 0.95f; agentDrivenProperties.AiFlyingMissileCheckRadius = 250f; agentDrivenProperties.AiShooterError = 0.0001f; //agentDrivenProperties.AiRangerLeadErrorMin = 0f; //agentDrivenProperties.AiRangerLeadErrorMax = 0f; if (equippedItem != null && equippedItem.RelevantSkill == DefaultSkills.Bow) { agentDrivenProperties.AiRangerVerticalErrorMultiplier = MBMath.ClampFloat(0.025f - effectiveSkill * 0.0001f, 0.01f, 0.025f); //bow agentDrivenProperties.AiRangerHorizontalErrorMultiplier = MBMath.ClampFloat(0.025f - effectiveSkill * 0.0001f, 0.01f, 0.025f); //bow } else if (equippedItem != null && equippedItem.RelevantSkill == DefaultSkills.Crossbow) { agentDrivenProperties.AiRangerVerticalErrorMultiplier = MBMath.ClampFloat(0.015f - effectiveSkill * 0.0001f, 0.005f, 0.015f); //crossbow agentDrivenProperties.AiRangerHorizontalErrorMultiplier = MBMath.ClampFloat(0.015f - effectiveSkill * 0.0001f, 0.005f, 0.015f); //crossbow } else { agentDrivenProperties.AiRangerVerticalErrorMultiplier = MBMath.ClampFloat(0.030f - effectiveSkill * 0.0001f, 0.01f, 0.030f); // javelins and axes etc agentDrivenProperties.AiRangerHorizontalErrorMultiplier = MBMath.ClampFloat(0.030f - effectiveSkill * 0.0001f, 0.01f, 0.030f); // javelins and axes etc } agentDrivenProperties.AIAttackOnParryChance = MBMath.ClampFloat(meleeLevel * 0.4f, 0.1f, 0.30f); //0.3f - 0.1f * agent.Defensiveness; //0.2-0.3f // chance to break own parry guard - 0 constant parry in reaction to enemy, 1 constant breaking of parry agentDrivenProperties.AIDecideOnAttackChance = MBMath.ClampFloat(meleeLevel * 0.3f, 0.15f, 0.5f); //0.15f * agent.Defensiveness; //0-0.15f - how often is direction changed (or swtich to parry) when preparing for attack agentDrivenProperties.AIAttackOnDecideChance = 0.5f; //MBMath.ClampFloat(0.23f * CalculateAIAttackOnDecideMaxValue() * (3f - agent.Defensiveness), 0.05f, 1f); //0.05-1f, 0.66-line, 0.44 - shield wall - aggressiveness / chance of attack instead of anything else / when set to 0 AI never attacks on its own agentDrivenProperties.AiDefendWithShieldDecisionChanceValue = MBMath.ClampFloat(1f - (meleeLevel * 1f), 0.1f, 1.0f); //MBMath.ClampMin(1f, 0.2f + 0.5f * num + 0.2f * num3); 0.599-0.799 = 200 skill line/wall - chance for passive constant block //agentDrivenProperties.AiRaiseShieldDelayTimeBase = -0.4f; //MBMath.ClampFloat(-0.5f + (meleeLevel * 1.25f), -0.5f, 0f); //-0.75f + 0.5f * meleeLevel; delay between block decision and actual block for AI agentDrivenProperties.AiAttackCalculationMaxTimeFactor = meleeLevel; agentDrivenProperties.AiAttackingShieldDefenseChance = MBMath.ClampFloat(meleeLevel * 2f, 0.1f, 1.0f);; //0.2f + 0.3f * meleeLevel; agentDrivenProperties.AiAttackingShieldDefenseTimer = MBMath.ClampFloat(-0.3f + (meleeLevel * 0.6f), -0.3f, 0f); //-0.3f + 0.3f * meleeLevel; agentDrivenProperties.AiShootFreq = MBMath.ClampFloat(effectiveSkill * 1.5f, 0.1f, 0.9f); // when set to 0 AI never shoots //agentDrivenProperties.AiWaitBeforeShootFactor = 0f; //agentDrivenProperties.AiMinimumDistanceToContinueFactor = 5f; //2f + 0.3f * (3f - meleeSkill); //agentDrivenProperties.AIHoldingReadyMaxDuration = 0.1f; //MBMath.Lerp(0.25f, 0f, MBMath.Min(1f, num * 1.2f)); //agentDrivenProperties.AIHoldingReadyVariationPercentage = //num; //agentDrivenProperties.ReloadSpeed = 0.19f; //0.12 for heavy crossbows, 0.19f for light crossbows, composite bows and longbows. if (agent.IsRangedCached) { //agent.SetScriptedCombatFlags(Agent.AISpecialCombatModeFlags.IgnoreAmmoLimitForRangeCalculation); agent.SetScriptedCombatFlags(agent.GetScriptedCombatFlags() | Agent.AISpecialCombatModeFlags.IgnoreAmmoLimitForRangeCalculation); //agent.ResetAiWaitBeforeShootFactor(); } }
public ImprovedCombatAIAgentStatCalculateModel(AgentStatCalculateModel previousModel) { _previousModel = previousModel; }