/// <summary> /// Checks that the user and target of a /// <see cref="AfterInteractEvent"/> are within a certain distance /// without any entity that matches the collision mask obstructing them. /// If the <paramref name="range"/> is zero or negative, /// this method will only check if nothing obstructs the entity and component. /// </summary> /// <param name="args">The event args to use.</param> /// <param name="range"> /// Maximum distance between the two entity and set of map coordinates. /// </param> /// <param name="collisionMask">The mask to check for collisions.</param> /// <param name="predicate"> /// A predicate to check whether to ignore an entity or not. /// If it returns true, it will be ignored. /// </param> /// <param name="ignoreInsideBlocker"> /// If true and both the user and target are inside /// the obstruction, ignores the obstruction and considers the interaction /// unobstructed. /// Therefore, setting this to true makes this check more permissive, /// such as allowing an interaction to occur inside something impassable /// (like a wall). The default, false, makes the check more restrictive. /// </param> /// <param name="popup"> /// Whether or not to popup a feedback message on the user entity for /// it to see. /// </param> /// <returns> /// True if the two points are within a given range without being obstructed. /// </returns> public bool InRangeUnobstructed( AfterInteractEvent args, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored?predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { var user = args.User; var target = args.Target; predicate ??= e => e == user; MapCoordinates otherPosition; if (target == null) { otherPosition = args.ClickLocation.ToMap(EntityManager); } else { otherPosition = target.Transform.MapPosition; predicate += e => e == target; } return(InRangeUnobstructed(user, otherPosition, range, collisionMask, predicate, ignoreInsideBlocker, popup)); }
private void OnAfterInteract(EntityUid uid, RCDAmmoComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach) { return; } if (args.Target is not { Valid : true } target || !EntityManager.TryGetComponent(target, out RCDComponent? rcdComponent)) { return; } if (rcdComponent.MaxAmmo - rcdComponent.CurrentAmmo < component.RefillAmmo) { rcdComponent.Owner.PopupMessage(args.User, Loc.GetString("rcd-ammo-component-after-interact-full-text")); args.Handled = true; return; } rcdComponent.CurrentAmmo = Math.Min(rcdComponent.MaxAmmo, rcdComponent.CurrentAmmo + component.RefillAmmo); rcdComponent.Owner.PopupMessage(args.User, Loc.GetString("rcd-ammo-component-after-interact-refilled-text")); EntityManager.QueueDeleteEntity(uid); args.Handled = true; }
private void OnAfterInteract(EntityUid uid, SharpComponent component, AfterInteractEvent args) { if (!args.CanReach) { return; } if (args.Target is null || !TryComp <SharedButcherableComponent>(args.Target, out var butcher)) { return; } if (butcher.Type != ButcheringType.Knife) { return; } if (TryComp <MobStateComponent>(args.Target, out var mobState) && !mobState.IsDead()) { return; } if (!component.Butchering.Add(args.Target.Value)) { return; } var doAfter = new DoAfterEventArgs(args.User, component.ButcherDelayModifier * butcher.ButcherDelay, default, args.Target)
private void OnAfterInteract(EntityUid uid, EmagComponent component, AfterInteractEvent args) { if (!args.CanReach || args.Target == null) { return; } if (_tagSystem.HasTag(args.Target.Value, "EmagImmune")) { return; } if (component.Charges <= 0) { _popupSystem.PopupEntity(Loc.GetString("emag-no-charges"), args.User, Filter.Entities(args.User)); return; } var emaggedEvent = new GotEmaggedEvent(args.User); RaiseLocalEvent(args.Target.Value, emaggedEvent, false); if (emaggedEvent.Handled) { _popupSystem.PopupEntity(Loc.GetString("emag-success", ("target", Identity.Entity(args.Target.Value, EntityManager))), args.User, Filter.Entities(args.User), PopupType.Medium); _adminLogger.Add(LogType.Emag, LogImpact.High, $"{ToPrettyString(args.User):player} emagged {ToPrettyString(args.Target.Value):target}"); component.Charges--; return; } }
/// <summary> /// Feed someone else /// </summary> private void OnFeedFood(EntityUid uid, FoodComponent foodComponent, AfterInteractEvent args) { if (args.Handled || args.Target == null) { return; } if (!_actionBlockerSystem.CanInteract(args.User) || !_actionBlockerSystem.CanUse(args.User)) { return; } if (!args.User.InRangeUnobstructed(uid, popup: true)) { args.Handled = true; return; } if (args.User == args.Target) { args.Handled = TryUseFood(uid, args.User); return; } if (!args.User.InRangeUnobstructed(args.Target.Value, popup: true)) { args.Handled = true; return; } args.Handled = TryForceFeed(uid, args.User, args.Target.Value); }
private void OnInjectorAfterInteract(EntityUid uid, InjectorComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach) { return; } if (component.CancelToken != null) { args.Handled = true; return; } //Make sure we have the attacking entity if (args.Target is not { Valid : true } target || !HasComp <SolutionContainerManagerComponent>(uid)) { return; } // Is the target a mob? If yes, use a do-after to give them time to respond. if (HasComp <MobStateComponent>(target) || HasComp <BloodstreamComponent>(target)) { InjectDoAfter(component, args.User, target); args.Handled = true; return; } UseInjector(target, args.User, component); args.Handled = true; }
private void OnAfterInteract(EntityUid uid, AgentIDCardComponent component, AfterInteractEvent args) { if (!TryComp <AccessComponent>(args.Target, out var targetAccess) || !TryComp <IdCardComponent>(uid, out var targetIDCard) || args.Target == null) { return; } if (!TryComp <AccessComponent>(uid, out var access) || !TryComp <IdCardComponent>(uid, out var idCard)) { return; } var beforeLength = access.Tags.Count; access.Tags.UnionWith(targetAccess.Tags); var addedLength = access.Tags.Count - beforeLength; if (addedLength == 0) { _popupSystem.PopupEntity(Loc.GetString("agent-id-no-new", ("card", args.Target)), args.Target.Value, Filter.Entities(args.User)); return; } else if (addedLength == 1) { _popupSystem.PopupEntity(Loc.GetString("agent-id-new-1", ("card", args.Target)), args.Target.Value, Filter.Entities(args.User)); return; } _popupSystem.PopupEntity(Loc.GetString("agent-id-new", ("number", addedLength), ("card", args.Target)), args.Target.Value, Filter.Entities(args.User)); }
private void OnAfterInteract(EntityUid uid, BibleComponent component, AfterInteractEvent args) { if (!args.CanReach) { return; } var currentTime = _gameTiming.CurTime; if (currentTime < component.CooldownEnd) { return; } if (args.Target == null || args.Target == args.User || !HasComp <MobStateComponent>(args.Target)) { return; } component.LastAttackTime = currentTime; component.CooldownEnd = component.LastAttackTime + TimeSpan.FromSeconds(component.CooldownTime); RaiseLocalEvent(uid, new RefreshItemCooldownEvent(component.LastAttackTime, component.CooldownEnd), false); if (!HasComp <BibleUserComponent>(args.User)) { _popupSystem.PopupEntity(Loc.GetString("bible-sizzle"), args.User, Filter.Entities(args.User)); SoundSystem.Play(Filter.Pvs(args.User), "/Audio/Effects/lightburn.ogg", args.User); _damageableSystem.TryChangeDamage(args.User, component.DamageOnUntrainedUse, true); return; } if (!_invSystem.TryGetSlotEntity(args.Target.Value, "head", out var entityUid)) { if (_random.Prob(component.FailChance)) { var othersFailMessage = Loc.GetString("bible-heal-fail-others", ("user", args.User), ("target", args.Target), ("bible", uid)); _popupSystem.PopupEntity(othersFailMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User)); var selfFailMessage = Loc.GetString("bible-heal-fail-self", ("target", args.Target), ("bible", uid)); _popupSystem.PopupEntity(selfFailMessage, args.User, Filter.Entities(args.User)); SoundSystem.Play(Filter.Pvs(args.Target.Value), "/Audio/Effects/hit_kick.ogg", args.User); _damageableSystem.TryChangeDamage(args.Target.Value, component.DamageOnFail, true); return; } } var othersMessage = Loc.GetString("bible-heal-success-others", ("user", args.User), ("target", args.Target), ("bible", uid)); _popupSystem.PopupEntity(othersMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User)); var selfMessage = Loc.GetString("bible-heal-success-self", ("target", args.Target), ("bible", uid)); _popupSystem.PopupEntity(selfMessage, args.User, Filter.Entities(args.User)); SoundSystem.Play(Filter.Pvs(args.Target.Value), "/Audio/Effects/holy.ogg", args.User); _damageableSystem.TryChangeDamage(args.Target.Value, component.Damage, true); }
private void AfterInteract(EntityUid uid, DrinkComponent component, AfterInteractEvent args) { if (args.Handled || args.Target == null || !args.CanReach) { return; } args.Handled = TryDrink(args.User, args.Target.Value, component); }
/// <summary> /// Feed someone else /// </summary> private void OnFeedFood(EntityUid uid, FoodComponent foodComponent, AfterInteractEvent args) { if (args.Handled || args.Target == null || !args.CanReach) { return; } args.Handled = TryFeed(args.User, args.Target.Value, foodComponent); }
private void OnAfterInteract(EntityUid uid, SharpComponent component, AfterInteractEvent args) { if (args.Target is null || !args.CanReach) { return; } TryStartButcherDoafter(uid, args.Target.Value, args.User); }
private void OnAfterInteract(EntityUid uid, StickyComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach || args.Target == null) { return; } // try stick object to a clicked target entity args.Handled = StartSticking(uid, args.User, args.Target.Value, component); }
private void OnHealingAfterInteract(EntityUid uid, HealingComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach || args.Target == null) { return; } args.Handled = true; Heal(uid, args.User, args.Target.Value, component); }
private void OnAfterInteract(EntityUid uid, FloorTileComponent component, AfterInteractEvent args) { if (!args.CanReach) { return; } if (!TryComp <StackComponent>(uid, out var stack)) { return; } if (component.OutputTiles == null) { return; } // this looks a bit sussy but it might be because it needs to be able to place off of grids and expand them var location = args.ClickLocation.AlignWithClosestGridTile(); var locationMap = location.ToMap(EntityManager); if (locationMap.MapId == MapId.Nullspace) { return; } _mapManager.TryGetGrid(location.GetGridId(EntityManager), out var mapGrid); foreach (var currentTile in component.OutputTiles) { var currentTileDefinition = (ContentTileDefinition)_tileDefinitionManager[currentTile]; if (mapGrid != null) { var tile = mapGrid.GetTileRef(location); var baseTurf = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId]; if (HasBaseTurf(currentTileDefinition, baseTurf.ID)) { if (!_stackSystem.Use(uid, 1, stack)) { continue; } PlaceAt(mapGrid, location, currentTileDefinition.TileId, component.PlaceTileSound); } } else if (HasBaseTurf(currentTileDefinition, "space")) { mapGrid = _mapManager.CreateGrid(locationMap.MapId); mapGrid.WorldPosition = locationMap.Position; location = new EntityCoordinates(mapGrid.GridEntityId, Vector2.Zero); PlaceAt(mapGrid, location, _tileDefinitionManager[component.OutputTiles[0]].TileId, component.PlaceTileSound, mapGrid.TileSize / 2f); } } }
public void OnAfterInteract(EntityUid uid, HyposprayComponent comp, AfterInteractEvent args) { if (!args.CanReach) { return; } var target = args.Target; var user = args.User; comp.TryDoInject(target, user); }
public static bool InRangeUnobstructed( this AfterInteractEvent args, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored?predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { return(SharedInteractionSystem.InRangeUnobstructed(args, range, collisionMask, predicate, ignoreInsideBlocker, popup)); }
private void OnCuffAfterInteract(EntityUid uid, HandcuffComponent component, AfterInteractEvent args) { if (component.Cuffing) { return; } if (args.Target is not { Valid : true } target || !EntityManager.TryGetComponent <CuffableComponent>(args.Target.Value, out var cuffed)) { return; } if (component.Broken) { args.User.PopupMessage(Loc.GetString("handcuff-component-cuffs-broken-error")); return; } if (!EntityManager.TryGetComponent <HandsComponent?>(target, out var hands)) { args.User.PopupMessage(Loc.GetString("handcuff-component-target-has-no-hands-error", ("targetName", args.Target))); return; } if (cuffed.CuffedHandCount >= hands.Count) { args.User.PopupMessage(Loc.GetString("handcuff-component-target-has-no-free-hands-error", ("targetName", args.Target))); return; } if (!args.CanReach) { args.User.PopupMessage(Loc.GetString("handcuff-component-too-far-away-error")); return; } if (args.Target == args.User) { args.User.PopupMessage(Loc.GetString("handcuff-component-target-self")); } else { args.User.PopupMessage(Loc.GetString("handcuff-component-start-cuffing-target-message", ("targetName", args.Target))); args.User.PopupMessage(target, Loc.GetString("handcuff-component-start-cuffing-by-other-message", ("otherName", args.User))); } SoundSystem.Play(component.StartCuffSound.GetSound(), Filter.Pvs(uid), uid); component.TryUpdateCuff(args.User, target, cuffed); args.Handled = true; }
/// <summary> /// Clicked with utensil /// </summary> private void OnAfterInteract(EntityUid uid, UtensilComponent component, AfterInteractEvent ev) { if (ev.Target == null) { return; } if (TryUseUtensil(ev.User, ev.Target.Value, component)) { ev.Handled = true; } }
private void OnCrayonAfterInteract(EntityUid uid, CrayonComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach) { return; } if (component.Charges <= 0) { if (component.DeleteEmpty) { UseUpCrayon(uid, args.User); } else { _popup.PopupEntity(Loc.GetString("crayon-interact-not-enough-left-text"), uid, Filter.Entities(args.User)); } args.Handled = true; return; } if (!args.ClickLocation.IsValid(EntityManager)) { _popup.PopupEntity(Loc.GetString("crayon-interact-invalid-location"), uid, Filter.Entities(args.User)); args.Handled = true; return; } if (!_decals.TryAddDecal(component.SelectedState, args.ClickLocation.Offset(new Vector2(-0.5f, -0.5f)), out _, Color.FromName(component._color), cleanable: true)) { return; } if (component.UseSound != null) { SoundSystem.Play(Filter.Pvs(uid), component.UseSound.GetSound(), uid, AudioHelpers.WithVariation(0.125f)); } // Decrease "Ammo" component.Charges--; Dirty(component); _logs.Add(LogType.CrayonDraw, LogImpact.Low, $"{EntityManager.ToPrettyString(args.User):user} drew a {component._color:color} {component.SelectedState}"); args.Handled = true; if (component.DeleteEmpty && component.Charges <= 0) { UseUpCrayon(uid, args.User); } }
private void OnAfterInteract(EntityUid uid, GasAnalyzerComponent component, AfterInteractEvent args) { if (!args.CanReach) { _popup.PopupEntity(Loc.GetString("gas-analyzer-component-player-cannot-reach-message"), args.User, Filter.Entities(args.User)); return; } if (TryComp(args.User, out ActorComponent? actor)) { component.OpenInterface(actor.PlayerSession, args.ClickLocation); } args.Handled = true; }
private void OnAfterInteract(EntityUid uid, FireExtinguisherComponent component, AfterInteractEvent args) { if (args.Target == null || !args.CanReach) { return; } if (args.Handled) { return; } args.Handled = true; if (component.HasSafety && component.Safety) { _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), uid, Filter.Entities(args.User)); return; } if (args.Target is not { Valid : true } target || !_solutionContainerSystem.TryGetDrainableSolution(target, out var targetSolution) || !_solutionContainerSystem.TryGetRefillableSolution(uid, out var container)) { return; } var transfer = container.AvailableVolume; if (TryComp <SolutionTransferComponent>(uid, out var solTrans)) { transfer = solTrans.TransferAmount; } transfer = FixedPoint2.Min(transfer, targetSolution.DrainAvailable); if (transfer > 0) { var drained = _solutionContainerSystem.Drain(target, targetSolution, transfer); _solutionContainerSystem.TryAddSolution(uid, container, drained); SoundSystem.Play(Filter.Pvs(uid), component.RefillSound.GetSound(), uid); _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-after-interact-refilled-message", ("owner", uid)), uid, Filter.Entities(args.Target.Value)); } }
private void OnAfterInteract(EntityUid uid, DoorRemoteComponent component, AfterInteractEvent args) { if (args.Handled || args.Target == null || !TryComp <DoorComponent>(args.Target, out var doorComponent) || // If it isn't a door we don't use it !HasComp <AccessReaderComponent>(args.Target) || // Remotes do not work on doors without access requirements !TryComp <AirlockComponent>(args.Target, out var airlockComponent) || // Remotes only work on airlocks !_interactionSystem.InRangeUnobstructed(args.User, doorComponent.Owner, -1f, CollisionGroup.Opaque)) { return; } args.Handled = true; if (component.Mode == DoorRemoteComponent.OperatingMode.OpenClose) { _sharedDoorSystem.TryToggleDoor(doorComponent.Owner, user: args.Used); } if (component.Mode == DoorRemoteComponent.OperatingMode.ToggleBolts && airlockComponent.IsPowered()) { if (_doorSystem.HasAccess(doorComponent.Owner, args.Used)) { airlockComponent.SetBoltsWithAudio(!airlockComponent.IsBolted()); } else { if (doorComponent.State != DoorState.Open) { _sharedDoorSystem.Deny(airlockComponent.Owner, user: args.User); } else if (doorComponent.DenySound != null) { SoundSystem.Play(Filter.Pvs(args.Target.Value), doorComponent.DenySound.GetSound(), args.Target.Value); } } } if (component.Mode == DoorRemoteComponent.OperatingMode.ToggleEmergencyAccess && airlockComponent.IsPowered()) { if (_doorSystem.HasAccess(doorComponent.Owner, args.Used)) { _sharedAirlockSystem.ToggleEmergencyAccess(airlockComponent); } } }
private void OnAfterInteract(EntityUid uid, ResearchDiskComponent component, AfterInteractEvent args) { if (!args.CanReach) { return; } if (!TryComp <ResearchServerComponent>(args.Target, out var server)) { return; } server.Points += component.Points; _popupSystem.PopupEntity(Loc.GetString("research-disk-inserted", ("points", component.Points)), args.Target.Value, Filter.Entities(args.User)); EntityManager.QueueDeleteEntity(uid); }
private void OnAfterInteract(EntityUid uid, PriceGunComponent component, AfterInteractEvent args) { if (!args.CanReach || args.Target == null) { return; } if (TryComp(args.Used, out UseDelayComponent? useDelay) && useDelay.ActiveDelay) { return; } var price = _pricingSystem.GetPrice(args.Target.Value); _popupSystem.PopupEntity(Loc.GetString("price-gun-pricing-result", ("object", args.Target.Value), ("price", $"{price:F2}")), args.User, Filter.Entities(args.User)); _useDelay.BeginDelay(uid, useDelay); }
/// <summary> /// Used for melee weapons that want some behavior on AfterInteract, /// but also want the cooldown (stun batons, flashes) /// </summary> private void OnAfterInteract(EntityUid uid, MeleeWeaponComponent comp, AfterInteractEvent args) { if (!args.CanReach) { return; } var curTime = _gameTiming.CurTime; if (curTime < comp.CooldownEnd) { return; } var owner = EntityManager.GetEntity(uid); if (args.Target == null) { return; } var location = args.User.Transform.Coordinates; var diff = args.ClickLocation.ToMapPos(owner.EntityManager) - location.ToMapPos(owner.EntityManager); var angle = Angle.FromWorldVec(diff); var hitEvent = new MeleeInteractEvent(args.Target, args.User); RaiseLocalEvent(uid, hitEvent, false); if (!hitEvent.CanInteract) { return; } SendAnimation(comp.ClickArc, angle, args.User, owner, new List <IEntity>() { args.Target }, comp.ClickAttackEffect, false); comp.LastAttackTime = curTime; comp.CooldownEnd = comp.LastAttackTime + TimeSpan.FromSeconds(comp.CooldownTime); RaiseLocalEvent(uid, new RefreshItemCooldownEvent(comp.LastAttackTime, comp.CooldownEnd), false); }
private void OnAfterInteract(EntityUid uid, ForensicPadComponent component, AfterInteractEvent args) { if (component.CancelToken != null || !args.CanReach || args.Target == null) { return; } if (HasComp <ForensicScannerComponent>(args.Target)) { return; } args.Handled = true; if (component.Used) { _popupSystem.PopupEntity(Loc.GetString("forensic-pad-already-used"), args.Target.Value, Filter.Entities(args.User)); return; } if (_inventory.TryGetSlotEntity(args.Target.Value, "gloves", out var gloves)) { _popupSystem.PopupEntity(Loc.GetString("forensic-pad-gloves", ("target", Identity.Entity(args.Target.Value, EntityManager))), args.Target.Value, Filter.Entities(args.User)); return; } if (TryComp <FingerprintComponent>(args.Target, out var fingerprint) && fingerprint.Fingerprint != null) { if (args.User != args.Target) { _popupSystem.PopupEntity(Loc.GetString("forensic-pad-start-scan-user", ("target", Identity.Entity(args.Target.Value, EntityManager))), args.Target.Value, Filter.Entities(args.User)); _popupSystem.PopupEntity(Loc.GetString("forensic-pad-start-scan-target", ("user", Identity.Entity(args.User, EntityManager))), args.Target.Value, Filter.Entities(args.Target.Value)); } StartScan(args.User, args.Target.Value, component, fingerprint.Fingerprint); return; } if (TryComp <FiberComponent>(args.Target, out var fiber)) { StartScan(args.User, args.Target.Value, component, string.IsNullOrEmpty(fiber.FiberColor) ? Loc.GetString("forensic-fibers", ("material", fiber.FiberMaterial)) : Loc.GetString("forensic-fibers-colored", ("color", fiber.FiberColor), ("material", fiber.FiberMaterial))); } }
public static bool InRangeUnobstructed( this AfterInteractEvent args, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored?predicate = null, bool ignoreInsideBlocker = false, bool popup = false) { var user = args.User; var target = args.Target; if (target == null) { return(SharedInteractionSystem.InRangeUnobstructed(user, args.ClickLocation, range, collisionMask, predicate, ignoreInsideBlocker, popup)); } else { return(SharedInteractionSystem.InRangeUnobstructed(user, target.Value, range, collisionMask, predicate, ignoreInsideBlocker, popup)); } }
private void OnAfterInteract(EntityUid uid, TelecrystalComponent component, AfterInteractEvent args) { if (args.Handled || !args.CanReach) { return; } if (args.Target == null || !EntityManager.TryGetComponent(args.Target.Value, out UplinkComponent? uplink)) { return; } // TODO: when uplink will have some auth logic (like PDA ringtone code) // check if uplink open before adding TC // No metagaming by using this on every PDA around just to see if it gets used up. var acc = uplink.UplinkAccount; if (acc == null) { return; } EntityManager.TryGetComponent(uid, out SharedStackComponent? stack); var tcCount = stack != null ? stack.Count : 1; if (!_accounts.AddToBalance(acc, tcCount)) { return; } var msg = Loc.GetString("telecrystal-component-sucs-inserted", ("source", args.Used), ("target", args.Target)); args.User.PopupMessage(args.User, msg); EntityManager.DeleteEntity(uid); args.Handled = true; }
private void AfterInteract(EntityUid uid, DrinkComponent component, AfterInteractEvent args) { if (args.Handled || args.Target == null) { return; } if (!_actionBlockerSystem.CanInteract(args.User) || !_actionBlockerSystem.CanUse(args.User)) { return; } if (!args.User.InRangeUnobstructed(uid, popup: true)) { args.Handled = true; return; } if (args.User == args.Target) { args.Handled = TryUseDrink(uid, args.User); return; } if (!args.User.InRangeUnobstructed(args.Target.Value, popup: true)) { args.Handled = true; return; } if (args.User == args.Target) { args.Handled = TryUseDrink(uid, args.User, component); } else { args.Handled = TryForceDrink(uid, args.User, args.Target.Value, component); } }
private void OnAfterInteract(EntityUid uid, AbsorbentComponent component, AfterInteractEvent args) { if (!args.CanReach) // if user cannot reach the target { return; } if (args.Handled) // if the event was already handled { return; } _solutionSystem.TryGetSolution(args.Used, AbsorbentComponent.SolutionName, out var absorbedSolution); if (absorbedSolution is null) { return; } var toolAvailableVolume = absorbedSolution.AvailableVolume; var toolCurrentVolume = absorbedSolution.CurrentVolume; // For adding liquid to an empty floor tile if (args.Target is null) // if a tile is clicked { ReleaseToFloor(args.ClickLocation, component, absorbedSolution); args.Handled = true; args.User.PopupMessage(args.User, Loc.GetString("mopping-system-release-to-floor")); return; } else if (args.Target is not null) { // Handle our do_after logic HandleDoAfter(args.User, args.Used, args.Target.Value, component, toolCurrentVolume, toolAvailableVolume); } args.Handled = true; return; }