Example #1
0
        /// <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));
        }
Example #2
0
        /// <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;
        }