242 lines
7.5 KiB
C#
242 lines
7.5 KiB
C#
using Barotrauma.Networking;
|
|
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Xml.Linq;
|
|
using Lidgren.Network;
|
|
|
|
namespace Barotrauma.Items.Components
|
|
{
|
|
class Pickable : ItemComponent, IServerSerializable
|
|
{
|
|
protected Character picker;
|
|
|
|
protected List<InvSlotType> allowedSlots;
|
|
|
|
private float pickTimer;
|
|
|
|
private Character activePicker;
|
|
|
|
public List<InvSlotType> AllowedSlots
|
|
{
|
|
get { return allowedSlots; }
|
|
}
|
|
|
|
public Character Picker
|
|
{
|
|
get { return picker; }
|
|
}
|
|
|
|
public Pickable(Item item, XElement element)
|
|
: base(item, element)
|
|
{
|
|
allowedSlots = new List<InvSlotType>();
|
|
|
|
string slotString = element.GetAttributeString("slots", "Any");
|
|
string[] slotCombinations = slotString.Split(',');
|
|
foreach (string slotCombination in slotCombinations)
|
|
{
|
|
string[] slots = slotCombination.Split('+');
|
|
InvSlotType allowedSlot = InvSlotType.None;
|
|
foreach (string slot in slots)
|
|
{
|
|
switch (slot.ToLowerInvariant())
|
|
{
|
|
case "bothhands":
|
|
allowedSlot = InvSlotType.LeftHand | InvSlotType.RightHand;
|
|
break;
|
|
default:
|
|
allowedSlot = allowedSlot | (InvSlotType)Enum.Parse(typeof(InvSlotType), slot.Trim());
|
|
break;
|
|
}
|
|
}
|
|
allowedSlots.Add(allowedSlot);
|
|
}
|
|
|
|
canBePicked = true;
|
|
}
|
|
|
|
public override bool Pick(Character picker)
|
|
{
|
|
//return if someone is already trying to pick the item
|
|
if (pickTimer > 0.0f) return false;
|
|
if (picker == null || picker.Inventory == null) return false;
|
|
|
|
if (PickingTime > 0.0f)
|
|
{
|
|
if (picker.PickingItem == null && PickingTime <= float.MaxValue)
|
|
{
|
|
#if SERVER
|
|
item.CreateServerEvent(this);
|
|
#endif
|
|
CoroutineManager.StartCoroutine(WaitForPick(picker, PickingTime));
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return OnPicked(picker);
|
|
}
|
|
}
|
|
|
|
public virtual bool OnPicked(Character picker)
|
|
{
|
|
if (picker.Inventory.TryPutItem(item, picker, allowedSlots))
|
|
{
|
|
if (!picker.HasSelectedItem(item) && item.body != null) item.body.Enabled = false;
|
|
this.picker = picker;
|
|
|
|
for (int i = item.linkedTo.Count - 1; i >= 0; i--)
|
|
{
|
|
item.linkedTo[i].RemoveLinked(item);
|
|
}
|
|
item.linkedTo.Clear();
|
|
|
|
DropConnectedWires(picker);
|
|
|
|
ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker);
|
|
|
|
#if CLIENT
|
|
if (!GameMain.Instance.LoadingScreenOpen && picker == Character.Controlled) GUI.PlayUISound(GUISoundType.PickItem);
|
|
PlaySound(ActionType.OnPicked, item.WorldPosition, picker);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
#if CLIENT
|
|
if (!GameMain.Instance.LoadingScreenOpen && picker == Character.Controlled) GUI.PlayUISound(GUISoundType.PickItemFail);
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
private IEnumerable<object> WaitForPick(Character picker, float requiredTime)
|
|
{
|
|
activePicker = picker;
|
|
picker.PickingItem = item;
|
|
|
|
var leftHand = picker.AnimController.GetLimb(LimbType.LeftHand);
|
|
var rightHand = picker.AnimController.GetLimb(LimbType.RightHand);
|
|
|
|
pickTimer = 0.0f;
|
|
while (pickTimer < requiredTime && Screen.Selected != GameMain.SubEditorScreen)
|
|
{
|
|
if (picker.IsKeyDown(InputType.Aim) || !picker.CanInteractWith(item))
|
|
{
|
|
StopPicking(picker);
|
|
yield return CoroutineStatus.Success;
|
|
}
|
|
|
|
#if CLIENT
|
|
picker.UpdateHUDProgressBar(
|
|
this,
|
|
item.WorldPosition,
|
|
pickTimer / requiredTime,
|
|
Color.Red, Color.Green);
|
|
#endif
|
|
|
|
picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
|
|
|
|
pickTimer += CoroutineManager.DeltaTime;
|
|
|
|
yield return CoroutineStatus.Running;
|
|
}
|
|
|
|
StopPicking(picker);
|
|
|
|
bool isNotRemote = true;
|
|
#if CLIENT
|
|
isNotRemote = !picker.IsRemotePlayer;
|
|
#endif
|
|
if (isNotRemote) OnPicked(picker);
|
|
|
|
yield return CoroutineStatus.Success;
|
|
}
|
|
|
|
private void StopPicking(Character picker)
|
|
{
|
|
if (picker != null)
|
|
{
|
|
picker.AnimController.Anim = AnimController.Animation.None;
|
|
picker.PickingItem = null;
|
|
}
|
|
activePicker = null;
|
|
pickTimer = 0.0f;
|
|
}
|
|
|
|
protected void DropConnectedWires(Character character)
|
|
{
|
|
Vector2 pos = character == null ? item.SimPosition : character.SimPosition;
|
|
|
|
foreach (ConnectionPanel connectionPanel in item.GetComponents<ConnectionPanel>())
|
|
{
|
|
foreach (Connection c in connectionPanel.Connections)
|
|
{
|
|
foreach (Wire w in c.Wires)
|
|
{
|
|
if (w == null) continue;
|
|
w.Item.Drop(character);
|
|
w.Item.SetTransform(pos, 0.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Drop(Character dropper)
|
|
{
|
|
if (picker == null)
|
|
{
|
|
picker = dropper;
|
|
}
|
|
|
|
Vector2 bodyDropPos = Vector2.Zero;
|
|
|
|
if (picker == null || picker.Inventory == null)
|
|
{
|
|
if (item.ParentInventory != null && item.ParentInventory.Owner != null)
|
|
{
|
|
bodyDropPos = item.ParentInventory.Owner.SimPosition;
|
|
|
|
if (item.body != null) item.body.ResetDynamics();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DropConnectedWires(picker);
|
|
|
|
item.Submarine = picker.Submarine;
|
|
bodyDropPos = picker.SimPosition;
|
|
|
|
picker.Inventory.RemoveItem(item);
|
|
picker = null;
|
|
}
|
|
|
|
if (item.body != null && !item.body.Enabled)
|
|
{
|
|
item.body.ResetDynamics();
|
|
item.SetTransform(bodyDropPos, 0.0f);
|
|
item.body.Enabled = true;
|
|
}
|
|
}
|
|
|
|
public virtual void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
|
{
|
|
msg.Write(activePicker == null ? (ushort)0 : activePicker.ID);
|
|
}
|
|
|
|
public virtual void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
|
{
|
|
ushort pickerID = msg.ReadUInt16();
|
|
if (pickerID == 0)
|
|
{
|
|
StopPicking(activePicker);
|
|
}
|
|
else
|
|
{
|
|
Pick(Entity.FindEntityByID(pickerID) as Character);
|
|
}
|
|
}
|
|
}
|
|
}
|