// TODO 1: test this function more // TODO 2: balance damages // will recursively add events to BodyDamageEvent event list (per body part) private void TakeDamage(BodyNode node, Damage damage) { // Debug.Log("TAKE DAMAGE: index " + node.Index); float r1 = UnityEngine.Random.value; // unused float r2 = UnityEngine.Random.value; if (0 <= node.Index) { var bodyPart = _bodyParts[node.Index]; // get damage event from body part hp system var dmgEvent = bodyPart.TakeDamage(damage) as HpSystemDamageEvent; var bodyPartHpEvent = new BodyPartHpEvent(bodyPart, dmgEvent.HpSystemEvent); // add current event to the body event system this._eventSystem.OnEvent(bodyPartHpEvent); } // Debug.Log($"bodyPart [{node.Index}] {bodyPart.NameCustom}, children: " + node.ChildrenCount); // apply damage to node's children if (node.HasChildren) { var children = node.Children.ToArray(); var sb = new StringBuilder(); foreach (var i in children) { sb.Append(i + ", "); } // Debug.Log("children: " + sb.ToString()); // sample indices of children to pick which children will be applied damage to Vector2Int indices = Samplers.SampleFromPdf( r2, GetBodyPartSizes(new IndexedEnumerator <BodyPart>(this._bodyParts, children)), damage.Dispersion); // get the children var damagedNodes = new IndexedEnumerator <BodyNode>( this._bodyNodes, new SliceEnumerator <int>(children, indices[0], indices[1] + 1).ToArray() ); // Debug.Log("damaged nodes count " + damagedNodes.Count()); damagedNodes.Reset(); // need to reset since its an iterator // compute the damage amount passed on to children of current body part var damageAfterMultiplier = damage * damage.Penetration; foreach (var damagedNode in damagedNodes) { TakeDamage(damagedNode, damageAfterMultiplier); } } }
override public void TakeDamage(Damage damage) { if (this.BodyParts.Count > 0) { if (this.BodyParts.Count == 1) { this.BodyParts[0].TakeDamage(damage); } else { Vector2Int indices = Samplers.SampleFromPdf(UnityEngine.Random.value, this.GetBodyPartSizes, damage.dispersion); foreach (var bodyPart in this.BodyParts.ToArray().Slice(indices.x, indices.y)) { bodyPart.TakeDamage(damage); } } } else { return; } }