private float _timer;
private readonly Dictionary<Entity<FlammableComponent>, float> _fireEvents = new();
+ private readonly List<EntityUid> _toRemove = new();
public override void Initialize()
{
SubscribeLocalEvent<IgniteOnMeleeHitComponent, MeleeHitEvent>(OnMeleeHit);
- SubscribeLocalEvent<ExtinguishOnInteractComponent, UseInHandEvent>(OnExtinguishUsingInHand);
SubscribeLocalEvent<ExtinguishOnInteractComponent, ActivateInWorldEvent>(OnExtinguishActivateInWorld);
}
private void OnExtinguishActivateInWorld(EntityUid uid, ExtinguishOnInteractComponent component, ActivateInWorldEvent args)
{
- TryHandExtinguish(uid, component);
- }
-
- private void OnExtinguishUsingInHand(EntityUid uid, ExtinguishOnInteractComponent component, UseInHandEvent args)
- {
- TryHandExtinguish(uid, component);
- }
+ if (args.Handled)
+ return;
- private void TryHandExtinguish(EntityUid uid, ExtinguishOnInteractComponent component)
- {
if (!TryComp(uid, out FlammableComponent? flammable))
return;
+
if (!flammable.OnFire)
return;
- if (TryComp(uid, out UseDelayComponent? useDelay) && _useDelay.ActiveDelay(uid, useDelay))
+
+ args.Handled = true;
+
+ if (!_useDelay.BeginDelay(uid))
return;
- _useDelay.BeginDelay(uid);
_audio.PlayPvs(component.ExtinguishAttemptSound, uid);
if (_random.Prob(component.Probability))
{
AdjustFireStacks(uid, component.StackDelta, flammable);
- } else
+ }
+ else
{
_popup.PopupEntity(Loc.GetString(component.ExtinguishFailed), uid);
}
{
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
// which don't collide with one another, shouldn't work here.
if (args.OtherFixtureId != FlammableFixtureID && args.OurFixtureId != FlammableFixtureID)
return;
- if (!EntityManager.TryGetComponent(otherUid, out FlammableComponent? otherFlammable))
+ if (!flammable.FireSpread)
+ return;
+
+ if (!TryComp(otherUid, out FlammableComponent? otherFlammable) || !otherFlammable.FireSpread)
return;
- if (!flammable.FireSpread || !otherFlammable.FireSpread)
+ 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 (otherFlammable.OnFire)
+ otherFlammable.FireStacks += flammable.FireStacks / 2;
+ Ignite(otherUid, uid, otherFlammable);
+ if (flammable.CanExtinguish)
{
- 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;
- Ignite(otherUid, uid, otherFlammable);
- }
- else
- {
- flammable.FireStacks /= 2;
- otherFlammable.FireStacks += flammable.FireStacks;
- Ignite(otherUid, uid, otherFlammable);
- }
+ flammable.FireStacks /= 2;
+ UpdateAppearance(uid, flammable);
}
}
- else if (otherFlammable.OnFire)
+ else
{
- otherFlammable.FireStacks /= 2;
- flammable.FireStacks += otherFlammable.FireStacks;
+ flammable.FireStacks += otherFlammable.FireStacks / 2;
Ignite(uid, otherUid, flammable);
+ if (otherFlammable.CanExtinguish)
+ {
+ otherFlammable.FireStacks /= 2;
+ UpdateAppearance(otherUid, otherFlammable);
+ }
}
}
// 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.
// 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)
if (flammable.OnFire && flammable.FireStacks <= 0)
Extinguish(uid, flammable);
-
- UpdateAppearance(uid, flammable);
+ else
+ UpdateAppearance(uid, flammable);
}
public void Extinguish(EntityUid uid, FlammableComponent? flammable = null)
flammable.OnFire = false;
flammable.FireStacks = 0;
- flammable.Collided.Clear();
-
UpdateAppearance(uid, flammable);
}
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);
- }
- }
}
}
}