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);
        }
Пример #2
0
        public static bool Prefix(AttackDirector.AttackSequence __instance, MessageCenterMessage message, List <List <Weapon> > ___sortedWeapons, ref int[][] ___numberOfShots, ref WeaponHitInfo?[][] ___weaponHitInfo)
        {
            try
            {
                AttackSequenceFireMessage attackSequenceFireMessage = (AttackSequenceFireMessage)message;
                if (attackSequenceFireMessage.sequenceId != __instance.id)
                {
                    return(false);
                }
                int    groupIdx  = attackSequenceFireMessage.groupIdx;
                int    weaponIdx = attackSequenceFireMessage.weaponIdx;
                Weapon weapon    = ___sortedWeapons[groupIdx][weaponIdx];

                Logger.Debug($"---");
                Logger.Debug($"[AttackDirector.AttackSequence_OnAttackSequenceFire_PREFIX] ({weapon.parent.DisplayName}) STARTED AttackSequence: {__instance.id}, WeaponGroup: {groupIdx}, Weapon: {weapon.Name}({weaponIdx})");

                //if(weapon.weaponDef.ComponentTags.Contains("component_type_srmstreak"))
                if (weapon.Type == WeaponType.SRM && weapon.AmmoCategoryValue.Name == "SRMStreak")
                {
                    WeaponHitInfo weaponHitInfo = ___weaponHitInfo[groupIdx][weaponIdx].Value;
                    bool          streakWillHit = weaponHitInfo.DidShotHitChosenTarget(0); // If first missile hits/misses, all will hit/miss
                    Logger.Info($"[AttackDirector.AttackSequence_OnAttackSequenceFire_PREFIX] ({weapon.Name}) streakWillHit: {streakWillHit}");

                    // Fire targeting laser
                    Vector3 floatieVector = new Vector3();
                    Utilities.CreateAndFireStreakTargetingLaser(__instance, weapon, out floatieVector, streakWillHit);

                    if (streakWillHit)
                    {
                        // Only floaties, everything else is prepared at this point

                        // Big Floatie
                        //__instance.Director.Combat.MessageCenter.PublishMessage(new FloatieMessage(__instance.chosenTarget.GUID, __instance.chosenTarget.GUID, "STREAK LOCKED-ON", FloatieMessage.MessageNature.CriticalHit));

                        // Small Floatie
                        FloatieMessage hitFloatie = new FloatieMessage(__instance.attacker.GUID, __instance.chosenTarget.GUID, "STREAK LOCKED-ON", __instance.Director.Combat.Constants.CombatUIConstants.floatieSizeMedium, FloatieMessage.MessageNature.Suppression, floatieVector.x, floatieVector.y, floatieVector.z);
                        __instance.Director.Combat.MessageCenter.PublishMessage(hitFloatie);

                        return(true);
                    }
                    else
                    {
                        // Cancel firing, see code of original method...

                        // Mark Streak SRMs as having fired nevertheless because a failed lock on should be handled like "fired"
                        new Traverse(weapon).Property("HasFired").SetValue(true);
                        weapon.CompleteFiring();
                        Logger.Info($"[AttackDirector.AttackSequence_OnAttackSequenceFire_PREFIX] ({weapon.Name}) HasFired: {weapon.HasFired}, RoundsSinceLastFire: {weapon.roundsSinceLastFire}");

                        // If weapon already prefired we would need to reincrement ammo (Note that Weapon.OffsetAmmo() is a custom extension method)
                        if (weapon.HasPreFired)
                        {
                            weapon.OffsetAmmo();
                        }

                        // Send out all necessary messages to keep the current AttackSequence in sync
                        AttackSequenceWeaponPreFireCompleteMessage weaponPreFireCompleteMessage = new AttackSequenceWeaponPreFireCompleteMessage(__instance.stackItemUID, __instance.id, groupIdx, weaponIdx);
                        __instance.Director.Combat.MessageCenter.PublishMessage(weaponPreFireCompleteMessage);

                        int numberOfShots = ___numberOfShots[groupIdx][weaponIdx];
                        for (int j = 0; j < numberOfShots; j++)
                        {
                            float hitDamage       = weapon.DamagePerShotAdjusted(weapon.parent.occupiedDesignMask);
                            float structureDamage = weapon.StructureDamagePerShotAdjusted(weapon.parent.occupiedDesignMask);
                            AttackSequenceImpactMessage impactMessage = new AttackSequenceImpactMessage(weaponHitInfo, j, hitDamage, structureDamage);
                            __instance.Director.Combat.MessageCenter.PublishMessage(impactMessage);
                        }

                        AttackSequenceResolveDamageMessage resolveDamageMessage = new AttackSequenceResolveDamageMessage(weaponHitInfo);
                        __instance.Director.Combat.MessageCenter.PublishMessage(resolveDamageMessage);

                        AttackSequenceWeaponCompleteMessage weaponCompleteMessage = new AttackSequenceWeaponCompleteMessage(__instance.stackItemUID, __instance.id, groupIdx, weaponIdx);
                        __instance.Director.Combat.MessageCenter.PublishMessage(weaponCompleteMessage);

                        // Big Floaties
                        //__instance.Director.Combat.MessageCenter.PublishMessage(new FloatieMessage(weapon.parent.GUID, weapon.parent.GUID, "STREAK LOCK-ON FAILED", FloatieMessage.MessageNature.Debuff));
                        //__instance.Director.Combat.MessageCenter.PublishMessage(new FloatieMessage(__instance.chosenTarget.GUID, __instance.chosenTarget.GUID, "STREAK LOCK-ON AVOIDED", FloatieMessage.MessageNature.Buff));

                        // Small Floatie
                        FloatieMessage missFloatie = new FloatieMessage(__instance.attacker.GUID, __instance.chosenTarget.GUID, "STREAK LOCK-ON FAILED", __instance.Director.Combat.Constants.CombatUIConstants.floatieSizeMedium, FloatieMessage.MessageNature.Dodge, floatieVector.x, floatieVector.y, floatieVector.z);
                        __instance.Director.Combat.MessageCenter.PublishMessage(missFloatie);



                        // Skip original method!
                        return(false);
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                Logger.Error(e);

                return(true);
            }
        }