static bool PointInsideRect(Point2 point, Point2 rectCenter, HitBoxType rectSize) { double left = rectCenter.x - rectSize.Width / 2, right = rectCenter.x + rectSize.Width / 2, top = rectCenter.y - rectSize.Height / 2, bottom = rectCenter.y + rectSize.Height / 2; return(point.x >= left && point.x <= right && point.y >= top && point.y <= bottom); }
/// <summary> /// Initializes a new instance of the <see cref="ShotEventArgs"/> class. /// </summary> /// <param name="shooter"><inheritdoc cref="Shooter"/></param> /// <param name="target"><inheritdoc cref="Target"/></param> /// <param name="hitboxType"><inheritdoc cref="HitboxType"/></param> /// <param name="distance"><inheritdoc cref="Distance"/></param> /// <param name="damage"><inheritdoc cref="Damage"/></param> /// <param name="canHurt"><inheritdoc cref="CanHurt"/></param> public ShotEventArgs(Player shooter, GameObject target, HitBoxType hitboxType, float distance, float damage, bool canHurt = true) { Shooter = shooter; Target = target; #pragma warning disable CS0618 // Type or member is obsolete HitboxType = hitboxType.ToString().ToLowerInvariant(); #pragma warning restore CS0618 // Type or member is obsolete HitboxTypeEnum = hitboxType; Distance = distance; Damage = damage; CanHurt = canHurt; }
/// <summary> /// Initializes a new instance of the <see cref="HitBox"/> class by copying the values from the /// given template. /// </summary> public HitBox(HitBox template) { // Copy the data fields from the given templates this.hitBoxType = template.hitBoxType; this.boneName = template.boneName; this.offset = template.offset; this.size = template.size; // Duplicate the 'hitFrames' array this.hitFrames = ArrayUtils.Copy <int>(template.hitFrames); // Create a deep copy of the HitInfo instance> this.hitInfo = new HitInfo(template.hitInfo); }
public UnitForCollision(Unit unit) { this.unit = unit; this.hp = unit.Hp; this.team = unit.Owner; //создаем чуть увеиченный хитбокс, чтобы считать снаряд точкой //решение не идеально точное, но сойдет hitBox = new HitBoxType { Height = unit.HitBox.Height + Const.ShellRadius * 2, Width = unit.HitBox.Width + Const.ShellRadius * 2 }; this.maxRadius = Math.Sqrt(Geometry.Sqr(hitBox.Width / 2) + Geometry.Sqr(hitBox.Height / 2)); }
private static void Postfix(WeaponManager __instance, HitBoxType hitboxType, GameObject target) { // If limb damage is disabled; just don't do anything on the patch. if (!HardcoreSl.Instance.Config.EnableLimbDamage) { return; } if (target == null || __instance.gameObject == null) { return; } if (!ReferenceHub.TryGetHub(target, out var targetHub) || !ReferenceHub.TryGetHub(__instance.gameObject, out var ourHub)) { return; } // Copied basically from HurtPlayer. Prevent limb damage on friendly fire targets. bool ff = targetHub.characterClassManager.Fraction == ourHub.characterClassManager.Fraction; if (ff && !GameCore.ConfigFile.ServerConfig.GetBool("friendly_fire")) { return; } if (!__instance.TryGetComponent(out PlayerHardcoreComponent instanceComponent) || !target.TryGetComponent(out PlayerHardcoreComponent targetComponent)) { return; } // No limb damage on SCPs - with the exception of 049-2. if (targetHub.characterClassManager.IsAnyScp() && targetHub.characterClassManager.CurClass != RoleType.Scp0492) { return; } float dis = Vector3.Distance(__instance.camera.transform.position, target.transform.position); float damage = __instance.weapons[__instance.curWeapon].damageOverDistance.Evaluate(dis); targetComponent.RegisterHit(hitboxType, damage, instanceComponent); }
public PlayerShootEvent(Player player, Player target, Weapon weapon, WeaponSound?weaponSound, Vector sourcePosition, Vector targetPosition, HitBoxType targetHitbox, Vector direction, bool spawnHitmarker = true, bool spawnBloodDecal = true) : base(player) { this.Target = target; this.Weapon = weapon; this.ShouldSpawnHitmarker = spawnHitmarker; this.ShouldSpawnBloodDecal = spawnBloodDecal; this.SourcePosition = sourcePosition; this.TargetPosition = targetPosition; this.TargetHitbox = targetHitbox; this.Direction = direction; this.WeaponSound = weaponSound; }
private static bool Prefix(WeaponManager __instance, GameObject target, HitBoxType hitboxType, Vector3 dir, Vector3 sourcePos, Vector3 targetPos) { try { bool npc = Npc.Dictionary.ContainsKey(__instance.gameObject); if (!__instance._iawRateLimit.CanExecute(true)) { return(false); } int itemIndex = __instance._hub.inventory.GetItemIndex(); if (!npc) { if (itemIndex < 0 || itemIndex >= __instance._hub.inventory.items.Count || __instance.curWeapon < 0 || __instance._hub.inventory.curItem != __instance.weapons[__instance.curWeapon].inventoryID || __instance._hub.inventory.items[itemIndex].durability <= 0.0) { return(false); } if (Vector3.Distance(__instance._hub.playerMovementSync.RealModelPosition, sourcePos) > 5.5f) { __instance.GetComponent <CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.6 (difference between real source position and provided source position is too big)", "gray"); return(false); } if (sourcePos.y - __instance._hub.playerMovementSync.LastSafePosition.y > 1.78f) { __instance.GetComponent <CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.7 (Y axis difference between last safe position and provided source position is too big)", "gray"); return(false); } if (Math.Abs(sourcePos.y - __instance._hub.playerMovementSync.RealModelPosition.y) > 2.7f) { __instance.GetComponent <CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.8 (|Y| axis difference between real position and provided source position is too big)", "gray"); return(false); } } if ((__instance._reloadCooldown > 0f || __instance._fireCooldown > 0f) && !__instance.isLocalPlayer) { return(false); } Log.Debug("Invoking shooting event", Loader.ShouldDebugBeShown); var shootingEventArgs = new ShootingEventArgs(Player.Get(__instance.gameObject), target, targetPos); Exiled.Events.Handlers.Player.OnShooting(shootingEventArgs); if (!shootingEventArgs.IsAllowed) { return(false); } targetPos = shootingEventArgs.Position; // <Exiled if (!npc) { __instance._hub.inventory.items.ModifyDuration(itemIndex, __instance._hub.inventory.items[itemIndex].durability - 1f); } __instance.scp268.ServerDisable(); __instance._fireCooldown = 1f / (__instance.weapons[__instance.curWeapon].shotsPerSecond * __instance.weapons[__instance.curWeapon].allEffects.firerateMultiplier) * 0.9f; float sourceRangeScale = __instance.weapons[__instance.curWeapon].allEffects.audioSourceRangeScale; sourceRangeScale = sourceRangeScale * sourceRangeScale * 70f; __instance.GetComponent <Scp939_VisionController>().MakeNoise(Mathf.Clamp(sourceRangeScale, 5f, 100f)); bool flag = target != null; if (targetPos == Vector3.zero) { if (Physics.Raycast(sourcePos, dir, out RaycastHit raycastHit, 500f, __instance.raycastMask)) { HitboxIdentity component = raycastHit.collider.GetComponent <HitboxIdentity>(); if (component != null) { WeaponManager componentInParent = component.GetComponentInParent <WeaponManager>(); if (componentInParent != null) { flag = false; target = componentInParent.gameObject; hitboxType = component.id; targetPos = componentInParent.transform.position; } } } } else if (Physics.Linecast(sourcePos, targetPos, out RaycastHit raycastHit, __instance.raycastMask)) { HitboxIdentity component = raycastHit.collider.GetComponent <HitboxIdentity>(); if (component != null) { WeaponManager componentInParent = component.GetComponentInParent <WeaponManager>(); if (componentInParent != null) { if (componentInParent.gameObject == target) { flag = false; } else if (componentInParent.scp268.Enabled) { flag = false; target = componentInParent.gameObject; hitboxType = component.id; targetPos = componentInParent.transform.position; } } } } ReferenceHub referenceHub = null; if (target != null) { referenceHub = ReferenceHub.GetHub(target); } if (referenceHub != null && __instance.GetShootPermission(referenceHub.characterClassManager, false)) { if (!npc) { if (Math.Abs(__instance._hub.playerMovementSync.RealModelPosition.y - referenceHub.playerMovementSync.RealModelPosition.y) > 35f) { __instance.GetComponent <CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.1 (too big Y-axis difference between source and target)", "gray"); return(false); } if (Vector3.Distance(referenceHub.playerMovementSync.RealModelPosition, targetPos) > 5f) { __instance.GetComponent <CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.2 (difference between real target position and provided target position is too big)", "gray"); return(false); } if (Physics.Linecast(__instance._hub.playerMovementSync.RealModelPosition, sourcePos, __instance.raycastServerMask)) { __instance.GetComponent <CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.3 (collision between source positions detected)", "gray"); return(false); } if (flag && Physics.Linecast(sourcePos, targetPos, __instance.raycastServerMask)) { __instance.GetComponent <CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.4 (collision on shot line detected)", "gray"); return(false); } if (referenceHub.gameObject == __instance.gameObject) { __instance.GetComponent <CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.5 (target is itself)", "gray"); return(false); } Vector3 positionOffset = referenceHub.playerMovementSync.RealModelPosition - __instance._hub.playerMovementSync.RealModelPosition; float sqrMagnitude = positionOffset.sqrMagnitude; if (Math.Abs(positionOffset.y) < 10f && sqrMagnitude > 7.84f && (referenceHub.characterClassManager.CurClass != global::RoleType.Scp0492 || sqrMagnitude > 9f) && ((referenceHub.characterClassManager.CurClass != global::RoleType.Scp93953 && referenceHub.characterClassManager.CurClass != global::RoleType.Scp93989) || sqrMagnitude > 18.49f)) { float angl = Math.Abs(global::Misc.AngleIgnoreY(positionOffset, __instance.transform.forward)); if (angl > 45f) { __instance.GetComponent <global::CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.12 (too big angle)", "gray"); return(false); } if (__instance._lastAngleReset > 0f && angl > 25f && Math.Abs(global::Misc.AngleIgnoreY(positionOffset, __instance._lastAngle)) > 60f) { __instance._lastAngle = positionOffset; __instance._lastAngleReset = 0.4f; __instance.GetComponent <global::CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.13 (too big angle v2)", "gray"); return(false); } __instance._lastAngle = positionOffset; __instance._lastAngleReset = 0.4f; } if (__instance._lastRotationReset > 0f && (__instance._hub.playerMovementSync.Rotations.x < 68f || __instance._hub.playerMovementSync.Rotations.x > 295f)) { float num5 = __instance._hub.playerMovementSync.Rotations.x - __instance._lastRotation; if (num5 >= 0f && num5 <= 0.0005f) { __instance._lastRotation = __instance._hub.playerMovementSync.Rotations.x; __instance._lastRotationReset = 0.35f; __instance.GetComponent <global::CharacterClassManager>().TargetConsolePrint(__instance.connectionToClient, "Shot rejected - Code W.9 (no recoil)", "gray"); return(false); } } __instance._lastRotation = __instance._hub.playerMovementSync.Rotations.x; __instance._lastRotationReset = 0.35f; } float num2 = Vector3.Distance(__instance.camera.transform.position, target.transform.position); float num3 = __instance.weapons[(int)__instance.curWeapon].damageOverDistance.Evaluate(num2); switch (referenceHub.characterClassManager.CurClass) { case RoleType.Scp106: num3 /= 10f; goto IL_6D1; case RoleType.Scp049: case RoleType.Scp079: case RoleType.Scp096: case RoleType.Scp173: case RoleType.Scp93953: case RoleType.Scp93989: goto IL_6D1; default: switch (hitboxType) { case HitBoxType.HEAD: num3 *= 4; float num4 = 1 / (__instance.weapons[(int)__instance.curWeapon].shotsPerSecond * __instance.weapons[(int)__instance.curWeapon].allEffects.firerateMultiplier); __instance._headshotsL++; __instance._headshotsS++; __instance._headshotsResetS = num4 * 1.86f; __instance._headshotsResetL = num4 * 2.9f; if (__instance._headshotsS >= 3) { __instance._hub.playerMovementSync.AntiCheatKillPlayer("Headshots limit exceeded in time window A\n(debug code: W.10)", "W.10"); return(false); } if (__instance._headshotsL >= 4) { __instance._hub.playerMovementSync.AntiCheatKillPlayer("Headshots limit exceeded in time window B\n(debug code: W.11)", "W.11"); return(false); } break; case HitBoxType.ARM: case HitBoxType.LEG: num3 /= 2; break; } break; } IL_6D1: num3 *= __instance.weapons[(int)__instance.curWeapon].allEffects.damageMultiplier; num3 *= __instance.overallDamagerFactor; // >Exiled Log.Debug("Invoking late shoot.", Loader.ShouldDebugBeShown); var shotEventArgs = new ShotEventArgs(Player.Get(__instance.gameObject), target, hitboxType, num2, num3); Exiled.Events.Handlers.Player.OnShot(shotEventArgs); if (!shotEventArgs.CanHurt) { return(false); } // <Exiled __instance._hub.playerStats.HurtPlayer( new PlayerStats.HitInfo( shotEventArgs.Damage, __instance._hub.LoggedNameFromRefHub(), DamageTypes.FromWeaponId(__instance.curWeapon), __instance._hub.queryProcessor.PlayerId), referenceHub.gameObject); __instance.RpcConfirmShot(hitmarker: true, __instance.curWeapon); __instance.PlaceDecal(isBlood: true, new Ray(__instance.camera.position, dir), (int)referenceHub.characterClassManager.CurClass, num2); } else if (target != null && hitboxType == HitBoxType.WINDOW && target.GetComponent <BreakableWindow>() != null) { float time = Vector3.Distance(__instance.camera.transform.position, target.transform.position); float damage = __instance.weapons[__instance.curWeapon].damageOverDistance.Evaluate(time); target.GetComponent <BreakableWindow>().ServerDamageWindow(damage); __instance.RpcConfirmShot(hitmarker: true, __instance.curWeapon); } else { __instance.PlaceDecal(isBlood: false, new Ray(__instance.camera.position, dir), __instance.curWeapon, 0f); __instance.RpcConfirmShot(hitmarker: false, __instance.curWeapon); } return(false); } catch (Exception e) { Exiled.API.Features.Log.Error($"{typeof(ShootFixPatch).FullName}.{nameof(Prefix)}:\n{e}"); return(true); } }
public void SetHitbox(Rectangle rect, HitBoxType type) { BoundingBox = rect; this.type = type; }
public BasicHitBox(Rectangle rect, HitBoxType type) { BoundingBox = rect; this.type = type; }
public BasicHitBox(Rectangle rect) { BoundingBox = rect; this.type = HitBoxType.Basic; }
void DrawHitBoxesList(MeleeAttackObject attackObject) { if (attackObject != null && attackObject.hitBoxes != null) { for (int i = 0; i < attackObject.hitBoxes.Count; i++) { try { GUILayout.BeginHorizontal(); if (attackObject.hitBoxes[i] != null && attackObject.hitBoxes[i].transform == attackObject.transform || (attackObject.GetComponent <HitBox>() != null)) { DestroyImmediate(attackObject.GetComponent <HitBox>()); attackObject.hitBoxes.RemoveAt(i); GUILayout.EndHorizontal(); break; } Color color = GUI.color; GUI.color = seletedHitboxIndex == i ? new Color(1, 1, 0, 0.6f) : color; if (GUILayout.Button("Hit Box " + (i + 1), EditorStyles.miniButton)) { if (seletedHitboxIndex == i) { seletedHitboxIndex = -1; } else { seletedHitboxIndex = i; } } GUI.color = color; if (attackObject.hitBoxes.Count > 1 && GUILayout.Button("X", EditorStyles.miniButton, GUILayout.Width(20))) { if (attackObject.hitBoxes[i] != null && attackObject.hitBoxes[i].transform != attackObject.transform) { DestroyImmediate(attackObject.hitBoxes[i].gameObject); } attackObject.hitBoxes.RemoveAt(i); GUILayout.EndHorizontal(); break; } GUILayout.EndHorizontal(); } catch { } } } if (seletedHitboxIndex > -1 && seletedHitboxIndex < attackObject.hitBoxes.Count) { GUILayout.BeginVertical("box"); var hitBox = attackObject.hitBoxes[seletedHitboxIndex]; if (hitBox) { EditorGUILayout.ObjectField("Selected Hit Box " + (seletedHitboxIndex + 1), hitBox, typeof(HitBox), true); //GUILayout.Box("Hit Settings", GUILayout.ExpandWidth(true)); hitBox.damagePercentage = EditorGUILayout.IntSlider("Damage Percentage", hitBox.damagePercentage, 0, 100); #if UNITY_2017_1_OR_NEWER hitBox.triggerType = (HitBoxType)EditorGUILayout.EnumFlagsField("Trigger Type", hitBox.triggerType); #else hitBox.triggerType = (vHitBoxType)EditorGUILayout.EnumMaskField("Trigger Type", hitBox.triggerType); #endif if (GUI.changed) { EditorUtility.SetDirty(hitBox); } } GUILayout.EndVertical(); } GUILayout.Space(10); if (!inCreateHitBox && GUILayout.Button("Create New Hit Box", EditorStyles.miniButton)) { inCreateHitBox = true; damagePercentage = 100; triggerType = HitBoxType.Damage | HitBoxType.Recoil; } if (inCreateHitBox) { GUILayout.Box("New Hit Box", GUILayout.ExpandWidth(true)); damagePercentage = EditorGUILayout.IntSlider("Damage Percentage", damagePercentage, 0, 100); #if UNITY_2017_1_OR_NEWER triggerType = (HitBoxType)EditorGUILayout.EnumFlagsField("Trigger Type", triggerType); #else triggerType = (vHitBoxType)EditorGUILayout.EnumMaskField("Trigger Type", triggerType); #endif GUILayout.BeginHorizontal(); if (GUILayout.Button("Create", EditorStyles.miniButton, GUILayout.ExpandWidth(true))) { var type = typeof(BoxCollider); var hitObject = new GameObject("hitBox", typeof(HitBox), type); hitObject.transform.localScale = Vector3.one * 0.2f; hitObject.transform.parent = attackObject.transform; hitObject.transform.localPosition = Vector3.zero; hitObject.transform.localEulerAngles = Vector3.zero; var hitBox = hitObject.GetComponent <HitBox>(); hitBox.damagePercentage = damagePercentage; hitBox.triggerType = triggerType; attackObject.hitBoxes.Add(hitBox); inCreateHitBox = false; } if (GUILayout.Button("Cancel", EditorStyles.miniButton, GUILayout.ExpandWidth(true))) { inCreateHitBox = false; } GUILayout.EndHorizontal(); } GUILayout.Space(10); }
public override float Process(Npc npc) { if (!npc.NPCPlayer.ReferenceHub.characterClassManager.IsAnyScp()) { if (npc.AvailableWeapons.Count > 0) { if (!npc.ItemHeld.IsWeapon(false)) { npc.ItemHeld = npc.AvailableWeapons.Keys.ElementAt(0); return(0.5f); } npc.Stop(); Vector3 heading = (npc.CurrentAIPlayerTarget.Position - npc.NPCPlayer.Position); Quaternion lookRot = Quaternion.LookRotation(heading.normalized); npc.NPCPlayer.Rotations = new Vector2(lookRot.eulerAngles.x, lookRot.eulerAngles.y); bool miss = Plugin.Random.Next(0, 100) >= accuracy; int hitbox_value = Plugin.Random.Next(0, 100); HitBoxType hitbox = HitBoxType.NULL; int min = int.MaxValue; foreach (HitBoxType box in hitboxes.Keys) { if (hitbox_value < hitboxes[box] && hitboxes[box] <= min) { min = hitboxes[box]; hitbox = box; } } npc.NPCPlayer.ReferenceHub.weaponManager.CallCmdShoot(miss ? npc.gameObject : npc.CurrentAIPlayerTarget.GameObject, hitbox, npc.NPCPlayer.CameraTransform.forward, npc.NPCPlayer.Position, npc.CurrentAIPlayerTarget.Position); bool end = !npc.CurrentAIPlayerTarget.IsAlive; if (use_ammo) { npc.AvailableWeapons[npc.ItemHeld]--; if (npc.AvailableWeapons[npc.ItemHeld] <= 0) { npc.NPCPlayer.ReferenceHub.weaponManager.RpcReload(npc.NPCPlayer.ReferenceHub.weaponManager.curWeapon); npc.AvailableWeapons[npc.ItemHeld] = (int)npc.NPCPlayer.ReferenceHub.weaponManager.weapons[npc.NPCPlayer.ReferenceHub.weaponManager.curWeapon].maxAmmo; if (end) { npc.FireEvent(new Events.NPCTargetKilledEvent(npc, npc.CurrentAIPlayerTarget)); IsFinished = true; } return(npc.NPCPlayer.ReferenceHub.weaponManager.weapons[npc.NPCPlayer.ReferenceHub.weaponManager.curWeapon].reloadingTime); } } if (end) { npc.FireEvent(new Events.NPCTargetKilledEvent(npc, npc.CurrentAIPlayerTarget)); IsFinished = true; return(0f); } } else { IsFinished = true; return(0f); } return(firerate * Plugin.Instance.Config.NpcFireCooldownMultiplier * npc.NPCPlayer.ReferenceHub.weaponManager._fireCooldown); } else { float cd = 0f; npc.OnTargetLostBehaviour = Npc.TargetLostBehaviour.STOP; npc.Follow(npc.CurrentAIPlayerTarget); if (Vector3.Distance(npc.CurrentAIPlayerTarget.Position, npc.NPCPlayer.Position) <= 1.5f) { if (npc.NPCPlayer.Role.Is939()) { npc.NPCPlayer.GameObject.GetComponent <Scp939PlayerScript>().CallCmdShoot(npc.CurrentAIPlayerTarget.GameObject); } else { switch (npc.NPCPlayer.Role) { case RoleType.Scp106: npc.NPCPlayer.GameObject.GetComponent <Scp106PlayerScript>().CallCmdMovePlayer(npc.CurrentAIPlayerTarget.GameObject, ServerTime.time); cd = 2f; break; case RoleType.Scp173: npc.NPCPlayer.GameObject.GetComponent <Scp173PlayerScript>().CallCmdHurtPlayer(npc.CurrentAIPlayerTarget.GameObject); break; case RoleType.Scp049: npc.CurrentAIPlayerTarget.Hurt(99999f, DamageTypes.Scp049, npc.NPCPlayer.Nickname); cd = PlayableScps.Scp049.KillCooldown; break; case RoleType.Scp0492: npc.NPCPlayer.GameObject.GetComponent <Scp049_2PlayerScript>().CallCmdShootAnim(); npc.NPCPlayer.GameObject.GetComponent <Scp049_2PlayerScript>().CallCmdHurtPlayer(npc.CurrentAIPlayerTarget.GameObject); cd = 1f; break; case RoleType.Scp096: npc.CurrentAIPlayerTarget.Hurt(99999f, DamageTypes.Scp096, npc.NPCPlayer.Nickname, npc.NPCPlayer.Id); break; } } if (!npc.CurrentAIPlayerTarget.IsAlive) { npc.AttachedCoroutines.Add(MEC.Timing.CallDelayed(0.1f, () => { npc.FireEvent(new Events.NPCTargetKilledEvent(npc, npc.CurrentAIPlayerTarget)); })); npc.Stop(); Player target = npc.CurrentAIPlayerTarget; npc.CurrentAIPlayerTarget = null; if (npc.ProcessSCPLogic && npc.NPCPlayer.Role == RoleType.Scp049) { npc.AttachedCoroutines.Add(Timing.RunCoroutine(ReviveCoroutine(npc, target))); IsFinished = true; return(PlayableScps.Scp049.TimeToRevive + 0.5f); } } } return(cd); } }
private IEnumerator <float> ShootCoroutine(Npc npc, Player p, HitBoxType hitbox, int amount) { for (int i = 0; i < amount; i++) { if (!npc.NPCPlayer.ReferenceHub.characterClassManager.IsAnyScp()) { if (npc.AvailableWeapons.Count > 0) { if (!npc.ItemHeld.IsWeapon(false)) { npc.ItemHeld = npc.AvailableWeapons.Keys.ElementAt(0); } npc.Stop(); Vector3 heading = (p.Position - npc.NPCPlayer.Position); Quaternion lookRot = Quaternion.LookRotation(heading.normalized); npc.NPCPlayer.Rotations = new Vector2(lookRot.eulerAngles.x, lookRot.eulerAngles.y); npc.NPCPlayer.ReferenceHub.weaponManager.CallCmdShoot(p.GameObject, hitbox, npc.NPCPlayer.CameraTransform.forward, npc.NPCPlayer.Position, p.Position); } yield return(Timing.WaitForSeconds(Plugin.Instance.Config.NpcFireCooldownMultiplier * npc.NPCPlayer.ReferenceHub.weaponManager._fireCooldown)); } else { float cd = 0f; npc.Follow(p); if (Vector3.Distance(p.Position, npc.NPCPlayer.Position) <= 1.5f) { if (npc.NPCPlayer.Role.Is939()) { npc.NPCPlayer.GameObject.GetComponent <Scp939PlayerScript>().CallCmdShoot(p.GameObject); } else { switch (npc.NPCPlayer.Role) { case RoleType.Scp106: npc.NPCPlayer.GameObject.GetComponent <Scp106PlayerScript>().CallCmdMovePlayer(p.GameObject, ServerTime.time); cd = 2f; break; case RoleType.Scp173: npc.NPCPlayer.GameObject.GetComponent <Scp173PlayerScript>().CallCmdHurtPlayer(p.GameObject); break; case RoleType.Scp049: p.Hurt(99999f, DamageTypes.Scp049, npc.NPCPlayer.Nickname); cd = PlayableScps.Scp049.KillCooldown; break; case RoleType.Scp0492: npc.NPCPlayer.GameObject.GetComponent <Scp049_2PlayerScript>().CallCmdShootAnim(); npc.NPCPlayer.GameObject.GetComponent <Scp049_2PlayerScript>().CallCmdHurtPlayer(p.GameObject); cd = 1f; break; } } npc.Stop(); } yield return(Timing.WaitForSeconds(cd)); } } }