Flammable system bug fixes. (#21594)
This commit is contained in:
@@ -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)]
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user