void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) { if (!InteractionChecks.InRangeUnobstructed(eventArgs)) { return; } if (eventArgs.Target == null) { return; } if (!eventArgs.Target.TryGetComponent(out DamageableComponent damagecomponent)) { return; } if (Owner.TryGetComponent(out StackComponent stackComponent)) { if (!stackComponent.Use(1)) { Owner.Delete(); return; } damagecomponent.TakeHealing(Damage, Heal); return; } damagecomponent.TakeHealing(Damage, Heal); Owner.Delete(); }
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) { if (!InteractionChecks.InRangeUnobstructed(eventArgs)) { return; } if (eventArgs.Target == null) { return; } if (eventArgs.Target.TryGetComponent <BodySystem.BodyManagerComponent>(out BodySystem.BodyManagerComponent bodyManager)) { _surgeryOptionsCache.Clear(); var toSend = new Dictionary <string, string>(); foreach (var(key, value) in bodyManager.PartDictionary) { if (value.SurgeryCheck(_surgeryToolClass)) { _surgeryOptionsCache.Add(key, value); toSend.Add(key, value.Name); } } if (_surgeryOptionsCache.Count > 0) { OpenSurgeryUI(eventArgs.User); UpdateSurgeryUI(eventArgs.User, toSend); _performerCache = eventArgs.User; _targetCache = bodyManager; } } }
/// <summary> /// Called when clicking on entities while holding in active hand /// </summary> /// <param name="eventArgs"></param> void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) { if (!InteractionChecks.InRangeUnobstructed(eventArgs)) { return; } //Make sure we have the attacking entity if (eventArgs.Target == null || !_internalContents.Injector) { return; } var targetEntity = eventArgs.Target; //Handle injecting/drawing for solutions if (targetEntity.TryGetComponent <SolutionComponent>(out var targetSolution) && targetSolution.Injectable) { if (_toggleState == InjectorToggleMode.Inject) { TryInject(targetSolution, eventArgs.User); } else if (_toggleState == InjectorToggleMode.Draw) { TryDraw(targetSolution, eventArgs.User); } }
private void InteractionActivate(IEntity user, IEntity used) { var activateMsg = new ActivateInWorldMessage(user, used); RaiseLocalEvent(activateMsg); if (activateMsg.Handled) { return; } if (!used.TryGetComponent(out IActivate activateComp)) { return; } // all activates should only fire when in range / unbostructed var activateEventArgs = new ActivateEventArgs { User = user, Target = used }; if (InteractionChecks.InRangeUnobstructed(activateEventArgs)) { activateComp.Activate(activateEventArgs); } }
/// <inheritdoc /> public void AfterInteract(AfterInteractEventArgs eventArgs) { if (!InteractionChecks.InRangeUnobstructed(eventArgs)) { return; } if (!_mapManager.TryGetGrid(eventArgs.ClickLocation.GridID, out var grid)) { return; } var snapPos = grid.SnapGridCellFor(eventArgs.ClickLocation, SnapGridOffset.Center); var snapCell = grid.GetSnapGridCell(snapPos, SnapGridOffset.Center); if (grid.GetTileRef(snapPos).Tile.IsEmpty) { return; } foreach (var snapComp in snapCell) { if (snapComp.Owner.TryGetComponent <WireComponent>(out var wire) && wire.WireType == _blockingWireType) { return; } } if (Owner.TryGetComponent(out StackComponent stack) && !stack.Use(1)) { return; } _entityManager.SpawnEntity(_wirePrototypeID, grid.GridTileToLocal(snapPos)); }
public override Outcome Execute(float frameTime) { if (!ContainerHelpers.TryGetContainer(_target, out var container)) { return(Outcome.Success); } if (!InteractionChecks.InRangeUnobstructed(_owner, container.Owner.Transform.MapPosition, ignoredEnt: container.Owner)) { return(Outcome.Failed); } if (!container.Owner.TryGetComponent(out EntityStorageComponent? storageComponent) || storageComponent.IsWeldedShut) { return(Outcome.Failed); } if (!storageComponent.Open) { var activateArgs = new ActivateEventArgs { User = _owner, Target = _target }; storageComponent.Activate(activateArgs); } var blackboard = UtilityAiHelpers.GetBlackboard(_owner); blackboard?.GetState <LastOpenedStorageState>().SetValue(container.Owner); return(Outcome.Success); }
/// <summary> /// Uses an empty hand on an entity /// Finds components with the InteractHand interface and calls their function /// </summary> public void Interaction(IEntity user, IEntity attacked) { var message = new AttackHandMessage(user, attacked); RaiseLocalEvent(message); if (message.Handled) { return; } var attackHands = attacked.GetAllComponents <IInteractHand>().ToList(); var attackHandEventArgs = new InteractHandEventArgs { User = user, Target = attacked }; // all attackHands should only fire when in range / unbostructed if (InteractionChecks.InRangeUnobstructed(attackHandEventArgs)) { foreach (var attackHand in attackHands) { if (attackHand.InteractHand(attackHandEventArgs)) { // If an InteractHand returns a status completion we finish our attack return; } } } // Else we run Activate. InteractionActivate(user, attacked); }
private bool TryStartStructureConstruction(IEntity placingEnt, GridCoordinates loc, string prototypeName, Angle angle) { var prototype = _prototypeManager.Index <ConstructionPrototype>(prototypeName); if (!InteractionChecks.InRangeUnobstructed(placingEnt, loc.ToMap(_mapManager), ignoredEnt: placingEnt, insideBlockerValid: prototype.CanBuildInImpassable)) { return(false); } if (prototype.Stages.Count < 2) { throw new InvalidOperationException($"Prototype '{prototypeName}' does not have enough stages."); } var stage0 = prototype.Stages[0]; if (!(stage0.Forward is ConstructionStepMaterial matStep)) { throw new NotImplementedException(); } // Try to find the stack with the material in the user's hand. var hands = placingEnt.GetComponent <HandsComponent>(); var activeHand = hands.GetActiveHand?.Owner; if (activeHand == null) { return(false); } if (!activeHand.TryGetComponent(out StackComponent stack) || !ConstructionComponent.MaterialStackValidFor(matStep, stack)) { return(false); } if (!stack.Use(matStep.Amount)) { return(false); } // OK WE'RE GOOD CONSTRUCTION STARTED. Get <AudioSystem>().PlayAtCoords("/Audio/items/deconstruct.ogg", loc); if (prototype.Stages.Count == 2) { // Exactly 2 stages, so don't make an intermediate frame. var ent = _serverEntityManager.SpawnEntity(prototype.Result, loc); ent.Transform.LocalRotation = angle; } else { var frame = _serverEntityManager.SpawnEntity("structureconstructionframe", loc); var construction = frame.GetComponent <ConstructionComponent>(); construction.Init(prototype); frame.Transform.LocalRotation = angle; } return(true); }
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) { if (!InteractionChecks.InRangeUnobstructed(eventArgs)) { return; } UseFood(eventArgs.Target); }
/// <inheritdoc /> public void AfterInteract(AfterInteractEventArgs eventArgs) { if (!InteractionChecks.InRangeUnobstructed(eventArgs)) { return; } if (!_mapManager.TryGetGrid(eventArgs.ClickLocation.GridID, out var grid)) { return; } var snapPos = grid.SnapGridCellFor(eventArgs.ClickLocation, SnapGridOffset.Center); var snapCell = grid.GetSnapGridCell(snapPos, SnapGridOffset.Center); if (grid.GetTileRef(snapPos).Tile.IsEmpty) { return; } var found = false; foreach (var snapComp in snapCell) { if (!snapComp.Owner.HasComponent <PowerTransferComponent>()) { continue; } found = true; break; } if (found) { return; } bool hasItemSpriteComp = Owner.TryGetComponent(out SpriteComponent itemSpriteComp); if (Owner.TryGetComponent(out StackComponent stack) && !stack.Use(1)) { return; } GridCoordinates coordinates = grid.GridTileToLocal(snapPos); var newWire = _entityManager.SpawnEntity("Wire", coordinates); if (newWire.TryGetComponent(out SpriteComponent wireSpriteComp) && hasItemSpriteComp) { wireSpriteComp.Color = itemSpriteComp.Color; } //TODO: There is no way to set this wire as above or below the floor }
public bool InteractUsing(InteractUsingEventArgs eventArgs) { // default interaction check for AttackBy allows inside blockers, so we will check if its blocked if // we're not allowed to build on impassable stuff if (Prototype.CanBuildInImpassable == false) { if (!InteractionChecks.InRangeUnobstructed(eventArgs, false)) { return(false); } } var stage = Prototype.Stages[Stage]; if (TryProcessStep(stage.Forward, eventArgs.Using, eventArgs.User)) { Stage++; if (Stage == Prototype.Stages.Count - 1) { // Oh boy we get to finish construction! var entMgr = IoCManager.Resolve <IServerEntityManager>(); var ent = entMgr.SpawnEntity(Prototype.Result, Transform.GridPosition); ent.GetComponent <ITransformComponent>().LocalRotation = Transform.LocalRotation; Owner.Delete(); return(true); } stage = Prototype.Stages[Stage]; if (stage.Icon != null) { Sprite.LayerSetSprite(0, stage.Icon); } } else if (TryProcessStep(stage.Backward, eventArgs.Using, eventArgs.User)) { Stage--; if (Stage == 0) { // Deconstruction complete. Owner.Delete(); return(true); } stage = Prototype.Stages[Stage]; if (stage.Icon != null) { Sprite.LayerSetSprite(0, stage.Icon); } } return(true); }
///<summary> /// Method to handle clicking on a tile to then appropriately RCD it. This can have several behaviours depending on mode. /// @param eventAargs = An action event telling us what tile was clicked on. We use this to exrapolate where to place the new tile / remove the old one etc. ///</summary> public void AfterInteract(AfterInteractEventArgs eventArgs) { var mapGrid = _mapManager.GetGrid(eventArgs.ClickLocation.GridID); var tile = mapGrid.GetTileRef(eventArgs.ClickLocation); var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); //Less expensive checks first. Failing those ones, we need to check that the tile isn't obstructed. if (_ammo <= 0 || coordinates == GridCoordinates.InvalidGrid || !InteractionChecks.InRangeUnobstructed(eventArgs)) { return; } var targetTile = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId]; var canPlaceTile = targetTile.IsSubFloor; //Boolean to check if we're able to build the desired tile. This defaults to checking for subfloors, but is overridden by "deconstruct" which sets it to the inverse. switch (this._mode) { //Floor mode just needs the tile to be a space tile (subFloor) case RcdMode.Floors: break; //We don't want to place a space tile on something that's already a space tile. Let's do the inverse of the last check. case RcdMode.Deconstruct: canPlaceTile = !targetTile.IsSubFloor; break; //Walls are a special behaviour, and require us to build a new object with a transform rather than setting a grid tile, thus we early return to avoid the tile set code. case RcdMode.Walls: var snapPos = mapGrid.SnapGridCellFor(eventArgs.ClickLocation, SnapGridOffset.Center); var ent = _serverEntityManager.SpawnEntity("solid_wall", mapGrid.GridTileToLocal(snapPos)); ent.Transform.LocalRotation = Owner.Transform.LocalRotation; //Now apply icon smoothing. _entitySystemManager.GetEntitySystem <AudioSystem>().PlayFromEntity("/Audio/Items/deconstruct.ogg", Owner); _ammo--; return; //Alright we're done here default: return; //I don't know why this would happen, but sure I guess. Get out of here invalid state! } ITileDefinition desiredTile = null; desiredTile = _tileDefinitionManager[_outputTile]; if (canPlaceTile) //If desiredTile is null by this point, something has gone horribly wrong and you need to fix it. { mapGrid.SetTile(eventArgs.ClickLocation, new Tile(desiredTile.TileId)); _entitySystemManager.GetEntitySystem <AudioSystem>().PlayFromEntity("/Audio/Items/deconstruct.ogg", Owner); _ammo--; } }
/// <summary> /// Uses a weapon/object on an entity /// Finds components with the InteractUsing interface and calls their function /// </summary> public void Interaction(IEntity user, IEntity weapon, IEntity attacked, GridCoordinates clickLocation) { var attackMsg = new AttackByMessage(user, weapon, attacked, clickLocation); RaiseLocalEvent(attackMsg); if (attackMsg.Handled) { return; } var attackBys = attacked.GetAllComponents <IInteractUsing>().ToList(); var attackByEventArgs = new InteractUsingEventArgs { User = user, ClickLocation = clickLocation, Using = weapon, Target = attacked }; // all AttackBys should only happen when in range / unobstructed, so no range check is needed if (InteractionChecks.InRangeUnobstructed(attackByEventArgs)) { foreach (var attackBy in attackBys) { if (attackBy.InteractUsing(attackByEventArgs)) { // If an InteractUsing returns a status completion we finish our attack return; } } } var afterAtkMsg = new AfterAttackMessage(user, weapon, attacked, clickLocation); RaiseLocalEvent(afterAtkMsg); if (afterAtkMsg.Handled) { return; } // If we aren't directly attacking the nearby object, lets see if our item has an after attack we can do var afterAttacks = weapon.GetAllComponents <IAfterInteract>().ToList(); var afterAttackEventArgs = new AfterInteractEventArgs { User = user, ClickLocation = clickLocation, Target = attacked }; foreach (var afterAttack in afterAttacks) { afterAttack.AfterInteract(afterAttackEventArgs); } }
public static void FlashAreaHelper(IEntity source, float range, float duration, string sound = null) { foreach (var entity in IoCManager.Resolve<IEntityManager>().GetEntitiesInRange(source.Transform.GridPosition, range)) { if (!InteractionChecks.InRangeUnobstructed(source, entity.Transform.MapPosition, range, ignoredEnt:entity)) continue; if(entity.TryGetComponent(out FlashableComponent flashable)) flashable.Flash(duration); } if (!string.IsNullOrEmpty(sound)) { IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>().PlayAtCoords(sound, source.Transform.GridPosition); } }
public bool TryUnbuckle(IEntity user, bool force = false) { if (BuckledTo == null) { return(false); } if (!force) { if (!ActionBlockerSystem.CanInteract(user)) { _notifyManager.PopupMessage(user, user, Loc.GetString("You can't do that!")); return(false); } var strapPosition = Owner.Transform.MapPosition; var range = SharedInteractionSystem.InteractionRange / 2; if (!InteractionChecks.InRangeUnobstructed(user, strapPosition, range)) { _notifyManager.PopupMessage(user, user, Loc.GetString("You can't reach there!")); return(false); } } if (BuckledTo.Owner.TryGetComponent(out StrapComponent strap)) { strap.Remove(this); _entitySystem.GetEntitySystem <AudioSystem>() .PlayFromEntity(strap.UnbuckleSound, Owner); } Owner.Transform.DetachParent(); Owner.Transform.WorldRotation = BuckledTo.Owner.Transform.WorldRotation; BuckledTo = null; if (Owner.TryGetComponent(out AppearanceComponent appearance)) { appearance.SetData(BuckleVisuals.Buckled, false); } if (Owner.TryGetComponent(out StunnableComponent stunnable) && stunnable.KnockedDown) { StandingStateHelper.Down(Owner); }
public bool CanPickup(IEntity user) { if (!ActionBlockerSystem.CanPickup(user)) { return(false); } if (user.Transform.MapID != Owner.Transform.MapID) { return(false); } var userPos = user.Transform.MapPosition; var itemPos = Owner.Transform.WorldPosition; return(InteractionChecks.InRangeUnobstructed(user, itemPos, ignoredEnt: Owner, insideBlockerValid: true)); }
public void AfterInteract(AfterInteractEventArgs eventArgs) { if (!InteractionChecks.InRangeUnobstructed(eventArgs)) { return; } var attacked = eventArgs.Target; var mapGrid = _mapManager.GetGrid(eventArgs.ClickLocation.GridID); var tile = mapGrid.GetTileRef(eventArgs.ClickLocation); var tileDef = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId]; if (tileDef.IsSubFloor && attacked == null && _stack.Use(1)) { var desiredTile = _tileDefinitionManager[_outputTile]; mapGrid.SetTile(eventArgs.ClickLocation, new Tile(desiredTile.TileId)); EntitySystem.Get <AudioSystem>().PlayAtCoords("/Audio/Items/genhit.ogg", eventArgs.ClickLocation); } }
// TODO: When I spawn new entities they seem to duplicate clothing or something? public override Outcome Execute(float frameTime) { if (_target == null || _target.Deleted || !_target.HasComponent <ItemComponent>() || ContainerHelpers.IsInContainer(_target) || !InteractionChecks.InRangeUnobstructed(_owner, _target.Transform.MapPosition)) { return(Outcome.Failed); } if (!_owner.TryGetComponent(out HandsComponent handsComponent)) { return(Outcome.Failed); } var emptyHands = false; foreach (var hand in handsComponent.ActivePriorityEnumerable()) { if (handsComponent.GetItem(hand) == null) { if (handsComponent.ActiveHand != hand) { handsComponent.ActiveHand = hand; } emptyHands = true; break; } } if (!emptyHands) { return(Outcome.Failed); } var interactionSystem = IoCManager.Resolve <IEntitySystemManager>().GetEntitySystem <InteractionSystem>(); interactionSystem.Interaction(_owner, _target); return(Outcome.Success); }
private void HandleDragDropMessage(DragDropMessage msg, EntitySessionEventArgs args) { var performer = args.SenderSession.AttachedEntity; if (!EntityManager.TryGetEntity(msg.Dropped, out var dropped)) { return; } if (!EntityManager.TryGetEntity(msg.Target, out var target)) { return; } var interactionArgs = new DragDropEventArgs(performer, msg.DropLocation, dropped, target); // must be in range of both the target and the object they are drag / dropping if (!InteractionChecks.InRangeUnobstructed(interactionArgs)) { return; } // trigger dragdrops on the dropped entity foreach (var dragDrop in dropped.GetAllComponents <IDragDrop>()) { if (dragDrop.CanDragDrop(interactionArgs) && dragDrop.DragDrop(interactionArgs)) { return; } } // trigger dragdropons on the targeted entity foreach (var dragDropOn in target.GetAllComponents <IDragDropOn>()) { if (dragDropOn.CanDragDropOn(interactionArgs) && dragDropOn.DragDropOn(interactionArgs)) { return; } } }
public override bool TryUseFood(IEntity user, IEntity target, UtensilComponent utensilUsed = null) { if (user == null) { return(false); } var trueTarget = target ?? user; if (!trueTarget.TryGetComponent(out StomachComponent stomach)) { return(false); } if (!InteractionChecks.InRangeUnobstructed(user, trueTarget.Transform.MapPosition)) { return(false); } var transferAmount = ReagentUnit.Min(_transferAmount, _contents.CurrentVolume); var split = _contents.SplitSolution(transferAmount); if (!stomach.TryTransferSolution(split)) { _contents.TryAddSolution(split); trueTarget.PopupMessage(user, Loc.GetString("You can't eat any more!")); return(false); } if (_useSound != null) { _entitySystem.GetEntitySystem <AudioSystem>() .PlayFromEntity(_useSound, trueTarget, AudioParams.Default.WithVolume(-1f)); } trueTarget.PopupMessage(user, Loc.GetString("You swallow the pill.")); Owner.Delete(); return(true); }
public bool CanPickup(IEntity user) { if (!ActionBlockerSystem.CanPickup(user)) { return(false); } if (user.Transform.MapID != Owner.Transform.MapID) { return(false); } if (Owner.TryGetComponent(out ICollidableComponent physics) && physics.Anchored) { return(false); } var itemPos = Owner.Transform.MapPosition; return(InteractionChecks.InRangeUnobstructed(user, itemPos, ignoredEnt: Owner, ignoreInsideBlocker: true)); }
public override Outcome Execute(float frameTime) { if (!InteractionChecks.InRangeUnobstructed(_owner, _target.Transform.MapPosition)) { return(Outcome.Failed); } if (!_target.TryGetComponent(out EntityStorageComponent storageComponent) || storageComponent.IsWeldedShut) { return(Outcome.Failed); } if (storageComponent.Open) { var activateArgs = new ActivateEventArgs { User = _owner, Target = _target }; storageComponent.Activate(activateArgs); } return(Outcome.Success); }
public override Outcome Execute(float frameTime) { if (_useTarget.Transform.GridID != _owner.Transform.GridID) { return(Outcome.Failed); } if (!InteractionChecks.InRangeUnobstructed(_owner, _useTarget.Transform.MapPosition)) { return(Outcome.Failed); } if (_owner.TryGetComponent(out CombatModeComponent combatModeComponent)) { combatModeComponent.IsInCombatMode = false; } // Click on da thing var interactionSystem = IoCManager.Resolve <IEntitySystemManager>().GetEntitySystem <InteractionSystem>(); interactionSystem.UseItemInHand(_owner, _useTarget.Transform.GridPosition, _useTarget.Uid); return(Outcome.Success); }
public virtual bool TryUseFood(IEntity user, IEntity target, UtensilComponent utensilUsed = null) { if (user == null) { return(false); } if (UsesRemaining <= 0) { user.PopupMessage(user, Loc.GetString("{0:TheName} is empty!", Owner)); return(false); } var trueTarget = target ?? user; if (!trueTarget.TryGetComponent(out StomachComponent stomach)) { return(false); } var utensils = utensilUsed != null ? new List <UtensilComponent> { utensilUsed } : null; if (_utensilsNeeded != UtensilType.None) { utensils = new List <UtensilComponent>(); var types = UtensilType.None; if (user.TryGetComponent(out HandsComponent hands)) { foreach (var item in hands.GetAllHeldItems()) { if (!item.Owner.TryGetComponent(out UtensilComponent utensil)) { continue; } utensils.Add(utensil); types |= utensil.Types; } } if (!types.HasFlag(_utensilsNeeded)) { trueTarget.PopupMessage(user, Loc.GetString("You need to be holding a {0} to eat that!", _utensilsNeeded)); return(false); } } if (!InteractionChecks.InRangeUnobstructed(user, trueTarget.Transform.MapPosition)) { return(false); } var transferAmount = ReagentUnit.Min(_transferAmount, _contents.CurrentVolume); var split = _contents.SplitSolution(transferAmount); if (!stomach.TryTransferSolution(split)) { _contents.TryAddSolution(split); trueTarget.PopupMessage(user, Loc.GetString("You can't eat any more!")); return(false); } _entitySystem.GetEntitySystem <AudioSystem>() .PlayFromEntity(_useSound, trueTarget, AudioParams.Default.WithVolume(-1f)); trueTarget.PopupMessage(user, Loc.GetString("Nom")); // If utensils were used if (utensils != null) { foreach (var utensil in utensils) { utensil.TryBreak(user); } } if (UsesRemaining > 0) { return(true); } if (string.IsNullOrEmpty(_trashPrototype)) { Owner.Delete(); return(true); } //We're empty. Become trash. var position = Owner.Transform.GridPosition; var finisher = Owner.EntityManager.SpawnEntity(_trashPrototype, position); // If the user is holding the item if (user.TryGetComponent(out HandsComponent handsComponent) && handsComponent.IsHolding(Owner)) { Owner.Delete(); // Put the trash in the user's hand if (finisher.TryGetComponent(out ItemComponent item) && handsComponent.CanPutInHand(item)) { handsComponent.PutInHand(item); } }
public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession?session = null) { base.HandleNetworkMessage(message, channel, session); if (session == null) { throw new ArgumentException(nameof(session)); } switch (message) { case RemoveEntityMessage remove: { EnsureInitialCalculated(); var player = session.AttachedEntity; if (player == null) { break; } var ownerTransform = Owner.Transform; var playerTransform = player.Transform; if (!playerTransform.GridPosition.InRange(_mapManager, ownerTransform.GridPosition, 2) || !ownerTransform.IsMapTransform && !playerTransform.ContainsEntity(ownerTransform)) { break; } var entity = _entityManager.GetEntity(remove.EntityUid); if (entity == null || _storage?.Contains(entity) == false) { break; } var item = entity.GetComponent <ItemComponent>(); if (item == null || !player.TryGetComponent(out HandsComponent hands)) { break; } if (!hands.CanPutInHand(item)) { break; } hands.PutInHand(item); break; } case InsertEntityMessage _: { EnsureInitialCalculated(); var player = session.AttachedEntity; if (player == null) { break; } var storagePosition = Owner.Transform.MapPosition; if (!InteractionChecks.InRangeUnobstructed(player, storagePosition)) { break; } PlayerInsertEntity(player); break; } case CloseStorageUIMessage _: { if (!(session is IPlayerSession playerSession)) { break; } UnsubscribeSession(playerSession); break; } } }
private bool IsRCDStillValid(AfterInteractEventArgs eventArgs, IMapGrid mapGrid, TileRef tile, MapIndices snapPos, RcdMode startingMode) { //Less expensive checks first. Failing those ones, we need to check that the tile isn't obstructed. if (_ammo <= 0) { _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"The RCD is out of ammo!"); return(false); } if (_mode != startingMode) { return(false); } var coordinates = mapGrid.GridTileToLocal(tile.GridIndices); if (coordinates == GridCoordinates.InvalidGrid || !InteractionChecks.InRangeUnobstructed(eventArgs)) { return(false); } switch (_mode) { //Floor mode just needs the tile to be a space tile (subFloor) case RcdMode.Floors: if (!tile.Tile.IsEmpty) { _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"You can only build a floor on space!"); return(false); } return(true); //We don't want to place a space tile on something that's already a space tile. Let's do the inverse of the last check. case RcdMode.Deconstruct: if (tile.Tile.IsEmpty) { return(false); } //They tried to decon a turf but the turf is blocked if (eventArgs.Target == null && tile.IsBlockedTurf(true)) { _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!"); return(false); } //They tried to decon a non-turf but it's not in the whitelist if (eventArgs.Target != null && !eventArgs.Target.TryGetComponent(out RCDDeconstructWhitelist rcd_decon)) { _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"You can't deconstruct that!"); return(false); } return(true); //Walls are a special behaviour, and require us to build a new object with a transform rather than setting a grid tile, thus we early return to avoid the tile set code. case RcdMode.Walls: if (tile.Tile.IsEmpty) { _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"Cannot build a wall on space!"); return(false); } if (tile.IsBlockedTurf(true)) { _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!"); return(false); } return(true); case RcdMode.Airlock: if (tile.Tile.IsEmpty) { _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"Cannot build an airlock on space!"); return(false); } if (tile.IsBlockedTurf(true)) { _serverNotifyManager.PopupMessage(Owner, eventArgs.User, $"That tile is obstructed!"); return(false); } return(true); default: return(false); //I don't know why this would happen, but sure I guess. Get out of here invalid state! } }
private bool TryBuckle(IEntity user, IEntity to) { if (user == null || user == to) { return(false); } if (!ActionBlockerSystem.CanInteract(user)) { _notifyManager.PopupMessage(user, user, Loc.GetString("You can't do that!")); return(false); } var strapPosition = Owner.Transform.MapPosition; var range = SharedInteractionSystem.InteractionRange / 2; if (!InteractionChecks.InRangeUnobstructed(user, strapPosition, range)) { _notifyManager.PopupMessage(user, user, Loc.GetString("You can't reach there!")); return(false); } if (!user.TryGetComponent(out HandsComponent hands)) { _notifyManager.PopupMessage(user, user, Loc.GetString("You don't have hands!")); return(false); } if (hands.GetActiveHand != null) { _notifyManager.PopupMessage(user, user, Loc.GetString("Your hand isn't free!")); return(false); } if (BuckledTo != null) { _notifyManager.PopupMessage(Owner, user, Loc.GetString(Owner == user ? "You are already buckled in!" : "{0:They} are already buckled in!", Owner)); return(false); } if (!to.TryGetComponent(out StrapComponent strap)) { _notifyManager.PopupMessage(Owner, user, Loc.GetString(Owner == user ? "You can't buckle yourself there!" : "You can't buckle {0:them} there!", Owner)); return(false); } var parent = to.Transform.Parent; while (parent != null) { if (parent == user.Transform) { _notifyManager.PopupMessage(Owner, user, Loc.GetString(Owner == user ? "You can't buckle yourself there!" : "You can't buckle {0:them} there!", Owner)); return(false); } parent = parent.Parent; } if (!strap.HasSpace(this)) { _notifyManager.PopupMessage(Owner, user, Loc.GetString(Owner == user ? "You can't fit there!" : "{0:They} can't fit there!", Owner)); return(false); } _entitySystem.GetEntitySystem <AudioSystem>() .PlayFromEntity(strap.BuckleSound, Owner); if (!strap.TryAdd(this)) { _notifyManager.PopupMessage(Owner, user, Loc.GetString(Owner == user ? "You can't buckle yourself there!" : "You can't buckle {0:them} there!", Owner)); return(false); } BuckledTo = strap; if (Owner.TryGetComponent(out AppearanceComponent appearance)) { appearance.SetData(BuckleVisuals.Buckled, true); } var ownTransform = Owner.Transform; var strapTransform = strap.Owner.Transform; ownTransform.GridPosition = strapTransform.GridPosition; ownTransform.AttachParent(strapTransform); switch (strap.Position) { case StrapPosition.None: ownTransform.WorldRotation = strapTransform.WorldRotation; break; case StrapPosition.Stand: StandingStateHelper.Standing(Owner); ownTransform.WorldRotation = strapTransform.WorldRotation; break; case StrapPosition.Down: StandingStateHelper.Down(Owner); ownTransform.WorldRotation = Angle.South; break; } BuckleStatus(); return(true); }