Add Buckling (#1155)
* Create BuckleableComponent.cs * Add strap component and keybind to buckle targeted entity * Remove buckle keybind, turn it into a verb * Add moving and attaching the buckled entity to the strap * Fix reality collapsing when clicking on a buckled entity * Add strap position to buckle a mob in the standing or down position * Add new default strap position that makes no change to the mob's standing state * Add Strap component to office chairs and stools * Add Strap component to the pilot chair * Add buckled status effect icon * Add status effect click behaviour * Add buckling and unbuckling sounds * Change Buckle verb to only appear when an entity can be currently buckled * Rotate buckled entity in the direction of the seat * Disable entity rotation when buckled * Fix buckle rotation on beds * Buckling now finds the closest strap to the buckleable entity * Fix rotation when unbuckling an entity * Move buckle verb to StrapComponent * Added buckled entity unbuckle verb, range and interaction checks * Add checks for currently occupied straps * Add unbuckling entity if its respective strap component is removed * Add Clickable, InteractionOutline and Collidable components to bed * Add rotation property to strap component * Rename Buckleable to Buckle * Add Buckle and Strap sizes to buckle multiple entities in the same strap * Remove out of range popup message from strap verb GetData * Move BuckledTo setter logic to its methods * Fix Strap BuckledEntities being public * Fix not updating status when Buckle component is removed * Change BuckleComponent.BuckledTo to be of type StrapComponent * Fix NRE when unbuckling * Add buckle perspective messages * Fix not equals comparison in strap verb * Add added check to Strap TryAdd * Change buckle.ogg and unbuckle.ogg from stereo to mono * Remove -2f volume on buckle and unbuckle sounds * Add summary to Strap TryAdd and Remove methods * Make buckled entities unable to fall * Fix default strap position not rotating the buckled entity * Add downing after unbuckling an entity if it is knocked down * Prevent an entity from buckling onto itself Fixes stack overflow error * Disable recursive buckling * Add buckling onto straps by clicking them with an empty hand * Add recursive buckle check to the trybuckle method as well * Fix being able to click on a different strap to unbuckle from the current one * Merge TryUnbuckle and ForceUnbuckle with a force argument * Remove explicit unimplemented status effect clicking cases * Add documentation to EffectBlockerSystem and ActionBlockerSystem
This commit is contained in:
@@ -174,6 +174,8 @@ namespace Content.Client
|
|||||||
"Utensil",
|
"Utensil",
|
||||||
"UnarmedCombat",
|
"UnarmedCombat",
|
||||||
"TimedSpawner",
|
"TimedSpawner",
|
||||||
|
"Buckle",
|
||||||
|
"Strap"
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var ignoreName in registerIgnore)
|
foreach (var ignoreName in registerIgnore)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.GameObjects.Components.Strap;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
[UsedImplicitly]
|
||||||
|
public class BuckleVisualizer2D : SpeciesVisualizer2D
|
||||||
|
{
|
||||||
|
public override void OnChangeData(AppearanceComponent component)
|
||||||
|
{
|
||||||
|
if (!component.TryGetData<bool>(SharedBuckleComponent.BuckleVisuals.Buckled, out var buckled) ||
|
||||||
|
!buckled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!component.TryGetData<int>(SharedStrapComponent.StrapVisuals.RotationAngle, out var angle))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetRotation(component, Angle.FromDegrees(angle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using Content.Client.UserInterface;
|
using Content.Client.UserInterface;
|
||||||
using Content.Client.Utility;
|
using Content.Client.Utility;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.Input;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.Interfaces.ResourceManagement;
|
using Robust.Client.Interfaces.ResourceManagement;
|
||||||
using Robust.Client.Interfaces.UserInterface;
|
using Robust.Client.Interfaces.UserInterface;
|
||||||
@@ -10,6 +11,7 @@ using Robust.Client.Player;
|
|||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Input;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Network;
|
using Robust.Shared.Interfaces.Network;
|
||||||
using Robust.Shared.Interfaces.Timing;
|
using Robust.Shared.Interfaces.Timing;
|
||||||
@@ -94,31 +96,34 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
_cooldown.Clear();
|
_cooldown.Clear();
|
||||||
_ui.VBox.DisposeAllChildren();
|
_ui.VBox.DisposeAllChildren();
|
||||||
|
|
||||||
foreach (var (key, statusEffect) in _status.OrderBy(x => (int) x.Key))
|
foreach (var (key, effect) in _status.OrderBy(x => (int) x.Key))
|
||||||
{
|
{
|
||||||
var status = new Control()
|
var texture = _resourceCache.GetTexture(effect.Icon);
|
||||||
{
|
var status = new StatusControl(key, texture);
|
||||||
Children =
|
|
||||||
{
|
|
||||||
new TextureRect
|
|
||||||
{
|
|
||||||
TextureScale = (2, 2),
|
|
||||||
Texture = _resourceCache.GetTexture(statusEffect.Icon)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (statusEffect.Cooldown.HasValue)
|
if (effect.Cooldown.HasValue)
|
||||||
{
|
{
|
||||||
var cooldown = new CooldownGraphic();
|
var cooldown = new CooldownGraphic();
|
||||||
status.Children.Add(cooldown);
|
status.Children.Add(cooldown);
|
||||||
_cooldown[key] = cooldown;
|
_cooldown[key] = cooldown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status.OnPressed += args => StatusPressed(args, status);
|
||||||
|
|
||||||
_ui.VBox.AddChild(status);
|
_ui.VBox.AddChild(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void StatusPressed(BaseButton.ButtonEventArgs args, StatusControl status)
|
||||||
|
{
|
||||||
|
if (args.Event.Function != EngineKeyFunctions.UIClick)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendNetworkMessage(new ClickStatusMessage(status.Effect));
|
||||||
|
}
|
||||||
|
|
||||||
public void RemoveStatusEffect(StatusEffect name)
|
public void RemoveStatusEffect(StatusEffect name)
|
||||||
{
|
{
|
||||||
_status.Remove(name);
|
_status.Remove(name);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Content.Client.GameObjects.Components.Mobs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetRotation(AppearanceComponent component, Angle rotation)
|
protected void SetRotation(AppearanceComponent component, Angle rotation)
|
||||||
{
|
{
|
||||||
var sprite = component.Owner.GetComponent<ISpriteComponent>();
|
var sprite = component.Owner.GetComponent<ISpriteComponent>();
|
||||||
|
|
||||||
|
|||||||
25
Content.Client/GameObjects/Components/Mobs/StatusControl.cs
Normal file
25
Content.Client/GameObjects/Components/Mobs/StatusControl.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
|
||||||
|
namespace Content.Client.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
public class StatusControl : BaseButton
|
||||||
|
{
|
||||||
|
public readonly StatusEffect Effect;
|
||||||
|
|
||||||
|
public StatusControl(StatusEffect effect, [CanBeNull] Texture texture)
|
||||||
|
{
|
||||||
|
Effect = effect;
|
||||||
|
|
||||||
|
var item = new TextureRect
|
||||||
|
{
|
||||||
|
TextureScale = (2, 2),
|
||||||
|
Texture = texture
|
||||||
|
};
|
||||||
|
|
||||||
|
Children.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
321
Content.Server/GameObjects/Components/Mobs/BuckleComponent.cs
Normal file
321
Content.Server/GameObjects/Components/Mobs/BuckleComponent.cs
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
using Content.Server.GameObjects.Components.Strap;
|
||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Server.Interfaces;
|
||||||
|
using Content.Server.Mobs;
|
||||||
|
using Content.Server.Utility;
|
||||||
|
using Content.Shared.GameObjects;
|
||||||
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using Content.Shared.GameObjects.Components.Strap;
|
||||||
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class BuckleComponent : SharedBuckleComponent, IActionBlocker, IInteractHand, IEffectBlocker
|
||||||
|
{
|
||||||
|
#pragma warning disable 649
|
||||||
|
[Dependency] private readonly IEntitySystemManager _entitySystem;
|
||||||
|
[Dependency] private readonly IServerNotifyManager _notifyManager;
|
||||||
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
private int _size;
|
||||||
|
|
||||||
|
[ViewVariables, CanBeNull]
|
||||||
|
public StrapComponent BuckledTo { get; private set; }
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public int Size => _size;
|
||||||
|
|
||||||
|
private void BuckleStatus()
|
||||||
|
{
|
||||||
|
if (Owner.TryGetComponent(out ServerStatusEffectsComponent status))
|
||||||
|
{
|
||||||
|
status.ChangeStatusEffectIcon(StatusEffect.Buckled,
|
||||||
|
BuckledTo == null
|
||||||
|
? "/Textures/Mob/UI/Buckle/unbuckled.png"
|
||||||
|
: "/Textures/Mob/UI/Buckle/buckled.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StandingStateHelper.Standing(Owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Owner.TryGetComponent(out SpeciesComponent species))
|
||||||
|
{
|
||||||
|
species.CurrentDamageState.EnterState(Owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuckleStatus();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ToggleBuckle(IEntity user, IEntity to)
|
||||||
|
{
|
||||||
|
if (BuckledTo == null)
|
||||||
|
{
|
||||||
|
return TryBuckle(user, to);
|
||||||
|
}
|
||||||
|
else if (BuckledTo.Owner == to)
|
||||||
|
{
|
||||||
|
return TryUnbuckle(user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
|
serializer.DataField(ref _size, "size", 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Startup()
|
||||||
|
{
|
||||||
|
base.Startup();
|
||||||
|
BuckleStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnRemove()
|
||||||
|
{
|
||||||
|
base.OnRemove();
|
||||||
|
|
||||||
|
if (BuckledTo != null && BuckledTo.Owner.TryGetComponent(out StrapComponent strap))
|
||||||
|
{
|
||||||
|
strap.Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuckledTo = null;
|
||||||
|
BuckleStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
return TryUnbuckle(eventArgs.User);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IActionBlocker.CanMove()
|
||||||
|
{
|
||||||
|
return BuckledTo == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IActionBlocker.CanChangeDirection()
|
||||||
|
{
|
||||||
|
return BuckledTo == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IEffectBlocker.CanFall()
|
||||||
|
{
|
||||||
|
return BuckledTo == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Verb]
|
||||||
|
private sealed class BuckleVerb : Verb<BuckleComponent>
|
||||||
|
{
|
||||||
|
protected override void GetData(IEntity user, BuckleComponent component, VerbData data)
|
||||||
|
{
|
||||||
|
if (!ActionBlockerSystem.CanInteract(user) ||
|
||||||
|
component.BuckledTo == null)
|
||||||
|
{
|
||||||
|
data.Visibility = VerbVisibility.Invisible;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Text = Loc.GetString("Unbuckle");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Activate(IEntity user, BuckleComponent component)
|
||||||
|
{
|
||||||
|
component.TryUnbuckle(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Network;
|
||||||
|
using Robust.Shared.Players;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.Components.Mobs
|
namespace Content.Server.GameObjects.Components.Mobs
|
||||||
{
|
{
|
||||||
@@ -59,6 +62,44 @@ namespace Content.Server.GameObjects.Components.Mobs
|
|||||||
|
|
||||||
Dirty();
|
Dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
|
||||||
|
{
|
||||||
|
base.HandleNetworkMessage(message, netChannel, session);
|
||||||
|
|
||||||
|
if (session == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(session));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case ClickStatusMessage msg:
|
||||||
|
{
|
||||||
|
var player = session.AttachedEntity;
|
||||||
|
|
||||||
|
if (player != Owner)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement clicking other status effects in the HUD
|
||||||
|
switch (msg.Effect)
|
||||||
|
{
|
||||||
|
case StatusEffect.Buckled:
|
||||||
|
if (!player.TryGetComponent(out BuckleComponent buckle))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buckle.TryUnbuckle(player);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ namespace Content.Server.GameObjects.Components.Mobs
|
|||||||
seconds = MathF.Min(_knockdownTimer + (seconds * KnockdownTimeModifier), _knockdownCap);
|
seconds = MathF.Min(_knockdownTimer + (seconds * KnockdownTimeModifier), _knockdownCap);
|
||||||
|
|
||||||
if (seconds <= 0f)
|
if (seconds <= 0f)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
StandingStateHelper.Down(Owner);
|
StandingStateHelper.Down(Owner);
|
||||||
|
|
||||||
|
|||||||
215
Content.Server/GameObjects/Components/Strap/StrapComponent.cs
Normal file
215
Content.Server/GameObjects/Components/Strap/StrapComponent.cs
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Server.GameObjects.Components.Mobs;
|
||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
|
using Content.Shared.GameObjects;
|
||||||
|
using Content.Shared.GameObjects.Components.Strap;
|
||||||
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Strap
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class StrapComponent : SharedStrapComponent, IInteractHand
|
||||||
|
{
|
||||||
|
private StrapPosition _position;
|
||||||
|
private string _buckleSound;
|
||||||
|
private string _unbuckleSound;
|
||||||
|
private int _rotation;
|
||||||
|
private int _size;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The entity that is currently buckled here, synced from <see cref="BuckleComponent.BuckledTo"/>
|
||||||
|
/// </summary>
|
||||||
|
private HashSet<IEntity> BuckledEntities { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The change in position to the strapped mob
|
||||||
|
/// </summary>
|
||||||
|
public override StrapPosition Position
|
||||||
|
{
|
||||||
|
get => _position;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_position = value;
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sound to be played when a mob is buckled
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public string BuckleSound => _buckleSound;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sound to be played when a mob is unbuckled
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public string UnbuckleSound => _unbuckleSound;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The angle in degrees to rotate the player by when they get strapped
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public int Rotation => _rotation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of the strap which is compared against when buckling entities
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public int Size => _size;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sum of the sizes of all the buckled entities in this strap
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public int OccupiedSize { get; private set; }
|
||||||
|
|
||||||
|
public bool HasSpace(BuckleComponent buckle)
|
||||||
|
{
|
||||||
|
return OccupiedSize + buckle.Size <= _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a buckled entity. Called from <see cref="BuckleComponent.TryBuckle"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buckle">The component to add</param>
|
||||||
|
/// <param name="force">Whether or not to check if the strap has enough space</param>
|
||||||
|
/// <returns>True if added, false otherwise</returns>
|
||||||
|
public bool TryAdd(BuckleComponent buckle, bool force = false)
|
||||||
|
{
|
||||||
|
if (!force && !HasSpace(buckle))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BuckledEntities.Add(buckle.Owner))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OccupiedSize += buckle.Size;
|
||||||
|
|
||||||
|
if (buckle.Owner.TryGetComponent(out AppearanceComponent appearance))
|
||||||
|
{
|
||||||
|
appearance.SetData(StrapVisuals.RotationAngle, _rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a buckled entity. Called from <see cref="BuckleComponent.TryUnbuckle"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buckle">The component to remove</param>
|
||||||
|
public void Remove(BuckleComponent buckle)
|
||||||
|
{
|
||||||
|
if (BuckledEntities.Remove(buckle.Owner))
|
||||||
|
{
|
||||||
|
OccupiedSize -= buckle.Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
|
serializer.DataField(ref _position, "position", StrapPosition.None);
|
||||||
|
serializer.DataField(ref _buckleSound, "buckleSound", "/Audio/effects/buckle.ogg");
|
||||||
|
serializer.DataField(ref _unbuckleSound, "unbuckleSound", "/Audio/effects/unbuckle.ogg");
|
||||||
|
serializer.DataField(ref _rotation, "rotation", 0);
|
||||||
|
|
||||||
|
var defaultSize = 100;
|
||||||
|
|
||||||
|
serializer.DataField(ref _size, "size", defaultSize);
|
||||||
|
BuckledEntities = new HashSet<IEntity>(_size / defaultSize);
|
||||||
|
|
||||||
|
OccupiedSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnRemove()
|
||||||
|
{
|
||||||
|
base.OnRemove();
|
||||||
|
|
||||||
|
foreach (var entity in BuckledEntities)
|
||||||
|
{
|
||||||
|
if (entity.TryGetComponent(out BuckleComponent buckle))
|
||||||
|
{
|
||||||
|
buckle.TryUnbuckle(entity, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BuckledEntities.Clear();
|
||||||
|
OccupiedSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Verb]
|
||||||
|
private sealed class StrapVerb : Verb<StrapComponent>
|
||||||
|
{
|
||||||
|
protected override void GetData(IEntity user, StrapComponent component, VerbData data)
|
||||||
|
{
|
||||||
|
data.Visibility = VerbVisibility.Invisible;
|
||||||
|
|
||||||
|
if (!ActionBlockerSystem.CanInteract(component.Owner) ||
|
||||||
|
!user.TryGetComponent(out BuckleComponent buckle) ||
|
||||||
|
buckle.BuckledTo != null && buckle.BuckledTo != component ||
|
||||||
|
user == component.Owner)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parent = component.Owner.Transform.Parent;
|
||||||
|
while (parent != null)
|
||||||
|
{
|
||||||
|
if (parent == user.Transform)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = parent.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userPosition = user.Transform.MapPosition;
|
||||||
|
var strapPosition = component.Owner.Transform.MapPosition;
|
||||||
|
var range = SharedInteractionSystem.InteractionRange / 2;
|
||||||
|
var inRange = EntitySystem.Get<SharedInteractionSystem>()
|
||||||
|
.InRangeUnobstructed(userPosition, strapPosition, range,
|
||||||
|
predicate: entity => entity == user || entity == component.Owner);
|
||||||
|
|
||||||
|
if (!inRange)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Visibility = VerbVisibility.Visible;
|
||||||
|
data.Text = buckle.BuckledTo == null ? Loc.GetString("Buckle") : Loc.GetString("Unbuckle");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Activate(IEntity user, StrapComponent component)
|
||||||
|
{
|
||||||
|
if (!user.TryGetComponent(out BuckleComponent buckle))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buckle.ToggleBuckle(user, component.Owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (!eventArgs.User.TryGetComponent(out BuckleComponent buckle))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buckle.ToggleBuckle(eventArgs.User, Owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.EntitySystems
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This interface gives components the ability to block certain effects
|
||||||
|
/// from affecting the owning entity. For actions see <see cref="IActionBlocker"/>
|
||||||
|
/// </summary>
|
||||||
|
public interface IEffectBlocker
|
||||||
|
{
|
||||||
|
bool CanFall() => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Utility methods to check if an effect is allowed to affect a specific entity.
|
||||||
|
/// For actions see <see cref="ActionBlockerSystem"/>
|
||||||
|
/// </summary>
|
||||||
|
public class EffectBlockerSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public static bool CanFall(IEntity entity)
|
||||||
|
{
|
||||||
|
var canFall = true;
|
||||||
|
foreach (var blocker in entity.GetAllComponents<IEffectBlocker>())
|
||||||
|
{
|
||||||
|
canFall &= blocker.CanFall(); // Sets var to false if false
|
||||||
|
}
|
||||||
|
|
||||||
|
return canFall;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,13 +7,11 @@ using Content.Shared.GameObjects.Components.Inventory;
|
|||||||
using Content.Shared.Input;
|
using Content.Shared.Input;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects.EntitySystemMessages;
|
using Robust.Server.GameObjects.EntitySystemMessages;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
|
||||||
using Robust.Server.Interfaces.Player;
|
using Robust.Server.Interfaces.Player;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Input;
|
using Robust.Shared.Input;
|
||||||
using Robust.Shared.Input.Binding;
|
using Robust.Shared.Input.Binding;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
|
||||||
using Robust.Shared.Interfaces.Map;
|
using Robust.Shared.Interfaces.Map;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Server.Interfaces.GameObjects;
|
using Content.Server.Interfaces.GameObjects;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.GameObjects.Components.Mobs;
|
using Content.Shared.GameObjects.Components.Mobs;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Random;
|
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
|
|
||||||
namespace Content.Server.Mobs
|
namespace Content.Server.Mobs
|
||||||
{
|
{
|
||||||
@@ -23,22 +20,30 @@ namespace Content.Server.Mobs
|
|||||||
/// <returns>False if the mob was already downed or couldn't set the state</returns>
|
/// <returns>False if the mob was already downed or couldn't set the state</returns>
|
||||||
public static bool Down(IEntity entity, bool playSound = true, bool dropItems = true)
|
public static bool Down(IEntity entity, bool playSound = true, bool dropItems = true)
|
||||||
{
|
{
|
||||||
if (!entity.TryGetComponent(out AppearanceComponent appearance)) return false;
|
if (!EffectBlockerSystem.CanFall(entity) ||
|
||||||
|
!entity.TryGetComponent(out AppearanceComponent appearance))
|
||||||
appearance.TryGetData<SharedSpeciesComponent.MobState>(SharedSpeciesComponent.MobVisuals.RotationState, out var oldState);
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var newState = SharedSpeciesComponent.MobState.Down;
|
var newState = SharedSpeciesComponent.MobState.Down;
|
||||||
if (newState == oldState)
|
appearance.TryGetData<SharedSpeciesComponent.MobState>(SharedSpeciesComponent.MobVisuals.RotationState, out var oldState);
|
||||||
return false;
|
|
||||||
|
|
||||||
|
if (newState != oldState)
|
||||||
|
{
|
||||||
appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, newState);
|
appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, newState);
|
||||||
|
}
|
||||||
|
|
||||||
if (playSound)
|
if (playSound)
|
||||||
|
{
|
||||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>()
|
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>()
|
||||||
.PlayFromEntity(AudioHelpers.GetRandomFileFromSoundCollection("bodyfall"), entity, AudioHelpers.WithVariation(0.25f));
|
.PlayFromEntity(AudioHelpers.GetRandomFileFromSoundCollection("bodyfall"), entity, AudioHelpers.WithVariation(0.25f));
|
||||||
|
}
|
||||||
|
|
||||||
if(dropItems)
|
if(dropItems)
|
||||||
|
{
|
||||||
DropAllItemsInHands(entity, false);
|
DropAllItemsInHands(entity, false);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components.Mobs
|
||||||
|
{
|
||||||
|
public class SharedBuckleComponent : Component
|
||||||
|
{
|
||||||
|
public sealed override string Name => "Buckle";
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum BuckleVisuals
|
||||||
|
{
|
||||||
|
Buckled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,5 @@ namespace Content.Shared.GameObjects.Components.Mobs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Down,
|
Down,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,21 @@ namespace Content.Shared.GameObjects.Components.Mobs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A message that calls the click interaction on a status effect
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class ClickStatusMessage : ComponentMessage
|
||||||
|
{
|
||||||
|
public readonly StatusEffect Effect;
|
||||||
|
|
||||||
|
public ClickStatusMessage(StatusEffect effect)
|
||||||
|
{
|
||||||
|
Directed = true;
|
||||||
|
Effect = effect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public struct StatusEffectStatus
|
public struct StatusEffectStatus
|
||||||
{
|
{
|
||||||
@@ -40,5 +55,6 @@ namespace Content.Shared.GameObjects.Components.Mobs
|
|||||||
Hunger,
|
Hunger,
|
||||||
Thirst,
|
Thirst,
|
||||||
Stun,
|
Stun,
|
||||||
|
Buckled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.GameObjects.Components.Strap
|
||||||
|
{
|
||||||
|
public enum StrapPosition
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// (Default) Makes no change to the buckled mob
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes the mob stand up
|
||||||
|
/// </summary>
|
||||||
|
Stand,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes the mob lie down
|
||||||
|
/// </summary>
|
||||||
|
Down
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class SharedStrapComponent : Component
|
||||||
|
{
|
||||||
|
public sealed override string Name => "Strap";
|
||||||
|
|
||||||
|
public virtual StrapPosition Position { get; set; }
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum StrapVisuals
|
||||||
|
{
|
||||||
|
RotationAngle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,10 @@ using Robust.Shared.Interfaces.GameObjects;
|
|||||||
|
|
||||||
namespace Content.Shared.GameObjects.EntitySystems
|
namespace Content.Shared.GameObjects.EntitySystems
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This interface gives components the ability to block certain actions from
|
||||||
|
/// being done by the owning entity. For effects see <see cref="IEffectBlocker"/>
|
||||||
|
/// </summary>
|
||||||
public interface IActionBlocker
|
public interface IActionBlocker
|
||||||
{
|
{
|
||||||
bool CanMove() => true;
|
bool CanMove() => true;
|
||||||
@@ -27,6 +31,10 @@ namespace Content.Shared.GameObjects.EntitySystems
|
|||||||
bool CanChangeDirection() => true;
|
bool CanChangeDirection() => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Utility methods to check if a specific entity is allowed to perform an action.
|
||||||
|
/// For effects see <see cref="EffectBlockerSystem"/>
|
||||||
|
/// </summary>
|
||||||
public class ActionBlockerSystem : EntitySystem
|
public class ActionBlockerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
public static bool CanMove(IEntity entity)
|
public static bool CanMove(IEntity entity)
|
||||||
@@ -34,7 +42,7 @@ namespace Content.Shared.GameObjects.EntitySystems
|
|||||||
bool canmove = true;
|
bool canmove = true;
|
||||||
foreach(var actionblockercomponents in entity.GetAllComponents<IActionBlocker>())
|
foreach(var actionblockercomponents in entity.GetAllComponents<IActionBlocker>())
|
||||||
{
|
{
|
||||||
canmove &= actionblockercomponents.CanMove(); //sets var to false if false
|
canmove &= actionblockercomponents.CanMove(); // Sets var to false if false
|
||||||
}
|
}
|
||||||
return canmove;
|
return canmove;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
Resources/Audio/effects/buckle.ogg
Normal file
BIN
Resources/Audio/effects/buckle.ogg
Normal file
Binary file not shown.
BIN
Resources/Audio/effects/unbuckle.ogg
Normal file
BIN
Resources/Audio/effects/unbuckle.ogg
Normal file
Binary file not shown.
@@ -12,6 +12,8 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Buildings/furniture.rsi
|
sprite: Buildings/furniture.rsi
|
||||||
state: stool_base
|
state: stool_base
|
||||||
|
- type: Strap
|
||||||
|
position: Stand
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: bar stool
|
name: bar stool
|
||||||
@@ -38,6 +40,8 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Buildings/furniture.rsi
|
sprite: Buildings/furniture.rsi
|
||||||
state: officechair_white
|
state: officechair_white
|
||||||
|
- type: Strap
|
||||||
|
position: Stand
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: dark office chair
|
name: dark office chair
|
||||||
@@ -53,6 +57,8 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Buildings/furniture.rsi
|
sprite: Buildings/furniture.rsi
|
||||||
state: officechair_dark
|
state: officechair_dark
|
||||||
|
- type: Strap
|
||||||
|
position: Stand
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: chair
|
name: chair
|
||||||
@@ -68,6 +74,8 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Buildings/furniture.rsi
|
sprite: Buildings/furniture.rsi
|
||||||
state: chair
|
state: chair
|
||||||
|
- type: Strap
|
||||||
|
position: Stand
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: wooden chair
|
name: wooden chair
|
||||||
@@ -84,11 +92,17 @@
|
|||||||
name: bed
|
name: bed
|
||||||
id: Bed
|
id: Bed
|
||||||
components:
|
components:
|
||||||
|
- type: Clickable
|
||||||
|
- type: InteractionOutline
|
||||||
|
- type: Collidable
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Buildings/furniture.rsi
|
sprite: Buildings/furniture.rsi
|
||||||
state: bed
|
state: bed
|
||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Buildings/furniture.rsi
|
sprite: Buildings/furniture.rsi
|
||||||
state: bed
|
state: bed
|
||||||
|
- type: Strap
|
||||||
|
position: Down
|
||||||
|
rotation: -90
|
||||||
placement:
|
placement:
|
||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
|
|||||||
@@ -10,19 +10,16 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Buildings/furniture.rsi
|
sprite: Buildings/furniture.rsi
|
||||||
state: chair
|
state: chair
|
||||||
|
|
||||||
- type: Collidable
|
- type: Collidable
|
||||||
|
|
||||||
- type: Clickable
|
- type: Clickable
|
||||||
- type: InteractionOutline
|
- type: InteractionOutline
|
||||||
|
|
||||||
- type: EntityStorage
|
- type: EntityStorage
|
||||||
showContents: true
|
showContents: true
|
||||||
noDoor: true
|
noDoor: true
|
||||||
|
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
- type: Destructible
|
- type: Destructible
|
||||||
thresholdvalue: 100
|
thresholdvalue: 100
|
||||||
|
|
||||||
- type: Physics
|
- type: Physics
|
||||||
- type: ShuttleController
|
- type: ShuttleController
|
||||||
|
- type: Strap
|
||||||
|
position: Stand
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Both humans and NPCs inherit from this.
|
# Both humans and NPCs inherit from this.
|
||||||
# Anything player specific (e.g. UI, input) goes under HumanMob_Content
|
# Anything human specific (e.g. UI, input) goes under HumanMob_Content
|
||||||
- type: entity
|
- type: entity
|
||||||
save: false
|
save: false
|
||||||
name: Urist McHands
|
name: Urist McHands
|
||||||
@@ -127,12 +127,14 @@
|
|||||||
- type: Appearance
|
- type: Appearance
|
||||||
visuals:
|
visuals:
|
||||||
- type: SpeciesVisualizer2D
|
- type: SpeciesVisualizer2D
|
||||||
|
- type: BuckleVisualizer2D
|
||||||
- type: CombatMode
|
- type: CombatMode
|
||||||
- type: Teleportable
|
- type: Teleportable
|
||||||
- type: CharacterInfo
|
- type: CharacterInfo
|
||||||
- type: FootstepSound
|
- type: FootstepSound
|
||||||
- type: HumanoidAppearance
|
- type: HumanoidAppearance
|
||||||
- type: AnimationPlayer
|
- type: AnimationPlayer
|
||||||
|
- type: Buckle
|
||||||
- type: UnarmedCombat
|
- type: UnarmedCombat
|
||||||
range: 0.8
|
range: 0.8
|
||||||
arcwidth: 30
|
arcwidth: 30
|
||||||
|
|||||||
BIN
Resources/Textures/Mob/UI/Buckle/buckled.png
Normal file
BIN
Resources/Textures/Mob/UI/Buckle/buckled.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Resources/Textures/Mob/UI/Buckle/unbuckled.png
Normal file
BIN
Resources/Textures/Mob/UI/Buckle/unbuckled.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 97 B |
Reference in New Issue
Block a user