private void MonitorSystem() { if (!livingHealthBehaviour.IsDead) { Vector3Int position = objectBehaviour.AssumedWorldPositionServer(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); if (!IsEVACompatible()) { temperature = node.GasMix.Temperature; pressure = node.GasMix.Pressure; CheckPressureDamage(); } else { pressure = 101.325f; temperature = 293.15f; } if (livingHealthBehaviour.OverallHealth >= HealthThreshold.SoftCrit) { //if (Breathe(node)) // { // AtmosManager.Update(node); // } } else { bloodSystem.OxygenDamage += 1; } } }
//Find the APC in the same room as the light switch and assign it to RelatedAPC private void DetectAPC() { if (RelatedAPC != null) { return; } int layerMask = LayerMask.GetMask("WallMounts"); var possibleApcs = Physics2D.OverlapCircleAll(GetCastPos(), radius, layerMask); int thisRoomNum = MatrixManager.GetMetaDataAt(Vector3Int.RoundToInt(transform.position - transform.up)).RoomNumber; foreach (Collider2D col in possibleApcs) { if (col.tag == "APC") { //Light switch has no room number, assign it to the first APC it finds so it still functions if (thisRoomNum == -1) { RelatedAPC = col.gameObject.GetComponent <APC>(); break; } if (MatrixManager.GetMetaDataAt(Vector3Int.RoundToInt(col.transform.position - col.transform.up)).RoomNumber == thisRoomNum) { RelatedAPC = col.gameObject.GetComponent <APC>(); break; } } } if (RelatedAPC == null && !SelfPowered) { SyncLightSwitch(isOn, States.PowerCut); } }
private void MonitorSystem() { if (!livingHealthBehaviour.IsDead) { Vector3Int position = objectBehaviour.AssumedLocation().RoundToInt(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); PressureStatus = CheckPressureStatus(node.GasMix.Pressure); TempStatus = CheckTempStatus(node.GasMix.Temperature); if (!IsEVACompatible()) { CheckPressureDamage(node.GasMix.Pressure); } if (livingHealthBehaviour.OverallHealth >= HealthThreshold.SoftCrit) { if (Breathe(node)) { AtmosManager.Update(node); } } else { bloodSystem.OxygenDamage += 1; } } }
private void MonitorSystem() { if (!healthMaster.IsDead) { Vector3Int position = objectBehaviour.AssumedWorldPositionServer(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); if (!IsEVACompatible()) { healthStateController.SetTemperature(node.GasMix.Temperature); healthStateController.SetPressure(node.GasMix.Pressure); CheckPressureDamage(); } else { healthStateController.SetPressure(101.325f); healthStateController.SetTemperature(293.15f); } // if(healthMaster.OverallHealth >= HealthThreshold.SoftCrit) // { // if (Breathe(node)) // { // AtmosManager.Update(node); // } // } } }
private void UpdateCycle() { if (!CustomNetworkManager.IsServer) { return; } var pos = registerTile.WorldPosition; if (pos == posCache && metaDataNode.GasMix.Temperature > AtmosDefines.WATER_VAPOR_FREEZE) { metaDataNode.GasMix.AddGas(Gas.WaterVapor, 2f); Despawn.ServerSingle(gameObject); return; } else { posCache = pos; metaDataNode = MatrixManager.GetMetaDataAt(pos); if (metaDataNode.GasMix.Temperature > AtmosDefines.WATER_VAPOR_FREEZE) { metaDataNode.GasMix.AddGas(Gas.WaterVapor, 2f); Despawn.ServerSingle(gameObject); return; } } }
private void OnWelderUse(Interaction interaction) { if (Validations.HasUsedActiveWelder(interaction) == false) { return; } var pos = registerTile.WorldPositionServer; //If in inventory use player pos instead, check root in case player is in something if (pickupable.ItemSlot != null) { pos = pickupable.ItemSlot.GetRootStorage().gameObject.WorldPosServer().RoundToInt(); } //If hidden then stop if (pos == TransformState.HiddenPos) { return; } Chat.AddActionMsgToChat(interaction.Performer, $"You melt the {gameObject.ExpensiveName()} with the {interaction.UsedObject.ExpensiveName()}", $"{interaction.Performer.ExpensiveName()} melts the {gameObject.ExpensiveName()} with the {interaction.UsedObject.ExpensiveName()}"); if (isHotIce == false) { MeltIce(MatrixManager.GetMetaDataAt(pos)); return; } MeltHotIce(MatrixManager.GetMetaDataAt(pos)); }
//Removes all plasma from tiles, in effect putting out fires public static void ExtinguishTile(Vector3 worldPos) { var worldPosInt = worldPos.CutToInt(); var matrix = MatrixManager.AtPoint(worldPosInt); var localPosInt = MatrixManager.WorldToLocalInt(worldPosInt, matrix); MetaDataNode node = MatrixManager.GetMetaDataAt(worldPosInt); node.GasMix.RemoveGas(Atmospherics.Gas.Plasma, node.GasMix.GetMoles(Atmospherics.Gas.Plasma)); }
public void OnSpawnServer(SpawnInfo info) { var registerTile = gameObject.RegisterTile(); metaNode = MatrixManager.GetMetaDataAt(registerTile.WorldPosition); registerTile.OnLocalPositionChangedServer.AddListener((newLocalPosition) => { metaNode = MatrixManager.GetMetaDataAt(registerTile.WorldPosition); }); }
public override void ImplantPeriodicUpdate() { base.ImplantPeriodicUpdate(); Vector3Int position = healthMaster.ObjectBehaviour.AssumedWorldPositionServer(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); if (TryBreathing(node, TotalModified)) { AtmosManager.Update(node); } }
public override void ImplantPeriodicUpdate() { base.ImplantPeriodicUpdate(); // Disable breathing for dead and brain damaged players if (RelatedPart.HealthMaster.IsDead) { return; } Brain brain = RelatedPart.HealthMaster.brain; if (brain && brain.RelatedPart.TotalModified <= 0.2f) { return; } Vector3Int position = RelatedPart.HealthMaster.ObjectBehaviour.AssumedWorldPositionServer(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); var TotalModified = 1f; foreach (var modifier in bodyPart.AppliedModifiers) { var toMultiply = 1f; if (modifier == bodyPart.DamageModifier) { toMultiply = Mathf.Max(0f, Mathf.Max(bodyPart.MaxHealth - bodyPart.TotalDamageWithoutOxyCloneRadStam, 0) / bodyPart.MaxHealth); } else if (modifier == bodyPart.HungerModifier) { continue; } else { toMultiply = Mathf.Max(0f, modifier.Multiplier); } TotalModified *= toMultiply; } if (TryBreathing(node, TotalModified)) { AtmosManager.Instance.UpdateNode(node); } if (RelatedPart.IsBleedingInternally) { InternalDamageLogic(); } }
private void ServerUpdateCycle() { var pos = registerTile.WorldPosition; if (pos != posCache) { metaDataNode = MatrixManager.GetMetaDataAt(pos); posCache = pos; } if (metaDataNode.GasMix.Temperature > AtmosDefines.WATER_VAPOR_FREEZE) { metaDataNode.GasMix.AddGas(Gas.WaterVapor, 2f); Despawn.ServerSingle(gameObject); } }
private void ServerDoCPR(GameObject performer, GameObject target, BodyPartType TargetBodyPart) { var health = target.GetComponent <LivingHealthMasterBase>(); Vector3Int position = health.ObjectBehaviour.AssumedWorldPositionServer(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); bool hasLung = false; bool hasHeart = false; foreach (var bodyPart in health.BodyPartList) { if (bodyPart.BodyPartType == TargetBodyPart) { foreach (var organ in bodyPart.OrganList) { if (organ is Lungs lung) { lung.TryBreathing(node, 1); hasLung = true; } if (organ is Heart heart) { heart.Heartbeat(1); hasHeart = true; } } } } if (hasHeart && hasLung) { Chat.AddActionMsgToChat( performer, $"You perform CPR on {targetName}.", $"{performerName} performs CPR on {targetName}."); Chat.AddExamineMsgFromServer(target, $"You feel fresh air enter your lungs. It feels good!"); } else { Chat.AddActionMsgToChat( performer, $"You perform CPR on {targetName}. It doesn't seem to work, maybe they're missing something.", $"{performerName} performs CPR on {targetName} In vain."); } }
/// <summary> /// Checks each side of the door, returns true if not considered safe and updates pressureLevel. /// Used to allow the player to be made aware of the pressure difference for safety. /// </summary> /// <returns></returns> private bool DoorUnderPressure() { if (!enablePressureWarning) { // Pressure warning system is disabled, so pretend everything is fine. return(false); } // Obtain the adjacent tiles to the door. var upMetaNode = MatrixManager.GetMetaDataAt(registerTile.WorldPositionServer + Vector3Int.up); var downMetaNode = MatrixManager.GetMetaDataAt(registerTile.WorldPositionServer + Vector3Int.down); var leftMetaNode = MatrixManager.GetMetaDataAt(registerTile.WorldPositionServer + Vector3Int.left); var rightMetaNode = MatrixManager.GetMetaDataAt(registerTile.WorldPositionServer + Vector3Int.right); // Only find the pressure comparison if both opposing sides are atmos. passable. // If both sides are not atmos. passable, then we don't care about the pressure difference. var vertPressureDiff = 0.0; var horzPressureDiff = 0.0; if (!upMetaNode.IsOccupied || !downMetaNode.IsOccupied) { vertPressureDiff = Math.Abs(upMetaNode.GasMix.Pressure - downMetaNode.GasMix.Pressure); } if (!leftMetaNode.IsOccupied || !rightMetaNode.IsOccupied) { horzPressureDiff = Math.Abs(leftMetaNode.GasMix.Pressure - rightMetaNode.GasMix.Pressure); } // Set pressureLevel according to the pressure difference found. if (vertPressureDiff >= pressureThresholdWarning || horzPressureDiff >= pressureThresholdWarning) { pressureLevel = PressureLevel.Warning; return(true); } else if (vertPressureDiff >= pressureThresholdCaution || horzPressureDiff >= pressureThresholdCaution) { pressureLevel = PressureLevel.Caution; return(true); } else { pressureLevel = PressureLevel.Safe; return(false); } }
private void MonitorSystem() { if (!livingHealthBehaviour.IsDead) { Vector3Int position = transform.position.RoundToInt(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); if (!IsEVACompatible()) { CheckPressureDamage(node.GasMix.Pressure); } if (Breathe(node)) { AtmosManager.Update(node); } } }
public override void ImplantPeriodicUpdate() { base.ImplantPeriodicUpdate(); Vector3Int position = RelatedPart.HealthMaster.ObjectBehaviour.AssumedWorldPositionServer(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); var TotalModified = 1f; foreach (var Modifier in RelatedPart.AppliedModifiers) { var toMultiply = 1f; if (Modifier == RelatedPart.DamageModifier) { toMultiply = Mathf.Max(0f, Mathf.Max(RelatedPart.MaxHealth - RelatedPart.TotalDamageWithoutOxyCloneRadStam, 0) / RelatedPart.MaxHealth); } else if (Modifier == RelatedPart.HungerModifier) { continue; } else { toMultiply = Mathf.Max(0f, Modifier.Multiplier); } TotalModified *= toMultiply; } if (TryBreathing(node, TotalModified)) { AtmosManager.Update(node); } if (RelatedPart.IsBleedingInternally) { InternalDamageLogic(); } }
private void ServerUpdateCycle() { var pos = registerTile.WorldPosition; //If in an itemslot try to get that root position if (pickupable.ItemSlot != null) { pos = pickupable.ItemSlot.GetRootStorage().gameObject.WorldPosServer().RoundToInt(); } //If the position is still hidden then the shard or the top pickupable is also hidden if (pos == TransformState.HiddenPos) { return; } //Cache pos so we dont try to get the metadata every update if we haven't moved if (pos != posCache) { metaDataNode = MatrixManager.GetMetaDataAt(pos); posCache = pos; } if (metaDataNode == null) { return; } if (isHotIce == false && metaDataNode.GasMix.Temperature > AtmosDefines.WATER_VAPOR_FREEZE) { MeltIce(metaDataNode); } if (isHotIce && metaDataNode.GasMix.Temperature > 373.15) { MeltHotIce(metaDataNode); } }
/// <summary> /// Used to call a spray coming from the player, where position is the target, bottle is the ReagentContainer of the item, /// spray is the prefab to spray, and customCol and col are for if you want the spray to have custom colours. /// </summary> /// <param name="bottle"></param> /// <param name="position"></param> /// <param name="spray"></param> /// <param name="customCol"></param> /// <param name="col"></param> /// <returns></returns> public static IEnumerator TriggerSpray(ReagentContainer bottle, Vector3 position, GameObject spray, bool customCol = false, Color col = new Color()) { //Work out direction from player for spray transformations int xDir = -(PlayerManager.PlayerScript.WorldPos.x - position.CutToInt().x); int yDir = -(PlayerManager.PlayerScript.WorldPos.y - position.CutToInt().y); //Create spray game objects GameObject SprayGO = PoolManager.PoolNetworkInstantiate(spray, PlayerManager.PlayerScript.WorldPos); GameObject SprayGO2; GameObject SprayGO3; if (Mathf.Abs(xDir) == Mathf.Abs(yDir)) { SprayGO2 = PoolManager.PoolNetworkInstantiate(spray, PlayerManager.PlayerScript.WorldPos + new Vector3(-yDir, xDir)); SprayGO3 = PoolManager.PoolNetworkInstantiate(spray, PlayerManager.PlayerScript.WorldPos + new Vector3(yDir, -xDir)); } else { SprayGO2 = PoolManager.PoolNetworkInstantiate(spray, PlayerManager.PlayerScript.WorldPos + new Vector3(yDir, xDir)); SprayGO3 = PoolManager.PoolNetworkInstantiate(spray, PlayerManager.PlayerScript.WorldPos + new Vector3(-yDir, -xDir)); } SprayGO2.SetActive(false); SprayGO3.SetActive(false); bool canSpray = false; string effect = ""; //Search for chemicals in container to determine effects of spray foreach (KeyValuePair <string, float> Chemical in bottle.Contents) { if (Chemical.Key == "cleaner") { if (Chemical.Value >= 5f) { canSpray = true; effect = "cleaning"; } } else if (Chemical.Key == "water") { if (Chemical.Value >= 5f) { canSpray = true; effect = "extinguish"; } } else { if (Chemical.Value >= 5f) //Still sprays if there are more than 5 of any liquid in container { canSpray = true; } } } if (canSpray) { Transform spraySprite = SprayGO.transform.GetChild(0); Transform spray2Sprite = SprayGO2.transform.GetChild(0); Transform spray3Sprite = SprayGO3.transform.GetChild(0); //For custom colours if (customCol) { spraySprite.gameObject.GetComponent <SpriteRenderer>().color = col; spray2Sprite.gameObject.GetComponent <SpriteRenderer>().color = col; spray3Sprite.gameObject.GetComponent <SpriteRenderer>().color = col; } //For directions of spray if (xDir > 0) { spraySprite.Rotate(new Vector3(0, 0, 180)); spray2Sprite.Rotate(new Vector3(0, 0, 180)); spray3Sprite.Rotate(new Vector3(0, 0, 180)); } else if (xDir == 0) { spraySprite.Rotate(new Vector3(0, 0, 90 * -yDir)); spray2Sprite.Rotate(new Vector3(0, 0, 90 * -yDir)); spray3Sprite.Rotate(new Vector3(0, 0, 90 * -yDir)); } //Cleaning spray if (effect == "cleaning") { for (int j = 0; j < 3; j++) { //Clean and move if no wall CleanTile(position + new Vector3(j * xDir, j * yDir)); if (!(MatrixManager.GetMetaDataAt(SprayGO.transform.position.CutToInt() + new Vector3(xDir, yDir).CutToInt()).IsOccupied)) { SprayGO.transform.Translate(new Vector3(xDir, yDir)); } yield return(new WaitForSecondsRealtime(0.5f)); } } //Extinguishing spray else if (effect == "extinguish") { SprayGO2.SetActive(true); SprayGO3.SetActive(true); for (int j = 0; j < 3; j++) { //Put out fire and move if no walls ExtinguishTile(position + new Vector3(j * xDir, j * yDir)); ExtinguishTile(position + new Vector3((j * xDir) - yDir, (j * yDir) + xDir)); ExtinguishTile(position + new Vector3((j * xDir) + yDir, (j * yDir) - xDir)); if (!(MatrixManager.GetMetaDataAt(SprayGO.transform.position.CutToInt() + new Vector3(xDir, yDir).CutToInt()).IsOccupied)) { SprayGO.transform.Translate(new Vector3(xDir, yDir)); } if (!(MatrixManager.GetMetaDataAt(SprayGO2.transform.position.CutToInt() + new Vector3(xDir, yDir).CutToInt()).IsOccupied)) { SprayGO2.transform.Translate(new Vector3(xDir, yDir)); } if (!(MatrixManager.GetMetaDataAt(SprayGO3.transform.position.CutToInt() + new Vector3(xDir, yDir).CutToInt()).IsOccupied)) { SprayGO3.transform.Translate(new Vector3(xDir, yDir)); } yield return(new WaitForSecondsRealtime(0.5f)); } } else { for (int j = 0; j < 3; j++) { //Move if no walls if (!(MatrixManager.GetMetaDataAt(SprayGO.transform.position.CutToInt() + new Vector3(xDir, yDir).CutToInt()).IsOccupied)) { SprayGO.transform.Translate(new Vector3(xDir, yDir)); } SprayGO.transform.Translate(new Vector3(xDir, yDir)); yield return(new WaitForSecondsRealtime(0.5f)); } } //Destroy spray objects after 3 moves GameObject.Destroy(SprayGO); GameObject.Destroy(SprayGO2); GameObject.Destroy(SprayGO3); } }