Flammable system bug fixes. (#21594)

This commit is contained in:
Leon Friedrich
2023-11-14 22:55:45 +11:00
committed by GitHub
parent ec76958b51
commit 16a96976d3
3 changed files with 64 additions and 77 deletions

View File

@@ -6,16 +6,15 @@ namespace Content.Server.Atmos.Components
[RegisterComponent] [RegisterComponent]
public sealed partial class FlammableComponent : Component public sealed partial class FlammableComponent : Component
{ {
[ViewVariables] [DataField]
public bool Resisting = false; public bool Resisting;
[ViewVariables]
public readonly List<EntityUid> Collided = new();
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField]
public bool OnFire { get; set; } public bool OnFire { get; set; }
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField]
public float FireStacks { get; set; } public float FireStacks { get; set; }
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]

View File

@@ -56,6 +56,7 @@ namespace Content.Server.Atmos.EntitySystems
private float _timer; private float _timer;
private readonly Dictionary<Entity<FlammableComponent>, float> _fireEvents = new(); private readonly Dictionary<Entity<FlammableComponent>, float> _fireEvents = new();
private readonly List<EntityUid> _toRemove = new();
public override void Initialize() public override void Initialize()
{ {
@@ -73,7 +74,6 @@ namespace Content.Server.Atmos.EntitySystems
SubscribeLocalEvent<IgniteOnMeleeHitComponent, MeleeHitEvent>(OnMeleeHit); SubscribeLocalEvent<IgniteOnMeleeHitComponent, MeleeHitEvent>(OnMeleeHit);
SubscribeLocalEvent<ExtinguishOnInteractComponent, UseInHandEvent>(OnExtinguishUsingInHand);
SubscribeLocalEvent<ExtinguishOnInteractComponent, ActivateInWorldEvent>(OnExtinguishActivateInWorld); SubscribeLocalEvent<ExtinguishOnInteractComponent, ActivateInWorldEvent>(OnExtinguishActivateInWorld);
} }
@@ -142,29 +142,26 @@ namespace Content.Server.Atmos.EntitySystems
private void OnExtinguishActivateInWorld(EntityUid uid, ExtinguishOnInteractComponent component, ActivateInWorldEvent args) private void OnExtinguishActivateInWorld(EntityUid uid, ExtinguishOnInteractComponent component, ActivateInWorldEvent args)
{ {
TryHandExtinguish(uid, component); if (args.Handled)
} return;
private void OnExtinguishUsingInHand(EntityUid uid, ExtinguishOnInteractComponent component, UseInHandEvent args)
{
TryHandExtinguish(uid, component);
}
private void TryHandExtinguish(EntityUid uid, ExtinguishOnInteractComponent component)
{
if (!TryComp(uid, out FlammableComponent? flammable)) if (!TryComp(uid, out FlammableComponent? flammable))
return; return;
if (!flammable.OnFire) if (!flammable.OnFire)
return; return;
if (TryComp(uid, out UseDelayComponent? useDelay) && _useDelay.ActiveDelay(uid, useDelay))
args.Handled = true;
if (!_useDelay.BeginDelay(uid))
return; return;
_useDelay.BeginDelay(uid);
_audio.PlayPvs(component.ExtinguishAttemptSound, uid); _audio.PlayPvs(component.ExtinguishAttemptSound, uid);
if (_random.Prob(component.Probability)) if (_random.Prob(component.Probability))
{ {
AdjustFireStacks(uid, component.StackDelta, flammable); AdjustFireStacks(uid, component.StackDelta, flammable);
} else }
else
{ {
_popup.PopupEntity(Loc.GetString(component.ExtinguishFailed), uid); _popup.PopupEntity(Loc.GetString(component.ExtinguishFailed), uid);
} }
@@ -173,52 +170,56 @@ namespace Content.Server.Atmos.EntitySystems
{ {
var otherUid = args.OtherEntity; var otherUid = args.OtherEntity;
// Collisions cause events to get raised directed at both entities. We only want to handle this collision
// once, hence the uid check.
if (otherUid.Id < uid.Id)
return;
// Normal hard collisions, though this isn't generally possible since most flammable things are mobs // Normal hard collisions, though this isn't generally possible since most flammable things are mobs
// which don't collide with one another, shouldn't work here. // which don't collide with one another, shouldn't work here.
if (args.OtherFixtureId != FlammableFixtureID && args.OurFixtureId != FlammableFixtureID) if (args.OtherFixtureId != FlammableFixtureID && args.OurFixtureId != FlammableFixtureID)
return; return;
if (!EntityManager.TryGetComponent(otherUid, out FlammableComponent? otherFlammable)) if (!flammable.FireSpread)
return; return;
if (!flammable.FireSpread || !otherFlammable.FireSpread) if (!TryComp(otherUid, out FlammableComponent? otherFlammable) || !otherFlammable.FireSpread)
return; return;
if (!flammable.OnFire && !otherFlammable.OnFire)
return; // Neither are on fire
if (flammable.OnFire && otherFlammable.OnFire)
{
// Both are on fire -> equalize fire stacks.
var avg = (flammable.FireStacks + otherFlammable.FireStacks) / 2;
flammable.FireStacks = flammable.CanExtinguish ? avg : Math.Max(flammable.FireStacks, avg);
otherFlammable.FireStacks = otherFlammable.CanExtinguish ? avg : Math.Max(otherFlammable.FireStacks, avg);
UpdateAppearance(uid, flammable);
UpdateAppearance(otherUid, otherFlammable);
return;
}
// Only one is on fire -> attempt to spread the fire.
if (flammable.OnFire) if (flammable.OnFire)
{
if (otherFlammable.OnFire)
{
if (flammable.CanExtinguish)
{
var fireSplit = (flammable.FireStacks + otherFlammable.FireStacks) / 2;
flammable.FireStacks = fireSplit;
otherFlammable.FireStacks = fireSplit;
}
else
{
otherFlammable.FireStacks = flammable.FireStacks / 2;
}
}
else
{
if (!flammable.CanExtinguish)
{ {
otherFlammable.FireStacks += flammable.FireStacks / 2; otherFlammable.FireStacks += flammable.FireStacks / 2;
Ignite(otherUid, uid, otherFlammable); Ignite(otherUid, uid, otherFlammable);
if (flammable.CanExtinguish)
{
flammable.FireStacks /= 2;
UpdateAppearance(uid, flammable);
}
} }
else else
{ {
flammable.FireStacks /= 2; flammable.FireStacks += otherFlammable.FireStacks / 2;
otherFlammable.FireStacks += flammable.FireStacks; Ignite(uid, otherUid, flammable);
Ignite(otherUid, uid, otherFlammable); if (otherFlammable.CanExtinguish)
}
}
}
else if (otherFlammable.OnFire)
{ {
otherFlammable.FireStacks /= 2; otherFlammable.FireStacks /= 2;
flammable.FireStacks += otherFlammable.FireStacks; UpdateAppearance(otherUid, otherFlammable);
Ignite(uid, otherUid, flammable); }
} }
} }
@@ -254,7 +255,7 @@ namespace Content.Server.Atmos.EntitySystems
// This is intended so that matches & candles can re-use code for un-shaded layers on in-hand sprites. // This is intended so that matches & candles can re-use code for un-shaded layers on in-hand sprites.
// However, this could cause conflicts if something is ACTUALLY both a toggleable light and flammable. // However, this could cause conflicts if something is ACTUALLY both a toggleable light and flammable.
// if that ever happens, then fire visuals will need to implement their own in-hand sprite management. // if that ever happens, then fire visuals will need to implement their own in-hand sprite management.
_appearance.SetData(uid, ToggleableLightVisuals.Enabled, true, appearance); _appearance.SetData(uid, ToggleableLightVisuals.Enabled, flammable.OnFire, appearance);
} }
public void AdjustFireStacks(EntityUid uid, float relativeFireStacks, FlammableComponent? flammable = null) public void AdjustFireStacks(EntityUid uid, float relativeFireStacks, FlammableComponent? flammable = null)
@@ -266,7 +267,7 @@ namespace Content.Server.Atmos.EntitySystems
if (flammable.OnFire && flammable.FireStacks <= 0) if (flammable.OnFire && flammable.FireStacks <= 0)
Extinguish(uid, flammable); Extinguish(uid, flammable);
else
UpdateAppearance(uid, flammable); UpdateAppearance(uid, flammable);
} }
@@ -282,8 +283,6 @@ namespace Content.Server.Atmos.EntitySystems
flammable.OnFire = false; flammable.OnFire = false;
flammable.FireStacks = 0; flammable.FireStacks = 0;
flammable.Collided.Clear();
UpdateAppearance(uid, flammable); UpdateAppearance(uid, flammable);
} }
@@ -409,24 +408,6 @@ namespace Content.Server.Atmos.EntitySystems
700f, 50f, uid, true); 700f, 50f, uid, true);
} }
for (var i = flammable.Collided.Count - 1; i >= 0; i--)
{
var otherUid = flammable.Collided[i];
if (!otherUid.IsValid() || !EntityManager.EntityExists(otherUid))
{
flammable.Collided.RemoveAt(i);
continue;
}
// TODO: Sloth, please save our souls!
// no
if (!_lookup.GetWorldAABB(uid, transform).Intersects(_lookup.GetWorldAABB(otherUid)))
{
flammable.Collided.RemoveAt(i);
}
}
} }
} }
} }

View File

@@ -77,13 +77,20 @@ public sealed class UseDelaySystem : EntitySystem
} }
} }
public void BeginDelay(EntityUid uid, UseDelayComponent? component = null) /// <summary>
/// Attempts tp start a use-delay for some entity. Returns true unless there is already an active delay.
/// </summary>
/// <remarks>
/// Note that this will always return true if the entity does not have a use delay component, as in that case there
/// is no reason to block/prevent an interaction.
/// </remarks>
public bool BeginDelay(EntityUid uid, UseDelayComponent? component = null)
{ {
if (!Resolve(uid, ref component, false)) if (!Resolve(uid, ref component, false))
return; return true;
if (component.ActiveDelay) if (component.ActiveDelay)
return; return false;
DebugTools.Assert(!_activeDelays.Contains(component)); DebugTools.Assert(!_activeDelays.Contains(component));
_activeDelays.Add(component); _activeDelays.Add(component);
@@ -91,12 +98,12 @@ public sealed class UseDelaySystem : EntitySystem
var currentTime = _gameTiming.CurTime; var currentTime = _gameTiming.CurTime;
component.LastUseTime = currentTime; component.LastUseTime = currentTime;
component.DelayEndTime = currentTime + component.Delay; component.DelayEndTime = currentTime + component.Delay;
Dirty(component); Dirty(uid, component);
// TODO just merge these components? var cooldown = EnsureComp<ItemCooldownComponent>(uid);
var cooldown = EnsureComp<ItemCooldownComponent>(component.Owner);
cooldown.CooldownStart = currentTime; cooldown.CooldownStart = currentTime;
cooldown.CooldownEnd = component.DelayEndTime; cooldown.CooldownEnd = component.DelayEndTime;
return true;
} }
public bool ActiveDelay(EntityUid uid, UseDelayComponent? component = null) public bool ActiveDelay(EntityUid uid, UseDelayComponent? component = null)