/// <summary> /// If the damage in a DamageableComponent was changed, this function should be called. /// </summary> /// <remarks> /// This updates cached damage information, flags the component as dirty, and raises a damage changed event. /// The damage changed event is used by other systems, such as damage thresholds. /// </remarks> public void DamageChanged(DamageableComponent component, DamageSpecifier?damageDelta = null) { component.DamagePerGroup = component.Damage.GetDamagePerGroup(); component.TotalDamage = component.Damage.Total; component.Dirty(); RaiseLocalEvent(component.Owner.Uid, new DamageChangedEvent(component, damageDelta), false); }
/// <summary> /// Initialize a damageable component /// </summary> private void DamageableInit(EntityUid uid, DamageableComponent component, ComponentInit _) { if (component.DamageContainerID != null && _prototypeManager.TryIndex <DamageContainerPrototype>(component.DamageContainerID, out var damageContainerPrototype)) { // Initialize damage dictionary, using the types and groups from the damage // container prototype foreach (var type in damageContainerPrototype.SupportedTypes) { component.Damage.DamageDict.TryAdd(type, FixedPoint2.Zero); } foreach (var groupID in damageContainerPrototype.SupportedGroups) { var group = _prototypeManager.Index <DamageGroupPrototype>(groupID); foreach (var type in group.DamageTypes) { component.Damage.DamageDict.TryAdd(type, FixedPoint2.Zero); } } } else { // No DamageContainerPrototype was given. So we will allow the container to support all damage types foreach (var type in _prototypeManager.EnumeratePrototypes <DamageTypePrototype>()) { component.Damage.DamageDict.TryAdd(type.ID, FixedPoint2.Zero); } } component.DamagePerGroup = component.Damage.GetDamagePerGroup(); component.TotalDamage = component.Damage.Total; }
/// <summary> /// If the damage in a DamageableComponent was changed, this function should be called. /// </summary> /// <remarks> /// This updates cached damage information, flags the component as dirty, and raises a damage changed event. /// The damage changed event is used by other systems, such as damage thresholds. /// </remarks> public void DamageChanged(DamageableComponent component, DamageSpecifier?damageDelta = null, bool interruptsDoAfters = true) { component.DamagePerGroup = component.Damage.GetDamagePerGroup(); component.TotalDamage = component.Damage.Total; component.Dirty(); if (EntityManager.TryGetComponent <AppearanceComponent>(component.Owner, out var appearance) && damageDelta != null) { appearance.SetData(DamageVisualizerKeys.DamageUpdateGroups, damageDelta.GetDamagePerGroup().Keys.ToList()); } RaiseLocalEvent(component.Owner, new DamageChangedEvent(component, damageDelta, interruptsDoAfters), false); }
private void OnIrradiated(EntityUid uid, DamageableComponent component, OnIrradiatedEvent args) { var damageValue = FixedPoint2.New(args.TotalRads); // Radiation should really just be a damage group instead of a list of types. DamageSpecifier damage = new(); foreach (var typeId in component.RadiationDamageTypeIDs) { damage.DamageDict.Add(typeId, damageValue); } TryChangeDamage(uid, damage); }
/// <summary> /// Sets all damage types supported by a <see cref="DamageableComponent"/> to the specified value. /// </summary> /// <remakrs> /// Does nothing If the given damage value is negative. /// </remakrs> public void SetAllDamage(DamageableComponent component, FixedPoint2 newValue) { if (newValue < 0) { // invalid value return; } foreach (var type in component.Damage.DamageDict.Keys) { component.Damage.DamageDict[type] = newValue; } // Setting damage does not count as 'dealing' damage, even if it is set to a larger value, so we pass an // empty damage delta. DamageChanged(component, new DamageSpecifier()); }
public DamageChangedEvent(DamageableComponent damageable, DamageSpecifier?damageDelta) { Damageable = damageable; DamageDelta = damageDelta; if (DamageDelta == null) { return; } foreach (var damageChange in DamageDelta.DamageDict.Values) { if (damageChange > 0) { DamageIncreased = true; break; } } }
public DamageChangedEvent(DamageableComponent damageable, DamageSpecifier?damageDelta, bool interruptsDoAfters) { Damageable = damageable; DamageDelta = damageDelta; if (DamageDelta == null) { return; } foreach (var damageChange in DamageDelta.DamageDict.Values) { if (damageChange > 0) { DamageIncreased = true; break; } } InterruptsDoAfters = interruptsDoAfters && DamageIncreased; }
private void DamageableHandleState(EntityUid uid, DamageableComponent component, ref ComponentHandleState args) { if (args.Current is not DamageableComponentState state) { return; } component.DamageModifierSetId = state.ModifierSetId; // Has the damage actually changed? DamageSpecifier newDamage = new() { DamageDict = new(state.DamageDict) }; var delta = component.Damage - newDamage; delta.TrimZeros(); if (!delta.Empty) { component.Damage = newDamage; DamageChanged(component, delta); } }
/// <summary> /// Directly sets the damage specifier of a damageable component. /// </summary> /// <remarks> /// Useful for some unfriendly folk. Also ensures that cached values are updated and that a damage changed /// event is raised. /// </remarks> public void SetDamage(DamageableComponent damageable, DamageSpecifier damage) { damageable.Damage = damage; DamageChanged(damageable); }
private void DamageableGetState(EntityUid uid, DamageableComponent component, ref ComponentGetState args) { args.State = new DamageableComponentState(component.Damage.DamageDict, component.DamageModifierSetId); }