static public BlockMissionObject DrawFBXMeshMissionObjectAt(Mission mission, Vec3 pos, string filename) { // if (prefab == null) GameEntity prefab = GameEntity.CreateEmpty(mission.Scene, false); prefab.EntityFlags |= EntityFlags.DontSaveToScene; //prefab.AddMesh(Mesh.GetFromResource("order_arrow_a"), true); // prefab.SetVisibilityExcludeParents(true); if (MeshListByFileName.ContainsKey(filename) == false) { MeshListByFileName.Add(filename, CreateMesh(filename)); } foreach (var mesh in MeshListByFileName[filename]) { prefab.AddMesh(mesh, false); } prefab.RecomputeBoundingBox(); PhysicsShape shape = prefab.GetBodyShape(); // shape. prefab.AddPhysics(1000, new Vec3(0, 0, 0), null, new Vec3(), new Vec3(), PhysicsMaterial.GetFromIndex(0), false, 0); GameEntity blockEntity = prefab; MatrixFrame identity2 = MatrixFrame.Identity; identity2.origin = pos; identity2.origin.x += 7.5f; identity2.origin.z = 7.5f; identity2.rotation.ApplyScaleLocal(1f); MatrixFrame frame2 = identity2; blockEntity.SetFrame(ref frame2); blockEntity.SetVisibilityExcludeParents(true); blockEntity.SetAlpha(1f); blockEntity.CreateAndAddScriptComponent("BlockMissionObject"); BlockMissionObject missionObject = blockEntity.GetFirstScriptOfType <BlockMissionObject>(); mission.AddActiveMissionObject(missionObject); return(missionObject); }
public static void GetAttackCollisionResults(Mission.Missile missile, bool isHorseArcher, float armorAmountFloat, WeaponComponentData shieldOnBack, AgentFlag victimAgentFlag, float victimAgentAbsorbedDamageRatio, float damageMultiplierOfBone, float combatDifficultyMultiplier, MissionWeapon victimShield, bool canGiveDamageToAgentShield, bool isVictimAgentLeftStance, bool isFriendlyFire, bool doesAttackerHaveMountAgent, bool doesVictimHaveMountAgent, Vec2 attackerAgentMovementVelocity, Vec3 attackerAgentMountMovementDirection, float attackerMovementDirectionAsAngle, Vec2 victimAgentMovementVelocity, Vec3 victimAgentMountMovementDirection, float victimMovementDirectionAsAngle, bool isVictimAgentSameWithAttackerAgent, bool isAttackerAgentMine, bool isAttackerAgentHasRiderAgent, bool isAttackerAgentRiderAgentIsMine, bool isAttackerAgentMount, bool isVictimAgentMine, bool isVictimAgentHasRiderAgent, bool isVictimAgentRiderAgentIsMine, bool isVictimAgentMount, bool isAttackerAgentNull, bool isAttackerAIControlled, BasicCharacterObject attackerAgentCharacter, BasicCharacterObject victimAgentCharacter, Vec3 attackerAgentMovementDirection, Vec3 attackerAgentVelocity, float attackerAgentMountChargeDamageProperty, Vec3 attackerAgentCurrentWeaponOffset, bool isAttackerAgentHuman, bool isAttackerAgentActive, bool isAttackerAgentCharging, bool isVictimAgentNull, float victimAgentScale, float victimAgentWeight, float victimAgentTotalEncumbrance, bool isVictimAgentHuman, Vec3 victimAgentVelocity, Vec3 victimAgentPosition, int weaponAttachBoneIndex, MissionWeapon offHandItem, bool isHeadShot, bool crushedThrough, bool IsVictimRiderAgentSameAsAttackerAgent, float momentumRemaining, ref AttackCollisionData attackCollisionData, bool cancelDamage, string victimAgentName, out CombatLogData combatLog) { float distance = 0f; if (attackCollisionData.IsMissile) { distance = (attackCollisionData.MissileStartingPosition - attackCollisionData.CollisionGlobalPosition).Length; } combatLog = new CombatLogData(isVictimAgentSameWithAttackerAgent, isAttackerAgentHuman, isAttackerAgentMine, isAttackerAgentHasRiderAgent, isAttackerAgentRiderAgentIsMine, isAttackerAgentMount, isVictimAgentHuman, isVictimAgentMine, false, isVictimAgentHasRiderAgent, isVictimAgentRiderAgentIsMine, isVictimAgentMount, false, IsVictimRiderAgentSameAsAttackerAgent, false, false, distance); ItemObject itemFromWeaponKind = ItemObject.GetItemFromWeaponKind(attackCollisionData.AffectorWeaponKind); WeaponComponentData weaponComponentData = (itemFromWeaponKind != null) ? itemFromWeaponKind.GetWeaponWithUsageIndex(attackCollisionData.CurrentUsageIndex) : null; bool flag = Extensions.HitWithAnotherBone(ref attackCollisionData, weaponAttachBoneIndex); Vec3 agentVelocityContribution = Extensions.GetAgentVelocityContribution(doesAttackerHaveMountAgent, attackerAgentMovementVelocity, attackerAgentMountMovementDirection, attackerMovementDirectionAsAngle); Vec3 agentVelocityContribution2 = Extensions.GetAgentVelocityContribution(doesVictimHaveMountAgent, victimAgentMovementVelocity, victimAgentMountMovementDirection, victimMovementDirectionAsAngle); if (attackCollisionData.IsColliderAgent) { combatLog.IsRangedAttack = attackCollisionData.IsMissile; combatLog.HitSpeed = (attackCollisionData.IsMissile ? (agentVelocityContribution2 - attackCollisionData.MissileVelocity).Length : (agentVelocityContribution - agentVelocityContribution2).Length); } float baseMagnitude; int speedBonus; Mission.ComputeBlowMagnitude(ref attackCollisionData, doesVictimHaveMountAgent, weaponComponentData, isAttackerAgentNull, attackerAgentCharacter, attackerAgentMovementDirection, attackerAgentVelocity, attackerAgentMountChargeDamageProperty, attackerAgentCurrentWeaponOffset, isAttackerAgentHuman, isAttackerAgentActive, isAttackerAgentCharging, isVictimAgentNull, victimAgentScale, victimAgentWeight, victimAgentTotalEncumbrance, isVictimAgentHuman, victimAgentVelocity, victimAgentPosition, momentumRemaining, cancelDamage, flag, attackCollisionData.MissileTotalDamage, agentVelocityContribution, agentVelocityContribution2, out attackCollisionData.BaseMagnitude, out baseMagnitude, out attackCollisionData.MovementSpeedDamageModifier, out speedBonus); DamageTypes damageType = (itemFromWeaponKind == null || flag || attackCollisionData.IsAlternativeAttack || attackCollisionData.IsFallDamage || attackCollisionData.IsHorseCharge) ? DamageTypes.Blunt : ((DamageTypes)attackCollisionData.DamageType); combatLog.DamageType = damageType; if (!attackCollisionData.IsColliderAgent && attackCollisionData.EntityExists) { string name = PhysicsMaterial.GetFromIndex(attackCollisionData.PhysicsMaterialIndex).Name; bool isWoodenBody = name == "wood" || name == "wood_weapon" || name == "wood_shield"; attackCollisionData.BaseMagnitude *= Extensions.GetEntityDamageMultiplier(isAttackerAgentCharging, weaponComponentData, damageType, isWoodenBody); attackCollisionData.InflictedDamage = MBMath.ClampInt((int)attackCollisionData.BaseMagnitude, 0, 2000); combatLog.InflictedDamage = attackCollisionData.InflictedDamage; } int num = 0; if (attackCollisionData.IsColliderAgent && !isVictimAgentNull) { if (attackCollisionData.IsAlternativeAttack) { baseMagnitude = attackCollisionData.BaseMagnitude; } if (attackCollisionData.AttackBlockedWithShield) { Mission.ComputeBlowDamageOnShield(isAttackerAgentNull, isAttackerAgentActive, isAttackerAgentCharging, canGiveDamageToAgentShield, isVictimAgentLeftStance, victimShield, ref attackCollisionData, weaponComponentData, attackCollisionData.BaseMagnitude); attackCollisionData.AbsorbedByArmor = attackCollisionData.InflictedDamage; } else { Mission.ComputeBlowDamage(armorAmountFloat, shieldOnBack, victimAgentFlag, victimAgentAbsorbedDamageRatio, damageMultiplierOfBone, combatDifficultyMultiplier, damageType, baseMagnitude, attackCollisionData.CollisionGlobalPosition, itemFromWeaponKind, attackCollisionData.AttackBlockedWithShield, attackCollisionData.CollidedWithShieldOnBack, speedBonus, cancelDamage, attackCollisionData.IsFallDamage, out attackCollisionData.InflictedDamage, out attackCollisionData.AbsorbedByArmor, out num); } GCOToolbox.GCOToolbox.ProjectileBalance.ApplyProjectileArmorResistance(armorAmountFloat, ref attackCollisionData, missile, isHorseArcher); combatLog.InflictedDamage = attackCollisionData.InflictedDamage; combatLog.AbsorbedDamage = attackCollisionData.AbsorbedByArmor; //combatLog.AttackProgress = attackCollisionData.AttackProgress; //issionGameModels.Current.AgentApplyDamageModel.CalculateDamage(attackerAgentCharacter, victimAgentCharacter, offHandItem, isHeadShot, isVictimAgentMount, isVictimAgentHuman, doesAttackerHaveMountAgent, isVictimAgentNull, isAttackerAgentHuman, attackCollisionData, weaponComponentData); //combatLog.ExtraDamage = attackCollisionData.InflictedDamage - combatLog.InflictedDamage; } if (!attackCollisionData.IsFallDamage && isFriendlyFire && !isAttackerAIControlled && GameNetwork.IsSessionActive) { int num2 = attackCollisionData.IsMissile ? MultiplayerOptions.OptionType.FriendlyFireDamageRangedSelfPercent.GetIntValue(MultiplayerOptions.MultiplayerOptionsAccessMode.CurrentMapOptions) : MultiplayerOptions.OptionType.FriendlyFireDamageMeleeSelfPercent.GetIntValue(MultiplayerOptions.MultiplayerOptionsAccessMode.CurrentMapOptions); attackCollisionData.SelfInflictedDamage = MBMath.Round((float)attackCollisionData.InflictedDamage * ((float)num2 * 0.01f)); int num3 = attackCollisionData.IsMissile ? MultiplayerOptions.OptionType.FriendlyFireDamageRangedFriendPercent.GetIntValue(MultiplayerOptions.MultiplayerOptionsAccessMode.CurrentMapOptions) : MultiplayerOptions.OptionType.FriendlyFireDamageMeleeFriendPercent.GetIntValue(MultiplayerOptions.MultiplayerOptionsAccessMode.CurrentMapOptions); attackCollisionData.InflictedDamage = MBMath.Round((float)attackCollisionData.InflictedDamage * ((float)num3 * 0.01f)); if (isVictimAgentMount && !doesAttackerHaveMountAgent) { attackCollisionData.InflictedDamage = MBMath.Round((float)attackCollisionData.InflictedDamage * 0.1f); } combatLog.InflictedDamage = attackCollisionData.InflictedDamage; combatLog.IsFriendlyFire = true; } if (attackCollisionData.AttackBlockedWithShield && attackCollisionData.InflictedDamage > 0 && (int)victimShield.HitPoints - attackCollisionData.InflictedDamage <= 0) { attackCollisionData.IsShieldBroken = true; } }
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); }