public void ServerPerformInteraction(HandApply interaction) { if (MachineParts == null) { return; } //unscrew ToolUtils.ServerUseToolWithActionMessages(interaction, secondsToScrewdrive, "You start to deconstruct the machine...", $"{interaction.Performer.ExpensiveName()} starts to deconstruct the machine...", "You deconstruct the machine.", $"{interaction.Performer.ExpensiveName()} deconstructs the machine.", () => { //drop all our contents ItemStorage itemStorage = null; // rare cases were gameObject is destroyed for some reason and then the method is called if (gameObject != null) { itemStorage = GetComponent <ItemStorage>(); } if (itemStorage != null) { itemStorage.ServerDropAll(); } var frame = Spawn.ServerPrefab(framePrefab, SpawnDestination.At(gameObject)).GameObject; frame.GetComponent <MachineFrame>().ServerInitFromComputer(this); Despawn.ServerSingle(gameObject); }); }
public void WhenDestroyed(DestructionInfo info) { //drop all our contents ItemStorage itemStorage = null; // rare cases were gameObject is destroyed for some reason and then the method is called if (gameObject == null) { return; } itemStorage = GetComponent <ItemStorage>(); if (itemStorage != null) { itemStorage.ServerDropAll(); } var frame = Spawn.ServerPrefab(framePrefab, SpawnDestination.At(gameObject)).GameObject; frame.GetComponent <ComputerFrame>().ServerInitFromComputer(this); _ = Despawn.ServerSingle(gameObject); integrity.OnWillDestroyServer.RemoveListener(WhenDestroyed); }
/// <summary> /// Stage 1, Add cable to continue or welder to destroy frame. /// </summary> /// <param name="interaction"></param> private void InitialStateInteraction(HandApply interaction) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Cable) && Validations.HasUsedAtLeast(interaction, 5)) { //add 5 cables ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding cables to the frame...", $"{interaction.Performer.ExpensiveName()} starts adding cables to the frame...", "You add cables to the frame.", $"{interaction.Performer.ExpensiveName()} adds cables to the frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 5); stateful.ServerChangeState(cablesAddedState); //sprite change spriteRender.sprite = boxCable; ServerChangeSprite(SpriteStates.BoxCable); }); } else if (Validations.HasUsedActiveWelder(interaction)) { //deconsruct ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start deconstructing the frame...", $"{interaction.Performer.ExpensiveName()} starts deconstructing the frame...", "You deconstruct the frame.", $"{interaction.Performer.ExpensiveName()} deconstructs the frame.", () => { Spawn.ServerPrefab(CommonPrefabs.Instance.Metal, SpawnDestination.At(gameObject), 5); Despawn.ServerSingle(gameObject); }); } }
public void WhenDestroyed(DestructionInfo info) { //drop all our contents ItemStorage itemStorage = null; // rare cases were gameObject is destroyed for some reason and then the method is called if (gameObject == null) { return; } itemStorage = GetComponent <ItemStorage>(); if (itemStorage != null) { itemStorage.ServerDropAll(); } SpawnResult frameSpawn = Spawn.ServerPrefab(CommonPrefabs.Instance.MachineFrame, SpawnDestination.At(gameObject)); if (!frameSpawn.Successful) { Logger.LogError($"Failed to spawn frame! Is {this} missing references in the inspector?", Category.Construction); return; } GameObject frame = frameSpawn.GameObject; frame.GetComponent <MachineFrame>().ServerInitFromComputer(this); _ = Despawn.ServerSingle(gameObject); integrity.OnWillDestroyServer.RemoveListener(WhenDestroyed); }
/// <summary> /// Spawns a ghost for the indicated mind's body and transfers the connection's control to it. /// </summary> /// <param name="conn"></param> /// <param name="oldBody"></param> /// <param name="characterSettings"></param> /// <param name="occupation"></param> /// <returns></returns> public static void ServerSpawnGhost(Mind forMind) { if (forMind == null) { Logger.LogError("Mind was null for ServerSpawnGhost", Category.Server); return; } //determine where to spawn the ghost var body = forMind.GetCurrentMob(); if (body == null) { Logger.LogError("Body was null for ServerSpawnGhost", Category.Server); return; } var settings = body.GetComponent <PlayerScript>().characterSettings; var connection = body.GetComponent <NetworkIdentity>().connectionToClient; var registerTile = body.GetComponent <RegisterTile>(); if (registerTile == null) { Logger.LogErrorFormat("Cannot spawn ghost for body {0} because it has no registerTile", Category.ItemSpawn, body.name); return; } Vector3Int spawnPosition = TransformState.HiddenPos; var objBeh = body.GetComponent <ObjectBehaviour>(); if (objBeh != null) { spawnPosition = objBeh.AssumedWorldPositionServer(); } if (spawnPosition == TransformState.HiddenPos) { //spawn ghost at occupation location if we can't determine where their body is Transform spawnTransform = GetSpawnForJob(forMind.occupation.JobType); if (spawnTransform == null) { Logger.LogErrorFormat("Unable to determine spawn position for occupation {1}. Cannot spawn ghost.", Category.ItemSpawn, forMind.occupation.DisplayName); return; } spawnPosition = spawnTransform.transform.position.CutToInt(); } var matrixInfo = MatrixManager.AtPoint(spawnPosition, true); var parentNetId = matrixInfo.NetID; var parentTransform = matrixInfo.Objects; //using parentTransform.rotation rather than Quaternion.identity because objects should always //be upright w.r.t. localRotation, NOT world rotation var ghost = UnityEngine.Object.Instantiate(CustomNetworkManager.Instance.ghostPrefab, spawnPosition, parentTransform.rotation, parentTransform); ghost.GetComponent <PlayerScript>().registerTile.ServerSetNetworkedMatrixNetID(parentNetId); forMind.Ghosting(ghost); ServerTransferPlayer(connection, ghost, body, EVENT.GhostSpawned, settings); //fire all hooks var info = SpawnInfo.Ghost(forMind.occupation, settings, CustomNetworkManager.Instance.ghostPrefab, SpawnDestination.At(spawnPosition, parentTransform)); Spawn._ServerFireClientServerSpawnHooks(SpawnResult.Single(info, ghost)); }
/// <summary> /// Spawns a new player character and transfers the connection's control into the new body. /// If existingMind is null, creates the new mind and assigns it to the new body. /// /// Fires server and client side player spawn hooks. /// </summary> /// <param name="connection">connection to give control to the new player character</param> /// <param name="occupation">occupation of the new player character</param> /// <param name="characterSettings">settings of the new player character</param> /// <param name="existingMind">existing mind to transfer to the new player, if null new mind will be created /// and assigned to the new player character</param> /// <param name="spawnPos">world position to spawn at</param> /// <param name="spawnItems">If spawning a player, should the player spawn without the defined initial equipment for their occupation?</param> /// <param name="willDestroyOldBody">if true, indicates the old body is going to be destroyed rather than pooled, /// thus we shouldn't send any network message which reference's the old body's ID since it won't exist.</param> /// /// <returns>the spawned object</returns> private static GameObject ServerSpawnInternal(NetworkConnection connection, Occupation occupation, CharacterSettings characterSettings, Mind existingMind, Vector3Int?spawnPos = null, bool spawnItems = true, bool willDestroyOldBody = false) { //determine where to spawn them if (spawnPos == null) { Transform spawnTransform; //Spawn normal location for special jobs or if less than 2 minutes passed if (GameManager.Instance.stationTime < ARRIVALS_SPAWN_TIME || occupation.LateSpawnIsArrivals == false) { spawnTransform = GetSpawnForJob(occupation.JobType); } else { spawnTransform = GetSpawnForLateJoin(occupation.JobType); //Fallback to assistant spawn location if none found for late join if (spawnTransform == null && occupation.JobType != JobType.NULL) { spawnTransform = GetSpawnForJob(JobType.ASSISTANT); } } if (spawnTransform == null) { Logger.LogErrorFormat( "Unable to determine spawn position for connection {0} occupation {1}. Cannot spawn player.", Category.ItemSpawn, connection.address, occupation.DisplayName); return(null); } spawnPos = spawnTransform.transform.position.CutToInt(); } //create the player object var newPlayer = ServerCreatePlayer(spawnPos.GetValueOrDefault()); var newPlayerScript = newPlayer.GetComponent <PlayerScript>(); //get the old body if they have one. var oldBody = existingMind?.GetCurrentMob(); //transfer control to the player object ServerTransferPlayer(connection, newPlayer, oldBody, EVENT.PlayerSpawned, characterSettings, willDestroyOldBody); if (existingMind == null) { //create the mind of the player Mind.Create(newPlayer, occupation); } else { //transfer the mind to the new body existingMind.SetNewBody(newPlayerScript); } var ps = newPlayer.GetComponent <PlayerScript>(); var connectedPlayer = PlayerList.Instance.Get(connection); connectedPlayer.Name = ps.playerName; connectedPlayer.Job = ps.mind.occupation.JobType; UpdateConnectedPlayersMessage.Send(); //fire all hooks var info = SpawnInfo.Player(occupation, characterSettings, CustomNetworkManager.Instance.humanPlayerPrefab, SpawnDestination.At(spawnPos), spawnItems: spawnItems); Spawn._ServerFireClientServerSpawnHooks(SpawnResult.Single(info, newPlayer)); return(newPlayer); }
public void ServerPerformInteraction(HandApply interaction) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { if (coverOpen) { coverOpen = false; if (activated) { stateSync = FireAlarmState.TopLightSpriteAlert; } else { stateSync = FireAlarmState.TopLightSpriteNormal; } } else { coverOpen = true; if (hasCables) { stateSync = FireAlarmState.OpenCabledSprite; } else { stateSync = FireAlarmState.OpenEmptySprite; } } ToolUtils.ServerPlayToolSound(interaction); return; } if (coverOpen) { if (hasCables && Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wirecutter)) { //cut out cables Chat.AddActionMsgToChat(interaction, $"You remove the cables.", $"{interaction.Performer.ExpensiveName()} removes the cables."); ToolUtils.ServerPlayToolSound(interaction); Spawn.ServerPrefab(CommonPrefabs.Instance.SingleCableCoil, SpawnDestination.At(gameObject), 5); stateSync = FireAlarmState.OpenEmptySprite; hasCables = false; activated = false; return; } if (!hasCables && Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Cable) && Validations.HasUsedAtLeast(interaction, 5)) { //add 5 cables ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding cables to the frame...", $"{interaction.Performer.ExpensiveName()} starts adding cables to the frame...", "You add cables to the frame.", $"{interaction.Performer.ExpensiveName()} adds cables to the frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 5); hasCables = true; stateSync = FireAlarmState.OpenCabledSprite; }); } } else { InternalToggleState(); } }
public void ServerPerformInteraction(HandApply interaction) { if (CurrentState == initialState) { if (objectBehaviour.IsPushable) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) { if (!ServerValidations.IsAnchorBlocked(interaction)) { //wrench in place ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start wrenching the frame into place...", $"{interaction.Performer.ExpensiveName()} starts wrenching the frame into place...", "You wrench the frame into place.", $"{interaction.Performer.ExpensiveName()} wrenches the frame into place.", () => objectBehaviour.ServerSetAnchored(true, interaction.Performer)); } } else if (Validations.HasUsedActiveWelder(interaction)) { //deconsruct ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start deconstructing the frame...", $"{interaction.Performer.ExpensiveName()} starts deconstructing the frame...", "You deconstruct the frame.", $"{interaction.Performer.ExpensiveName()} deconstructs the frame.", () => { Spawn.ServerPrefab(CommonPrefabs.Instance.Metal, SpawnDestination.At(gameObject), 5); _ = Despawn.ServerSingle(gameObject); }); } } else { //already wrenched in place if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) { //unwrench ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start to unfasten the frame...", $"{interaction.Performer.ExpensiveName()} starts to unfasten the frame...", "You unfasten the frame.", $"{interaction.Performer.ExpensiveName()} unfastens the frame.", () => objectBehaviour.ServerSetAnchored(false, interaction.Performer)); } else if (Validations.HasUsedComponent <ComputerCircuitboard>(interaction) && circuitBoardSlot.IsEmpty) { //stick in the circuit board Chat.AddActionMsgToChat(interaction, $"You place the {interaction.UsedObject.ExpensiveName()} inside the frame.", $"{interaction.Performer.ExpensiveName()} places the {interaction.UsedObject.ExpensiveName()} inside the frame."); Inventory.ServerTransfer(interaction.HandSlot, circuitBoardSlot); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver) && circuitBoardSlot.IsOccupied) { //screw in the circuit board Chat.AddActionMsgToChat(interaction, $"You screw {circuitBoardSlot.ItemObject.ExpensiveName()} into place.", $"{interaction.Performer.ExpensiveName()} screws {circuitBoardSlot.ItemObject.ExpensiveName()} into place."); ToolUtils.ServerPlayToolSound(interaction); stateful.ServerChangeState(circuitScrewedState); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar) && circuitBoardSlot.IsOccupied) { //wrench out the circuit board Chat.AddActionMsgToChat(interaction, $"You remove the {circuitBoardSlot.ItemObject.ExpensiveName()} from the frame.", $"{interaction.Performer.ExpensiveName()} removes the {circuitBoardSlot.ItemObject.ExpensiveName()} from the frame."); ToolUtils.ServerPlayToolSound(interaction); Inventory.ServerDrop(circuitBoardSlot); } } } else if (CurrentState == circuitScrewedState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //unscrew circuit board Chat.AddActionMsgToChat(interaction, $"You unfasten the circuit board.", $"{interaction.Performer.ExpensiveName()} unfastens the circuit board."); ToolUtils.ServerPlayToolSound(interaction); stateful.ServerChangeState(initialState); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Cable) && Validations.HasUsedAtLeast(interaction, 5)) { //add 5 cables ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding cables to the frame...", $"{interaction.Performer.ExpensiveName()} starts adding cables to the frame...", "You add cables to the frame.", $"{interaction.Performer.ExpensiveName()} adds cables to the frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 5); stateful.ServerChangeState(cablesAddedState); }); } } else if (CurrentState == cablesAddedState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wirecutter)) { //cut out cables Chat.AddActionMsgToChat(interaction, $"You remove the cables.", $"{interaction.Performer.ExpensiveName()} removes the cables."); ToolUtils.ServerPlayToolSound(interaction); Spawn.ServerPrefab(CommonPrefabs.Instance.SingleCableCoil, SpawnDestination.At(gameObject), 5); stateful.ServerChangeState(circuitScrewedState); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.GlassSheet) && Validations.HasUsedAtLeast(interaction, 2)) { //add glass ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start to put in the glass panel...", $"{interaction.Performer.ExpensiveName()} starts to put in the glass panel...", "You put in the glass panel.", $"{interaction.Performer.ExpensiveName()} puts in the glass panel.", () => { Inventory.ServerConsume(interaction.HandSlot, 2); stateful.ServerChangeState(glassAddedState); }); } } else if (CurrentState == glassAddedState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //screw in monitor, completing construction Chat.AddActionMsgToChat(interaction, $"You connect the monitor.", $"{interaction.Performer.ExpensiveName()} connects the monitor."); ToolUtils.ServerPlayToolSound(interaction); var circuitBoard = circuitBoardSlot.ItemObject?.GetComponent <ComputerCircuitboard>(); if (circuitBoard == null) { Logger.LogWarningFormat("Cannot complete computer, circuit board not in frame {0}. Probably a coding error.", Category.Construction, name); return; } Spawn.ServerPrefab(circuitBoard.ComputerToSpawn, SpawnDestination.At(gameObject)); _ = Despawn.ServerSingle(gameObject); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar)) { //remove glass Chat.AddActionMsgToChat(interaction, $"You remove the glass panel.", $"{interaction.Performer.ExpensiveName()} removes the glass panel."); ToolUtils.ServerPlayToolSound(interaction); Spawn.ServerPrefab(CommonPrefabs.Instance.GlassSheet, SpawnDestination.At(gameObject), 2); stateful.ServerChangeState(cablesAddedState); } } }
/// <summary> /// Stage 5, complete construction, or remove board and return to stage 3. /// </summary> /// <param name="interaction"></param> private void PartsAddedStateInteraction(HandApply interaction) { //Complete construction, spawn new machine and send data over to it. if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { var spawnedObject = Spawn.ServerPrefab(machineParts.machine, SpawnDestination.At(gameObject)).GameObject.GetComponent <Machine>(); if (spawnedObject == null) { Logger.LogWarning(machineParts.machine + " is missing the machine script!", Category.ItemSpawn); return; } //Send circuit board data to the new machine spawnedObject.SetBasicPartsUsed(basicPartsUsed); spawnedObject.SetPartsInFrame(partsInFrame); spawnedObject.SetMachineParts(machineParts); //Despawn frame Despawn.ServerSingle(gameObject); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar) && circuitBoardSlot.IsOccupied) { //wrench out the circuit board, when it has all the parts in. Chat.AddActionMsgToChat(interaction, $"You remove the {circuitBoardSlot.ItemObject.ExpensiveName()} from the frame.", $"{interaction.Performer.ExpensiveName()} removes the {circuitBoardSlot.ItemObject.ExpensiveName()} from the frame."); ToolUtils.ServerPlayToolSound(interaction); Inventory.ServerDrop(circuitBoardSlot); stateful.ServerChangeState(wrenchedState); //If frame in mapped; count == 0 and its the only time putBoardInManually will be false as putting in board makes it true if (partsInFrame.Count == 0 && !putBoardInManually) { foreach (var part in machineParts.machineParts) { Spawn.ServerPrefab(part.basicItem, gameObject.WorldPosServer(), gameObject.transform.parent, count: part.amountOfThisPart); } } else { foreach (var item in partsInFrame) //Moves the hidden objects back on to the gameobject. { if (item.Key == null) //Shouldnt ever happen, but just incase { continue; } var pos = gameObject.GetComponent <CustomNetTransform>().ServerPosition; item.Key.GetComponent <CustomNetTransform>().AppearAtPositionServer(pos); } } putBoardInManually = false; //Sprite change spriteRender.sprite = boxCable; ServerChangeSprite(SpriteStates.BoxCable); //Reset data partsInFrame.Clear(); basicPartsUsed.Clear(); } }
/// <summary> /// Clone the item and syncs it over the network. This only works if toClone has a PoolPrefabTracker /// attached or its name matches a prefab name, otherwise we don't know what prefab to create. /// </summary> /// <param name="toClone">GameObject to clone. This only works if toClone has a PoolPrefabTracker /// attached or its name matches a prefab name, otherwise we don't know what prefab to create.. Intended to work for any object, but don't /// be surprised if it doesn't as there are LOTS of prefabs in the game which might need unique behavior for how they should spawn. If you are trying /// to clone something and it isn't properly setting itself up, check to make sure each component that needs to set something up has /// properly implemented IOnStageServer or IOnStageClient when IsCloned = true</param> /// <param name="worldPosition">world position to appear at. Defaults to HiddenPos (hidden / invisible)</param> /// <param name="localRotation">local rotation to spawn with, defaults to Quaternion.identity</param> /// <param name="parent">Parent to spawn under, defaults to no parent. Most things /// should always be spawned under the Objects transform in their matrix. Many objects (due to RegisterTile) /// usually take care of properly parenting themselves when spawned so in many cases you can leave it null.</param> /// <returns>the newly created GameObject</returns> public static SpawnResult ServerClone(GameObject toClone, Vector3?worldPosition = null, Transform parent = null, Quaternion?localRotation = null) { return(Server( SpawnInfo.Clone(toClone, SpawnDestination.At(worldPosition, parent, localRotation)))); }
public override IEnumerator Process() { var clientStorage = SentByPlayer.Script.ItemStorage; var usedSlot = clientStorage.GetActiveHandSlot(); if (usedSlot == null || usedSlot.ItemObject == null) { yield break; } var hasConstructionMenu = usedSlot.ItemObject.GetComponent <BuildingMaterial>(); if (hasConstructionMenu == null) { yield break; } var entry = hasConstructionMenu.BuildList.Entries.ToArray()[EntryIndex]; if (!entry.CanBuildWith(hasConstructionMenu)) { yield break; } //check if the space to construct on is passable if (!MatrixManager.IsPassableAt((Vector3Int)SentByPlayer.GameObject.TileWorldPosition(), true, includingPlayers: false)) { Chat.AddExamineMsg(SentByPlayer.GameObject, "It won't fit here."); yield break; } //if we are building something impassable, check if there is anything on the space other than the performer. var atPosition = MatrixManager.GetAt <RegisterTile>((Vector3Int)SentByPlayer.GameObject.TileWorldPosition(), true); if (entry.Prefab == null) { //requires immediate attention, show it regardless of log filter: Logger.Log($"Construction entry is missing prefab for {entry.Name}"); yield break; } var registerTile = entry.Prefab.GetComponent <RegisterTile>(); if (registerTile == null) { Logger.LogWarningFormat("Buildable prefab {0} has no registerTile, no idea if it's passable", Category.Construction, entry.Prefab); } var builtObjectIsImpassable = registerTile == null || !registerTile.IsPassable(true); foreach (var thingAtPosition in atPosition) { if (entry.OnePerTile) { //can only build one of this on a given tile if (entry.Prefab.Equals(Spawn.DeterminePrefab(thingAtPosition.gameObject))) { Chat.AddExamineMsg(SentByPlayer.GameObject, $"There's already one here."); yield break; } } if (builtObjectIsImpassable) { //if the object we are building is itself impassable, we should check if anything blocks construciton. //otherwise it's fine to add it to the pile on the tile if (ServerValidations.IsConstructionBlocked(SentByPlayer.GameObject, null, SentByPlayer.GameObject.TileWorldPosition())) { yield break; } } } //build and consume void ProgressComplete() { if (entry.ServerBuild(SpawnDestination.At(SentByPlayer.Script.registerTile), hasConstructionMenu)) { Chat.AddActionMsgToChat(SentByPlayer.GameObject, $"You finish building the {entry.Name}.", $"{SentByPlayer.GameObject.ExpensiveName()} finishes building the {entry.Name}."); } } Chat.AddActionMsgToChat(SentByPlayer.GameObject, $"You begin building the {entry.Name}...", $"{SentByPlayer.GameObject.ExpensiveName()} begins building the {entry.Name}..."); ToolUtils.ServerUseTool(SentByPlayer.GameObject, usedSlot.ItemObject, ActionTarget.Tile(SentByPlayer.Script.registerTile.WorldPositionServer), entry.BuildTime, ProgressComplete); }
private void DeconstructBelt() { Spawn.ServerPrefab(CommonPrefabs.Instance.Metal, SpawnDestination.At(gameObject), 5); Despawn.ServerSingle(gameObject); }
private float AddDamage(float damage, AttackType attackType, MetaDataNode data, BasicTile basicTile, Vector3 worldPosition) { if (basicTile.indestructible || damage < basicTile.damageDeflection) { return(0); } var damageTaken = basicTile.Armor.GetDamage(damage < basicTile.damageDeflection ? 0 : damage, attackType); data.AddTileDamage(Layer.LayerType, damageTaken); if (basicTile.SoundOnHit != null && !string.IsNullOrEmpty(basicTile.SoundOnHit.AssetAddress) && basicTile.SoundOnHit.AssetAddress != "null") { if (damage >= 1) { SoundManager.PlayNetworkedAtPos(basicTile.SoundOnHit, worldPosition); } } var totalDamageTaken = data.GetTileDamage(Layer.LayerType); if (totalDamageTaken >= basicTile.MaxHealth) { if (basicTile.SoundOnDestroy.Count > 0) { SoundManager.PlayNetworkedAtPos(basicTile.SoundOnDestroy.RandomElement(), worldPosition); } data.RemoveTileDamage(Layer.LayerType); tileChangeManager.RemoveTile(data.Position, Layer.LayerType); tileChangeManager.RemoveOverlaysOfType(data.Position, LayerType.Effects, TileChangeManager.OverlayType.Damage); if (Layer.LayerType == LayerType.Floors || Layer.LayerType == LayerType.Base) { tileChangeManager.RemoveOverlaysOfType(data.Position, LayerType.Floors, TileChangeManager.OverlayType.Cleanable); } if (Layer.LayerType == LayerType.Walls) { tileChangeManager.RemoveOverlaysOfType(data.Position, LayerType.Walls, TileChangeManager.OverlayType.Cleanable); } //Add new tile if needed //TODO change floors to using overlays, but generic overlay will need to be sprited if (basicTile.ToTileWhenDestroyed != null) { var damageLeft = totalDamageTaken - basicTile.MaxHealth; var tile = basicTile.ToTileWhenDestroyed as BasicTile; var overFlowProtection = 0; while (damageLeft > 0 && tile != null) { overFlowProtection++; if (tile.MaxHealth <= damageLeft) { damageLeft -= tile.MaxHealth; tile = tile.ToTileWhenDestroyed as BasicTile; } else { //Atm we just set remaining damage to 0, instead of absorbing it for the new tile damageLeft = 0; tileChangeManager.UpdateTile(data.Position, tile); break; } if (overFlowProtection > maxOverflowProtection) { Logger.LogError($"Overflow protection triggered on {basicTile.name}, ToTileWhenDestroyed is spawning tiles in a loop", Category.TileMaps); break; } } damageTaken = damageLeft; } if (basicTile.SpawnOnDestroy != null) { basicTile.SpawnOnDestroy.SpawnAt(SpawnDestination.At(worldPosition, metaTileMap.ObjectLayer.gameObject.transform)); } basicTile.LootOnDespawn?.SpawnLoot(worldPosition); } else { if (basicTile.DamageOverlayList != null) { foreach (var overlayData in basicTile.DamageOverlayList.DamageOverlays) { if (overlayData.damagePercentage <= totalDamageTaken / basicTile.MaxHealth) { tileChangeManager.AddOverlay(data.Position, overlayData.overlayTile); break; } } } //All the damage was absorbed, none left to return for next layer damageTaken = 0; } if (basicTile.MaxHealth < basicTile.MaxHealth - totalDamageTaken) { data.ResetDamage(Layer.LayerType); } if (damageTaken > totalDamageTaken) { Logger.LogError($"Applying damage to {basicTile.DisplayName} increased the damage to be dealt, when it should have decreased!", Category.Damage); return(totalDamageTaken); } //Return how much damage is left return(damageTaken); }
public void ServerPerformInteraction(HandApply interaction) { if (stateSync == MountedMonitorState.OpenCabled || stateSync == MountedMonitorState.OpenEmpty) { if (!hasCables && Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Cable) && Validations.HasUsedAtLeast(interaction, 5)) { //add 5 cables ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding cables to the frame...", $"{interaction.Performer.ExpensiveName()} starts adding cables to the frame...", "You add cables to the frame.", $"{interaction.Performer.ExpensiveName()} adds cables to the frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 5); hasCables = true; stateSync = MountedMonitorState.OpenCabled; }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.GlassSheet) && Validations.HasUsedAtLeast(interaction, 2)) { //add 2 glass ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start to put in the glass panel...", $"{interaction.Performer.ExpensiveName()} starts to put in the glass panel...", "You put in the glass panel.", $"{interaction.Performer.ExpensiveName()} puts in the glass panel.", () => { Inventory.ServerConsume(interaction.HandSlot, 2); stateSync = MountedMonitorState.NonScrewedPanel; }); } else if (hasCables && Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wirecutter)) { //cut out cables Chat.AddActionMsgToChat(interaction, $"You remove the cables.", $"{interaction.Performer.ExpensiveName()} removes the cables."); ToolUtils.ServerPlayToolSound(interaction); Spawn.ServerPrefab(CommonPrefabs.Instance.SingleCableCoil, SpawnDestination.At(gameObject), 5); stateSync = MountedMonitorState.OpenEmpty; hasCables = false; currentTimerSeconds = 0; doorControllers.Clear(); NewdoorControllers.Clear(); } } else if (stateSync == MountedMonitorState.NonScrewedPanel) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar)) { //remove glass Chat.AddActionMsgToChat(interaction, $"You remove the glass panel.", $"{interaction.Performer.ExpensiveName()} removes the glass panel."); ToolUtils.ServerPlayToolSound(interaction); Spawn.ServerPrefab(CommonPrefabs.Instance.GlassSheet, SpawnDestination.At(gameObject), 2); if (hasCables) { stateSync = MountedMonitorState.OpenCabled; } else { stateSync = MountedMonitorState.OpenEmpty; } } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //screw in monitor, completing construction Chat.AddActionMsgToChat(interaction, $"You connect the monitor.", $"{interaction.Performer.ExpensiveName()} connects the monitor."); ToolUtils.ServerPlayToolSound(interaction); if (hasCables) { stateSync = MountedMonitorState.StatusText; } } } else { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //disconnect the monitor Chat.AddActionMsgToChat(interaction, $"You disconnect the monitor.", $"{interaction.Performer.ExpensiveName()} disconnect the monitor."); ToolUtils.ServerPlayToolSound(interaction); stateSync = MountedMonitorState.NonScrewedPanel; } else if (stateSync == MountedMonitorState.Image) { ChangeChannelMessage(interaction); stateSync = MountedMonitorState.StatusText; } else if (stateSync == MountedMonitorState.StatusText) { if (channel == StatusDisplayChannel.DoorTimer) { if (AccessRestrictions == null || AccessRestrictions.CheckAccess(interaction.Performer)) { AddTime(60); } else { Chat.AddExamineMsg(interaction.Performer, $"Access Denied."); // Play sound SoundManager.PlayNetworkedAtPos(CommonSounds.Instance.AccessDenied, gameObject.AssumedWorldPosServer(), sourceObj: gameObject); } } else { ChangeChannelMessage(interaction); stateSync = MountedMonitorState.Image; } } } }
public void ServerPerformInteraction(HandApply interaction) { //Anchor or disassemble if (CurrentState == initialState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) { if (ServerValidations.IsAnchorBlocked(interaction) == false) { //wrench in place ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start wrenching the Ai core frame into place...", $"{interaction.Performer.ExpensiveName()} starts wrenching the Ai core frame into place...", "You wrench the Ai core frame into place.", $"{interaction.Performer.ExpensiveName()} wrenches the Ai core frame into place.", () => { objectBehaviour.ServerSetAnchored(true, interaction.Performer); stateful.ServerChangeState(anchoredState); }); return; } Chat.AddExamineMsgFromServer(interaction.Performer, "Unable to anchor Ai core frame here"); } else if (Validations.HasUsedActiveWelder(interaction)) { //Deconstruct ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start deconstructing the Ai core frame...", $"{interaction.Performer.ExpensiveName()} starts deconstructing the Ai core frame...", "You deconstruct the Ai core frame.", $"{interaction.Performer.ExpensiveName()} deconstructs the Ai core frame.", () => { Spawn.ServerPrefab(CommonPrefabs.Instance.Plasteel, SpawnDestination.At(gameObject), 5); _ = Despawn.ServerSingle(gameObject); }); } return; } //Adding Circuit board or unanchor if (CurrentState == anchoredState) { if (Validations.HasUsedItemTrait(interaction, aiCoreCircuitBoardTrait)) { //Add Circuit board ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding the circuit board to the Ai core frame...", $"{interaction.Performer.ExpensiveName()} starts adding a circuit board to the Ai core frame...", "You add a circuit board to the Ai core frame.", $"{interaction.Performer.ExpensiveName()} adds a circuit board to the Ai core frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 1); stateful.ServerChangeState(circuitAddedState); spriteHandler.ChangeSprite(1); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) { //Unanchor ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start unwrenching the Ai core frame from the floor...", $"{interaction.Performer.ExpensiveName()} starts unwrenching the Ai core frame from the floor...", "You unwrench the Ai core frame from the floor.", $"{interaction.Performer.ExpensiveName()} unwrenches the Ai core frame from the floor.", () => { objectBehaviour.ServerSetAnchored(false, interaction.Performer); stateful.ServerChangeState(initialState); }); } return; } //Screwdriver or remove Circuit board if (CurrentState == circuitAddedState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //Screwdriver ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start screwing in the circuit board...", $"{interaction.Performer.ExpensiveName()} starts screwing in the circuit board...", "You screw in the circuit board.", $"{interaction.Performer.ExpensiveName()} screws in the circuit board.", () => { stateful.ServerChangeState(screwState); spriteHandler.ChangeSprite(2); }); } else if (interaction.HandObject == null) { //Remove Circuit board Chat.AddActionMsgToChat(interaction, "You remove the circuit board from the frame", $"{interaction.Performer.ExpensiveName()} removes the circuit board from the frame"); Spawn.ServerPrefab(aiCoreCircuitBoardPrefab, SpawnDestination.At(gameObject)); stateful.ServerChangeState(anchoredState); spriteHandler.ChangeSprite(0); } return; } //Add wire or unscrew if (CurrentState == screwState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Cable)) { //Add wire ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding wire to the Ai core frame...", $"{interaction.Performer.ExpensiveName()} starts adding wire to the Ai core frame...", "You add wire to the Ai core frame.", $"{interaction.Performer.ExpensiveName()} adds wire to the Ai core frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 1); stateful.ServerChangeState(wireAddedState); spriteHandler.ChangeSprite(3); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //Remove unscrew ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start unscrewing in the circuit board...", $"{interaction.Performer.ExpensiveName()} starts unscrewing in the circuit board...", "You remove unscrew the circuit board.", $"{interaction.Performer.ExpensiveName()} unscrews the circuit board.", () => { stateful.ServerChangeState(circuitAddedState); spriteHandler.ChangeSprite(1); }); } return; } //Add brain, or skip brain and add reinforced glass or remove wire if (CurrentState == wireAddedState) { //TODO add brain adding interaction // if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.brain)) // { // //Add brain // Chat.AddActionMsgToChat(interaction, $"You place the {interaction.UsedObject.ExpensiveName()} inside the turret frame.", // $"{interaction.Performer.ExpensiveName()} places the {interaction.UsedObject.ExpensiveName()} inside the turret frame."); // _ = Despawn.ServerSingle(interaction.UsedObject); // stateful.ServerChangeState(brainAddedState); // spriteHandler.ChangeSprite(4); // } /*else */ if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.ReinforcedGlassSheet)) { //Skip adding brain and add reinforced glass straight away instead if (Validations.HasUsedAtLeast(interaction, 2) == false) { Chat.AddExamineMsgFromServer(interaction.Performer, "You need to use 2 reinforced glass sheets"); return; } ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding the reinforced glass to the front of the Ai core...", $"{interaction.Performer.ExpensiveName()} starts add reinforced glass to the front of the Ai core...", "You add reinforced glass to the front of the Ai core.", $"{interaction.Performer.ExpensiveName()} adds reinforced glass to the front of the Ai core.", () => { Inventory.ServerConsume(interaction.HandSlot, 2); stateful.ServerChangeState(glassState); spriteHandler.ChangeSprite(5); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wirecutter)) { //Remove wire ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start cutting out the wire...", $"{interaction.Performer.ExpensiveName()} starts cutting out the wire...", "You cut out the wire.", $"{interaction.Performer.ExpensiveName()} cuts out the wire.", () => { Spawn.ServerPrefab(CommonPrefabs.Instance.SingleCableCoil, SpawnDestination.At(gameObject), 1); stateful.ServerChangeState(screwState); spriteHandler.ChangeSprite(2); }); } return; } //Add reinforced glass or remove brain if (CurrentState == brainAddedState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.ReinforcedGlassSheet)) { //Add reinforced glass if (Validations.HasUsedAtLeast(interaction, 2) == false) { Chat.AddExamineMsgFromServer(interaction.Performer, "You need to use 2 reinforced glass sheets"); return; } ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding the reinforced glass to the front of the Ai core...", $"{interaction.Performer.ExpensiveName()} starts add reinforced glass to the front of the Ai core...", "You add reinforced glass to the front of the Ai core.", $"{interaction.Performer.ExpensiveName()} adds reinforced glass to the front of the Ai core.", () => { Inventory.ServerConsume(interaction.HandSlot, 2); stateful.ServerChangeState(glassState); spriteHandler.ChangeSprite(5); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar)) { //Remove brain ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start removing the MMI/Positron Brain from the Ai core...", $"{interaction.Performer.ExpensiveName()} starts removing the MMI/Positron Brain from the Ai core...", "You remove the MMI/Positron Brain from the Ai core.", $"{interaction.Performer.ExpensiveName()} removes the MMI/Positron Brain from the Ai core.", () => { //TODO remove brain logic stateful.ServerChangeState(wireAddedState); spriteHandler.ChangeSprite(3); }); } return; } //Screw to finish or remove glass if (CurrentState == glassState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //Finish ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start screwing in the glass to the frame...", $"{interaction.Performer.ExpensiveName()} starts screwing in the glass to the frame...", "You screw in the glass to the frame.", $"{interaction.Performer.ExpensiveName()} screws in the glass to the frame.", () => { var newCore = Spawn.ServerPrefab(aiCorePrefab, SpawnDestination.At(gameObject), 1); if (newCore.Successful) { //TODO set up ai core when we have brain newCore.GameObject.GetComponent <AiVessel>().SetLinkedPlayer(null); } _ = Despawn.ServerSingle(gameObject); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar)) { //Crowbar out glass ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start removing the reinforced glass from the Ai core frame...", $"{interaction.Performer.ExpensiveName()} starts removing removing the reinforced glass from the Ai core frame...", "You remove the reinforced glass from the Ai core frame.", $"{interaction.Performer.ExpensiveName()} removes the reinforced glass from the Ai core frame.", () => { //TODO check for brain // if () // { // stateful.ServerChangeState(brainAddedState); // spriteHandler.ChangeSprite(4); // return; // } Spawn.ServerPrefab(CommonPrefabs.Instance.ReinforcedGlassSheet, SpawnDestination.At(gameObject), 2); stateful.ServerChangeState(wireAddedState); spriteHandler.ChangeSprite(3); }); } } }
/// <summary> /// FOR DEV / TESTING ONLY! Simulates destroying and recreating an item by putting it in the pool and taking it back /// out again. If item is not pooled, simply destroys and recreates it as if calling Despawn and then Spawn /// Can use this to validate that the object correctly re-initializes itself after spawning - /// no state should be left over from its previous incarnation. /// </summary> /// <returns>the re-created object</returns> public static GameObject ServerPoolTestRespawn(GameObject target) { var poolPrefabTracker = target.GetComponent <PoolPrefabTracker>(); if (poolPrefabTracker == null) { //destroy / create using normal approach with no pooling Logger.LogWarningFormat("Object {0} has no pool prefab tracker, thus cannot be pooled. It will be destroyed / created" + " without going through the pool.", Category.ItemSpawn, target.name); //determine prefab var position = target.TileWorldPosition(); var prefab = DeterminePrefab(target); if (prefab == null) { Logger.LogErrorFormat("Object {0} at {1} cannot be respawned because it has no PoolPrefabTracker and its name" + " does not match a prefab name, so we cannot" + " determine the prefab to instantiate. Please fix this object so that it" + " has an attached PoolPrefabTracker or so its name matches the prefab it was created from.", Category.ItemSpawn, target.name, position); return(null); } Despawn.ServerSingle(target); return(ServerPrefab(prefab, position.To3Int()).GameObject); } else { //destroy / create with pooling //save previous position var destination = SpawnDestination.At(target); var worldPos = target.TileWorldPosition(); var transform = target.GetComponent <IPushable>(); var prevParent = target.transform.parent; //this simulates going into the pool Despawn._ServerFireDespawnHooks(DespawnResult.Single(DespawnInfo.Single(target))); if (transform != null) { transform.VisibleState = false; } //this simulates coming back out of the pool target.SetActive(true); target.transform.parent = prevParent; target.transform.position = worldPos.To3Int(); var cnt = target.GetComponent <CustomNetTransform>(); if (cnt) { cnt.ReInitServerState(); cnt.NotifyPlayers(); //Sending out clientState for already spawned items } var prefab = DeterminePrefab(target); SpawnInfo spawnInfo = SpawnInfo.Spawnable( SpawnablePrefab.For(prefab), destination); _ServerFireClientServerSpawnHooks(SpawnResult.Single(spawnInfo, target)); return(target); } }
public void ServerPerformInteraction(HandApply interaction) { //Anchor or disassemble if (CurrentState == initialState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) { if (!ServerValidations.IsAnchorBlocked(interaction)) { //wrench in place ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start wrenching the turret frame into place...", $"{interaction.Performer.ExpensiveName()} starts wrenching the turret frame into place...", "You wrench the turret frame into place.", $"{interaction.Performer.ExpensiveName()} wrenches the turret frame into place.", () => { objectBehaviour.ServerSetAnchored(true, interaction.Performer); stateful.ServerChangeState(anchoredState); }); return; } Chat.AddExamineMsgFromServer(interaction.Performer, "Unable to anchor turret frame here"); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar)) { //deconstruct ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start deconstructing the turret frame...", $"{interaction.Performer.ExpensiveName()} starts deconstructing the turret frame...", "You deconstruct the turret frame.", $"{interaction.Performer.ExpensiveName()} deconstructs the turret frame.", () => { Spawn.ServerPrefab(CommonPrefabs.Instance.Metal, SpawnDestination.At(gameObject), 5); _ = Despawn.ServerSingle(gameObject); }); } return; } //Adding metal or unanchor if (CurrentState == anchoredState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.MetalSheet)) { //Add metal ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding a metal cover to the turret frame...", $"{interaction.Performer.ExpensiveName()} starts adding a metal cover to the turret frame...", "You add a metal cover to the turret frame.", $"{interaction.Performer.ExpensiveName()} adds a metal cover to the turret frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 1); stateful.ServerChangeState(metalAddedState); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) { //Unanchor ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start unwrenching the turret frame from the floor...", $"{interaction.Performer.ExpensiveName()} starts unwrenching the turret frame from the floor...", "You unwrench the turret frame from the floor.", $"{interaction.Performer.ExpensiveName()} unwrenches the turret frame from the floor.", () => { objectBehaviour.ServerSetAnchored(false, interaction.Performer); stateful.ServerChangeState(initialState); }); } return; } //Wrench or remove metal if (CurrentState == metalAddedState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) { //Wrench ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start wrenching the bolts on the turret frame...", $"{interaction.Performer.ExpensiveName()} starts wrenching the bolts on the turret frame...", "You wrench the bolts on the turret frame.", $"{interaction.Performer.ExpensiveName()} wrenches the bolts on the turret frame.", () => { stateful.ServerChangeState(wrenchState); }); } else if (Validations.HasUsedActiveWelder(interaction)) { //Remove metal ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start removing the metal cover from the turret frame...", $"{interaction.Performer.ExpensiveName()} starts removing the metal cover from the turret frame...", "You remove the metal cover from the turret frame.", $"{interaction.Performer.ExpensiveName()} removes the metal cover from the turret frame.", () => { Spawn.ServerPrefab(CommonPrefabs.Instance.Metal, SpawnDestination.At(gameObject), 1); stateful.ServerChangeState(anchoredState); }); } return; } //Add gun or unwrench if (CurrentState == wrenchState) { if (Validations.HasUsedItemTrait(interaction, gunTrait)) { //Add energy gun Chat.AddActionMsgToChat(interaction, $"You place the {interaction.UsedObject.ExpensiveName()} inside the turret frame.", $"{interaction.Performer.ExpensiveName()} places the {interaction.UsedObject.ExpensiveName()} inside the turret frame."); Inventory.ServerTransfer(interaction.HandSlot, gunSlot); stateful.ServerChangeState(gunAddedState); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) { //Remove unwrench bolts ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start removing the bolts from the turret frame...", $"{interaction.Performer.ExpensiveName()} starts removing the bolts from the turret frame...", "You remove the bolts from the turret frame.", $"{interaction.Performer.ExpensiveName()} removes the bolts from the turret frame.", () => { stateful.ServerChangeState(metalAddedState); }); } return; } //Add prox or remove gun if (CurrentState == gunAddedState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.ProximitySensor)) { //Add proximity sensor Chat.AddActionMsgToChat(interaction, $"You place the {interaction.UsedObject.ExpensiveName()} inside the turret frame.", $"{interaction.Performer.ExpensiveName()} places the {interaction.UsedObject.ExpensiveName()} inside the turret frame."); _ = Despawn.ServerSingle(interaction.UsedObject); stateful.ServerChangeState(proxAddedState); } else if (interaction.HandObject == null) { //Remove gun Chat.AddActionMsgToChat(interaction, $"You remove the {gunSlot.ItemObject.ExpensiveName()} from the frame.", $"{interaction.Performer.ExpensiveName()} removes the {gunSlot.ItemObject.ExpensiveName()} from the frame."); Inventory.ServerDrop(gunSlot); stateful.ServerChangeState(wrenchState); } return; } //Screw or remove prox if (CurrentState == proxAddedState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //Screw ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start closing the internal hatch of the turret frame...", $"{interaction.Performer.ExpensiveName()} starts closing the internal hatch of the turret frame...", "You close the internal hatch of the turret frame.", $"{interaction.Performer.ExpensiveName()} closes the internal hatch of the turret frame.", () => { stateful.ServerChangeState(screwState); }); } else if (interaction.HandObject == null) { //Remove prox Chat.AddActionMsgToChat(interaction, $"You remove the {gunSlot.ItemObject.ExpensiveName()} from the frame.", $"{interaction.Performer.ExpensiveName()} removes the {gunSlot.ItemObject.ExpensiveName()} from the frame."); Spawn.ServerPrefab(proximityPrefab, objectBehaviour.registerTile.WorldPosition, transform.parent); stateful.ServerChangeState(gunAddedState); } return; } //Add metal or unscrew if (CurrentState == screwState) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.MetalSheet)) { //Add metal ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding a metal cover to the turret frame...", $"{interaction.Performer.ExpensiveName()} starts adding a metal cover to the turret frame...", "You add a metal cover to the turret frame.", $"{interaction.Performer.ExpensiveName()} adds a metal cover to the turret frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 1); stateful.ServerChangeState(secondMetalAddedState); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //Unscrew ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start removing the bolts from the turret frame...", $"{interaction.Performer.ExpensiveName()} starts removing the bolts from the turret frame...", "You remove the bolts from the turret frame.", $"{interaction.Performer.ExpensiveName()} removes the bolts from the turret frame.", () => { stateful.ServerChangeState(proxAddedState); }); } return; } //Finish construction, or remove metal if (CurrentState == secondMetalAddedState) { if (Validations.HasUsedActiveWelder(interaction)) { //Weld to finish turret ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start welding the outer metal cover to the turret frame...", $"{interaction.Performer.ExpensiveName()} starts welding the outer metal cover to the turret frame...", "You weld the outer metal cover to the turret frame.", $"{interaction.Performer.ExpensiveName()} welds the outer metal cover to the turret frame.", () => { var spawnedTurret = Spawn.ServerPrefab(turretPrefab, objectBehaviour.registerTile.WorldPosition, transform.parent); if (spawnedTurret.Successful && spawnedTurret.GameObject.TryGetComponent <Turret>(out var turret)) { turret.SetUpTurret(gunSlot.Item.GetComponent <Gun>(), gunSlot); } _ = Despawn.ServerSingle(gameObject); });
private float AddDamage(float Energy, AttackType attackType, MetaDataNode data, BasicTile basicTile, Vector3 worldPosition) { float energyAbsorbed = 0; if (basicTile.indestructible || Energy < basicTile.damageDeflection) { if (attackType == AttackType.Bomb && basicTile.ExplosionImpassable == false) { return(Energy * 0.375f); } else { if (attackType == AttackType.Bomb) { return(energyAbsorbed * 0.85f); } else { return(energyAbsorbed); } } } var damageTaken = basicTile.Armor.GetDamage(Energy, attackType); data.AddTileDamage(Layer.LayerType, damageTaken); if (basicTile.SoundOnHit != null && !string.IsNullOrEmpty(basicTile.SoundOnHit.AssetAddress) && basicTile.SoundOnHit.AssetAddress != "null") { if (damageTaken >= 1) { SoundManager.PlayNetworkedAtPos(basicTile.SoundOnHit, worldPosition); } } var totalDamageTaken = data.GetTileDamage(Layer.LayerType); if (totalDamageTaken >= basicTile.MaxHealth) { float excessEnergy = basicTile.Armor.GetForce(totalDamageTaken - basicTile.MaxHealth, attackType); if (basicTile.SoundOnDestroy.Count > 0) { SoundManager.PlayNetworkedAtPos(basicTile.SoundOnDestroy.RandomElement(), worldPosition); } data.RemoveTileDamage(Layer.LayerType); tileChangeManager.RemoveTile(data.Position, Layer.LayerType); tileChangeManager.RemoveOverlaysOfType(data.Position, LayerType.Effects, OverlayType.Damage); if (Layer.LayerType == LayerType.Floors || Layer.LayerType == LayerType.Base) { tileChangeManager.RemoveOverlaysOfType(data.Position, LayerType.Floors, OverlayType.Cleanable); } if (Layer.LayerType == LayerType.Walls) { tileChangeManager.RemoveOverlaysOfType(data.Position, LayerType.Walls, OverlayType.Cleanable); tileChangeManager.RemoveOverlaysOfType(data.Position, LayerType.Effects, OverlayType.Mining); } //Add new tile if needed //TODO change floors to using overlays, but generic overlay will need to be sprited //TODO Use Armour values //TODO have tiles present but one z down if (basicTile.ToTileWhenDestroyed != null) { var tile = basicTile.ToTileWhenDestroyed as BasicTile; var overFlowProtection = 0; while (excessEnergy > 0 && tile != null) { overFlowProtection++; if (tile.MaxHealth <= excessEnergy) { excessEnergy -= tile.MaxHealth; tile = tile.ToTileWhenDestroyed as BasicTile; } else { //Atm we just set remaining damage to 0, instead of absorbing it for the new tile excessEnergy = 0; tileChangeManager.UpdateTile(data.Position, tile); break; } if (overFlowProtection > maxOverflowProtection) { Logger.LogError($"Overflow protection triggered on {basicTile.name}, ToTileWhenDestroyed is spawning tiles in a loop", Category.TileMaps); break; } } energyAbsorbed = Energy - excessEnergy; } if (basicTile.SpawnOnDestroy != null) { basicTile.SpawnOnDestroy.SpawnAt(SpawnDestination.At(worldPosition, metaTileMap.ObjectLayer.gameObject.transform)); } basicTile.LootOnDespawn?.SpawnLoot(worldPosition); } else { if (basicTile.DamageOverlayList != null) { foreach (var overlayData in basicTile.DamageOverlayList.DamageOverlays) { if (overlayData.damagePercentage <= totalDamageTaken / basicTile.MaxHealth) { tileChangeManager.AddOverlay(data.Position, overlayData.overlayTile); break; } } } //All the damage was absorbed, none left to return for next layer energyAbsorbed = Energy; } if (basicTile.MaxHealth < basicTile.MaxHealth - totalDamageTaken) { data.ResetDamage(Layer.LayerType); } if (attackType == AttackType.Bomb && basicTile.ExplosionImpassable == false) { return(energyAbsorbed * 0.375f); } else { if (attackType == AttackType.Bomb) { return(energyAbsorbed * 0.85f); } else { return(energyAbsorbed); } } }
public void ServerPerformInteraction(HandApply interaction) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { if (coverOpen) { coverOpen = false; if (activated) { stateSync = FireAlarmState.TopLightSpriteAlert; } else { stateSync = FireAlarmState.TopLightSpriteNormal; } } else { coverOpen = true; if (hasCables) { stateSync = FireAlarmState.OpenCabledSprite; } else { stateSync = FireAlarmState.OpenEmptySprite; } } ToolUtils.ServerPlayToolSound(interaction); return; } if (coverOpen) { if (hasCables && Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wirecutter)) { //cut out cables Chat.AddActionMsgToChat(interaction, $"You remove the cables.", $"{interaction.Performer.ExpensiveName()} removes the cables."); ToolUtils.ServerPlayToolSound(interaction); Spawn.ServerPrefab(CommonPrefabs.Instance.SingleCableCoil, SpawnDestination.At(gameObject), 5); stateSync = FireAlarmState.OpenEmptySprite; hasCables = false; activated = false; return; } if (!hasCables && Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Cable) && Validations.HasUsedAtLeast(interaction, 5)) { //add 5 cables ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding cables to the frame...", $"{interaction.Performer.ExpensiveName()} starts adding cables to the frame...", "You add cables to the frame.", $"{interaction.Performer.ExpensiveName()} adds cables to the frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 5); hasCables = true; stateSync = FireAlarmState.OpenCabledSprite; }); } } else { if (activated && !isInCooldown) { activated = false; stateSync = FireAlarmState.TopLightSpriteNormal; StartCoroutine(SwitchCoolDown()); foreach (var firelock in FireLockList) { if (firelock == null) { continue; } var controller = firelock.Controller; if (controller == null) { continue; } controller.TryOpen(); } } else { SendCloseAlerts(); } } }
public void ServerPerformInteraction(HandApply interaction) { if (stateSync == MountedMonitorState.OpenCabled || stateSync == MountedMonitorState.OpenEmpty) { if (!hasCables && Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Cable) && Validations.HasUsedAtLeast(interaction, 5)) { //add 5 cables ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start adding cables to the frame...", $"{interaction.Performer.ExpensiveName()} starts adding cables to the frame...", "You add cables to the frame.", $"{interaction.Performer.ExpensiveName()} adds cables to the frame.", () => { Inventory.ServerConsume(interaction.HandSlot, 5); hasCables = true; stateSync = MountedMonitorState.OpenCabled; }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.GlassSheet) && Validations.HasUsedAtLeast(interaction, 2)) { //add 2 glass ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start to put in the glass panel...", $"{interaction.Performer.ExpensiveName()} starts to put in the glass panel...", "You put in the glass panel.", $"{interaction.Performer.ExpensiveName()} puts in the glass panel.", () => { Inventory.ServerConsume(interaction.HandSlot, 2); stateSync = MountedMonitorState.NonScrewedPanel; }); } else if (hasCables && Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wirecutter)) { //cut out cables Chat.AddActionMsgToChat(interaction, $"You remove the cables.", $"{interaction.Performer.ExpensiveName()} removes the cables."); ToolUtils.ServerPlayToolSound(interaction); Spawn.ServerPrefab(CommonPrefabs.Instance.SingleCableCoil, SpawnDestination.At(gameObject), 5); stateSync = MountedMonitorState.OpenEmpty; hasCables = false; currentTimerSeconds = 0; doorControllers.Clear(); } } else if (stateSync == MountedMonitorState.NonScrewedPanel) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar)) { //remove glass Chat.AddActionMsgToChat(interaction, $"You remove the glass panel.", $"{interaction.Performer.ExpensiveName()} removes the glass panel."); ToolUtils.ServerPlayToolSound(interaction); Spawn.ServerPrefab(CommonPrefabs.Instance.GlassSheet, SpawnDestination.At(gameObject), 2); if (hasCables) { stateSync = MountedMonitorState.OpenCabled; } else { stateSync = MountedMonitorState.OpenEmpty; } } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //screw in monitor, completing construction Chat.AddActionMsgToChat(interaction, $"You connect the monitor.", $"{interaction.Performer.ExpensiveName()} connects the monitor."); ToolUtils.ServerPlayToolSound(interaction); if (hasCables) { stateSync = MountedMonitorState.StatusText; } } } else { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { //disconnect the monitor Chat.AddActionMsgToChat(interaction, $"You disconnect the monitor.", $"{interaction.Performer.ExpensiveName()} disconnect the monitor."); ToolUtils.ServerPlayToolSound(interaction); stateSync = MountedMonitorState.NonScrewedPanel; } else if (stateSync == MountedMonitorState.Image) { ChangeChannelMessage(interaction); stateSync = MountedMonitorState.StatusText; } else if (stateSync == MountedMonitorState.StatusText) { if (channel == StatusDisplayChannel.DoorTimer) { currentTimerSeconds += 60; if (currentTimerSeconds > 600) { currentTimerSeconds = 1; } if (!countingDown) { StartCoroutine(TickTimer()); } else { OnTextBroadcastReceived(StatusDisplayChannel.DoorTimer); } } else { ChangeChannelMessage(interaction); stateSync = MountedMonitorState.Image; } } } }
private void ReinforceGirder(HandApply interaction) { interaction.HandObject.GetComponent <Stackable>().ServerConsume(1); Spawn.ServerPrefab(reinforcedGirder, SpawnDestination.At(gameObject)); Despawn.ServerSingle(gameObject); }
public void ServerPerformInteraction(HandApply interaction) { if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Crowbar)) { //deconsruct ToolUtils.ServerUseToolWithActionMessages(interaction, 2f, "You start deconstructing the conveyor belt...", $"{interaction.Performer.ExpensiveName()} starts deconstructing the conveyor belt...", "You deconstruct the conveyor belt.", $"{interaction.Performer.ExpensiveName()} deconstructs the conveyor belt.", () => { Spawn.ServerPrefab(CommonPrefabs.Instance.Metal, SpawnDestination.At(gameObject), 5); Despawn.ServerSingle(gameObject); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Wrench)) //change direction { int count = (int)CurrentDirection + 1; if (count > 7) { count = 0; } ToolUtils.ServerUseToolWithActionMessages(interaction, 1f, "You start redirecting the conveyor belt...", $"{interaction.Performer.ExpensiveName()} starts redirecting the conveyor belt...", "You redirect the conveyor belt.", $"{interaction.Performer.ExpensiveName()} redirects the conveyor belt.", () => { CurrentDirection = (ConveyorDirection)count; UpdateDirection(CurrentDirection); spriteHandler.ChangeSpriteVariant(count); }); } else if (Validations.HasUsedItemTrait(interaction, CommonTraits.Instance.Screwdriver)) { ToolUtils.ServerUseToolWithActionMessages(interaction, 1f, "You start inverting the conveyor belt...", $"{interaction.Performer.ExpensiveName()} starts inverting the conveyor belt...", "You invert the conveyor belt.", $"{interaction.Performer.ExpensiveName()} invert the conveyor belt.", () => { switch (SyncInverted) { case true: SyncInverted = false; break; case false: SyncInverted = true; break; } }); } }