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); }
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); }