/// <summary> /// Turns this body part into ash while protecting items inside of that cannot be ashed. /// </summary> private void AshBodyPart() { if (currentBurnDamageLevel >= TraumaDamageLevel.CRITICAL) { if (this.BodyPartType == BodyPartType.Chest || this.BodyPartType == BodyPartType.Head) { return; //TODO is temporary weighting on Trauma discussion } IEnumerable <ItemSlot> internalItemList = OrganStorage.GetItemSlots(); foreach (ItemSlot item in internalItemList) { Integrity itemObject = item.ItemObject.OrNull()?.GetComponent <Integrity>(); if (itemObject != null) //Incase this is an empty slot { if (itemObject.Resistances.FireProof || itemObject.Resistances.Indestructable) { Inventory.ServerDrop(item); } } } _ = Spawn.ServerPrefab(OrganStorage.AshPrefab, HealthMaster.RegisterTile.WorldPosition); HealthMaster.DismemberBodyPart(this); _ = Despawn.ServerSingle(gameObject); } }
/// <summary> /// Adds a new body part to this body part, and removes the old part whose place is /// being taken if possible /// </summary> /// <param name="prevImplant">Old body part to be removed</param> /// <param name="newImplant">New body part to be added</param> public virtual void ImplantAdded(Pickupable prevImplant, Pickupable newImplant) { //Check what's being added and add sprites if appropriate if (newImplant) { BodyPart implant = newImplant.GetComponent <BodyPart>(); ContainBodyParts.Add(implant); implant.ContainedIn = this; //Initialisation j**z if (HealthMaster != null) { SetUpBodyPart(implant); } } //Remove sprites if appropriate if (prevImplant) { BodyPart implant = prevImplant.GetComponent <BodyPart>(); implant.HealthMaster = null; HealthMaster.RemoveImplant(implant); implant.RemovedFromBody(HealthMaster); implant.ContainedIn = null; ContainBodyParts.Remove(implant); //bodyPartSprites?.UpdateSpritesOnImplantRemoved(implant); } }
/// <summary> /// Server only - Tries to remove a body part /// </summary> public void TryRemoveFromBody(bool beingGibbed = false) { SetRemovedColor(); foreach (var bodyPart in HealthMaster.BodyPartList) { if (bodyPart.BodyPartType == BodyPartType.Chest) { bodyPart.IsBleeding = true; HealthMaster.ChangeBleedStacks(limbLossBleedingValue); } } DropItemsOnDismemberment(this); HealthMaster.BodyPartStorage.ServerTryRemove(gameObject); var bodyPartUISlot = GetComponent <BodyPartUISlots>(); var dynamicItemStorage = HealthMaster.GetComponent <DynamicItemStorage>(); dynamicItemStorage.Remove(bodyPartUISlot); //Fixes an error where externally bleeding body parts would continue to try bleeding even after their removal. if (IsBleedingExternally) { StopExternalBleeding(); } //this kills the crab if (DeathOnRemoval) { HealthMaster.Death(); } if (gibsEntireBodyOnRemoval && beingGibbed == false) { HealthMaster.Gib(); } }
/// <summary> /// Checks if the cut is big enough for the contained organs to escape. /// If the cut isn't big enough or has failed a chance check, apply internal damage + bleeding. /// </summary> private void Disembowel() { BodyPart randomBodyPart = ContainBodyParts.GetRandom(); float chance = UnityEngine.Random.Range(0.0f, 1.0f); if (chance >= spillChanceWhenCutPresent) { foreach (var bodyPart in ContainBodyParts) { chance = UnityEngine.Random.Range(0.0f, 1.0f); if (chance >= spillChanceWhenCutPresent) { HealthMaster.DismemberBodyPart(bodyPart); } } } else { randomBodyPart.ApplyInternalDamage(); } if (currentPierceDamageLevel >= TraumaDamageLevel.SMALL && isBleedingExternally == false && IsSurface) { StartCoroutine(ExternalBleedingLogic()); } }
/// <summary> /// Checks if the cut is big enough for the contained organs to escape. /// If the cut isn't big enough or has failed a chance check, apply internal damage + bleeding. /// </summary> private void Disembowel() { BodyPart randomBodyPart = OrganList.GetRandom().GetComponent <BodyPart>(); BodyPart randomCustomBodyPart = OptionalOrgans.GetRandom(); float chance = UnityEngine.Random.Range(0.0f, 1.0f); if (chance >= spillChanceWhenCutPresent) { HealthMaster.DismemberBodyPart(randomBodyPart); if (randomCustomBodyPart != null) { HealthMaster.DismemberBodyPart(randomCustomBodyPart); } } else { randomBodyPart.ApplyInternalDamage(); if (randomCustomBodyPart != null) { randomCustomBodyPart.ApplyInternalDamage(); } } if (currentPierceDamageLevel >= TraumaDamageLevel.SMALL && isBleedingExternally == false && IsSurface) { StartCoroutine(ExternalBleedingLogic()); } }
/// <summary> /// Ensures the health master of all sub body parts are the same as their parent, and that the /// health master and body part containers know of all contained body parts /// </summary> /// <param name="implant">Body Part to be initialized</param> public void SetUpBodyPart(BodyPart implant) { implant.HealthMaster = HealthMaster; if (HealthMaster == null) { return; } HealthMaster.AddNewImplant(implant); SubBodyPartAdded(implant); }
/// <summary> /// Limb bleed logic, continues on until isBleedingExternally is false. /// </summary> private IEnumerator Bleedout() { while (isBleedingExternally) { //add 1 bleedstack every 10 seconds until the wound is closed yield return(WaitFor.Seconds(10f)); if (IsBleeding) { HealthMaster.ChangeBleedStacks(1f); } } }
/// <summary> /// Turns this body part into ash while protecting items inside of that cannot be ashed. /// </summary> private void AshBodyPart() { if (currentBurnDamageLevel == BurnDamageLevels.CHARRED && currentBurnDamage > bodyPartAshesAboveThisDamage) { IEnumerable <ItemSlot> internalItemList = Storage.GetItemSlots(); IEnumerable <ItemSlot> PlayerItemList = healthMaster.playerScript.DynamicItemStorage.GetItemSlots(); foreach (ItemSlot item in internalItemList) { Integrity itemObject = item.ItemObject.GetComponent <Integrity>(); if (itemObject != null) //Incase this is an empty slot { if (itemObject.CannotBeAshed || itemObject.Resistances.Indestructable) { Inventory.ServerDrop(item); } } var organ = item.ItemObject?.GetComponent <BodyPart>(); if (organ != null) { if (organ.DeathOnRemoval) { HealthMaster.Death(); } } } if (PlayerItemList != null) //In case this is not a player { foreach (ItemSlot item in PlayerItemList) { Integrity itemObject = item.ItemObject.GetComponent <Integrity>(); if (itemObject != null) { if (itemObject.CannotBeAshed || itemObject.Resistances.Indestructable) { Inventory.ServerDrop(item); } else { Inventory.ServerDespawn(item); } } } } if (DeathOnRemoval) { healthMaster.Death(); } _ = Spawn.ServerPrefab(Storage.AshPrefab, HealthMaster.gameObject.RegisterTile().WorldPosition); _ = Despawn.ServerSingle(this.gameObject); } }
/// <summary> /// Limb bleed logic, continues on until isBleedingExternally is false. /// </summary> private IEnumerator Bleedout() { while (isBleedingExternally) { //Add 1 bleedstack every 10 seconds until the wound is closed yield return(WaitFor.Seconds(10f)); if (IsBleeding == false) { continue; } HealthMaster.OrNull()?.ChangeBleedStacks(1f); } }
/// <summary> /// Turns this body part into ash while protecting items inside of that cannot be ashed. /// </summary> private void AshBodyPart() { if (currentBurnDamageLevel >= TraumaDamageLevel.CRITICAL) { IEnumerable <ItemSlot> internalItemList = OrganStorage.GetItemSlots(); foreach (ItemSlot item in internalItemList) { Integrity itemObject = item.ItemObject.OrNull()?.GetComponent <Integrity>(); if (itemObject != null) //Incase this is an empty slot { if (itemObject.CannotBeAshed || itemObject.Resistances.Indestructable) { Inventory.ServerDrop(item); } } var organ = item.ItemObject.OrNull()?.GetComponent <BodyPart>(); if (organ != null) { if (organ.gibsEntireBodyOnRemoval) { HealthMaster.Gib(); return; } if (organ.DeathOnRemoval) { HealthMaster.Death(); } } } if (DeathOnRemoval && HealthMaster != null) { HealthMaster.Death(); } try { _ = Spawn.ServerPrefab(OrganStorage.AshPrefab, HealthMaster.gameObject.RegisterTile().WorldPosition); _ = Despawn.ServerSingle(this.gameObject); } catch (NullReferenceException exception) { Logger.LogError("Caught a NRE in BodyPartTraumaDamage.AshBodyPart() ", Category.Health); } } }
/// <summary> /// Checks if the player is lucky enough and is wearing enough protective armor to avoid getting his bodypart removed. /// </summary> private void DismemberBodyPartWithChance() { if (GibChance == 0) { return; } var armorChanceModifer = GibChance - SelfArmor.DismembermentProtectionChance; if (Severity == DamageSeverity.Max) { armorChanceModifer += 25; //Make it more likely that the bodypart can be gibbed in it's worst condition. } var chance = UnityEngine.Random.Range(0, 100); if (chance < armorChanceModifer) { HealthMaster.DismemberBodyPart(this); } }
//TODO: confusing, make it not depend from the inventory storage Action /// <summary> /// Both addition and removal of an organ /// </summary> public void OrganTransfer(Pickupable prevImplant, Pickupable newImplant) { if (newImplant && newImplant.TryGetComponent <Organ>(out var addedOrgan)) { addedOrgan.RelatedPart = this; OrganList.Add(addedOrgan); addedOrgan.Initialisation(); if (HealthMaster) { //TODO: horrible, remove -- organ prefabs have a bodypart component var bodyPart = addedOrgan.GetComponent <BodyPart>(); HealthMaster.ServerCreateSprite(bodyPart); } } else if (prevImplant && prevImplant.TryGetComponent <Organ>(out var removedOrgan)) { OrganList.Remove(removedOrgan); removedOrgan.RemovedFromBody(HealthMaster); removedOrgan.RelatedPart = null; } }
/// <summary> /// Checks if the player is lucky enough and is wearing enough protective armor to avoid getting his bodypart removed. /// </summary> private void DismemberBodyPartWithChance() { if (GibChance == 0) { return; } var armorChanceModifer = GibChance - SelfArmor.DismembermentProtectionChance; if (Severity == DamageSeverity.Max) { armorChanceModifer += 25; //Make it more likely that the bodypart can be gibbed in it's worst condition. } var chance = UnityEngine.Random.Range(0, 100); if (chance < armorChanceModifer) { if (this.BodyPartType == BodyPartType.Chest || this.BodyPartType == BodyPartType.Head) { return; //TODO is temporary weighting on Trauma discussion } HealthMaster.DismemberBodyPart(this); } }
/// <summary> /// Server only - Tries to remove a body part /// </summary> public void TryRemoveFromBody(bool beingGibbed = false) { bool alreadyBleeding = false; SetRemovedColor(); foreach (var bodyPart in HealthMaster.BodyPartList) { if (bodyPart.BodyPartType == BodyPartType.Chest && alreadyBleeding == false) { bodyPart.IsBleeding = true; alreadyBleeding = true; HealthMaster.ChangeBleedStacks(limbLossBleedingValue); } } DropItemsOnDismemberment(this); var bodyPartUISlot = GetComponent <BodyPartUISlots>(); var dynamicItemStorage = HealthMaster.GetComponent <DynamicItemStorage>(); dynamicItemStorage.Remove(bodyPartUISlot); //Fixes an error where externally bleeding body parts would continue to try bleeding even after their removal. if (IsBleedingExternally) { StopExternalBleeding(); } //this kills the crab if (DeathOnRemoval) { HealthMaster.Death(); } if (gibsEntireBodyOnRemoval && beingGibbed == false) { HealthMaster.Gib(); } if (ContainedIn != null) { if (beingGibbed) { ContainedIn.OrganStorage.ServerTryRemove(gameObject, DroppedAtWorldPositionOrThrowVector: ConverterExtensions.GetRandomRotatedVector2(-0.5f, 0.5f), Throw: true); } else { ContainedIn.OrganStorage.ServerTryRemove(gameObject); } } else { if (beingGibbed) { HealthMaster.OrNull()?.BodyPartStorage.OrNull()?.ServerTryRemove(gameObject, DroppedAtWorldPositionOrThrowVector: ConverterExtensions.GetRandomRotatedVector2(-0.5f, 0.5f), Throw: true); } else { HealthMaster.OrNull()?.BodyPartStorage.OrNull()?.ServerTryRemove(gameObject); } } }
/// <summary> /// Ensures the health master of all sub body parts are the same as their parent, and that the /// health master and body part containers know of all contained body parts /// </summary> /// <param name="implant">Body Part to be initialized</param> public void SetUpBodyPart(BodyPart implant) { implant.HealthMaster = HealthMaster; HealthMaster.AddNewImplant(implant); SubBodyPartAdded(implant); }