/// <summary> /// Spawns a ragdoll on the map based on the different arguments. /// </summary> /// <remarks> /// Tip: You can do, for example, '<paramref name="velocity"/>: "Vector3.up * 3"' to skip parameters. /// </remarks> /// <example> /// <code> /// // Code to spawn a fake ragdoll /// if (ev.Player == MyPlugin.TheInmortalPlayer) /// { /// var fakeRagdoll = Map.SpawnRagdoll(ev.Player.Role, ev.Player.Position, victimNick: ev.Player.DisplayNickname, playerId: ev.Player.Id); /// } /// </code> /// </example> /// <param name="roleType">The <see cref="RoleType"/> to use as ragdoll.</param> /// <param name="victimNick">The name from the victim, who the corpse belongs to.</param> /// <param name="hitInfo">The <see cref="PlayerStats.HitInfo"/> that displays who killed this ragdoll, and using which tool.</param> /// <param name="position">Where the ragdoll will be spawned.</param> /// <param name="rotation">The rotation for the ragdoll.</param> /// <param name="velocity">The initial velocity the ragdoll will have, as if it was exploded.</param> /// <param name="allowRecall">Sets this ragdoll as respawnable by SCP-049.</param> /// <param name="playerId">Used for recall. The <see cref="Player.Id"/> to be recalled.</param> /// <param name="mirrorOwnerId">Can be ignored. The <see cref="Dissonance.Integrations.MirrorIgnorance.MirrorIgnorancePlayer"/>'s PlayerId field, likely used in the client.</param> /// <returns>The Ragdoll component (requires Assembly-CSharp to be referenced).</returns> public static global::Ragdoll SpawnRagdoll( RoleType roleType, string victimNick, global::PlayerStats.HitInfo hitInfo, Vector3 position, Quaternion rotation = default, Vector3 velocity = default, bool allowRecall = false, int playerId = -1, string mirrorOwnerId = null) { global::Role role = CharacterClassManager._staticClasses.SafeGet(roleType); // Check if there's no ragdoll for this class, or if the class is invalid if (role.model_ragdoll == null) { return(null); } var @default = DefaultRagdollOwner; var ragdollInfo = new Ragdoll.Info() { ownerHLAPI_id = mirrorOwnerId != null ? mirrorOwnerId : @default.ownerHLAPI_id, PlayerId = playerId, DeathCause = hitInfo != default ? hitInfo : @default.DeathCause, ClassColor = role.classColor, FullName = role.fullName, Nick = victimNick, }; return(SpawnRagdoll(role, ragdollInfo, position, rotation, velocity, allowRecall)); }
/// <summary> /// Optimized method to Spawn a ragdoll on the map. /// Will only allocate the newly created GameObject, requires extra work and pre-loaded base game roles. /// </summary> /// <remarks> /// <list type="number"> /// <item> /// <para> /// EXILED already has an internal, default Ragdoll.Info: the use of this /// method to try to optimize a plugin is absolutely optional. /// </para> /// We recommend using: Map.SpawnRagdoll(RoleType roleType, string victimNick, Vector3 position) /// </item> /// <item> /// This method should only ever be used if you're dealing with massive /// server-sided lag. /// </item> /// <item> /// Ragdoll.Info's "ownerID" isn't the SteamID, but the /// <see cref="Dissonance.Integrations.MirrorIgnorance.MirrorIgnorancePlayer"/>'s PlayerId field. /// </item> /// </list> /// </remarks> /// <param name="role">Main game's <see cref="Role"/> thad defines the role to spawn a ragdoll.</param> /// <param name="ragdollInfo"><see cref="Ragdoll.Info"/> object containing the ragdoll's info.</param> /// <param name="position">Where the ragdoll will be spawned.</param> /// <param name="rotation">The rotation for the ragdoll.</param> /// <param name="velocity">The initial velocity the ragdoll will have, as if it was exploded.</param> /// <param name="allowRecall">Sets this ragdoll as respawnable by SCP-049.</param> /// <returns>The <see cref="Ragdoll"/> component created.</returns> public static Ragdoll SpawnRagdoll( Role role, Ragdoll.Info ragdollInfo, Vector3 position, Quaternion rotation = default, Vector3 velocity = default, bool allowRecall = false) { if (role.model_ragdoll == null) { return(null); } GameObject gameObject = Object.Instantiate(role.model_ragdoll, position + role.ragdoll_offset.position, Quaternion.Euler(rotation.eulerAngles + role.ragdoll_offset.rotation)); // Modify the Ragdoll's component Ragdoll ragdollObject = gameObject.GetComponent <Ragdoll>(); ragdollObject.Networkowner = ragdollInfo != null ? ragdollInfo : DefaultRagdollOwner; ragdollObject.NetworkallowRecall = allowRecall; ragdollObject.NetworkPlayerVelo = velocity; Mirror.NetworkServer.Spawn(gameObject); return(ragdollObject); }
private IEnumerator <float> DoTranquilize(Player player, float duration) { activeTranqs.Add(player); Vector3 oldPosition = player.Position; Item previousItem = player.CurrentItem; Vector3 previousScale = player.Scale; float newHealth = player.Health - Damage; List <PlayerEffect> activeEffects = NorthwoodLib.Pools.ListPool <PlayerEffect> .Shared.Rent(); if (newHealth <= 0) { yield break; } foreach (PlayerEffect effect in player.ReferenceHub.playerEffectsController.AllEffects.Values) { if (effect.IsEnabled) { activeEffects.Add(effect); } } try { if (DropItems) { if (player.Items.Count < 0) { foreach (Item item in player.Items.ToList()) { if (TryGet(item, out CustomItem customItem)) { customItem.Spawn(player.Position, item); player.RemoveItem(item); } } player.DropItems(); } } } catch (Exception e) { Log.Error($"{nameof(DoTranquilize)}: {e}"); } Ragdoll ragdoll = new Ragdoll(player, new UniversalDamageHandler(0f, DeathTranslations.Warhead), true); player.IsInvisible = true; player.Scale = Vector3.one * 0.2f; player.Health = newHealth; player.IsGodModeEnabled = true; player.EnableEffect <Amnesia>(duration); player.EnableEffect <Ensnared>(duration); yield return(Timing.WaitForSeconds(duration)); try { if (ragdoll != null) { NetworkServer.Destroy(ragdoll.GameObject); } if (player.GameObject == null) { yield break; } newHealth = player.Health; player.IsGodModeEnabled = false; player.Scale = previousScale; player.Health = newHealth; player.IsInvisible = false; if (!DropItems) { player.CurrentItem = previousItem; } foreach (PlayerEffect effect in activeEffects) { if ((effect.Duration - duration) > 0) { player.ReferenceHub.playerEffectsController.EnableEffect(effect, effect.Duration - duration); } } activeTranqs.Remove(player); NorthwoodLib.Pools.ListPool <PlayerEffect> .Shared.Return(activeEffects); } catch (Exception e) { Log.Error($"{nameof(DoTranquilize)}: {e}"); } if (Warhead.IsDetonated && player.Position.y < 900) { player.Hurt(new UniversalDamageHandler(-1f, DeathTranslations.Warhead)); yield break; } player.Position = oldPosition; }