Beispiel #1
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get SelectionStateMove_ProjectedHeatForState Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
Beispiel #2
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get CombatHUDWeaponSlot_SetHitChance Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
Beispiel #3
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get HostileDamageFactor_expectedDamageForMelee Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
Beispiel #4
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get CombatTestFire_MeleeAttackSequence Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
Beispiel #5
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get MechRepresentation_PlayImpactAnim Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
Beispiel #6
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get MeleeWithHighestPriorityEnemyNode_Tick Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
Beispiel #7
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get MoveTowardsHighestPriorityMoveCandidateNode_Tick Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
Beispiel #8
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get AIUtil_ExpectedDamageForMeleeAttackUsingUnitsBVs Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
 public static void Postfix(AbstractActor unit, bool isStationary, BehaviorTreeResults __result)
 {
     CustomAmmoCategoriesLog.Log.LogWrite("Choose result for " + unit.DisplayName + "\n");
     try
     {
         if (__result.nodeState == BehaviorNodeState.Failure)
         {
             CustomAmmoCategoriesLog.Log.LogWrite("  AI choosed not attack\n");
         }
         else
         if (__result.orderInfo is AttackOrderInfo)
         {
             CustomAmmoCategoriesLog.Log.LogWrite("  AI choosed to attack " + (__result.orderInfo as AttackOrderInfo).TargetUnit.DisplayName + "\n");
             CustomAmmoCategories.ChooseBestWeaponForTarget(unit, (__result.orderInfo as AttackOrderInfo).TargetUnit, isStationary);
         }
         else
         {
             CustomAmmoCategoriesLog.Log.LogWrite("  AI choosed something else beside attaking\n");
         }
         return;
     }
     catch (Exception e)
     {
         CustomAmmoCategoriesLog.Log.LogWrite("Exception " + e.ToString() + "\nFallback to default\n");
         return;
     }
 }
Beispiel #10
0
        private static WeaponCategory Category(Weapon weapon)
        {
            WeaponCategory result = CustomAmmoCategories.isWeaponUseInMelee(weapon);

            CustomAmmoCategoriesLog.Log.LogWrite("get AttackEvaluator_MakeAttackOrderForTarget_AP Category " + weapon.Category + "->" + result + "\n");
            return(result);
        }
Beispiel #11
0
 private static int ShotsWhenFiredDisplayOverider(Weapon weapon)
 {
     if (weapon.weaponDef.ComponentTags.Contains("wr-clustered_shots") || (CustomAmmoCategories.getWeaponDisabledClustering(weapon) == false))
     {
         return(weapon.ShotsWhenFired * weapon.ProjectilesPerShot);
     }
     else
     {
         return(weapon.ShotsWhenFired);
     }
 }
 public static bool Prefix(AbstractActor unit, ICombatant target, int enemyUnitIndex, bool isStationary)
 {
     CustomAmmoCategoriesLog.Log.LogWrite(unit.DisplayName + " choosing best weapon for target " + target.DisplayName + "\n");
     try {
         CustomAmmoCategories.ChooseBestWeaponForTarget(unit, target, isStationary);
         return(true);
     } catch (Exception e) {
         CustomAmmoCategoriesLog.Log.LogWrite("Exception " + e.ToString() + "\nFallback to default\n");
         return(true);
     }
 }
Beispiel #13
0
        public static bool Prefix(MissileEffect __instance)
        {
            bool isIndirect = (bool)typeof(MissileEffect).GetField("isIndirect", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);

            CustomAmmoCategoriesLog.Log.LogWrite("MissileEffect.PlayProjectile " + __instance.weapon.UIName + " real isIndirect = " + isIndirect + "\n");
            if (CustomAmmoCategories.getWeaponAlwaysIndirectVisuals(__instance.weapon) == true)
            {
                CustomAmmoCategoriesLog.Log.LogWrite(" always indirect\n");
                typeof(MissileEffect).GetField("isIndirect", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(__instance, (object)true);
            }
            return(true);
        }
        public static bool Prefix(AttackDirector.AttackSequence __instance, ref MessageCenterMessage message)
        {
            AttackSequenceImpactMessage impactMessage = (AttackSequenceImpactMessage)message;

            if (impactMessage.hitInfo.attackSequenceId != __instance.id)
            {
                return(true);
            }
            int    attackGroupIndex  = impactMessage.hitInfo.attackGroupIndex;
            int    attackWeaponIndex = impactMessage.hitInfo.attackWeaponIndex;
            Weapon weapon            = __instance.GetWeapon(attackGroupIndex, attackWeaponIndex);
            float  rawDamage         = impactMessage.hitDamage;
            float  realDamage        = rawDamage;

            CustomAmmoCategoriesLog.Log.LogWrite("OnAttackSequenceImpact\n");
            CustomAmmoCategoriesLog.Log.LogWrite("  attacker = " + __instance.attacker.DisplayName + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite("  target = " + __instance.target.DisplayName + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite("  weapon = " + weapon.UIName + "\n");
            CustomAmmoCategoriesLog.Log.LogWrite("  damage = " + rawDamage + "\n");
            if (realDamage >= 1.0f)
            {
                if (CustomAmmoCategories.getWeaponDamageVariance(weapon) > CustomAmmoCategories.Epsilon)
                {
                    realDamage = CustomAmmoCategories.WeaponDamageSimpleVariance(weapon, rawDamage);
                }
                if (CustomAmmoCategories.getWeaponDistantVariance(weapon) > CustomAmmoCategories.Epsilon)
                {
                    if (CustomAmmoCategories.getWeaponDistantVarianceReversed(weapon))
                    {
                        realDamage = CustomAmmoCategories.WeaponDamageDistance(__instance.attacker, __instance.target, weapon, realDamage, rawDamage);
                    }
                    else
                    {
                        realDamage = CustomAmmoCategories.WeaponDamageRevDistance(__instance.attacker, __instance.target, weapon, realDamage, rawDamage);
                    }
                }
            }
            else
            {
                CustomAmmoCategoriesLog.Log.LogWrite("WARNING! raw damage is less than 1.0f. Variance calculation is forbidden with this damage value\n", true);
            }
            CustomAmmoCategoriesLog.Log.LogWrite("  real damage = " + realDamage + "\n");
            if (realDamage < CustomAmmoCategories.Epsilon)
            {
                CustomAmmoCategoriesLog.Log.LogWrite("WARNING! real damage is less than epsilon. May be negative. That is sad. Rounding to zero\n", true);
                realDamage = 0.0f;
            }
            impactMessage.hitDamage = realDamage;
            return(true);
        }
 public static void Postfix(Weapon __instance, ICombatant target, Vector3 position, Quaternion rotation, ref bool __result)
 {
     if (__result == true)
     {
         float forbiddenRange = CustomAmmoCategories.getWeaponForbiddenRange(__instance);
         if (forbiddenRange > (double)CustomAmmoCategories.Epsilon)
         {
             float ActualRange = Vector3.Distance(position, target.TargetPosition);
             if (ActualRange < forbiddenRange)
             {
                 __result = false;
             }
         }
     }
 }
 public static void Postfix(LOFCache __instance, AbstractActor shootingUnit, ICombatant targetUnit, Weapon weapon, ref bool __result)
 {
     if (__result == true)
     {
         float forbiddenRange = CustomAmmoCategories.getWeaponForbiddenRange(weapon);
         if (forbiddenRange > (double)CustomAmmoCategories.Epsilon)
         {
             float ActualRange = Vector3.Distance(shootingUnit.CurrentPosition, targetUnit.CurrentPosition);
             if (ActualRange < forbiddenRange)
             {
                 __result = false;
             }
         }
     }
 }
 public static void Postfix(AbstractActor attackerUnit, Vector3 attackPosition, ICombatant targetUnit, Vector3 targetPosition, bool targetIsEvasive, Weapon weapon, int numTargets, ref float __result)
 {
     if (__result > CustomAmmoCategories.Epsilon)
     {
         float forbiddenRange = CustomAmmoCategories.getWeaponForbiddenRange(weapon);
         if (forbiddenRange > (double)CustomAmmoCategories.Epsilon)
         {
             float ActualRange = Vector3.Distance(attackPosition, targetPosition);
             if (ActualRange < forbiddenRange)
             {
                 __result = 0.0f;
             }
         }
     }
 }
        public static void Postfix(ToHit __instance, AbstractActor attacker, Weapon weapon, ICombatant target, Vector3 attackPosition, Vector3 targetPosition, LineOfFireLevel lofLevel, bool isCalledShot, ref string __result)
        {
            string str  = string.Empty;
            bool   flag = lofLevel < LineOfFireLevel.LOFObstructed && (CustomAmmoCategories.getIndirectFireCapable(weapon));
            float  weaponDirectFireModifier = CustomAmmoCategories.getDirectFireModifier(weapon);

            if (flag == false)
            {
                //CustomAmmoCategoriesLog.Log.LogWrite(attacker.DisplayName + " has LOS on " + target.DisplayName + ". Apply DirectFireModifier " + weaponDirectFireModifier + "\n");
                if (!NvMath.FloatIsNearZero(weaponDirectFireModifier))
                {
                    __result = string.Format("{0}WEAPON-DIRECT-FIRE {1:+#;-#}; ", (object)__result, (object)(int)weaponDirectFireModifier);
                }
            }
            CombatGameState combat = (CombatGameState)typeof(ToHit).GetField("combat", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);

            return;
        }
Beispiel #19
0
 public static void registerComponentsForVFX(this AbstractActor unit)
 {
     Log.LogWrite("registerComponentsForVFX " + unit.DisplayName + ":" + unit.GUID + "\n");
     foreach (MechComponent component in unit.allComponents)
     {
         string wGUID;
         if (CustomAmmoCategories.checkExistance(component.StatCollection, CustomAmmoCategories.GUIDStatisticName) == false)
         {
             wGUID = Guid.NewGuid().ToString();
             component.StatCollection.AddStatistic <string>(CustomAmmoCategories.GUIDStatisticName, wGUID);
         }
         else
         {
             wGUID = component.StatCollection.GetStatistic(CustomAmmoCategories.GUIDStatisticName).Value <string>();
         }
         Log.LogWrite(" " + component.defId + ":" + wGUID + "\n");
         ComponentVFXHelper.componentsVFXObjects[wGUID] = new VFXObjects(component);
     }
 }
        public static void Postfix(ToHit __instance, AbstractActor attacker, Weapon weapon, ICombatant target, Vector3 attackPosition, Vector3 targetPosition, LineOfFireLevel lofLevel, bool isCalledShot, ref float __result)
        {
            bool  flag = lofLevel < LineOfFireLevel.LOFObstructed && (CustomAmmoCategories.getIndirectFireCapable(weapon));
            float num  = __result;

            if (flag == false)
            {
                //float directFireModifier = CustomAmmoCategories.getDirectFireModifier(weapon);
                //CustomAmmoCategoriesLog.Log.LogWrite(attacker.DisplayName+" has LOS on "+target.DisplayName+ ". Apply DirectFireModifier "+directFireModifier+"\n");
                num += CustomAmmoCategories.getDirectFireModifier(weapon);
            }
            CombatGameState combat = (CombatGameState)typeof(ToHit).GetField("combat", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);

            if ((double)num < 0.0 && !combat.Constants.ResolutionConstants.AllowTotalNegativeModifier)
            {
                num = 0.0f;
            }
            __result = num;
            return;
        }
Beispiel #21
0
        public static ObjectSpawnDataSelf DestroyedVFX(this MechComponent component)
        {
            string wGUID;

            if (CustomAmmoCategories.checkExistance(component.StatCollection, CustomAmmoCategories.GUIDStatisticName) == false)
            {
                wGUID = Guid.NewGuid().ToString();
                component.StatCollection.AddStatistic <string>(CustomAmmoCategories.GUIDStatisticName, wGUID);
            }
            else
            {
                wGUID = component.StatCollection.GetStatistic(CustomAmmoCategories.GUIDStatisticName).Value <string>();
            }
            Log.LogWrite("DestroyedVFX(" + component.defId + ":" + wGUID + ")\n");
            if (ComponentVFXHelper.componentsVFXObjects.ContainsKey(wGUID))
            {
                return(ComponentVFXHelper.componentsVFXObjects[wGUID].destroyedObject);
            }
            return(null);
        }
Beispiel #22
0
        /*static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
         * {
         *  var targetPropertyGetter = AccessTools.Property(typeof(Weapon), "IndirectFireCapable").GetGetMethod();
         *  var replacementMethod = AccessTools.Method(typeof(ToHit_GetAllModifiers), nameof(IndirectFireCapable));
         *  return Transpilers.MethodReplacer(instructions, targetPropertyGetter, replacementMethod);
         * }
         *
         * private static bool IndirectFireCapable(Weapon weapon)
         * {
         *  //CustomAmmoCategoriesLog.Log.LogWrite("get ToHit_GetAllModifiers IndirectFireCapable\n");
         *  return CustomAmmoCategories.getIndirectFireCapable(weapon);
         * }*/

        public static bool Prefix(ToHit __instance, AbstractActor attacker, Weapon weapon, ICombatant target, Vector3 attackPosition, Vector3 targetPosition, LineOfFireLevel lofLevel, bool isCalledShot, ref float __result)
        {
            bool  flag = lofLevel < LineOfFireLevel.LOFObstructed && (CustomAmmoCategories.getIndirectFireCapable(weapon));
            float num  = __instance.GetRangeModifier(weapon, attackPosition, targetPosition)
                         + __instance.GetCoverModifier(attacker, target, lofLevel)
                         + __instance.GetSelfSpeedModifier(attacker)
                         + __instance.GetSelfSprintedModifier(attacker)
                         + __instance.GetSelfArmMountedModifier(weapon)
                         + __instance.GetStoodUpModifier(attacker)
                         + __instance.GetHeightModifier(attackPosition.y, targetPosition.y)
                         + __instance.GetHeatModifier(attacker)
                         + __instance.GetTargetTerrainModifier(target, targetPosition, false)
                         + __instance.GetSelfTerrainModifier(attackPosition, false)
                         + __instance.GetTargetSpeedModifier(target, weapon)
                         + __instance.GetSelfDamageModifier(attacker, weapon)
                         + __instance.GetTargetSizeModifier(target)
                         + __instance.GetTargetShutdownModifier(target, false)
                         + __instance.GetTargetProneModifier(target, false)
                         + __instance.GetWeaponAccuracyModifier(attacker, weapon)
                         + __instance.GetAttackerAccuracyModifier(attacker)
                         + __instance.GetEnemyEffectModifier(target)
                         + __instance.GetRefireModifier(weapon)
                         + __instance.GetTargetDirectFireModifier(target, flag)
                         + __instance.GetIndirectModifier(attacker, flag)
                         + __instance.GetMoraleAttackModifier(target, isCalledShot);

            if (flag == false)
            {
                float directFireModifier = CustomAmmoCategories.getDirectFireModifier(weapon);
                CustomAmmoCategoriesLog.Log.LogWrite(attacker.DisplayName + " has LOS on " + target.DisplayName + ". Apply DirectFireModifier " + directFireModifier + "\n");
                num += CustomAmmoCategories.getDirectFireModifier(weapon);
            }
            CombatGameState combat = (CombatGameState)typeof(ToHit).GetField("combat", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);

            if ((double)num < 0.0 && !combat.Constants.ResolutionConstants.AllowTotalNegativeModifier)
            {
                num = 0.0f;
            }
            __result = num;
            return(false);
        }
        public static void Postfix(AmmunitionDef __instance)
        {
            EffectData[]      effects = CustomAmmoCategories.findExtAmmo(__instance.Description.Id).statusEffects;
            List <EffectData> tmpList = new List <EffectData>();

            CustomAmmoCategoriesLog.Log.LogWrite("Checking on null status effects " + __instance.Description.Id + " " + effects.Length + ".\n");
            foreach (EffectData effect in effects)
            {
                if ((effect.Description != null))
                {
                    if ((effect.Description.Id != null) && (effect.Description.Name != null))
                    {
                        tmpList.Add(effect);
                        continue;
                    }
                    else
                    {
                        if (effect.Description.Id == null)
                        {
                            CustomAmmoCategoriesLog.Log.LogWrite("!Warning! effect id is null " + __instance.Description.Id + ".\n");
                        }
                        if (effect.Description.Name == null)
                        {
                            CustomAmmoCategoriesLog.Log.LogWrite("!Warning! effect name is null " + __instance.Description.Id + ".\n");
                        }
                    }
                }
                else
                {
                    CustomAmmoCategoriesLog.Log.LogWrite("!Warning! effect description is null " + __instance.Description.Id + ".\n");
                }
                CustomAmmoCategoriesLog.Log.LogWrite("!Warning! null status effect detected at ammo " + __instance.Description.Id + ".\n");
            }
            if (tmpList.Count != effects.Length)
            {
                CustomAmmoCategoriesLog.Log.LogWrite("!Warning! null (" + (effects.Length - tmpList.Count) + "/" + effects.Length + ") status effects detected at ammo " + __instance.Description.Id + ".Removing\n");
                CustomAmmoCategories.findExtAmmo(__instance.Description.Id).statusEffects = tmpList.ToArray();
            }
        }
Beispiel #24
0
        public static bool Prefix(WeaponEffect __instance)
        {
            CustomAmmoCategoriesLog.Log.LogWrite("WeaponEffect.PlayProjectile");
            try {
                //__instance.t = 0.0f;
                typeof(WeaponEffect).GetField("t", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(__instance, 0.0f);
                __instance.currentState = WeaponEffect.WeaponEffectState.Firing;
                GameObject projectileMeshObject = (GameObject)typeof(WeaponEffect).GetField("projectileMeshObject", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
                if ((UnityEngine.Object)projectileMeshObject != (UnityEngine.Object)null)
                {
                    projectileMeshObject.SetActive(true);
                }
                GameObject projectileLightObject = (GameObject)typeof(WeaponEffect).GetField("projectileLightObject", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
                if ((UnityEngine.Object)projectileLightObject != (UnityEngine.Object)null)
                {
                    projectileLightObject.SetActive(true);
                }
                ParticleSystem projectileParticles = (ParticleSystem)typeof(WeaponEffect).GetField("projectileParticles", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
                if ((UnityEngine.Object)projectileParticles != (UnityEngine.Object)null)
                {
                    projectileParticles.Stop(true);
                    projectileParticles.Clear(true);
                }
                Transform projectileTransform = (Transform)typeof(WeaponEffect).GetField("projectileTransform", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
                Transform startingTransform   = (Transform)typeof(WeaponEffect).GetField("startingTransform", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
                projectileTransform.position = startingTransform.position;
                Vector3 endPos = (Vector3)typeof(WeaponEffect).GetField("endPos", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
                projectileTransform.LookAt(endPos);
                typeof(WeaponEffect).GetField("startPos", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(__instance, startingTransform.position);
                //__instance.startPos = __instance.startingTransform.position;
                if ((UnityEngine.Object)projectileParticles != (UnityEngine.Object)null)
                {
                    BTCustomRenderer.SetVFXMultiplier(projectileParticles);
                    projectileParticles.Play(true);
                    BTLightAnimator componentInChildren = projectileParticles.GetComponentInChildren <BTLightAnimator>(true);
                    if ((UnityEngine.Object)componentInChildren != (UnityEngine.Object)null)
                    {
                        componentInChildren.StopAnimation();
                        componentInChildren.PlayAnimation();
                    }
                }
                if ((UnityEngine.Object)__instance.weapon.parent.GameRep != (UnityEngine.Object)null)
                {
                    int num;
                    switch ((ChassisLocations)__instance.weapon.Location)
                    {
                    case ChassisLocations.LeftArm:
                        num = 1;
                        break;

                    case ChassisLocations.RightArm:
                        num = 2;
                        break;

                    default:
                        num = 0;
                        break;
                    }
                    __instance.weapon.parent.GameRep.PlayFireAnim((AttackSourceLimb)num, CustomAmmoCategories.getWeaponAttackRecoil(__instance.weapon));
                }
                int hitIndex = (int)typeof(WeaponEffect).GetField("hitIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
                if (!__instance.AllowMissSkipping || __instance.hitInfo.hitLocations[hitIndex] != 0 && __instance.hitInfo.hitLocations[hitIndex] != 65536)
                {
                    return(false);
                }
                __instance.PublishWeaponCompleteMessage();
            } catch (Exception e) {
                CustomAmmoCategoriesLog.Log.LogWrite("Exception " + e.ToString() + "\nFallback to default\n");
                return(true);
            }
            return(false);
        }
Beispiel #25
0
        static void Postfix(TooltipPrefab_Weapon __instance, object data,
                            TextMeshProUGUI ___rangeType, TextMeshProUGUI ___damage)
        {
            Mod.Log.Debug?.Write("TP_W:SD entered.");

            ___rangeType.enabled = false;
            Transform rangeLabelT = ___rangeType.gameObject.transform.parent;

            rangeLabelT.gameObject.SetActive(false);

            Transform     layoutT  = rangeLabelT.gameObject.transform.parent;
            RectTransform rLayoutT = layoutT.gameObject.GetComponent <RectTransform>();

            LayoutRebuilder.ForceRebuildLayoutImmediate(rLayoutT);

            WeaponDef weaponDef = (WeaponDef)data;

            if (weaponDef != null)
            {
                Mod.Log.Debug?.Write($"  Updating tooltip for weapon: {weaponDef.Description.UIName}");
                if (CustomAmmoCategories.isRegistredWeapon(weaponDef.Description.Id))
                {
                    // Is a CAC weapon, use HasShells
                    ExtWeaponDef extDef = CustomAmmoCategories.getExtWeaponDef(weaponDef.Description.Id);
                    Mod.Log.Debug?.Write($" Found CAC extension for weapon.");
                    if (extDef == null)
                    {
                        Mod.Log.Warn?.Write($"Failed to load CAC ExtWeaponDef for {weaponDef.Description.Id}, but it was registered!");
                        return;
                    }

                    /*
                     * "ImprovedBallistic": true, - whether use or not own ballistic weapon effect engine.
                     *  Difference between "improved" and vanilla engine:
                     *  1. Improved mode uses ShotsWhenFire properly (vanilla had not used them at all)
                     *  3. Improved mode fire ShotsWhenFire volleys with ProjectilesPerShot bullets in each.
                     *      Bullets in one volley fired simultaneously instead of one by one (as in WeaponRealizer)
                     *      But damage still dealt once per volley, not per bullet, to keep compatibility with vanilla.
                     *  NOTE! If ImprovedBallistic is set DisableClustering is forced to true and "wr-clustered_shots" tag removed from definition.
                     *
                     *  "BallisticDamagePerPallet": true - if true damage inflicted per pallet instead of per shot.
                     *  Only working with ImprovedBallistic true, ballistic weapon effect and HasShels false
                     *              Damage will be divided by ProjectilesPerShot value, heat damage and stable damage too.
                     */

                    /*
                     *  PER HARKONNEN HALLOWED BY THINE NAME
                     *  If ImprovedBallistic = false OR
                     *     ImprovedBallistic = true AND (HasShells = true or BallisticDamageperPellet = false) - > damage x shots
                     *  If ImprovedBallistic = true and BallisticDamageperPellet = true and DamageNotDivided = true > damage x projectiles x shots
                     *  If ImprovedBallistic = true and BallisticDamageperPellet = true and DamageNotDivided = false > (damage/projectiles) x  projectiles x shots
                     */

                    if (extDef.ImprovedBallistic)
                    {
                        // Damage is damage * shotsWhenFired (each shot = volley of projectiles, projectiles are visual only)
                        float totalDamage = weaponDef.Damage * weaponDef.ShotsWhenFired;
                        if (weaponDef.ShotsWhenFired != 1)
                        {
                            string localText = $"{weaponDef.Damage} x {weaponDef.ShotsWhenFired} = {totalDamage}";
                            Mod.Log.Debug?.Write($"ImprovedBallistic weapon damage set to: {localText}<page>");
                            ___damage.SetText(localText);
                        }

                        if (extDef.HasShells == TripleBoolean.True || extDef.BallisticDamagePerPallet != TripleBoolean.True)
                        {
                            if (weaponDef.ShotsWhenFired != 1)
                            {
                                // damage x shots = total
                                totalDamage = weaponDef.Damage * weaponDef.ShotsWhenFired;
                                string localText = $"{weaponDef.Damage} x {weaponDef.ShotsWhenFired} = {totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + HasShells || !BallisticDamagePerPallet weapon damage set to: {localText}; ShotsWhenFired != 1");
                                ___damage.SetText(localText);
                            }
                            else
                            {
                                totalDamage = weaponDef.Damage * weaponDef.ShotsWhenFired;
                                string localText = $"{totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + HasShells || !BallisticDamagePerPallet weapon damage set to: {localText}; ShotsWhenFired == 1");
                                ___damage.SetText(localText);
                            }
                        }

                        if (extDef.BallisticDamagePerPallet == TripleBoolean.True && extDef.DamageNotDivided == TripleBoolean.True)
                        {
                            if (weaponDef.ShotsWhenFired != 1 && weaponDef.ProjectilesPerShot != 1)
                            {
                                totalDamage = weaponDef.Damage * weaponDef.ProjectilesPerShot * weaponDef.ShotsWhenFired;
                                string localText = $"{weaponDef.Damage} x {weaponDef.ProjectilesPerShot} x {weaponDef.ShotsWhenFired} = {totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + BallisticDamagePerPallet + DamageNotDivided weapon damage set to: {localText}; ProjectilesPerShot != 1 AND ShotsWhenFired != 1");
                                ___damage.SetText(localText);
                            }
                            else if (weaponDef.ShotsWhenFired == 1 && weaponDef.ProjectilesPerShot != 1)
                            {
                                totalDamage = weaponDef.Damage * weaponDef.ProjectilesPerShot * weaponDef.ShotsWhenFired;
                                string localText = $"{weaponDef.Damage} x {weaponDef.ProjectilesPerShot}= {totalDamage}";
                                Mod.Log.Debug?.Write(
                                    $"ImprovedBallistic + BallisticDamagePerPallet + DamageNotDivided weapon damage set to: {localText}; ProjectilesPerShot != 1 BUT ShotsWhenFired == 1");
                                ___damage.SetText(localText);
                            }
                            else if (weaponDef.ShotsWhenFired != 1 && weaponDef.ProjectilesPerShot == 1)
                            {
                                totalDamage = weaponDef.Damage * weaponDef.ProjectilesPerShot * weaponDef.ShotsWhenFired;
                                string localText = $"{weaponDef.Damage} x {weaponDef.ShotsWhenFired} = {totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + BallisticDamagePerPallet + DamageNotDivided weapon damage set to: {localText}; ProjectilesPerShot == 1 BUT ShotsWhenFired != 1");
                                ___damage.SetText(localText);
                            }
                            else
                            {
                                totalDamage = weaponDef.Damage * weaponDef.ProjectilesPerShot * weaponDef.ShotsWhenFired;
                                string localText = $"{totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + HasShells || !BallisticDamagePerPallet weapon damage set to: {localText}; ShotsWhenFired AND ProjectilesPerShot == 1");
                                ___damage.SetText(localText);
                            }
                        }

                        if (extDef.BallisticDamagePerPallet == TripleBoolean.True && extDef.DamageNotDivided != TripleBoolean.True)
                        {
                            if (weaponDef.ShotsWhenFired != 1 && weaponDef.ProjectilesPerShot != 1)
                            {
                                float damagePerPellet = weaponDef.Damage / weaponDef.ProjectilesPerShot;
                                totalDamage = damagePerPellet * weaponDef.ShotsWhenFired * weaponDef.ProjectilesPerShot;
                                string localText = $"{damagePerPellet} x {weaponDef.ShotsWhenFired} x {weaponDef.ProjectilesPerShot} = {totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + BallisticDamagePerPallet + !DamageNotDivided weapon damage set to: {localText}; ProjectilesPerShot != 1 AND ShotsWhenFired != 1");
                                ___damage.SetText(localText);
                            }
                            else if (weaponDef.ShotsWhenFired == 1 && weaponDef.ProjectilesPerShot != 1)
                            {
                                float damagePerPellet = weaponDef.Damage / weaponDef.ProjectilesPerShot;
                                totalDamage = damagePerPellet * weaponDef.ShotsWhenFired * weaponDef.ProjectilesPerShot;
                                string localText = $"{damagePerPellet} x {weaponDef.ProjectilesPerShot} = {totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + BallisticDamagePerPallet + !DamageNotDivided weapon damage set to: {localText}; ProjectilesPerShot != 1 BUT ShotsWhenFired == 1");
                                ___damage.SetText(localText);
                            }
                            else if (weaponDef.ShotsWhenFired != 1 && weaponDef.ProjectilesPerShot == 1)
                            {
                                float damagePerPellet = weaponDef.Damage / weaponDef.ProjectilesPerShot;
                                totalDamage = damagePerPellet * weaponDef.ShotsWhenFired * weaponDef.ProjectilesPerShot;
                                string localText = $"{damagePerPellet} x {weaponDef.ShotsWhenFired} = {totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + BallisticDamagePerPallet + !DamageNotDivided weapon damage set to: {localText}; ProjectilesPerShot == 1 BUT ShotsWhenFired != 1");
                                ___damage.SetText(localText);
                            }
                            else
                            {
                                float damagePerPellet = weaponDef.Damage / weaponDef.ProjectilesPerShot;
                                totalDamage = damagePerPellet * weaponDef.ShotsWhenFired * weaponDef.ProjectilesPerShot;
                                string localText = $"{totalDamage}";
                                Mod.Log.Debug?.Write($"ImprovedBallistic + BallisticDamagePerPallet + !DamageNotDivided weapon damage set to: {localText}; ProjectilesPerShot == 1 AND ShotsWhenFired == 1");
                                ___damage.SetText(localText);
                            }
                        }
                    }
                    else
                    {
                        // Vanilla calculations, so ProjectilesPerShot is visual only. See https://github.com/BattletechModders/IRTweaks/issues/8
                        float totalDamage = weaponDef.Damage * weaponDef.ShotsWhenFired;
                        if (weaponDef.ShotsWhenFired != 1)
                        {
                            string localText = $"{weaponDef.Damage} x {weaponDef.ShotsWhenFired} shots = {totalDamage}";
                            Mod.Log.Debug?.Write($"Vanilla + ShotsWhenFire > 1 weapon damage set to: {localText}");
                            ___damage.SetText(localText);
                        }
                        else
                        {
                            string localText = $"{weaponDef.Damage}";
                            Mod.Log.Debug?.Write($"Vanilla + 1 ShotsWhenFired weapon damage set to: {localText}");
                            ___damage.SetText(localText);
                        }
                    }

                    /*
                     * "AOEDamage": 0 - if > 0 alternative AoE damage algorithm will be used. Main projectile will not always miss.
                     *  Instead it will inflict damage twice  one for main target - direct hit (this damage can be have variance)
                     *  and second for all targets in AoE range including main.
                     *
                     *  "AOEHeatDamage": 0 - if > 0 alternative AoE damage algorithm will be used. Main projectile will not always miss.
                     *  Instead it will inflict damage twice one for main target - direct hit (this damage can be have variance)
                     *  and second for all targets in AoE range including main.
                     *
                     *  "AOEInstability": 0 - instability AoE damage
                     */
                }
                else
                {
                    // Not a CAC weapon, vanilla, so ProjectilesPerShot is visual only. See https://github.com/BattletechModders/IRTweaks/issues/8
                    float totalDamage = weaponDef.Damage * weaponDef.ShotsWhenFired;
                    if (weaponDef.ShotsWhenFired != 1)
                    {
                        string localText = $"{weaponDef.Damage} x {weaponDef.ShotsWhenFired} shots = {totalDamage}";
                        Mod.Log.Debug?.Write($"Vanilla + ShotsWhenFire > 1 weapon damage set to: {localText}");
                        ___damage.SetText(localText);
                    }
                    else
                    {
                        string localText = $"{weaponDef.Damage}";
                        Mod.Log.Debug?.Write($"Vanilla + 1 ShotsWhenFired weapon damage set to: {localText}");
                        ___damage.SetText(localText);
                    }
                }
            }
        }
Beispiel #26
0
 private static bool IndirectFireCapable(Weapon weapon)
 {
     //CustomAmmoCategoriesLog.Log.LogWrite("get LOFCache_UnitHasLOFToTarget IndirectFireCapable\n");
     return(CustomAmmoCategories.getIndirectFireCapable(weapon));
 }
Beispiel #27
0
 private static bool IndirectFireCapable(Weapon weapon)
 {
     //CustomAmmoCategoriesLog.Log.LogWrite("get AbstractActor_GetLongestRangeWeapon IndirectFireCapable\n");
     return(CustomAmmoCategories.getIndirectFireCapable(weapon));
 }
Beispiel #28
0
 private static bool IndirectFireCapable(Weapon weapon)
 {
     //CustomAmmoCategoriesLog.Log.LogWrite("get AIRoleAssignment_EvaluateSniper IndirectFireCapable\n");
     return(CustomAmmoCategories.getIndirectFireCapable(weapon));
 }
Beispiel #29
0
 public static bool Prefix(ToHit __instance, int evasivePips, Weapon weapon, ref float __result)
 {
     //CustomAmmoCategoriesLog.Log.LogWrite("ToHit.GetEvasivePipsModifier");
     try
     {
         float num = 0.0f;
         if (evasivePips > 0)
         {
             int index = Mathf.RoundToInt((float)((double)evasivePips - 1.0 - (weapon == null ? 0.0 : (double)(CustomAmmoCategories.getWeaponEvasivePipsIgnored(weapon)))));
             if (index > -1)
             {
                 CombatGameState combat = (CombatGameState)typeof(ToHit).GetField("combat", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
                 num += combat.Constants.ToHit.ToHitMovingPipUMs[index];
             }
         }
         __result = num;
         return(false);
     }
     catch (Exception e)
     {
         CustomAmmoCategoriesLog.Log.LogWrite("Exception " + e.ToString() + "\nFallback to default\n");
         return(true);
     }
 }
Beispiel #30
0
        public static bool Prefix(AttackDirector.AttackSequence __instance, Weapon weapon, int groupIdx, int weaponIdx, int numberOfShots, bool indirectFire, float dodgedDamage, ref WeaponHitInfo __result)
        {
            WeaponHitInfo hitInfo = new WeaponHitInfo();

            hitInfo.attackerId        = __instance.attacker.GUID;
            hitInfo.targetId          = __instance.target.GUID;
            hitInfo.numberOfShots     = numberOfShots;
            hitInfo.stackItemUID      = __instance.stackItemUID;
            hitInfo.attackSequenceId  = __instance.id;
            hitInfo.attackGroupIndex  = groupIdx;
            hitInfo.attackWeaponIndex = weaponIdx;
            hitInfo.toHitRolls        = new float[numberOfShots];
            hitInfo.locationRolls     = new float[numberOfShots];
            hitInfo.dodgeRolls        = new float[numberOfShots];
            hitInfo.dodgeSuccesses    = new bool[numberOfShots];
            hitInfo.hitLocations      = new int[numberOfShots];
            hitInfo.hitPositions      = new Vector3[numberOfShots];
            hitInfo.hitVariance       = new int[numberOfShots];
            hitInfo.hitQualities      = new AttackImpactQuality[numberOfShots];
            if (AttackDirector.hitLogger.IsLogEnabled)
            {
                Vector3         collisionWorldPos;
                LineOfFireLevel lineOfFire           = __instance.Director.Combat.LOS.GetLineOfFire(__instance.attacker, __instance.attackPosition, __instance.target, __instance.target.CurrentPosition, __instance.target.CurrentRotation, out collisionWorldPos);
                float           allModifiers         = __instance.Director.Combat.ToHit.GetAllModifiers(__instance.attacker, weapon, __instance.target, __instance.attackPosition + __instance.attacker.HighestLOSPosition, __instance.target.TargetPosition, lineOfFire, __instance.isMoraleAttack);
                string          modifiersDescription = __instance.Director.Combat.ToHit.GetAllModifiersDescription(__instance.attacker, weapon, __instance.target, __instance.attackPosition + __instance.attacker.HighestLOSPosition, __instance.target.TargetPosition, lineOfFire, __instance.isMoraleAttack);
                Pilot           pilot = __instance.attacker.GetPilot();
                AttackDirector.hitLogger.Log((object)string.Format("======================================== Unit Firing: {0} | Weapon: {1} | Shots: {2}", (object)__instance.attacker.DisplayName, (object)weapon.Name, (object)numberOfShots));
                AttackDirector.hitLogger.Log((object)string.Format("======================================== Hit Info: GROUP {0} | ID {1}", (object)groupIdx, (object)weaponIdx));
                AttackDirector.hitLogger.Log((object)string.Format("======================================== MODIFIERS: {0}... FINAL: [[ {1} ]] ", (object)modifiersDescription, (object)allModifiers));
                if (pilot != null)
                {
                    AttackDirector.hitLogger.Log((object)__instance.Director.Combat.ToHit.GetBaseToHitChanceDesc(__instance.attacker));
                }
                else
                {
                    AttackDirector.hitLogger.Log((object)string.Format("======================================== Gunnery Check: NO PILOT"));
                }
            }
            float toHitChance = __instance.Director.Combat.ToHit.GetToHitChance(__instance.attacker, weapon, __instance.target, __instance.attackPosition, __instance.target.CurrentPosition, __instance.numTargets, __instance.meleeAttackType, __instance.isMoraleAttack);

            if (Mech.TEST_KNOCKDOWN)
            {
                toHitChance = 1f;
            }
            if (AttackDirector.hitLogger.IsLogEnabled)
            {
                AttackDirector.hitLogger.Log((object)string.Format("======================================== HIT CHANCE: [[ {0:P2} ]]", (object)toHitChance));
            }
            hitInfo.attackDirection       = __instance.Director.Combat.HitLocation.GetAttackDirection(__instance.attackPosition, __instance.target);
            hitInfo.attackDirectionVector = __instance.Director.Combat.HitLocation.GetAttackDirectionVector(__instance.attackPosition, __instance.target);
            object[]         args       = new object[6];
            HitGeneratorType hitGenType = HitGeneratorType.NotSet;

            if (weapon.weaponDef.ComponentTags.Contains("wr-clustered_shots"))
            {
                hitGenType = HitGeneratorType.Individual;
            }
            if (hitGenType == HitGeneratorType.NotSet)
            {
                if (CustomAmmoCategories.checkExistance(weapon.StatCollection, CustomAmmoCategories.AmmoIdStatName) == true)
                {
                    string           ammoId  = weapon.StatCollection.GetStatistic(CustomAmmoCategories.AmmoIdStatName).Value <string>();
                    ExtAmmunitionDef extAmmo = CustomAmmoCategories.findExtAmmo(ammoId);
                    hitGenType = extAmmo.HitGenerator;
                }
                if (hitGenType == HitGeneratorType.NotSet)
                {
                    ExtWeaponDef extWeapon = CustomAmmoCategories.getExtWeaponDef(weapon.weaponDef.Description.Id);
                    hitGenType = extWeapon.HitGenerator;
                }
            }
            if (hitGenType != HitGeneratorType.NotSet)
            {
                switch (hitGenType)
                {
                case HitGeneratorType.Individual:
                    args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    typeof(AttackDirector.AttackSequence).GetMethod("GetIndividualHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    hitInfo = (WeaponHitInfo)args[0];
                    break;

                case HitGeneratorType.Cluster:
                    args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    typeof(AttackDirector.AttackSequence).GetMethod("GetClusteredHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    hitInfo = (WeaponHitInfo)args[0];
                    //__instance.GetClusteredHits(ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    break;

                case HitGeneratorType.Streak:
                    //args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    //typeof(AttackDirector.AttackSequence).GetMethod("GetClusteredHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    //hitInfo = (WeaponHitInfo)args[0];
                    AttackSequence_GenerateHitInfo.GetStreakHits(__instance, ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    //__instance.GetClusteredHits(ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    break;

                default:
                    AttackDirector.attackLogger.LogError((object)string.Format("GenerateHitInfo found invalid weapon type: {0}, using basic hit info", (object)hitGenType));
                    args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    typeof(AttackDirector.AttackSequence).GetMethod("GetIndividualHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    hitInfo = (WeaponHitInfo)args[0];
                    //__instance.GetIndividualHits(ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    break;
                }
            }
            else
            {
                switch (weapon.Type)
                {
                case WeaponType.Autocannon:
                case WeaponType.Gauss:
                case WeaponType.Laser:
                case WeaponType.PPC:
                case WeaponType.Flamer:
                case WeaponType.Melee:
                    args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    typeof(AttackDirector.AttackSequence).GetMethod("GetIndividualHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    hitInfo = (WeaponHitInfo)args[0];
                    //__instance.GetIndividualHits(ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    break;

                case WeaponType.LRM:
                    args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    typeof(AttackDirector.AttackSequence).GetMethod("GetClusteredHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    hitInfo = (WeaponHitInfo)args[0];
                    //__instance.GetClusteredHits(ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    break;

                case WeaponType.SRM:
                    args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    typeof(AttackDirector.AttackSequence).GetMethod("GetIndividualHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    hitInfo = (WeaponHitInfo)args[0];
                    //__instance.GetIndividualHits(ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    break;

                case WeaponType.MachineGun:
                    args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    typeof(AttackDirector.AttackSequence).GetMethod("GetIndividualHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    hitInfo = (WeaponHitInfo)args[0];
                    //__instance.GetIndividualHits(ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    break;

                default:
                    AttackDirector.attackLogger.LogError((object)string.Format("GenerateHitInfo found invalid weapon type: {0}, using basic hit info", (object)weapon.Type));
                    args[0] = hitInfo; args[1] = groupIdx; args[2] = weaponIdx; args[3] = weapon; args[4] = toHitChance; args[5] = dodgedDamage;
                    typeof(AttackDirector.AttackSequence).GetMethod("GetIndividualHits", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, args);
                    hitInfo = (WeaponHitInfo)args[0];
                    //__instance.GetIndividualHits(ref hitInfo, groupIdx, weaponIdx, weapon, toHitChance, dodgedDamage);
                    break;
                }
            }
            __result = hitInfo;
            return(false);
            //return hitInfo;
        }