Interaction Features (#101)
Various minor interaction features. There is no concept of gravity in the game yet, so items drift through space or the hallways of a station until they are stopped. Thrown items do not collide with walls because making them collidable makes them collide with EVERYTHING, including the player. We need collision groups in the physics system. Because of the previous problems the velocity things are throw at is set quite low, it can be tweaked after the other mentioned issues are resolved.
This commit is contained in:
committed by
Pieter-Jan Briers
parent
cd4442b81e
commit
ed39649721
@@ -18,6 +18,8 @@ namespace Content.Client.Input
|
||||
human.AddFunction(ContentKeyFunctions.OpenCharacterMenu);
|
||||
human.AddFunction(ContentKeyFunctions.ExamineEntity);
|
||||
human.AddFunction(ContentKeyFunctions.UseItemInHand);
|
||||
human.AddFunction(ContentKeyFunctions.ActivateItemInWorld);
|
||||
human.AddFunction(ContentKeyFunctions.ThrowItemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,10 @@ using Content.Server.GameObjects.Components.Weapon.Melee;
|
||||
using Content.Server.GameObjects.Components.Materials;
|
||||
using Content.Server.GameObjects.Components.Stack;
|
||||
using Content.Server.GameObjects.Components.Construction;
|
||||
using Content.Server.Players;
|
||||
using Content.Server.Mobs;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Server.Mobs;
|
||||
using Content.Server.Players;
|
||||
|
||||
namespace Content.Server
|
||||
{
|
||||
@@ -101,6 +102,7 @@ namespace Content.Server
|
||||
factory.Register<MeleeWeaponComponent>();
|
||||
|
||||
factory.Register<ServerStorageComponent>();
|
||||
factory.RegisterReference<ServerStorageComponent, IActivate>();
|
||||
|
||||
factory.Register<PowerDebugTool>();
|
||||
factory.Register<PoweredLightComponent>();
|
||||
|
||||
@@ -240,7 +240,7 @@ namespace Content.Server.GameObjects
|
||||
var activehand = hands.GetActiveHand;
|
||||
if (activehand != null && activehand.Owner.TryGetComponent(out ClothingComponent clothing))
|
||||
{
|
||||
hands.Drop(hands.ActiveIndex);
|
||||
hands.Drop(hands.ActiveIndex, null);
|
||||
if (!Equip(msg.Inventoryslot, clothing))
|
||||
{
|
||||
hands.PutInHand(clothing);
|
||||
|
||||
@@ -13,6 +13,7 @@ using SS14.Shared.Interfaces.GameObjects;
|
||||
using SS14.Shared.Interfaces.GameObjects.Components;
|
||||
using SS14.Shared.Interfaces.Network;
|
||||
using SS14.Shared.IoC;
|
||||
using SS14.Shared.Map;
|
||||
using SS14.Shared.Serialization;
|
||||
|
||||
namespace Content.Server.GameObjects
|
||||
@@ -141,8 +142,9 @@ namespace Content.Server.GameObjects
|
||||
/// Drops the item in a slot.
|
||||
/// </summary>
|
||||
/// <param name="slot">The slot to drop the item from.</param>
|
||||
/// <param name="coords"></param>
|
||||
/// <returns>True if an item was dropped, false otherwise.</returns>
|
||||
public bool Drop(string slot)
|
||||
public bool Drop(string slot, GridLocalCoordinates? coords)
|
||||
{
|
||||
if (!CanDrop(slot))
|
||||
{
|
||||
@@ -160,7 +162,9 @@ namespace Content.Server.GameObjects
|
||||
|
||||
// TODO: The item should be dropped to the container our owner is in, if any.
|
||||
var itemTransform = item.Owner.GetComponent<ITransformComponent>();
|
||||
itemTransform.LocalPosition = Owner.GetComponent<ITransformComponent>().LocalPosition;
|
||||
|
||||
itemTransform.LocalPosition = coords ?? Owner.GetComponent<ITransformComponent>().LocalPosition;
|
||||
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Content.Server.GameObjects
|
||||
/// <summary>
|
||||
/// Storage component for containing entities within this one, matches a UI on the client which shows stored entities
|
||||
/// </summary>
|
||||
public class ServerStorageComponent : SharedStorageComponent, IAttackby, IUse
|
||||
public class ServerStorageComponent : SharedStorageComponent, IAttackby, IUse, IActivate
|
||||
{
|
||||
private Container storage;
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Content.Server.GameObjects
|
||||
Logger.DebugS("Storage", "Storage (UID {0}) attacked by user (UID {1}) with entity (UID {2}).", Owner.Uid, user.Uid, attackwith.Uid);
|
||||
var hands = user.GetComponent<HandsComponent>();
|
||||
//Check that we can drop the item from our hands first otherwise we obviously cant put it inside
|
||||
if (hands.Drop(hands.ActiveIndex))
|
||||
if (hands.Drop(hands.ActiveIndex, null))
|
||||
{
|
||||
var inserted = Insert(attackwith);
|
||||
if (inserted)
|
||||
@@ -240,5 +240,11 @@ namespace Content.Server.GameObjects
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
void IActivate.Activate(IEntity user)
|
||||
{
|
||||
((IUse) this).UseEntity(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,18 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
bool UseEntity(IEntity user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface gives components behavior when being activated in the world.
|
||||
/// </summary>
|
||||
public interface IActivate
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when this component is activated by another entity.
|
||||
/// </summary>
|
||||
/// <param name="user">Entity that activated this component.</param>
|
||||
void Activate(IEntity user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Governs interactions during clicking on entities
|
||||
/// </summary>
|
||||
@@ -101,6 +113,26 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
var inputSys = EntitySystemManager.GetEntitySystem<InputSystem>();
|
||||
inputSys.BindMap.BindFunction(ContentKeyFunctions.UseItemInHand, new PointerInputCmdHandler(HandleUseItemInHand));
|
||||
inputSys.BindMap.BindFunction(ContentKeyFunctions.ActivateItemInWorld, new PointerInputCmdHandler((HandleUseItemInWorld)));
|
||||
}
|
||||
|
||||
private void HandleUseItemInWorld(ICommonSession session, GridLocalCoordinates coords, EntityUid uid)
|
||||
{
|
||||
if(!EntityManager.TryGetEntity(uid, out var used))
|
||||
return;
|
||||
|
||||
if(!used.TryGetComponent(out IActivate activateComp))
|
||||
return;
|
||||
|
||||
var playerEnt = ((IPlayerSession) session).AttachedEntity;
|
||||
|
||||
if(playerEnt == null || !playerEnt.IsValid())
|
||||
return;
|
||||
|
||||
if (!playerEnt.Transform.LocalPosition.InRange(used.Transform.LocalPosition, INTERACTION_RANGE))
|
||||
return;
|
||||
|
||||
activateComp.Activate(playerEnt);
|
||||
}
|
||||
|
||||
private void HandleUseItemInHand(ICommonSession session, GridLocalCoordinates coords, EntityUid uid)
|
||||
@@ -112,7 +144,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
//Get entity clicked upon from UID if valid UID, if not assume no entity clicked upon and null
|
||||
if (!EntityManager.TryGetEntity(clickedUid, out var attacked))
|
||||
return;
|
||||
attacked = null;
|
||||
|
||||
//Verify player has a transform component
|
||||
if (!player.TryGetComponent<ITransformComponent>(out var playerTransform))
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
using Content.Shared.Input;
|
||||
using System;
|
||||
using Content.Server.GameObjects.Components.Projectiles;
|
||||
using Content.Shared.Input;
|
||||
using SS14.Server.GameObjects;
|
||||
using SS14.Server.GameObjects.EntitySystems;
|
||||
using SS14.Server.Interfaces.Player;
|
||||
using SS14.Shared.GameObjects;
|
||||
using SS14.Shared.GameObjects.EntitySystemMessages;
|
||||
using SS14.Shared.GameObjects.Systems;
|
||||
using SS14.Shared.Input;
|
||||
using SS14.Shared.Interfaces.GameObjects.Components;
|
||||
using SS14.Shared.Map;
|
||||
using SS14.Shared.Maths;
|
||||
using SS14.Shared.Players;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
{
|
||||
internal class HandsSystem : EntitySystem
|
||||
{
|
||||
private const float ThrowSpeed = 1.0f;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -17,8 +26,9 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
var input = EntitySystemManager.GetEntitySystem<InputSystem>();
|
||||
input.BindMap.BindFunction(ContentKeyFunctions.SwapHands, InputCmdHandler.FromDelegate(HandleSwapHands));
|
||||
input.BindMap.BindFunction(ContentKeyFunctions.Drop, InputCmdHandler.FromDelegate(HandleDrop));
|
||||
input.BindMap.BindFunction(ContentKeyFunctions.Drop, new PointerInputCmdHandler(HandleDrop));
|
||||
input.BindMap.BindFunction(ContentKeyFunctions.ActivateItemInHand, InputCmdHandler.FromDelegate(HandleActivateItem));
|
||||
input.BindMap.BindFunction(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -29,11 +39,36 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
input.BindMap.UnbindFunction(ContentKeyFunctions.SwapHands);
|
||||
input.BindMap.UnbindFunction(ContentKeyFunctions.Drop);
|
||||
input.BindMap.UnbindFunction(ContentKeyFunctions.ActivateItemInHand);
|
||||
input.BindMap.UnbindFunction(ContentKeyFunctions.ThrowItemInHand);
|
||||
}
|
||||
|
||||
base.Shutdown();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SubscribeEvents()
|
||||
{
|
||||
SubscribeEvent<EntParentChangedMessage>(HandleParented);
|
||||
}
|
||||
|
||||
private static void HandleParented(object sender, EntitySystemMessage args)
|
||||
{
|
||||
var msg = (EntParentChangedMessage) args;
|
||||
|
||||
if (!msg.Entity.TryGetComponent(out ITransformComponent transform))
|
||||
return;
|
||||
|
||||
// if item is in a container
|
||||
if(transform.IsMapTransform)
|
||||
return;
|
||||
|
||||
if(!msg.Entity.TryGetComponent(out PhysicsComponent physics))
|
||||
return;
|
||||
|
||||
// set velocity to zero
|
||||
physics.LinearVelocity = Vector2.Zero;
|
||||
}
|
||||
|
||||
private static bool TryGetAttachedComponent<T>(IPlayerSession session, out T component)
|
||||
where T : Component
|
||||
{
|
||||
@@ -59,12 +94,25 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
handsComp.SwapHands();
|
||||
}
|
||||
|
||||
private static void HandleDrop(ICommonSession session)
|
||||
private static void HandleDrop(ICommonSession session, GridLocalCoordinates coords, EntityUid uid)
|
||||
{
|
||||
if (!TryGetAttachedComponent(session as IPlayerSession, out HandsComponent handsComp))
|
||||
var ent = ((IPlayerSession) session).AttachedEntity;
|
||||
|
||||
if(ent == null || !ent.IsValid())
|
||||
return;
|
||||
|
||||
handsComp.Drop(handsComp.ActiveIndex);
|
||||
if (!ent.TryGetComponent(out HandsComponent handsComp))
|
||||
return;
|
||||
|
||||
var transform = ent.Transform;
|
||||
|
||||
GridLocalCoordinates? dropPos = null;
|
||||
if (transform.LocalPosition.InRange(coords, InteractionSystem.INTERACTION_RANGE))
|
||||
{
|
||||
dropPos = coords;
|
||||
}
|
||||
|
||||
handsComp.Drop(handsComp.ActiveIndex, dropPos);
|
||||
}
|
||||
|
||||
private static void HandleActivateItem(ICommonSession session)
|
||||
@@ -74,5 +122,53 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
handsComp.ActivateItem();
|
||||
}
|
||||
|
||||
private static void HandleThrowItem(ICommonSession session, GridLocalCoordinates coords, EntityUid uid)
|
||||
{
|
||||
var plyEnt = ((IPlayerSession)session).AttachedEntity;
|
||||
|
||||
if (plyEnt == null || !plyEnt.IsValid())
|
||||
return;
|
||||
|
||||
if (!plyEnt.TryGetComponent(out HandsComponent handsComp))
|
||||
return;
|
||||
|
||||
if (handsComp.CanDrop(handsComp.ActiveIndex))
|
||||
{
|
||||
var throwEnt = handsComp.GetHand(handsComp.ActiveIndex).Owner;
|
||||
handsComp.Drop(handsComp.ActiveIndex, null);
|
||||
|
||||
if (!throwEnt.TryGetComponent(out ProjectileComponent projComp))
|
||||
{
|
||||
projComp = throwEnt.AddComponent<ProjectileComponent>();
|
||||
}
|
||||
|
||||
projComp.IgnoreEntity(plyEnt);
|
||||
|
||||
var transform = plyEnt.Transform;
|
||||
var dirVec = (coords.ToWorld().Position - transform.WorldPosition).Normalized;
|
||||
|
||||
if (!throwEnt.TryGetComponent(out PhysicsComponent physComp))
|
||||
{
|
||||
physComp = throwEnt.AddComponent<PhysicsComponent>();
|
||||
}
|
||||
|
||||
physComp.LinearVelocity = dirVec * ThrowSpeed;
|
||||
|
||||
|
||||
var wHomoDir = Vector3.UnitX;
|
||||
|
||||
transform.InvWorldMatrix.Transform(ref wHomoDir, out var lHomoDir);
|
||||
|
||||
lHomoDir.Normalize();
|
||||
var angle = new Angle(lHomoDir.Xy);
|
||||
|
||||
transform.LocalRotation = angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.GameObjects;
|
||||
using SS14.Shared.Interfaces.GameObjects;
|
||||
using System.Collections.Generic;
|
||||
using SS14.Shared.Map;
|
||||
|
||||
namespace Content.Server.Interfaces.GameObjects
|
||||
{
|
||||
@@ -65,8 +66,9 @@ namespace Content.Server.Interfaces.GameObjects
|
||||
/// Drops an item on the ground, removing it from the hand.
|
||||
/// </summary>
|
||||
/// <param name="index">The hand to drop from.</param>
|
||||
/// <param name="coords"></param>
|
||||
/// <returns>True if an item was successfully dropped, false otherwise.</returns>
|
||||
bool Drop(string index);
|
||||
bool Drop(string index, GridLocalCoordinates? coords);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the item in the specified hand can be dropped.
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace Content.Shared.Input
|
||||
public static readonly BoundKeyFunction ActivateItemInHand = "ActivateItemInHand";
|
||||
public static readonly BoundKeyFunction OpenCharacterMenu = "OpenCharacterMenu";
|
||||
public static readonly BoundKeyFunction ExamineEntity = "ExamineEntity";
|
||||
public static readonly BoundKeyFunction UseItemInHand = "UseItemInHand";
|
||||
public static readonly BoundKeyFunction UseItemInHand = "UseItemInHand"; // use hand item on world entity
|
||||
public static readonly BoundKeyFunction ActivateItemInWorld = "ActivateItemInWorld"; // default action on world entity
|
||||
public static readonly BoundKeyFunction ThrowItemInHand = "ThrowItemInHand";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,3 +19,10 @@ binds:
|
||||
- function: UseItemInHand
|
||||
key: MouseLeft
|
||||
type: state
|
||||
- function: ActivateItemInWorld
|
||||
key: E
|
||||
type: state
|
||||
- function: ThrowItemInHand
|
||||
key: MouseLeft
|
||||
mod1: Control
|
||||
type: state
|
||||
|
||||
2
engine
2
engine
Submodule engine updated: 22fdca62bb...71121f8fef
Reference in New Issue
Block a user