Example #1
0
        internal static bool MissileHitCallbackPrefix(ref bool __result, ref Mission __instance, out int hitParticleIndex, ref AttackCollisionData collisionData, int missileIndex, Vec3 missileStartingPosition, Vec3 missilePosition, Vec3 missileAngularVelocity, Vec3 movementVelocity, MatrixFrame attachGlobalFrame, MatrixFrame affectedShieldGlobalFrame, int numDamagedAgents, Agent attacker, Agent victim, GameEntity hitEntity)
        {
            var _missiles = MissionAccessTools.Get_missiles(ref __instance);

            Mission.Missile missile = _missiles[missileIndex];

            bool isHorseArcher = GCOToolbox.GCOToolbox.ProjectileBalance.CheckForHorseArcher(victim);
            bool makesRear     = GCOToolbox.GCOToolbox.ProjectileBalance.ApplyHorseCrippleLogic(victim, collisionData.VictimHitBodyPart);

            WeaponFlags         weaponFlags1      = missile.Weapon.CurrentUsageItem.WeaponFlags;
            float               momentumRemaining = 1f;
            WeaponComponentData shieldOnBack      = (WeaponComponentData)null;

            if (collisionData.AttackBlockedWithShield && weaponFlags1.HasAnyFlag <WeaponFlags>(WeaponFlags.CanPenetrateShield))
            {
                GetAttackCollisionResultsPrefix(ref __instance, isHorseArcher, missile, attacker, victim, hitEntity, momentumRemaining, ref collisionData, false, false, out shieldOnBack);
                EquipmentIndex wieldedItemIndex = victim.GetWieldedItemIndex(Agent.HandIndex.OffHand);
                if ((double)collisionData.InflictedDamage > (double)ManagedParameters.Instance.GetManagedParameter(ManagedParametersEnum.ShieldPenetrationOffset) + (double)ManagedParameters.Instance.GetManagedParameter(ManagedParametersEnum.ShieldPenetrationFactor) * (double)victim.Equipment[wieldedItemIndex].GetShieldArmorForCurrentUsage())
                {
                    AttackCollisionData.UpdateDataForShieldPenetration(ref collisionData);
                    momentumRemaining *= (float)(0.400000005960464 + (double)MBRandom.RandomFloat * 0.200000002980232);
                }
            }
            hitParticleIndex = -1;
            bool            flag1             = !GameNetwork.IsSessionActive;
            bool            missileHasPhysics = collisionData.MissileHasPhysics;
            PhysicsMaterial fromIndex         = PhysicsMaterial.GetFromIndex(collisionData.PhysicsMaterialIndex);
            int             num1  = fromIndex.IsValid ? (int)fromIndex.GetFlags() : 0;
            bool            flag2 = (weaponFlags1 & WeaponFlags.AmmoSticksWhenShot) > (WeaponFlags)0;
            bool            flag3 = (num1 & 1) == 0;
            bool            flag4 = (uint)(num1 & 8) > 0U;
            MissionObject   attachedMissionObject = (MissionObject)null;

            if (victim == null && (NativeObject)hitEntity != (NativeObject)null)
            {
                GameEntity gameEntity = hitEntity;
                do
                {
                    attachedMissionObject = gameEntity.GetFirstScriptOfType <MissionObject>();
                    gameEntity            = gameEntity.Parent;
                }while (attachedMissionObject == null && (NativeObject)gameEntity != (NativeObject)null);
                hitEntity = attachedMissionObject?.GameEntity;
            }
            Mission.MissileCollisionReaction collisionReaction1 = !flag4 ? (!weaponFlags1.HasAnyFlag <WeaponFlags>(WeaponFlags.Burning) ? (!flag3 || !flag2 ? Mission.MissileCollisionReaction.BounceBack : Mission.MissileCollisionReaction.Stick) : Mission.MissileCollisionReaction.BecomeInvisible) : Mission.MissileCollisionReaction.PassThrough;
            bool isCanceled = false;

            Mission.MissileCollisionReaction collisionReaction2;
            if (collisionData.MissileGoneUnderWater)
            {
                collisionReaction2 = Mission.MissileCollisionReaction.BecomeInvisible;
                hitParticleIndex   = 0;
            }
            else if (victim == null)
            {
                if ((NativeObject)hitEntity != (NativeObject)null)
                {
                    GetAttackCollisionResultsPrefix(ref __instance, isHorseArcher, missile, attacker, victim, hitEntity, momentumRemaining, ref collisionData, false, false, out shieldOnBack);
                    Blow missileBlow = __instance.CreateMissileBlow(attacker, ref collisionData, missile, missilePosition, missileStartingPosition);
                    __instance.RegisterBlow(attacker, (Agent)null, hitEntity, missileBlow, ref collisionData);
                }
                collisionReaction2 = collisionReaction1;
                hitParticleIndex   = 0;
            }
            else if (collisionData.AttackBlockedWithShield)
            {
                GetAttackCollisionResultsPrefix(ref __instance, isHorseArcher, missile, attacker, victim, hitEntity, momentumRemaining, ref collisionData, false, false, out shieldOnBack);
                collisionReaction2 = collisionData.IsShieldBroken ? Mission.MissileCollisionReaction.BecomeInvisible : collisionReaction1;
                hitParticleIndex   = 0;
            }
            else
            {
                if (attacker != null && attacker.IsFriendOf(victim))
                {
                    if (!missileHasPhysics)
                    {
                        if (flag1)
                        {
                            if (attacker.Controller == Agent.ControllerType.AI)
                            {
                                isCanceled = true;
                            }
                        }
                        else if (MultiplayerOptions.OptionType.FriendlyFireDamageRangedFriendPercent.GetIntValue(MultiplayerOptions.MultiplayerOptionsAccessMode.CurrentMapOptions) <= 0 && MultiplayerOptions.OptionType.FriendlyFireDamageRangedSelfPercent.GetIntValue(MultiplayerOptions.MultiplayerOptionsAccessMode.CurrentMapOptions) <= 0 || __instance.Mode == MissionMode.Duel)
                        {
                            isCanceled = true;
                        }
                    }
                }
                else if (victim.IsHuman && !attacker.IsEnemyOf(victim))
                {
                    isCanceled = true;
                }
                else if (flag1 && attacker != null && (attacker.Controller == Agent.ControllerType.AI && victim.RiderAgent != null) && attacker.IsFriendOf(victim.RiderAgent))
                {
                    isCanceled = true;
                }
                if (isCanceled)
                {
                    if (flag1 && attacker == Agent.Main && attacker.IsFriendOf(victim))
                    {
                        InformationManager.DisplayMessage(new InformationMessage(GameTexts.FindText("ui_you_hit_a_friendly_troop", (string)null).ToString(), Color.ConvertStringToColor("#D65252FF")));
                    }
                    collisionReaction2 = Mission.MissileCollisionReaction.BecomeInvisible;
                }
                else
                {
                    bool flag5 = (weaponFlags1 & WeaponFlags.MultiplePenetration) > (WeaponFlags)0;
                    GetAttackCollisionResultsPrefix(ref __instance, isHorseArcher, missile, attacker, victim, (GameEntity)null, momentumRemaining, ref collisionData, false, false, out shieldOnBack);
                    Blow missileBlow = __instance.CreateMissileBlow(attacker, ref collisionData, missile, missilePosition, missileStartingPosition);
                    if (makesRear)
                    {
                        missileBlow.BlowFlag = BlowFlags.MakesRear;
                    }

                    if (!collisionData.CollidedWithShieldOnBack & flag5 && numDamagedAgents > 0)
                    {
                        missileBlow.InflictedDamage     /= numDamagedAgents;
                        missileBlow.SelfInflictedDamage /= numDamagedAgents;
                    }
                    float managedParameter1 = ManagedParameters.Instance.GetManagedParameter(missileBlow.DamageType != DamageTypes.Cut ? (missileBlow.DamageType != DamageTypes.Pierce ? ManagedParametersEnum.DamageInterruptAttackThresholdBlunt : ManagedParametersEnum.DamageInterruptAttackThresholdPierce) : ManagedParametersEnum.DamageInterruptAttackThresholdCut);
                    if ((double)collisionData.InflictedDamage <= (double)managedParameter1)
                    {
                        missileBlow.BlowFlag |= BlowFlags.ShrugOff;
                    }
                    if (victim.State == AgentState.Active)
                    {
                        __instance.RegisterBlow(attacker, victim, (GameEntity)null, missileBlow, ref collisionData);
                    }
                    hitParticleIndex = ParticleSystemManager.GetRuntimeIdByName("psys_game_blood_sword_enter");
                    if (flag5 && numDamagedAgents < 3)
                    {
                        collisionReaction2 = Mission.MissileCollisionReaction.PassThrough;
                    }
                    else
                    {
                        collisionReaction2 = collisionReaction1;
                        if (collisionReaction1 == Mission.MissileCollisionReaction.Stick && !collisionData.CollidedWithShieldOnBack)
                        {
                            bool flag6 = __instance.CombatType == Mission.MissionCombatType.Combat;
                            if (flag6)
                            {
                                bool flag7 = victim.IsHuman && collisionData.VictimHitBodyPart == BoneBodyPartType.Head;
                                flag6 = victim.State != AgentState.Active || !flag7;
                            }
                            if (flag6)
                            {
                                float managedParameter2 = ManagedParameters.Instance.GetManagedParameter(ManagedParametersEnum.MissileMinimumDamageToStick);
                                float num2 = 2f * managedParameter2;
                                if (!GameNetwork.IsClientOrReplay && (double)missileBlow.InflictedDamage < (double)managedParameter2 && (double)missileBlow.AbsorbedByArmor > (double)num2)
                                {
                                    collisionReaction2 = Mission.MissileCollisionReaction.BounceBack;
                                }
                            }
                            else
                            {
                                collisionReaction2 = Mission.MissileCollisionReaction.BecomeInvisible;
                            }
                        }
                    }
                }
            }
            if (collisionData.CollidedWithShieldOnBack && shieldOnBack != null && (victim != null && victim.IsMainAgent))
            {
                InformationManager.DisplayMessage(new InformationMessage(GameTexts.FindText("ui_hit_shield_on_back", (string)null).ToString(), Color.ConvertStringToColor("#FFFFFFFF")));
            }
            MatrixFrame attachLocalFrame;

            if (!collisionData.MissileHasPhysics && !collisionData.MissileGoneUnderWater)
            {
                bool shouldMissilePenetrate = collisionReaction2 == Mission.MissileCollisionReaction.Stick;
                attachLocalFrame = __instance.CalculateAttachedLocalFrame(ref attachGlobalFrame, collisionData, missile.Weapon.CurrentUsageItem, victim, hitEntity, movementVelocity, missileAngularVelocity, affectedShieldGlobalFrame, shouldMissilePenetrate);
            }
            else
            {
                attachLocalFrame      = attachGlobalFrame;
                attachedMissionObject = (MissionObject)null;
            }
            Vec3 velocity        = Vec3.Zero;
            Vec3 angularVelocity = Vec3.Zero;

            if (collisionReaction2 == Mission.MissileCollisionReaction.BounceBack)
            {
                WeaponFlags weaponFlags2 = weaponFlags1 & WeaponFlags.AmmoBreakOnBounceBackMask;
                if (weaponFlags2 == WeaponFlags.AmmoCanBreakOnBounceBack && (double)collisionData.MissileVelocity.Length > (double)ManagedParameters.Instance.GetManagedParameter(ManagedParametersEnum.BreakableProjectileMinimumBreakSpeed) || weaponFlags2 == WeaponFlags.AmmoBreaksOnBounceBack)
                {
                    collisionReaction2 = Mission.MissileCollisionReaction.BecomeInvisible;
                    hitParticleIndex   = ParticleSystemManager.GetRuntimeIdByName("psys_game_broken_arrow");
                }
                else
                {
                    missile.CalculateBounceBackVelocity(missileAngularVelocity, collisionData, out velocity, out angularVelocity);
                }
            }
            __instance.HandleMissileCollisionReaction(missileIndex, collisionReaction2, attachLocalFrame, attacker, victim, collisionData.AttackBlockedWithShield, collisionData.CollisionBoneIndex, attachedMissionObject, velocity, angularVelocity, -1);
            foreach (MissionBehaviour missionBehaviour in __instance.MissionBehaviours)
            {
                missionBehaviour.OnMissileHit(attacker, victim, isCanceled);
            }
            __result = collisionReaction2 != Mission.MissileCollisionReaction.PassThrough;

            return(false);
        }
Example #2
0
        static bool Prefix(Mission __instance, ref bool __result, out int hitParticleIndex, ref AttackCollisionData collisionData,
                           Vec3 missileStartingPosition, Vec3 missilePosition, Vec3 missileAngularVelocity, Vec3 movementVelocity,
                           MatrixFrame attachGlobalFrame, MatrixFrame affectedShieldGlobalFrame, int numDamagedAgents, Agent attacker, Agent victim,
                           GameEntity hitEntity)
        {
            hitParticleIndex = -1;
            if (InvulnerableSettings.Instance.Enabled == false)
            {
                return(true);
            }
            if (victim == Agent.Main)
            {
                FieldInfo           missileField        = AccessTools.Field(typeof(Mission), "_missiles");
                var                 missiles            = (Dictionary <int, Mission.Missile>)missileField.GetValue(__instance);
                Mission.Missile     missile             = missiles[collisionData.AffectorWeaponSlotOrMissileIndex];
                MissionWeapon       weapon              = missile.Weapon;
                WeaponFlags         weaponFlags         = missile.Weapon.CurrentUsageItem.WeaponFlags;
                float               num                 = 1f;
                WeaponComponentData weaponComponentData = null;
                if (collisionData.AttackBlockedWithShield && weaponFlags.HasAnyFlag(WeaponFlags.CanPenetrateShield))
                {
                    return(true);    // Use original code
                }
                hitParticleIndex = -1;
                Mission.MissileCollisionReaction missileCollisionReaction = Mission.MissileCollisionReaction.BounceBack;
                bool            flag = !GameNetwork.IsSessionActive;
                bool            missileHasPhysics = collisionData.MissileHasPhysics;
                PhysicsMaterial fromIndex         = PhysicsMaterial.GetFromIndex(collisionData.PhysicsMaterialIndex);
                object          obj   = fromIndex.IsValid ? fromIndex.GetFlags() : PhysicsMaterialFlags.None;
                bool            flag2 = (weaponFlags & WeaponFlags.AmmoSticksWhenShot) > (WeaponFlags)0UL;
                object          obj2  = obj;
                bool            flag5 = false;
                if (collisionData.MissileGoneUnderWater)
                {
                    return(true);
                }
                else if (collisionData.AttackBlockedWithShield)
                {
                    return(true);
                }
                else
                {
                    // Friendly control
                    if (attacker != null && attacker.IsFriendOf(victim))
                    {
                        if (!missileHasPhysics)
                        {
                            if (flag)
                            {
                                if (attacker.Controller == Agent.ControllerType.AI)
                                {
                                    flag5 = true;
                                }
                            }
                            else if ((MultiplayerOptions.OptionType.FriendlyFireDamageRangedFriendPercent.GetIntValue(MultiplayerOptions.MultiplayerOptionsAccessMode.CurrentMapOptions) <= 0 && MultiplayerOptions.OptionType.FriendlyFireDamageRangedSelfPercent.GetIntValue(MultiplayerOptions.MultiplayerOptionsAccessMode.CurrentMapOptions) <= 0) || __instance.Mode == MissionMode.Duel)
                            {
                                flag5 = true;
                            }
                        }
                    }
                    else if (victim.IsHuman && !attacker.IsEnemyOf(victim))
                    {
                        flag5 = true;
                    }
                    else if (flag && attacker != null && attacker.Controller == Agent.ControllerType.AI && victim.RiderAgent != null && attacker.IsFriendOf(victim.RiderAgent))
                    {
                        flag5 = true;
                    }

                    if (flag5)
                    {
                        missileCollisionReaction = Mission.MissileCollisionReaction.BecomeInvisible;
                    }
                    else
                    {
                        // even weapons with multiple penetration can't penetrate me.
                        //bool flag6 = (weaponFlags & WeaponFlags.MultiplePenetration) > (WeaponFlags)0UL;
                        //if (flag6)
                        //{
                        //    return true;    // Use original code
                        //}

                        MethodInfo getAttackCollisionResultsMethod = typeof(Mission).GetMethod("GetAttackCollisionResults", BindingFlags.NonPublic | BindingFlags.Instance);
                        getAttackCollisionResultsMethod.Invoke(__instance, new object[] {
                            attacker, victim, null, num, collisionData, weapon, false, false, false, weaponComponentData
                        });
                        Blow blow = CreateMissileBlow(attacker, collisionData, weapon, missilePosition, missileStartingPosition);
                        blow.BlowFlag |= BlowFlags.ShrugOff;    // Any attack is so neglectable to our hero
                        if (victim.State == AgentState.Active)
                        {
                            MethodInfo registerBlowMethod = AccessTools.Method("Mission:RegisterBlow");
                            registerBlowMethod.Invoke(__instance, new object[] { attacker, victim, null, blow, collisionData, weapon });
                            //__instance.RegisterBlow(attacker, victim, null, blow, ref collisionData);
                        }
                    }
                }
                MatrixFrame attachLocalFrame;
                attachLocalFrame = attachGlobalFrame;


                // Any missile bounces back
                WeaponFlags weaponFlags2 = weaponFlags & WeaponFlags.AmmoBreakOnBounceBackMask;
                Vec3        zero         = Vec3.Zero;
                Vec3        zero2        = Vec3.Zero;
                if ((weaponFlags2 == WeaponFlags.AmmoCanBreakOnBounceBack &&
                     collisionData.MissileVelocity.Length >
                     ManagedParameters.Instance.GetManagedParameter(ManagedParametersEnum.BreakableProjectileMinimumBreakSpeed)) ||
                    weaponFlags2 == WeaponFlags.AmmoBreaksOnBounceBack)
                {
                    if (collisionData.MissileTotalDamage > InvulnerableSettings.Instance.ArrowBreakingThres)
                    {
                        missileCollisionReaction = Mission.MissileCollisionReaction.BecomeInvisible;
                        Mission.Current.Scene.CreateBurstParticle(ParticleSystemManager.GetRuntimeIdByName("psys_game_broken_arrow"), attachLocalFrame);
                    }
                    else
                    {
                        hitParticleIndex = ParticleSystemManager.GetRuntimeIdByName("psys_game_broken_arrow");  // For some reason, setting this doesn't work
                    }
                }
                else
                {
                    missile.CalculateBounceBackVelocity(missileAngularVelocity, collisionData, out zero, out zero2);
                    Mission.Current.Scene.CreateBurstParticle(ParticleSystemManager.GetRuntimeIdByName("psys_game_missile_metal_coll"), attachLocalFrame);
                }
                __instance.HandleMissileCollisionReaction(collisionData.AffectorWeaponSlotOrMissileIndex, missileCollisionReaction, attachLocalFrame,
                                                          attacker, null, collisionData.AttackBlockedWithShield, collisionData.CollisionBoneIndex, null, zero, zero2, -1);
                foreach (MissionBehaviour missionBehaviour in __instance.MissionBehaviours)
                {
                    missionBehaviour.OnMissileHit(attacker, null, flag5);
                }

                __result = true;
                return(false);
            }
            return(true);
        }