예제 #1
0
    //for internal IF2 usages only, does server side logic for processing tileapply
    public void ServerProcessInteraction(int tileInteractionIndex, GameObject performer, Vector2 targetVector, GameObject processorObj, ItemSlot usedSlot, GameObject usedObject, Intent intent)
    {
        //find the indicated tile interaction
        var success        = false;
        var worldPosTarget = (Vector2)performer.transform.position + targetVector;
        //pass the interaction down to the basic tile
        LayerTile tile = LayerTileAt(worldPosTarget);

        if (tile is BasicTile basicTile)
        {
            if (tileInteractionIndex >= basicTile.TileInteractions.Count)
            {
                //this sometimes happens due to lag, so bumping it down to trace
                Logger.LogTraceFormat("Requested TileInteraction at index {0} does not exist on this tile {1}.",
                                      Category.Interaction, tileInteractionIndex, basicTile.name);
                return;
            }

            var tileInteraction = basicTile.TileInteractions[tileInteractionIndex];
            var tileApply       = new TileApply(performer, usedObject, intent,
                                                (Vector2Int)WorldToCell(worldPosTarget), this, basicTile, usedSlot,
                                                targetVector);

            if (tileInteraction.WillInteract(tileApply, NetworkSide.Server) &&
                Cooldowns.TryStartServer(tileApply, CommonCooldowns.Instance.Interaction))
            {
                //perform
                tileInteraction.ServerPerformInteraction(tileApply);
            }
            else
            {
                tileInteraction.ServerRollbackClient(tileApply);
            }
        }
    }
예제 #2
0
    public override void ServerPerformInteraction(TileApply interaction)
    {
        if (!interaction.UsedObject.RegisterTile().Matrix.IsPassableAt(interaction.TargetCellPos, true, true, null, excludeTiles))
        {
            return;
        }

        StandardProgressActionConfig cfg = new StandardProgressActionConfig(StandardProgressActionType.Construction, false, false, false);
        var x = StandardProgressAction.Create(cfg, () =>
        {
            PlayerScript playerScript;
            if (interaction.UsedObject.TryGetComponent(out playerScript))
            {
                List <TileType> excludeTiles = new List <TileType>()
                {
                    TileType.Table
                };

                if (playerScript.registerTile.Matrix.IsPassableAt(interaction.TargetCellPos, true, true, null, excludeTiles))
                {
                    playerScript.PlayerSync.SetPosition(interaction.WorldPositionTarget);
                }
            }
            else
            {
                var transformComp = interaction.UsedObject.GetComponent <CustomNetTransform>();
                if (transformComp != null)
                {
                    transformComp.AppearAtPositionServer(interaction.WorldPositionTarget);
                }
            }
        }).ServerStartProgress(interaction.UsedObject.RegisterTile(), 3.0f, interaction.Performer);
    }
예제 #3
0
    public override void ServerPerformInteraction(TileApply interaction)
    {
        ToolUtils.ServerUseToolWithActionMessages(interaction, seconds,
                                                  performerStartActionMessage,
                                                  Chat.ReplacePerformer(othersStartActionMessage, interaction.Performer),
                                                  performerFinishActionMessage,
                                                  Chat.ReplacePerformer(othersFinishActionMessage, interaction.Performer),
                                                  () =>
        {
            interaction.TileChangeManager.RemoveTile(interaction.TargetCellPos, interaction.BasicTile.LayerType);
            interaction.TileChangeManager.RemoveFloorWallOverlaysOfType(interaction.TargetCellPos, TileChangeManager.OverlayType.Cleanable);

            //spawn things that need to be spawned
            if (interaction.BasicTile.SpawnOnDeconstruct != null &&
                interaction.BasicTile.SpawnAmountOnDeconstruct > 0)
            {
                Spawn.ServerPrefab(interaction.BasicTile.SpawnOnDeconstruct, interaction.WorldPositionTarget,
                                   count: interaction.BasicTile.SpawnAmountOnDeconstruct);
            }

            if (objectsToSpawn != null)
            {
                objectsToSpawn.SpawnAt(SpawnDestination.At(interaction.WorldPositionTarget));
            }

            interaction.TileChangeManager.SubsystemManager.UpdateAt(interaction.TargetCellPos);
        });
    }
예제 #4
0
    public override void ServerPerformInteraction(TileApply interaction)
    {
        string othersMessage = Chat.ReplacePerformer(othersStartActionMessage, interaction.Performer);

        Chat.AddActionMsgToChat(interaction.Performer, performerStartActionMessage, othersMessage);
        if (interaction.BasicTile.LayerType != LayerType.Underfloor)
        {
            return;
        }

        var PipeTile     = interaction.BasicTile as PipeTile;
        var matrix       = interaction.TileChangeManager.MetaTileMap.Layers[LayerType.Underfloor].matrix;
        var metaDataNode = matrix.GetMetaDataNode(interaction.TargetCellPos);

        for (var i = 0; i < metaDataNode.PipeData.Count; i++)
        {
            if (metaDataNode.PipeData[i].RelatedTile != PipeTile)
            {
                continue;
            }
            // var Transform =  matrix.UnderFloorLayer.GetMatrix4x4(metaDataNode.PipeData[i].NodeLocation, metaDataNode.PipeData[i].RelatedTile);
            // var pipe = Spawn.ServerPrefab(PipeTile.SpawnOnDeconstruct, interaction.WorldPositionTarget, localRotation : QuaternionFromMatrix(Transform)).GameObject;
            // var itempipe = pipe.GetComponent<PipeItemTile>();
            // itempipe.Colour = matrix.UnderFloorLayer.GetColour(metaDataNode.PipeData[i].NodeLocation, metaDataNode.PipeData[i].RelatedTile);
            // itempipe.Setsprite();
            // matrix.RemoveUnderFloorTile( metaDataNode.PipeData[i].NodeLocation, metaDataNode.PipeData[i].RelatedTile);
            // var savedpipe = metaDataNode.PipeData[i].pipeData;
            // metaDataNode.PipeData.RemoveAt(i);
            metaDataNode.PipeData[i].pipeData.DestroyThis();
            return;
        }
    }
예제 #5
0
    public bool Interact(PositionalHandApply interaction)
    {
        //translate to the tile interaction system

        //pass the interaction down to the basic tile
        LayerTile tile = LayerTileAt(interaction.WorldPositionTarget);

        if (tile is BasicTile basicTile)
        {
            var tileApply = new TileApply(interaction.Performer, interaction.UsedObject, interaction.Intent,
                                          (Vector2Int)WorldToCell(interaction.WorldPositionTarget), this, basicTile, interaction.HandSlot,
                                          interaction.TargetVector);

            var i = 0;
            foreach (var tileInteraction in basicTile.TileInteractions)
            {
                if (tileInteraction == null)
                {
                    continue;
                }
                if (tileInteraction.WillInteract(tileApply, NetworkSide.Client) &&
                    Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction))
                {
                    //request the tile interaction with this index
                    RequestInteractMessage.SendTileApply(tileApply, this, tileInteraction, i);
                    return(true);
                }

                i++;
            }
        }

        return(false);
    }
    //only intended to be used by core if2 classes
    public static void SendTileApply(TileApply tileApply, InteractableTiles interactableTiles, TileInteraction tileInteraction, int tileInteractionIndex)
    {
        //if we are client and the interaction has client prediction, trigger it.
        //Note that client prediction is not triggered for server player.
        if (!CustomNetworkManager.IsServer)
        {
            Logger.LogTraceFormat("Predicting TileApply interaction {0}", Category.Interaction, tileApply);
            tileInteraction.ClientPredictInteraction(tileApply);
        }
        if (!tileApply.Performer.Equals(PlayerManager.LocalPlayer))
        {
            Logger.LogError("Client attempting to perform an interaction on behalf of another player." +
                            " This is not allowed. Client can only perform an interaction as themselves. Message" +
                            " will not be sent.", Category.NetMessage);
            return;
        }

        var msg = new RequestInteractMessage()
        {
            ComponentType        = typeof(InteractableTiles),
            InteractionType      = typeof(TileApply),
            ProcessorObject      = interactableTiles.GetComponent <NetworkIdentity>().netId,
            Intent               = tileApply.Intent,
            TargetVector         = tileApply.TargetVector,
            TileInteractionIndex = tileInteractionIndex
        };

        msg.Send();
    }
예제 #7
0
        //only intended to be used by core if2 classes
        public static void SendTileApply(TileApply tileApply, InteractableTiles interactableTiles, TileInteraction tileInteraction)
        {
            //if we are client and the interaction has client prediction, trigger it.
            //Note that client prediction is not triggered for server player.
            if (!CustomNetworkManager.IsServer)
            {
                Logger.LogTraceFormat("Predicting TileApply interaction {0}", Category.Interaction, tileApply);
                tileInteraction.ClientPredictInteraction(tileApply);
            }
            if (!tileApply.Performer.Equals(PlayerManager.LocalPlayer))
            {
                Logger.LogError("Client attempting to perform an interaction on behalf of another player." +
                                " This is not allowed. Client can only perform an interaction as themselves. Message" +
                                " will not be sent.", Category.Exploits);
                return;
            }

            var msg = new NetMessage()
            {
                ComponentType   = typeof(InteractableTiles),
                InteractionType = typeof(TileApply),
                ProcessorObject = GetNetId(interactableTiles.gameObject),
                Intent          = tileApply.Intent,
                TargetPosition  = tileApply.TargetPosition
            };

            Send(msg);
        }
예제 #8
0
        private void DeconstructPipe(TileApply interaction)
        {
            DisposalPipe pipe = interaction.BasicTile as DisposalPipe;

            // Despawn pipe tile
            var matrix = MatrixManager.AtPoint(interaction.WorldPositionTarget.NormalizeTo3Int(), true).Matrix;

            matrix.RemoveUnderFloorTile(interaction.TargetCellPos, pipe);

            // Spawn pipe GameObject
            if (interaction.BasicTile.SpawnOnDeconstruct == null)
            {
                return;
            }

            var spawn = Spawn.ServerPrefab(interaction.BasicTile.SpawnOnDeconstruct, interaction.WorldPositionTarget);

            if (spawn.Successful == false)
            {
                return;
            }

            if (spawn.GameObject.TryGetComponent <Directional>(out var directional))
            {
                directional.FaceDirection(Orientation.FromEnum(pipe.DisposalPipeObjectOrientation));
            }

            if (spawn.GameObject.TryGetComponent <ObjectBehaviour>(out var behaviour))
            {
                behaviour.ServerSetPushable(false);
            }
        }
예제 #9
0
    private void PerformTileInteract(TileApply interaction)
    {
        foreach (var tileInteraction in interaction.BasicTile.TileInteractions)
        {
            if (tileInteraction == null)
            {
                continue;
            }
            if (tileInteraction.WillInteract(interaction, NetworkSide.Server))
            {
                //perform if not on cooldown
                if (Cooldowns.TryStartServer(interaction, CommonCooldowns.Instance.Interaction))
                {
                    tileInteraction.ServerPerformInteraction(interaction);
                }
                else
                {
                    //hit a cooldown, rollback in case client tried to predict it
                    tileInteraction.ServerRollbackClient(interaction);
                }

                // interaction should've triggered and did or we hit a cooldown, so we're
                // done processing this request.
                break;
            }
            else
            {
                tileInteraction.ServerRollbackClient(interaction);
            }
        }
    }
        private bool VerboseDisposalMachineExists(TileApply interaction)
        {
            Matrix matrix = interaction.TileChangeManager.MetaTileMap.Layers[LayerType.Underfloor].matrix;

            if ((interaction.BasicTile as DisposalPipe).PipeType == DisposalPipeType.Terminal)
            {
                DisposalMachine disposalMachine = matrix.GetFirst <DisposalMachine>(interaction.TargetCellPos, true);
                if (disposalMachine != null && disposalMachine.MachineAttachedOrGreater)
                {
                    string machineName = disposalMachine.name;
                    if (disposalMachine.TryGetComponent <ObjectAttributes>(out var attributes) &&
                        string.IsNullOrWhiteSpace(attributes.InitialName) == false)
                    {
                        machineName = attributes.InitialName;
                    }

                    Chat.AddExamineMsgFromServer(
                        interaction.Performer,
                        $"The {machineName} must be removed before you can cut the disposal pipe welds!");
                    return(true);
                }
            }

            return(false);
        }
예제 #11
0
    public bool Interact(MouseDrop interaction)
    {
        Logger.Log("Interaction detected on InteractableTiles.");

        LayerTile tile = LayerTileAt(interaction.ShadowWorldLocation, true);

        if (tile is BasicTile basicTile)
        {
            var tileApply     = new TileApply(interaction.Performer, interaction.UsedObject, interaction.Intent, (Vector2Int)WorldToCell(interaction.ShadowWorldLocation), this, basicTile, null, -((Vector2)interaction.Performer.transform.position - interaction.ShadowWorldLocation), TileApply.ApplyType.MouseDrop);
            var tileMouseDrop = new TileMouseDrop(interaction.Performer, interaction.UsedObject, interaction.Intent, (Vector2Int)WorldToCell(interaction.ShadowWorldLocation), this, basicTile, -((Vector2)interaction.Performer.transform.position - interaction.ShadowWorldLocation));
            foreach (var tileInteraction in basicTile.TileInteractions)
            {
                if (tileInteraction == null)
                {
                    continue;
                }
                if (tileInteraction.WillInteract(tileApply, NetworkSide.Client) &&
                    Cooldowns.TryStartClient(interaction, CommonCooldowns.Instance.Interaction))
                {
                    //request the tile interaction because we think one will happen
                    RequestInteractMessage.SendTileMouseDrop(tileMouseDrop, this);
                    return(true);
                }
            }
        }

        return(false);
    }
예제 #12
0
 public override bool WillInteract(TileApply interaction, NetworkSide side)
 {
     if (!DefaultWillInteract.Default(interaction, side))
     {
         return(false);
     }
     return(interaction.HandObject != null);
 }
        public override void ServerPerformInteraction(TileApply interaction)
        {
            if (VerboseDisposalMachineExists(interaction))
            {
                return;
            }

            Weld(interaction);
        }
예제 #14
0
 /// <summary>
 /// Performs common tool usage logic and also sends start / end action messages, and invokes a callback on success.
 /// </summary>
 /// <param name="tileApply">interaction causing the tool use</param>
 /// <param name="seconds">seconds taken to perform the action, 0 if it should be instant</param>
 /// <param name="performerStartActionMessage">message to show performer when action begins.</param>
 /// <param name="othersStartActionMessage">message to show others when action begins.</param>
 /// <param name="performerFinishActionMessage">message to show performer when action completes successfully.</param>
 /// <param name="othersFinishActionMessage">message to show others when action completes successfully.</param>
 /// <param name="onSuccessfulCompletion">called when action is completed</param>
 public static void ServerUseToolWithActionMessages(TileApply tileApply,
                                                    float seconds, string performerStartActionMessage, string othersStartActionMessage,
                                                    string performerFinishActionMessage,
                                                    string othersFinishActionMessage, Action onSuccessfulCompletion)
 {
     ServerUseToolWithActionMessages(tileApply.Performer, tileApply.HandObject,
                                     ActionTarget.Tile(tileApply.WorldPositionTarget), seconds, performerStartActionMessage, othersStartActionMessage,
                                     performerFinishActionMessage, othersFinishActionMessage, onSuccessfulCompletion);
 }
        public override bool WillInteract(TileApply interaction, NetworkSide side)
        {
            if (DefaultWillInteract.Default(interaction, side) == false)
            {
                return(false);
            }

            return(Validations.HasUsedActiveWelder(interaction));
        }
 private void Weld(TileApply interaction)
 {
     ToolUtils.ServerUseToolWithActionMessages(
         interaction, seconds,
         "You start slicing the welds that secure the disposal pipe...",
         $"{interaction.Performer.ExpensiveName()} starts cutting the disposal pipe welds...",
         "You cut the disposal pipe welds.",
         $"{interaction.Performer.ExpensiveName()} cuts the disposal pipe welds.",
         () => DeconstructPipe(interaction)
         );
 }
예제 #17
0
 /// <summary>
 /// Performs common tool usage logic and also sends start / end action messages, and invokes a callback on success.
 /// </summary>
 /// <param name="tileApply">interaction causing the tool use</param>
 /// <param name="seconds">seconds taken to perform the action, 0 if it should be instant</param>
 /// <param name="performerStartActionMessage">message to show performer when action begins.</param>
 /// <param name="othersStartActionMessage">message to show others when action begins.</param>
 /// <param name="performerFinishActionMessage">message to show performer when action completes successfully.</param>
 /// <param name="othersFinishActionMessage">message to show others when action completes successfully.</param>
 /// <param name="onSuccessfulCompletion">called when action is completed</param>
 /// <param name="performerFailMessage">message to show performer when action completes unsuccessfully.</param>
 /// <param name="othersFailMessage">message to show others when action completes unsuccessfully.</param>
 /// <param name="onFailComplete">called when action is completed unsuccessfully.</param>
 /// <param name="playSound">Whether to play default tool sound</param>
 public static void ServerUseToolWithActionMessages(TileApply tileApply,
                                                    float seconds, string performerStartActionMessage, string othersStartActionMessage,
                                                    string performerFinishActionMessage,
                                                    string othersFinishActionMessage, Action onSuccessfulCompletion, string performerFailMessage = "",
                                                    string othersFailMessage = "", Action onFailComplete = null, bool playSound = true)
 {
     ServerUseToolWithActionMessages(tileApply.Performer, tileApply.HandObject,
                                     ActionTarget.Tile(tileApply.WorldPositionTarget), seconds, performerStartActionMessage,
                                     othersStartActionMessage,
                                     performerFinishActionMessage, othersFinishActionMessage, onSuccessfulCompletion, performerFailMessage, othersFailMessage, onFailComplete, playSound);
 }
예제 #18
0
    /// <summary>
    /// Interaction callback to attempt to interact with tiles using a HandApply
    /// interaction. We check for both basic tiles and under floor tiles and
    /// attempt to apply its interaction. In the event that an electric cable
    /// tile is encountered, we open the cable cutting window.
    /// </summary>
    /// <param name="interaction">Position of interaction with a hand</param>
    public bool Interact(PositionalHandApply interaction)
    {
        // translate to the tile interaction system
        Vector3Int localPosition = WorldToCell(interaction.WorldPositionTarget);
        // pass the interaction down to the basic tile
        LayerTile tile = LayerTileAt(interaction.WorldPositionTarget, true);

        // If the tile we're looking at is a basic tile...
        if (tile is BasicTile basicTile)
        {
            // If the the tile is something that's supposed to be underneath floors...
            if (basicTile.LayerType == LayerType.Underfloor)
            {
                // Then we loop through each under floor layer in the matrix until we
                // can find an interaction.
                foreach (BasicTile underFloorTile in matrix.MetaTileMap.GetAllTilesByType <BasicTile>(localPosition, LayerType.Underfloor))
                {
                    // If pointing at electrical cable tile and player is holding
                    // Wirecutter in hand, we enable the cutting window and return false
                    // to indicate that we will not be interacting with anything... yet.
                    // TODO: Check how many cables we have first. Only open the cable
                    //       cutting window when the number of cables exceeds 2.
                    if (underFloorTile is ElectricalCableTile &&
                        Validations.HasItemTrait(PlayerManager.LocalPlayerScript.DynamicItemStorage.GetActiveHandSlot().ItemObject, CommonTraits.Instance.Wirecutter))
                    {
                        // open cable cutting ui window instead of cutting cable
                        EnableCableCuttingWindow();
                        // return false to not cut the cable
                        return(false);
                    }
                    // Else, we attempt to interact with the tile with whatever is in our
                    // at the target.
                    else
                    {
                        var underFloorApply = new TileApply(interaction.Performer, interaction.UsedObject, interaction.Intent,
                                                            (Vector2Int)localPosition, this, underFloorTile, interaction.HandSlot, interaction.TargetVector);

                        if (TryInteractWithTile(underFloorApply))
                        {
                            return(true);
                        }
                    }
                }
            }
            else
            {
                var tileApply = new TileApply(interaction.Performer, interaction.UsedObject, interaction.Intent,
                                              (Vector2Int)localPosition, this, basicTile, interaction.HandSlot, interaction.TargetVector);

                return(TryInteractWithTile(tileApply));
            }
        }
        return(false);
    }
예제 #19
0
 public override void ServerPerformInteraction(TileApply interaction)
 {
     ToolUtils.ServerUseToolWithActionMessages(interaction, seconds,
                                               performerStartActionMessage,
                                               Chat.ReplacePerformer(othersStartActionMessage, interaction.Performer),
                                               performerFinishActionMessage,
                                               Chat.ReplacePerformer(othersFinishActionMessage, interaction.Performer),
                                               () =>
     {
         interaction.TileChangeManager.UpdateTile(interaction.TargetCellPos, toTile);
         interaction.TileChangeManager.SubsystemManager.UpdateAt(interaction.TargetCellPos);
     });
 }
예제 #20
0
    // Start is called before the first frame update
    public override bool WillInteract(TileApply interaction, NetworkSide side)
    {
        if (!DefaultWillInteract.Default(interaction, side))
        {
            return(false);
        }
        if (requiredTrait == CommonTraits.Instance.Welder)
        {
            return(Validations.HasUsedActiveWelder(interaction));
        }

        return(Validations.HasItemTrait(interaction.HandObject, requiredTrait));
    }
예제 #21
0
    //for internal IF2 usages only, does server side logic for processing tileapply
    public void ServerProcessInteraction(GameObject performer, Vector2 targetVector, GameObject processorObj,
                                         ItemSlot usedSlot, GameObject usedObject, Intent intent, TileApply.ApplyType applyType)
    {
        //find the indicated tile interaction
        var        worldPosTarget = (Vector2)performer.transform.position + targetVector;
        Vector3Int localPosition  = WorldToCell(worldPosTarget);
        //pass the interaction down to the basic tile
        LayerTile tile = LayerTileAt(worldPosTarget, true);

        if (tile is BasicTile basicTile)
        {
            // check which tile interaction occurs in the correct order
            Logger.LogTraceFormat(
                "Server checking which tile interaction to trigger for TileApply on tile {0} at worldPos {1}",
                Category.Interaction, tile.name, worldPosTarget);

            if (basicTile.LayerType == LayerType.Underfloor)
            {
                foreach (var underFloorTile in matrix.UnderFloorLayer.GetAllTilesByType <BasicTile>(localPosition))
                {
                    var underFloorApply = new TileApply(
                        performer, usedObject, intent, (Vector2Int)localPosition,
                        this, underFloorTile, usedSlot, targetVector, applyType);

                    foreach (var tileInteraction in underFloorTile.TileInteractions)
                    {
                        if (tileInteraction == null)
                        {
                            continue;
                        }
                        if (tileInteraction.WillInteract(underFloorApply, NetworkSide.Server))
                        {
                            PerformTileInteract(underFloorApply);
                            break;
                        }
                    }
                }
            }
            else
            {
                var tileApply = new TileApply(
                    performer, usedObject, intent, (Vector2Int)localPosition,
                    this, basicTile, usedSlot, targetVector, applyType);

                PerformTileInteract(tileApply);
            }
        }
    }
예제 #22
0
 public override bool WillInteract(TileApply interaction, NetworkSide side)
 {
     if (!DefaultWillInteract.Default(interaction, side))
     {
         return(false);
     }
     if (interaction.TileApplyType != TileApply.ApplyType.HandApply)
     {
         return(false);
     }
     if (interaction.Intent == Intent.Harm)
     {
         return(false);
     }
     return(interaction.HandObject != null);
 }
예제 #23
0
    public override void ServerPerformInteraction(TileApply interaction)
    {
        if (!interaction.UsedObject.RegisterTile().Matrix.IsPassableAtOneMatrixOneTile(interaction.TargetCellPos, true, true, null, excludeTiles))
        {
            return;
        }

        StandardProgressActionConfig cfg = new StandardProgressActionConfig(StandardProgressActionType.Construction, false, false, false);
        var x = StandardProgressAction.Create(cfg, () =>
        {
            PlayerScript playerScript;
            if (interaction.UsedObject.TryGetComponent(out playerScript))
            {
                List <TileType> excludeTiles = new List <TileType>()
                {
                    TileType.Table
                };

                if (playerScript.registerTile.Matrix.IsPassableAtOneMatrixOneTile(interaction.TargetCellPos, true, true, null, excludeTiles))
                {
                    playerScript.PlayerSync.SetPosition(interaction.WorldPositionTarget);
                }
            }
            else
            {
                var transformComp = interaction.UsedObject.GetComponent <CustomNetTransform>();
                if (transformComp != null)
                {
                    transformComp.AppearAtPositionServer(interaction.WorldPositionTarget);
                }
            }
            if (canBreakOnClimb == false)
            {
                return;
            }
            if (DMMath.Prob(breakChance) && interaction.UsedObject.TryGetComponent <RegisterPlayer>(out var victim))
            {
                interaction.BasicTile.SpawnOnDestroy.SpawnAt(SpawnDestination.At(interaction.WorldPositionTarget));
                victim.ServerStun(stunTimeOnBreak);
                _ = SoundManager.PlayNetworkedAtPosAsync(soundOnBreak, interaction.WorldPositionTarget);
                Chat.AddActionMsgToChat(interaction.UsedObject,
                                        $"Your weight pushes onto the {interaction.BasicTile.DisplayName} and you break it and fall through it",
                                        $"{interaction.UsedObject.ExpensiveName()} falls through the {interaction.BasicTile.DisplayName} as it breaks from their weight.");
                victim.PlayerScript.playerHealth.ApplyDamageAll(interaction.Performer, damageOnBreak, AttackType.Melee, DamageType.Brute);
                interaction.TileChangeManager.MetaTileMap.RemoveTileWithlayer(interaction.TargetCellPos, interaction.BasicTile.LayerType);
            }
        }).ServerStartProgress(interaction.UsedObject.RegisterTile(), 3.0f, interaction.Performer);
        private void DeconstructPipe(TileApply interaction)
        {
            DisposalPipe pipeTile = interaction.BasicTile as DisposalPipe;

            // Despawn pipe tile
            var              matrix       = MatrixManager.AtPoint(interaction.WorldPositionTarget.NormalizeTo3Int(), true).Matrix;
            MetaDataNode     metaDataNode = matrix.GetMetaDataNode(interaction.TargetCellPos, false);
            DisposalPipeNode disPipeNode  = null;

            for (var i = 0; i < metaDataNode.DisposalPipeData.Count; i++)
            {
                if (metaDataNode.DisposalPipeData[i].DisposalPipeTile == pipeTile)
                {
                    disPipeNode = metaDataNode.DisposalPipeData[i];
                }
            }
            if (disPipeNode == null)
            {
                Logger.LogError($"Impossible to deconstruct the disposal pipe at {interaction.TargetCellPos} in {matrix.gameObject.scene.name} - {matrix.name}. Disposal pipe node wasn't found",
                                Category.Pipes);
                return;
            }
            matrix.TileChangeManager.RemoveTile(disPipeNode.NodeLocation, LayerType.Underfloor);

            // Spawn pipe GameObject
            if (interaction.BasicTile.SpawnOnDeconstruct == null)
            {
                return;
            }

            var spawn = Spawn.ServerPrefab(interaction.BasicTile.SpawnOnDeconstruct, interaction.WorldPositionTarget);

            if (spawn.Successful == false)
            {
                return;
            }

            if (spawn.GameObject.TryGetComponent <Directional>(out var directional))
            {
                directional.FaceDirection(Orientation.FromEnum(pipeTile.DisposalPipeObjectOrientation));
            }

            if (spawn.GameObject.TryGetComponent <ObjectBehaviour>(out var behaviour))
            {
                behaviour.ServerSetPushable(false);
            }
        }
예제 #25
0
 public override void ServerPerformInteraction(TileApply interaction)
 {
     ToolUtils.ServerUseToolWithActionMessages(interaction, seconds,
                                               performerStartActionMessage,
                                               Chat.ReplacePerformer(othersStartActionMessage, interaction.Performer),
                                               performerFinishActionMessage,
                                               Chat.ReplacePerformer(othersFinishActionMessage, interaction.Performer),
                                               () =>
     {
         interaction.TileChangeManager.UpdateTile(interaction.TargetCellPos, toTile);
         if (objectsToSpawn != null)
         {
             objectsToSpawn.SpawnAt(SpawnDestination.At(interaction.WorldPositionTarget));
         }
         interaction.TileChangeManager.SubsystemManager.UpdateAt(interaction.TargetCellPos);
     });
 }
예제 #26
0
 public override bool WillInteract(TileApply interaction, NetworkSide side)
 {
     if (!DefaultWillInteract.Default(interaction, side))
     {
         return(false);
     }
     if (interaction.Intent == Intent.Harm)
     {
         return(false);
     }
     if (interaction.HandObject != null)
     {
         return(false);
     }
     //don't allow spamming window knocks really fast
     return(Cooldowns.TryStart(interaction, this, 1, side));
 }
    //for internal IF2 usages only, does server side logic for processing tileapply
    public void ServerProcessInteraction(GameObject performer, Vector2 targetVector, GameObject processorObj, ItemSlot usedSlot, GameObject usedObject, Intent intent, TileApply.ApplyType applyType)
    {
        //find the indicated tile interaction
        var worldPosTarget = (Vector2)performer.transform.position + targetVector;
        //pass the interaction down to the basic tile
        LayerTile tile = LayerTileAt(worldPosTarget, true);

        if (tile is BasicTile basicTile)
        {
            // check which tile interaction occurs in the correct order
            Logger.LogTraceFormat("Server checking which tile interaction to trigger for TileApply on tile {0} at worldPos {1}", Category.Interaction,
                                  tile.name, worldPosTarget);
            var tileApply = new TileApply(performer, usedObject, intent,
                                          (Vector2Int)WorldToCell(worldPosTarget), this, basicTile, usedSlot,
                                          targetVector, applyType);
            foreach (var tileInteraction in basicTile.TileInteractions)
            {
                if (tileInteraction == null)
                {
                    continue;
                }
                if (tileInteraction.WillInteract(tileApply, NetworkSide.Server))
                {
                    //perform if not on cooldown
                    if (Cooldowns.TryStartServer(tileApply, CommonCooldowns.Instance.Interaction))
                    {
                        tileInteraction.ServerPerformInteraction(tileApply);
                    }
                    else
                    {
                        //hit a cooldown, rollback in case client tried to predict it
                        tileInteraction.ServerRollbackClient(tileApply);
                    }

                    // interaction should've triggered and did or we hit a cooldown, so we're
                    // done processing this request.
                    break;
                }
                else
                {
                    tileInteraction.ServerRollbackClient(tileApply);
                }
            }
        }
    }
예제 #28
0
        // We electrocute the performer in WillInteract() instead of ServerPerformInteraction()
        // because we would like for the performer to be able to perform other interactions
        // if the electrocution was merely mild.
        public override bool WillInteract(TileApply interaction, NetworkSide side)
        {
            this.interaction = interaction;

            if (!DefaultWillInteract.Default(interaction, side))
            {
                return(false);
            }

            // Let only the server continue, as ServerGetGrilleVoltage() depends on the server-side-only electrical system.
            if (side == NetworkSide.Client)
            {
                return(true);
            }

            bool othersWillInteract = false;

            foreach (var otherInteraction in interaction.BasicTile.TileInteractions)
            {
                if (otherInteraction == this)
                {
                    continue;
                }
                if (otherInteraction.WillInteract(interaction, side))
                {
                    othersWillInteract = true;
                    break;
                }
            }

            // If no other grille interactions were available, and the performer intends to harm: attack!
            // This is somewhat of a hack; other interactions should be handled by InteractionUtils,
            // however the server will not process other interactions (only other tile interactions) if this WillInteract()
            // returns true on the client (which it must, as the electrical system runs server-side only).
            // This means attack interactions would be incorrectly ignored.
            if (!othersWillInteract && (interaction.Intent == Intent.Harm || interaction.HandObject != null))
            {
                var matrix   = interaction.TileChangeManager.MetaTileMap.Layers[LayerType.Grills].matrix;
                var weaponNA = interaction.Performer.GetComponent <WeaponNetworkActions>();
                weaponNA.ServerPerformMeleeAttack(
                    matrix.transform.parent.gameObject, interaction.TargetVector, BodyPartType.None, interaction.BasicTile.LayerType);
            }

            return(Electrocute(ServerGetGrilleVoltage()));
        }
        public override void ServerPerformInteraction(TileApply interaction)
        {
            string othersMessage = Chat.ReplacePerformer(othersStartActionMessage, interaction.Performer);

            Chat.AddActionMsgToChat(interaction.Performer, performerStartActionMessage, othersMessage);
            if (interaction.BasicTile.LayerType != LayerType.Underfloor)
            {
                return;
            }

            var ElectricalCable = interaction.BasicTile as ElectricalCableTile;

            if (ElectricalCable == null)
            {
                return;
            }

            var matrix       = interaction.TileChangeManager.MetaTileMap.Layers[LayerType.Underfloor].matrix;
            var metaDataNode = matrix.GetMetaDataNode(interaction.TargetCellPos);

            foreach (var ElectricalData in metaDataNode.ElectricalData)
            {
                if (ElectricalData.RelatedTile != ElectricalCable)
                {
                    continue;
                }

                // Electrocute the performer. If shock is painful enough, cancel the interaction.
                ElectricityFunctions.WorkOutActualNumbers(ElectricalData.InData);
                float voltage       = ElectricalData.InData.Data.ActualVoltage;
                var   electrocution = new Electrocution(voltage, interaction.WorldPositionTarget, "cable");
                var   performerLHB  = interaction.Performer.GetComponent <LivingHealthMasterBase>();
                var   severity      = performerLHB.Electrocute(electrocution);
                if (severity > LivingShockResponse.Mild)
                {
                    return;
                }

                ElectricalData.InData.DestroyThisPlease();
                Spawn.ServerPrefab(ElectricalCable.SpawnOnDeconstruct, interaction.WorldPositionTarget,
                                   count: ElectricalCable.SpawnAmountOnDeconstruct);

                return;
            }
        }
예제 #30
0
 public override void ServerPerformInteraction(TileApply interaction)
 {
     if (interaction.HandObject == null)
     {
         Chat.AddActionMsgToChat(interaction.Performer,
                                 $"You knock on the {interaction.BasicTile.DisplayName}.", $"{interaction.Performer.ExpensiveName()} knocks on the {interaction.BasicTile.DisplayName}.");
         SoundManager.GlassknockAtPosition(interaction.WorldPositionTarget, interaction.Performer);
     }
     else
     {
         ToolUtils.ServerUseToolWithActionMessages(interaction, 4f,
                                                   $"You begin repairing the {interaction.BasicTile.DisplayName}...",
                                                   $"{interaction.Performer.ExpensiveName()} begins to repair the {interaction.BasicTile.DisplayName}...",
                                                   $"You repair the {interaction.BasicTile.DisplayName}.",
                                                   $"{interaction.Performer.ExpensiveName()} repairs the {interaction.BasicTile.DisplayName}.",
                                                   () => RepairWindow(interaction));
     }
 }