38f1ddb...178a853: v0.8.9.1, removed content folder
This commit is contained in:
@@ -11,24 +11,35 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
//the position(s) in the item that the Character grabs
|
||||
protected Vector2[] handlePos;
|
||||
|
||||
private Vector2[] scaledHandlePos;
|
||||
|
||||
private InputType prevPickKey;
|
||||
private string prevMsg;
|
||||
private List<RelatedItem> prevRequiredItems;
|
||||
private Dictionary<RelatedItem.RelationType, List<RelatedItem>> prevRequiredItems;
|
||||
|
||||
//the distance from the holding characters elbow to center of the physics body of the item
|
||||
protected Vector2 holdPos;
|
||||
|
||||
protected Vector2 aimPos;
|
||||
|
||||
//protected bool aimable;
|
||||
private float swingState;
|
||||
|
||||
private bool attachable, attached, attachedByDefault;
|
||||
private PhysicsBody body;
|
||||
public PhysicsBody Pusher
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
//the angle in which the Character holds the item
|
||||
protected float holdAngle;
|
||||
|
||||
public PhysicsBody Body
|
||||
{
|
||||
get { return item.body ?? body; }
|
||||
}
|
||||
|
||||
[Serialize(false, true)]
|
||||
public bool Attached
|
||||
{
|
||||
@@ -36,6 +47,13 @@ namespace Barotrauma.Items.Components
|
||||
set { attached = value; }
|
||||
}
|
||||
|
||||
[Serialize(true, true)]
|
||||
public bool Aimable
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool ControlPose
|
||||
{
|
||||
@@ -50,6 +68,13 @@ namespace Barotrauma.Items.Components
|
||||
set { attachable = value; }
|
||||
}
|
||||
|
||||
[Serialize(true, false)]
|
||||
public bool Reattachable
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool AttachedByDefault
|
||||
{
|
||||
@@ -57,7 +82,7 @@ namespace Barotrauma.Items.Components
|
||||
set { attachedByDefault = value; }
|
||||
}
|
||||
|
||||
[Serialize("0.0,0.0", false)]
|
||||
[Serialize("0.0,0.0", false),Editable]
|
||||
public Vector2 HoldPos
|
||||
{
|
||||
get { return ConvertUnits.ToDisplayUnits(holdPos); }
|
||||
@@ -71,25 +96,62 @@ namespace Barotrauma.Items.Components
|
||||
set { aimPos = ConvertUnits.ToSimUnits(value); }
|
||||
}
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
[Serialize(0.0f, false), Editable]
|
||||
public float HoldAngle
|
||||
{
|
||||
get { return MathHelper.ToDegrees(holdAngle); }
|
||||
set { holdAngle = MathHelper.ToRadians(value); }
|
||||
}
|
||||
|
||||
private Vector2 swingAmount;
|
||||
[Serialize("0.0,0.0", false), Editable]
|
||||
public Vector2 SwingAmount
|
||||
{
|
||||
get { return ConvertUnits.ToDisplayUnits(swingAmount); }
|
||||
set { swingAmount = ConvertUnits.ToSimUnits(value); }
|
||||
}
|
||||
|
||||
[Serialize(0.0f, false), Editable]
|
||||
public float SwingSpeed { get; set; }
|
||||
|
||||
[Serialize(false, false), Editable]
|
||||
public bool SwingWhenHolding { get; set; }
|
||||
[Serialize(false, false), Editable]
|
||||
public bool SwingWhenAiming { get; set; }
|
||||
[Serialize(false, false), Editable]
|
||||
public bool SwingWhenUsing { get; set; }
|
||||
|
||||
public Holdable(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
body = item.body;
|
||||
|
||||
handlePos = new Vector2[2];
|
||||
Pusher = null;
|
||||
if (element.GetAttributeBool("blocksplayers", false))
|
||||
{
|
||||
Pusher = new PhysicsBody(item.body.width, item.body.height, item.body.radius, item.body.Density)
|
||||
{
|
||||
BodyType = FarseerPhysics.Dynamics.BodyType.Dynamic,
|
||||
CollidesWith = Physics.CollisionCharacter,
|
||||
CollisionCategories = Physics.CollisionItemBlocking,
|
||||
Enabled = false
|
||||
};
|
||||
Pusher.FarseerBody.FixedRotation = false;
|
||||
Pusher.FarseerBody.GravityScale = 0.0f;
|
||||
}
|
||||
|
||||
handlePos = new Vector2[2];
|
||||
scaledHandlePos = new Vector2[2];
|
||||
Vector2 previousValue = Vector2.Zero;
|
||||
for (int i = 1; i < 3; i++)
|
||||
{
|
||||
handlePos[i - 1] = element.GetAttributeVector2("handle" + i, Vector2.Zero);
|
||||
|
||||
handlePos[i - 1] = ConvertUnits.ToSimUnits(handlePos[i - 1]);
|
||||
int index = i - 1;
|
||||
string attributeName = "handle" + i;
|
||||
var attribute = element.Attribute(attributeName);
|
||||
// If no value is defind for handle2, use the value of handle1.
|
||||
var value = attribute != null ? ConvertUnits.ToSimUnits(XMLExtensions.ParseVector2(attribute.Value)) : previousValue;
|
||||
handlePos[index] = value;
|
||||
previousValue = value;
|
||||
}
|
||||
|
||||
canBePicked = true;
|
||||
@@ -98,7 +160,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
prevMsg = Msg;
|
||||
prevPickKey = PickKey;
|
||||
prevRequiredItems = new List<RelatedItem>(requiredItems);
|
||||
prevRequiredItems = new Dictionary<RelatedItem.RelationType, List<RelatedItem>>(requiredItems);
|
||||
|
||||
if (item.Submarine != null)
|
||||
{
|
||||
@@ -131,7 +193,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
prevMsg = Msg;
|
||||
prevPickKey = PickKey;
|
||||
prevRequiredItems = new List<RelatedItem>(requiredItems);
|
||||
prevRequiredItems = new Dictionary<RelatedItem.RelationType, List<RelatedItem>>(requiredItems);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +218,8 @@ namespace Barotrauma.Items.Components
|
||||
item.body = body;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Pusher != null) Pusher.Enabled = false;
|
||||
if (item.body != null) item.body.Enabled = true;
|
||||
IsActive = false;
|
||||
|
||||
@@ -177,18 +240,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
heldHand = picker.AnimController.GetLimb(LimbType.LeftHand);
|
||||
arm = picker.AnimController.GetLimb(LimbType.LeftArm);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
heldHand = picker.AnimController.GetLimb(LimbType.RightHand);
|
||||
arm = picker.AnimController.GetLimb(LimbType.RightArm);
|
||||
}
|
||||
|
||||
|
||||
float xDif = (heldHand.SimPosition.X - arm.SimPosition.X) / 2f;
|
||||
float yDif = (heldHand.SimPosition.Y - arm.SimPosition.Y) / 2.5f;
|
||||
//hand simPosition is actually in the wrist so need to move the item out from it slightly
|
||||
item.SetTransform(heldHand.SimPosition + new Vector2(xDif,yDif), 0.0f);
|
||||
item.SetTransform(heldHand.SimPosition + new Vector2(xDif, yDif), 0.0f);
|
||||
}
|
||||
|
||||
picker.DeselectItem(item);
|
||||
@@ -242,12 +304,28 @@ namespace Barotrauma.Items.Components
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
public bool CanBeAttached()
|
||||
{
|
||||
if (!attachable || !Reattachable) return false;
|
||||
|
||||
//can be attached anywhere in sub editor
|
||||
if (Screen.Selected == GameMain.SubEditorScreen) return true;
|
||||
|
||||
//can be attached anywhere inside hulls
|
||||
if (item.CurrentHull != null) return true;
|
||||
|
||||
return Structure.GetAttachTarget(item.WorldPosition) != null;
|
||||
}
|
||||
|
||||
public bool CanBeDeattached()
|
||||
{
|
||||
if (!attachable || !attached) return true;
|
||||
|
||||
//don't allow deattaching if outside hulls and not in sub editor
|
||||
return item.CurrentHull != null || Screen.Selected == GameMain.SubEditorScreen;
|
||||
//allow deattaching everywhere in sub editor
|
||||
if (Screen.Selected == GameMain.SubEditorScreen) return true;
|
||||
|
||||
//don't allow deattaching if part of a sub and outside hulls
|
||||
return item.Submarine == null || item.CurrentHull != null;
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
@@ -281,7 +359,7 @@ namespace Barotrauma.Items.Components
|
||||
item.CreateServerEvent(this);
|
||||
if (picker != null)
|
||||
{
|
||||
Networking.GameServer.Log(picker.LogName + " detached " + item.Name + " from a wall", ServerLog.MessageType.ItemInteraction);
|
||||
GameServer.Log(picker.LogName + " detached " + item.Name + " from a wall", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -290,10 +368,25 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AttachToWall()
|
||||
public void AttachToWall()
|
||||
{
|
||||
if (!attachable) return;
|
||||
|
||||
//outside hulls/subs -> we need to check if the item is being attached on a structure outside the sub
|
||||
if (item.CurrentHull == null && item.Submarine == null)
|
||||
{
|
||||
Structure attachTarget = Structure.GetAttachTarget(item.WorldPosition);
|
||||
if (attachTarget != null)
|
||||
{
|
||||
if (attachTarget.Submarine != null)
|
||||
{
|
||||
//set to submarine-relative position
|
||||
item.SetTransform(ConvertUnits.ToSimUnits(item.WorldPosition - attachTarget.Submarine.Position), 0.0f, false);
|
||||
}
|
||||
item.Submarine = attachTarget.Submarine;
|
||||
}
|
||||
}
|
||||
|
||||
var containedItems = item.ContainedItems;
|
||||
if (containedItems != null)
|
||||
{
|
||||
@@ -309,12 +402,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Msg = prevMsg;
|
||||
PickKey = prevPickKey;
|
||||
requiredItems = new List<RelatedItem>(prevRequiredItems);
|
||||
requiredItems = new Dictionary<RelatedItem.RelationType, List<RelatedItem>>(prevRequiredItems);
|
||||
|
||||
attached = true;
|
||||
}
|
||||
|
||||
private void DeattachFromWall()
|
||||
public void DeattachFromWall()
|
||||
{
|
||||
if (!attachable) return;
|
||||
|
||||
@@ -328,15 +421,15 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (!attachable || item.body == null) return true;
|
||||
if (!attachable || item.body == null) return (character == null || character.IsKeyDown(InputType.Aim));
|
||||
if (character != null)
|
||||
{
|
||||
if (!character.IsKeyDown(InputType.Aim)) return false;
|
||||
if (character.CurrentHull == null) return false;
|
||||
if (!CanBeAttached()) return false;
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
GameServer.Log(character.LogName + " attached " + item.Name+" to a wall", ServerLog.MessageType.ItemInteraction);
|
||||
GameServer.Log(character.LogName + " attached " + item.Name + " to a wall", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
item.Drop();
|
||||
}
|
||||
@@ -356,42 +449,57 @@ namespace Barotrauma.Items.Components
|
||||
if (item.body == null || !item.body.Enabled) return;
|
||||
if (picker == null || !picker.HasEquippedItem(item))
|
||||
{
|
||||
if (Pusher != null) Pusher.Enabled = false;
|
||||
IsActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 swing = Vector2.Zero;
|
||||
if (swingAmount != Vector2.Zero)
|
||||
{
|
||||
swingState += deltaTime;
|
||||
swingState %= 1.0f;
|
||||
if (SwingWhenHolding ||
|
||||
(SwingWhenAiming && picker.IsKeyDown(InputType.Aim)) ||
|
||||
(SwingWhenUsing && picker.IsKeyDown(InputType.Aim) && picker.IsKeyDown(InputType.Use)))
|
||||
{
|
||||
swing = swingAmount * new Vector2(
|
||||
PerlinNoise.GetPerlin(swingState * SwingSpeed * 0.1f, swingState * SwingSpeed * 0.1f) - 0.5f,
|
||||
PerlinNoise.GetPerlin(swingState * SwingSpeed * 0.1f + 0.5f, swingState * SwingSpeed * 0.1f + 0.5f) - 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, picker);
|
||||
|
||||
if (item.body.Dir != picker.AnimController.Dir) Flip(item);
|
||||
|
||||
item.Submarine = picker.Submarine;
|
||||
|
||||
|
||||
if (picker.HasSelectedItem(item))
|
||||
{
|
||||
picker.AnimController.HoldItem(deltaTime, item, handlePos, holdPos, aimPos, picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero, holdAngle);
|
||||
scaledHandlePos[0] = handlePos[0] * item.Scale;
|
||||
scaledHandlePos[1] = handlePos[1] * item.Scale;
|
||||
picker.AnimController.HoldItem(deltaTime, item, scaledHandlePos, holdPos + swing, aimPos + swing, picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero, holdAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Limb equipLimb = null;
|
||||
if (picker.Inventory.IsInLimbSlot(item, InvSlotType.Face) || picker.Inventory.IsInLimbSlot(item, InvSlotType.Head))
|
||||
if (picker.Inventory.IsInLimbSlot(item, InvSlotType.Headset) || picker.Inventory.IsInLimbSlot(item, InvSlotType.Head))
|
||||
{
|
||||
equipLimb = picker.AnimController.GetLimb(LimbType.Head);
|
||||
}
|
||||
else if (picker.Inventory.IsInLimbSlot(item, InvSlotType.Torso))
|
||||
else if (picker.Inventory.IsInLimbSlot(item, InvSlotType.InnerClothes) ||
|
||||
picker.Inventory.IsInLimbSlot(item, InvSlotType.OuterClothes))
|
||||
{
|
||||
equipLimb = picker.AnimController.GetLimb(LimbType.Torso);
|
||||
}
|
||||
else if (picker.Inventory.IsInLimbSlot(item, InvSlotType.Legs))
|
||||
{
|
||||
equipLimb = picker.AnimController.GetLimb(LimbType.Waist);
|
||||
}
|
||||
|
||||
if (equipLimb != null)
|
||||
{
|
||||
float itemAngle = (equipLimb.Rotation + holdAngle * picker.AnimController.Dir);
|
||||
|
||||
Matrix itemTransfrom = Matrix.CreateRotationZ(equipLimb.Rotation);
|
||||
Vector2 transformedHandlePos = Vector2.Transform(handlePos[0], itemTransfrom);
|
||||
Vector2 transformedHandlePos = Vector2.Transform(handlePos[0] * item.Scale, itemTransfrom);
|
||||
|
||||
item.body.ResetDynamics();
|
||||
item.SetTransform(equipLimb.SimPosition - transformedHandlePos, itemAngle);
|
||||
@@ -434,20 +542,19 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
public override void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
if (!attachable || body == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Sent an attachment event for an item that's not attachable.");
|
||||
}
|
||||
base.ServerWrite(msg, c, extraData);
|
||||
if (!attachable || body == null) return;
|
||||
|
||||
msg.Write(Attached);
|
||||
msg.Write(body.SimPosition.X);
|
||||
msg.Write(body.SimPosition.Y);
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
public override void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
base.ClientRead(type, msg, sendingTime);
|
||||
bool shouldBeAttached = msg.ReadBoolean();
|
||||
Vector2 simPosition = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
||||
|
||||
@@ -459,9 +566,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (shouldBeAttached)
|
||||
{
|
||||
Drop(false, null);
|
||||
item.SetTransform(simPosition, 0.0f);
|
||||
AttachToWall();
|
||||
if (!attached)
|
||||
{
|
||||
Drop(false, null);
|
||||
item.SetTransform(simPosition, 0.0f);
|
||||
AttachToWall();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class LevelResource : ItemComponent, IServerSerializable
|
||||
{
|
||||
[Serialize(1.0f, false)]
|
||||
public float DeattachDuration
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float DeattachTimer
|
||||
{
|
||||
get { return deattachTimer; }
|
||||
set
|
||||
{
|
||||
deattachTimer = Math.Max(0.0f, value);
|
||||
//clients don't deattach the item until the server says so (handled in ClientRead)
|
||||
if (GameMain.Client == null && deattachTimer >= DeattachDuration)
|
||||
{
|
||||
holdable.DeattachFromWall();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PhysicsBody trigger;
|
||||
|
||||
private Holdable holdable;
|
||||
|
||||
private float deattachTimer;
|
||||
|
||||
public LevelResource(Item item, XElement element) : base(item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (!holdable.Attached)
|
||||
{
|
||||
trigger.Enabled = false;
|
||||
IsActive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Vector2.DistanceSquared(item.SimPosition, trigger.SimPosition) > 0.01f)
|
||||
{
|
||||
trigger.SetTransform(item.SimPosition, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
holdable = item.GetComponent<Holdable>();
|
||||
if (holdable == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error while initializing item \"" + item.Name + "\". Level resources require a Holdable component.");
|
||||
IsActive = false;
|
||||
return;
|
||||
}
|
||||
holdable.Reattachable = false;
|
||||
holdable.PickingTime = float.MaxValue;
|
||||
|
||||
var body = item.body ?? holdable.Body;
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
trigger = new PhysicsBody(body.width, body.height, body.radius, body.Density)
|
||||
{
|
||||
UserData = item
|
||||
};
|
||||
trigger.FarseerBody.IsSensor = true;
|
||||
trigger.FarseerBody.IsStatic = true;
|
||||
trigger.FarseerBody.CollisionCategories = Physics.CollisionWall;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
if (trigger != null)
|
||||
{
|
||||
trigger.Remove();
|
||||
trigger = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(deattachTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private HashSet<Entity> hitTargets = new HashSet<Entity>();
|
||||
|
||||
public Character User
|
||||
{
|
||||
get { return user; }
|
||||
}
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float Range
|
||||
{
|
||||
@@ -56,7 +61,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "attack") continue;
|
||||
attack = new Attack(subElement);
|
||||
attack = new Attack(subElement, item.Name + ", MeleeWeapon");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +83,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
SetUser(character);
|
||||
|
||||
if (hitPos < MathHelper.Pi * 0.69f) return false;
|
||||
if (hitPos < MathHelper.PiOver4) return false;
|
||||
|
||||
reloadTimer = reload;
|
||||
|
||||
@@ -129,6 +134,7 @@ namespace Barotrauma.Items.Components
|
||||
if (!picker.HasSelectedItem(item)) IsActive = false;
|
||||
|
||||
reloadTimer -= deltaTime;
|
||||
if (reloadTimer < 0) { reloadTimer = 0; }
|
||||
|
||||
if (!picker.IsKeyDown(InputType.Aim) && !hitting) hitPos = 0.0f;
|
||||
|
||||
@@ -138,32 +144,34 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
AnimController ac = picker.AnimController;
|
||||
|
||||
//TODO: refactor the hitting logic (get rid of the magic numbers, make it possible to use different kinds of animations for different items)
|
||||
if (!hitting)
|
||||
{
|
||||
if (picker.IsKeyDown(InputType.Aim))
|
||||
if (picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0)
|
||||
{
|
||||
hitPos = Math.Min(hitPos + deltaTime * 5.0f, MathHelper.Pi * 0.7f);
|
||||
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, -0.1f), new Vector2(-0.3f, 0.2f), false, hitPos);
|
||||
hitPos = MathUtils.WrapAnglePi(Math.Min(hitPos + deltaTime * 5f, MathHelper.PiOver4));
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, false, hitPos, holdAngle + hitPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, aimPos, false, holdAngle);
|
||||
hitPos = 0;
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, Vector2.Zero, false, holdAngle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hitPos -= deltaTime * 15.0f;
|
||||
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, -0.1f), new Vector2(-0.3f, 0.2f), false, hitPos);
|
||||
hitPos = MathUtils.WrapAnglePi(hitPos - deltaTime * 15f);
|
||||
ac.HoldItem(deltaTime, item, handlePos, new Vector2(2, 0), Vector2.Zero, false, hitPos, holdAngle + hitPos); // aimPos not used -> zero (new Vector2(-0.3f, 0.2f)), holdPos new Vector2(0.6f, -0.1f)
|
||||
if (hitPos < -MathHelper.PiOver4 * 1.2f)
|
||||
{
|
||||
RestoreCollision();
|
||||
hitting = false;
|
||||
hitTargets.Clear();
|
||||
hitPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SetUser(Character character)
|
||||
{
|
||||
if (user == character) return;
|
||||
@@ -173,14 +181,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (Limb limb in user.AnimController.Limbs)
|
||||
{
|
||||
try
|
||||
if (limb.body.FarseerBody != null)
|
||||
{
|
||||
item.body.FarseerBody.RestoreCollisionWith(limb.body.FarseerBody);
|
||||
}
|
||||
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
if (GameMain.World.BodyList.Contains(limb.body.FarseerBody))
|
||||
{
|
||||
item.body.FarseerBody.RestoreCollisionWith(limb.body.FarseerBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,11 +205,6 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
item.body.CollisionCategories = Physics.CollisionItem;
|
||||
item.body.CollidesWith = Physics.CollisionWall;
|
||||
|
||||
//foreach (Limb l in picker.AnimController.Limbs)
|
||||
//{
|
||||
// item.body.FarseerBody.RestoreCollisionWith(l.body.FarseerBody);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@@ -220,6 +221,8 @@ namespace Barotrauma.Items.Components
|
||||
Limb targetLimb = null;
|
||||
Structure targetStructure = null;
|
||||
|
||||
attack?.SetUser(user);
|
||||
|
||||
if (f2.Body.UserData is Limb)
|
||||
{
|
||||
targetLimb = (Limb)f2.Body.UserData;
|
||||
@@ -273,10 +276,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (targetLimb != null)
|
||||
{
|
||||
targetLimb.character.LastDamageSource = item;
|
||||
attack.DoDamageToLimb(user, targetLimb, item.WorldPosition, 1.0f);
|
||||
}
|
||||
else if (targetCharacter != null)
|
||||
{
|
||||
targetCharacter.LastDamageSource = item;
|
||||
attack.DoDamage(user, targetCharacter, item.WorldPosition, 1.0f);
|
||||
}
|
||||
else if (targetStructure != null)
|
||||
@@ -293,7 +298,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (GameMain.Server != null && targetCharacter != null) //TODO: Log structure hits
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { Networking.NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnUse, targetCharacter.ID });
|
||||
|
||||
GameMain.Server.CreateEntityEvent(item, new object[]
|
||||
{
|
||||
Networking.NetEntityEvent.Type.ApplyStatusEffect,
|
||||
ActionType.OnUse,
|
||||
null, //itemcomponent
|
||||
targetCharacter.ID, targetLimb
|
||||
});
|
||||
|
||||
string logStr = picker?.LogName + " used " + item.Name;
|
||||
if (item.ContainedItems != null && item.ContainedItems.Length > 0)
|
||||
@@ -303,9 +315,11 @@ namespace Barotrauma.Items.Components
|
||||
logStr += " on " + targetCharacter.LogName + ".";
|
||||
Networking.GameServer.Log(logStr, Networking.ServerLog.MessageType.Attack);
|
||||
}
|
||||
|
||||
|
||||
if (targetCharacter != null) //TODO: Allow OnUse to happen on structures too maybe??
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, targetCharacter);
|
||||
{
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, targetCharacter, targetLimb, user: user);
|
||||
}
|
||||
|
||||
if (DeleteOnUse)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
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
|
||||
class Pickable : ItemComponent, IServerSerializable
|
||||
{
|
||||
protected Character picker;
|
||||
|
||||
@@ -13,6 +15,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float pickTimer;
|
||||
|
||||
private Character activePicker;
|
||||
|
||||
public List<InvSlotType> AllowedSlots
|
||||
{
|
||||
get { return allowedSlots; }
|
||||
@@ -36,13 +40,14 @@ namespace Barotrauma.Items.Components
|
||||
InvSlotType allowedSlot = InvSlotType.None;
|
||||
foreach (string slot in slots)
|
||||
{
|
||||
if (slot.ToLowerInvariant() == "bothhands")
|
||||
switch (slot.ToLowerInvariant())
|
||||
{
|
||||
allowedSlot = InvSlotType.LeftHand | InvSlotType.RightHand;
|
||||
}
|
||||
else
|
||||
{
|
||||
allowedSlot = allowedSlot | (InvSlotType)Enum.Parse(typeof(InvSlotType), slot.Trim());
|
||||
case "bothhands":
|
||||
allowedSlot = InvSlotType.LeftHand | InvSlotType.RightHand;
|
||||
break;
|
||||
default:
|
||||
allowedSlot = allowedSlot | (InvSlotType)Enum.Parse(typeof(InvSlotType), slot.Trim());
|
||||
break;
|
||||
}
|
||||
}
|
||||
allowedSlots.Add(allowedSlot);
|
||||
@@ -59,8 +64,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (PickingTime > 0.0f)
|
||||
{
|
||||
if (picker.PickingItem == null)
|
||||
if (picker.PickingItem == null && PickingTime <= float.MaxValue)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
CoroutineManager.StartCoroutine(WaitForPick(picker, PickingTime));
|
||||
}
|
||||
return false;
|
||||
@@ -90,7 +96,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
#if CLIENT
|
||||
if (!GameMain.Instance.LoadingScreenOpen && picker == Character.Controlled) GUI.PlayUISound(GUISoundType.PickItem);
|
||||
PlaySound(ActionType.OnPicked, item.WorldPosition);
|
||||
PlaySound(ActionType.OnPicked, item.WorldPosition, picker);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -105,6 +111,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private IEnumerable<object> WaitForPick(Character picker, float requiredTime)
|
||||
{
|
||||
activePicker = picker;
|
||||
picker.PickingItem = item;
|
||||
|
||||
var leftHand = picker.AnimController.GetLimb(LimbType.LeftHand);
|
||||
@@ -127,7 +134,7 @@ namespace Barotrauma.Items.Components
|
||||
Color.Red, Color.Green);
|
||||
#endif
|
||||
|
||||
picker.AnimController.UpdateUseItem(true, item.SimPosition + Vector2.UnitY * ((pickTimer / 10.0f) % 0.1f));
|
||||
picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
|
||||
|
||||
pickTimer += CoroutineManager.DeltaTime;
|
||||
|
||||
@@ -143,28 +150,31 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void StopPicking(Character picker)
|
||||
{
|
||||
picker.AnimController.Anim = AnimController.Animation.None;
|
||||
picker.PickingItem = null;
|
||||
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;
|
||||
|
||||
var connectionPanel = item.GetComponent<ConnectionPanel>();
|
||||
if (connectionPanel == null) return;
|
||||
|
||||
foreach (Connection c in connectionPanel.Connections)
|
||||
foreach (ConnectionPanel connectionPanel in item.GetComponents<ConnectionPanel>())
|
||||
{
|
||||
foreach (Wire w in c.Wires)
|
||||
foreach (Connection c in connectionPanel.Connections)
|
||||
{
|
||||
if (w == null) continue;
|
||||
|
||||
w.Item.Drop(character);
|
||||
w.Item.SetTransform(pos, 0.0f);
|
||||
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)
|
||||
@@ -204,5 +214,22 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,18 +11,16 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
enum UsableIn
|
||||
{
|
||||
Air,Water,Both
|
||||
Air, Water, Both
|
||||
};
|
||||
|
||||
private float force;
|
||||
|
||||
private string particles;
|
||||
|
||||
private float useState;
|
||||
|
||||
private UsableIn usableIn;
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
|
||||
[Serialize(0.0f, false), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
|
||||
public float Force
|
||||
{
|
||||
get { return force; }
|
||||
@@ -30,6 +28,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
private string particles;
|
||||
[Serialize("", false)]
|
||||
public string Particles
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
@@ -81,7 +82,7 @@ namespace Barotrauma.Items.Components
|
||||
limbBodies.Add(l.body.FarseerBody);
|
||||
}
|
||||
|
||||
float degreeOfFailure = (100.0f - DegreeOfSuccess(character)) / 100.0f;
|
||||
float degreeOfFailure = 1.0f - DegreeOfSuccess(character);
|
||||
|
||||
degreeOfFailure *= degreeOfFailure;
|
||||
|
||||
@@ -90,50 +91,80 @@ namespace Barotrauma.Items.Components
|
||||
ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
|
||||
}
|
||||
|
||||
Projectile projectile = null;
|
||||
Item[] containedItems = item.ContainedItems;
|
||||
if (containedItems != null)
|
||||
if (containedItems == null) return true;
|
||||
|
||||
foreach (Item item in containedItems)
|
||||
{
|
||||
foreach (Item projectile in containedItems)
|
||||
projectile = item.GetComponent<Projectile>();
|
||||
if (projectile != null) break;
|
||||
}
|
||||
//projectile not found, see if one of the contained items contains projectiles
|
||||
if (projectile == null)
|
||||
{
|
||||
foreach (Item item in containedItems)
|
||||
{
|
||||
if (projectile == null) continue;
|
||||
//find the projectile-itemcomponent of the projectile,
|
||||
//and add the limbs of the shooter to the list of bodies to be ignored
|
||||
//so that the player can't shoot himself
|
||||
Projectile projectileComponent= projectile.GetComponent<Projectile>();
|
||||
if (projectileComponent == null) continue;
|
||||
|
||||
float spread = MathHelper.ToRadians(MathHelper.Lerp(Spread, UnskilledSpread, degreeOfFailure));
|
||||
float rotation = (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;
|
||||
rotation += spread * Rand.Range(-0.5f, 0.5f);
|
||||
|
||||
projectile.body.ResetDynamics();
|
||||
projectile.SetTransform(TransformedBarrelPos, rotation);
|
||||
|
||||
projectileComponent.User = character;
|
||||
projectileComponent.IgnoredBodies = new List<Body>(limbBodies);
|
||||
projectile.Use(deltaTime);
|
||||
projectileComponent.User = character;
|
||||
|
||||
projectile.body.ApplyTorque(projectile.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
|
||||
|
||||
//set the rotation of the projectile again because dropping the projectile resets the rotation
|
||||
projectile.SetTransform(projectile.SimPosition, rotation);
|
||||
|
||||
//recoil
|
||||
item.body.ApplyLinearImpulse(
|
||||
new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * item.body.Mass * -50.0f);
|
||||
|
||||
item.RemoveContained(projectile);
|
||||
|
||||
Rope rope = item.GetComponent<Rope>();
|
||||
if (rope != null) rope.Attach(projectile);
|
||||
|
||||
return true;
|
||||
Item[] containedSubItems = item.ContainedItems;
|
||||
foreach (Item subItem in containedSubItems)
|
||||
{
|
||||
projectile = subItem.GetComponent<Projectile>();
|
||||
|
||||
//apply OnUse statuseffects to the container in case it has to react to it somehow
|
||||
//(play a sound, spawn more projectiles, reduce condition...)
|
||||
subItem.GetComponent<ItemContainer>()?.Item.ApplyStatusEffects(ActionType.OnUse, deltaTime);
|
||||
if (projectile != null) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
if (projectile == null) return true;
|
||||
|
||||
float spread = MathHelper.ToRadians(MathHelper.Lerp(Spread, UnskilledSpread, degreeOfFailure));
|
||||
float rotation = (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;
|
||||
rotation += spread * Rand.Range(-0.5f, 0.5f);
|
||||
|
||||
projectile.User = character;
|
||||
//add the limbs of the shooter to the list of bodies to be ignored
|
||||
//so that the player can't shoot himself
|
||||
projectile.IgnoredBodies = new List<Body>(limbBodies);
|
||||
|
||||
Vector2 projectilePos = item.SimPosition;
|
||||
Vector2 sourcePos = character?.AnimController == null ? item.SimPosition : character.AnimController.AimSourceSimPos;
|
||||
Vector2 barrelPos = TransformedBarrelPos;
|
||||
//make sure there's no obstacles between the base of the weapon (or the shoulder of the character) and the end of the barrel
|
||||
if (Submarine.PickBody(sourcePos, barrelPos, projectile.IgnoredBodies) == null)
|
||||
{
|
||||
//no obstacles -> we can spawn the projectile at the barrel
|
||||
projectilePos = barrelPos;
|
||||
}
|
||||
else if ((sourcePos - barrelPos).LengthSquared() > 0.0001f)
|
||||
{
|
||||
//spawn the projectile body.GetMaxExtent() away from the position where the raycast hit the obstacle
|
||||
projectilePos = sourcePos - Vector2.Normalize(barrelPos - projectilePos) * Math.Max(projectile.Item.body.GetMaxExtent(), 0.1f);
|
||||
}
|
||||
|
||||
projectile.Item.body.ResetDynamics();
|
||||
projectile.Item.SetTransform(projectilePos, rotation);
|
||||
|
||||
projectile.Use(deltaTime);
|
||||
projectile.User = character;
|
||||
|
||||
projectile.Item.body.ApplyTorque(projectile.Item.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
|
||||
|
||||
//set the rotation of the projectile again because dropping the projectile resets the rotation
|
||||
projectile.Item.SetTransform(projectilePos,
|
||||
rotation + ((item.body.Dir == 1.0f) ? projectile.LaunchRotationRadians : projectile.LaunchRotationRadians - MathHelper.Pi));
|
||||
|
||||
//recoil
|
||||
item.body.ApplyLinearImpulse(
|
||||
new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * item.body.Mass * -50.0f);
|
||||
|
||||
item.RemoveContained(projectile.Item);
|
||||
|
||||
Rope rope = item.GetComponent<Rope>();
|
||||
if (rope != null) rope.Attach(projectile.Item);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@ using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
#if CLIENT
|
||||
using Barotrauma.Particles;
|
||||
#endif
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class RepairTool : ItemComponent
|
||||
partial class RepairTool : ItemComponent
|
||||
{
|
||||
private readonly List<string> fixableEntities;
|
||||
|
||||
@@ -20,9 +20,7 @@ namespace Barotrauma.Items.Components
|
||||
private Vector2 pickedPosition;
|
||||
|
||||
private Vector2 barrelPos;
|
||||
|
||||
private string particles;
|
||||
|
||||
|
||||
private float activeTimer;
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
@@ -44,25 +42,11 @@ namespace Barotrauma.Items.Components
|
||||
get; set;
|
||||
}
|
||||
[Serialize(0.0f, false)]
|
||||
public float ExtinquishAmount
|
||||
public float ExtinguishAmount
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
public ParticleEmitter ParticleEmitter
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private List<ParticleEmitter> ParticleEmitterHitStructure = new List<ParticleEmitter>();
|
||||
|
||||
private List<ParticleEmitter> ParticleEmitterHitItem = new List<ParticleEmitter>();
|
||||
|
||||
private List<ParticleEmitter> ParticleEmitterHitCharacter = new List<ParticleEmitter>();
|
||||
#endif
|
||||
|
||||
|
||||
[Serialize("0.0,0.0", false)]
|
||||
public Vector2 BarrelPos
|
||||
{
|
||||
@@ -92,26 +76,24 @@ namespace Barotrauma.Items.Components
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "fixable":
|
||||
fixableEntities.Add(subElement.Attribute("name").Value);
|
||||
if (subElement.Attribute("name") != null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in RepairTool " + item.Name + " - use identifiers instead of names to configure fixable entities.");
|
||||
fixableEntities.Add(subElement.Attribute("name").Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
fixableEntities.Add(subElement.GetAttributeString("identifier", ""));
|
||||
}
|
||||
break;
|
||||
#if CLIENT
|
||||
case "particleemitter":
|
||||
ParticleEmitter = new ParticleEmitter(subElement);
|
||||
break;
|
||||
case "particleemitterhititem":
|
||||
ParticleEmitterHitItem.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
case "particleemitterhitstructure":
|
||||
ParticleEmitterHitStructure.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
case "particleemitterhitcharacter":
|
||||
ParticleEmitterHitCharacter.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
InitProjSpecific(element);
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element);
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
activeTimer -= deltaTime;
|
||||
@@ -123,7 +105,7 @@ namespace Barotrauma.Items.Components
|
||||
if (character == null || character.Removed) return false;
|
||||
if (!character.IsKeyDown(InputType.Aim)) return false;
|
||||
|
||||
float degreeOfSuccess = DegreeOfSuccess(character)/100.0f;
|
||||
float degreeOfSuccess = DegreeOfSuccess(character);
|
||||
|
||||
if (Rand.Range(0.0f, 0.5f) > degreeOfSuccess)
|
||||
{
|
||||
@@ -163,32 +145,26 @@ namespace Barotrauma.Items.Components
|
||||
Repair(rayStart - character.Submarine.SimPosition, rayEnd - character.Submarine.SimPosition, deltaTime, character, degreeOfSuccess, ignoredBodies);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (ParticleEmitter != null)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
ParticleEmitter.Emit(
|
||||
deltaTime, item.WorldPosition + TransformedBarrelPos,
|
||||
item.CurrentHull, particleAngle, -particleAngle);
|
||||
}
|
||||
#endif
|
||||
|
||||
UseProjSpecific(deltaTime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
partial void UseProjSpecific(float deltaTime);
|
||||
|
||||
private void Repair(Vector2 rayStart, Vector2 rayEnd, float deltaTime, Character user, float degreeOfSuccess, List<Body> ignoredBodies)
|
||||
{
|
||||
Body targetBody = Submarine.PickBody(rayStart, rayEnd, ignoredBodies,
|
||||
Body targetBody = Submarine.PickBody(rayStart, rayEnd, ignoredBodies,
|
||||
Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionRepair, false);
|
||||
|
||||
if (ExtinquishAmount > 0.0f && item.CurrentHull != null)
|
||||
if (ExtinguishAmount > 0.0f && item.CurrentHull != null)
|
||||
{
|
||||
List<FireSource> fireSourcesInRange = new List<FireSource>();
|
||||
//step along the ray in 10% intervals, collecting all fire sources in the range
|
||||
for (float x = 0.0f; x <= Submarine.LastPickedFraction; x += 0.1f)
|
||||
{
|
||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(rayStart + (rayEnd - rayStart) * x);
|
||||
displayPos += item.CurrentHull.Submarine.Position;
|
||||
if (item.CurrentHull.Submarine != null) { displayPos += item.CurrentHull.Submarine.Position; }
|
||||
|
||||
Hull hull = Hull.FindHull(displayPos, item.CurrentHull);
|
||||
if (hull == null) continue;
|
||||
@@ -203,52 +179,25 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (FireSource fs in fireSourcesInRange)
|
||||
{
|
||||
fs.Extinguish(deltaTime, ExtinquishAmount);
|
||||
fs.Extinguish(deltaTime, ExtinguishAmount);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetBody == null || targetBody.UserData == null) return;
|
||||
|
||||
pickedPosition = Submarine.LastPickedPosition;
|
||||
|
||||
Structure targetStructure;
|
||||
Character targetCharacter;
|
||||
Limb targetLimb;
|
||||
Item targetItem;
|
||||
if ((targetStructure = (targetBody.UserData as Structure)) != null)
|
||||
|
||||
if (targetBody.UserData is Structure targetStructure)
|
||||
{
|
||||
if (!fixableEntities.Contains("structure") && !fixableEntities.Contains(targetStructure.Name)) return;
|
||||
if (!fixableEntities.Contains("structure") && !fixableEntities.Contains(targetStructure.Prefab.Identifier)) return;
|
||||
if (targetStructure.IsPlatform) return;
|
||||
|
||||
int sectionIndex = targetStructure.FindSectionIndex(ConvertUnits.ToDisplayUnits(pickedPosition));
|
||||
if (sectionIndex < 0) return;
|
||||
|
||||
#if CLIENT
|
||||
Vector2 progressBarPos = targetStructure.SectionPosition(sectionIndex);
|
||||
if (targetStructure.Submarine != null)
|
||||
{
|
||||
progressBarPos += targetStructure.Submarine.DrawPosition;
|
||||
}
|
||||
|
||||
var progressBar = user.UpdateHUDProgressBar(
|
||||
targetStructure,
|
||||
progressBarPos,
|
||||
1.0f - targetStructure.SectionDamage(sectionIndex) / targetStructure.Health,
|
||||
Color.Red, Color.Green);
|
||||
|
||||
if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f);
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetStructure.Submarine != null) particlePos += targetStructure.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitStructure)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
}
|
||||
#endif
|
||||
|
||||
FixStructureProjSpecific(user, deltaTime, targetStructure, sectionIndex);
|
||||
targetStructure.AddDamage(sectionIndex, -StructureFixAmount * degreeOfSuccess, user);
|
||||
|
||||
|
||||
//if the next section is small enough, apply the effect to it as well
|
||||
//(to make it easier to fix a small "left-over" section)
|
||||
for (int i = -1; i < 2; i += 2)
|
||||
@@ -263,34 +212,25 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((targetCharacter = (targetBody.UserData as Character)) != null)
|
||||
else if (targetBody.UserData is Character targetCharacter)
|
||||
{
|
||||
targetCharacter.AddDamage(CauseOfDeath.Damage, -LimbFixAmount * degreeOfSuccess, user);
|
||||
#if CLIENT
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetCharacter.Submarine != null) particlePos += targetCharacter.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitCharacter)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if ((targetLimb = (targetBody.UserData as Limb)) != null)
|
||||
{
|
||||
targetLimb.character.AddDamage(CauseOfDeath.Damage, -LimbFixAmount * degreeOfSuccess, user);
|
||||
Vector2 hitPos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetCharacter.Submarine != null) hitPos += targetCharacter.Submarine.Position;
|
||||
|
||||
#if CLIENT
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetLimb.character.Submarine != null) particlePos += targetLimb.character.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitCharacter)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
}
|
||||
#endif
|
||||
targetCharacter.LastDamageSource = item;
|
||||
targetCharacter.AddDamage(hitPos,
|
||||
new List<Affliction>() { AfflictionPrefab.Burn.Instantiate(-LimbFixAmount * degreeOfSuccess, user) }, 0.0f, false, 0.0f, user);
|
||||
FixCharacterProjSpecific(user, deltaTime, targetCharacter);
|
||||
}
|
||||
else if ((targetItem = (targetBody.UserData as Item)) != null)
|
||||
else if (targetBody.UserData is Limb targetLimb)
|
||||
{
|
||||
targetLimb.character.LastDamageSource = item;
|
||||
targetLimb.character.DamageLimb(targetLimb.WorldPosition, targetLimb,
|
||||
new List<Affliction>() { AfflictionPrefab.Burn.Instantiate(-LimbFixAmount * degreeOfSuccess, user) }, 0.0f, false, 0.0f, user);
|
||||
|
||||
FixCharacterProjSpecific(user, deltaTime, targetLimb.character);
|
||||
}
|
||||
else if (targetBody.UserData is Item targetItem)
|
||||
{
|
||||
targetItem.IsHighlighted = true;
|
||||
|
||||
@@ -298,31 +238,27 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ApplyStatusEffectsOnTarget(deltaTime, ActionType.OnUse, targetItem.AllPropertyObjects);
|
||||
|
||||
#if CLIENT
|
||||
if (item.Condition != prevCondition)
|
||||
var levelResource = targetItem.GetComponent<LevelResource>();
|
||||
if (levelResource != null && levelResource.IsActive &&
|
||||
levelResource.HasRequiredItems(user, addMessage: false))
|
||||
{
|
||||
Vector2 progressBarPos = targetItem.DrawPosition;
|
||||
|
||||
var progressBar = user.UpdateHUDProgressBar(
|
||||
targetItem,
|
||||
progressBarPos,
|
||||
targetItem.Condition / 100.0f,
|
||||
levelResource.DeattachTimer += deltaTime;
|
||||
#if CLIENT
|
||||
Character.Controlled?.UpdateHUDProgressBar(
|
||||
this,
|
||||
targetItem.WorldPosition,
|
||||
levelResource.DeattachTimer / levelResource.DeattachDuration,
|
||||
Color.Red, Color.Green);
|
||||
|
||||
if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f);
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitItem)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
FixItemProjSpecific(user, deltaTime, targetItem, prevCondition);
|
||||
}
|
||||
}
|
||||
|
||||
partial void FixStructureProjSpecific(Character user, float deltaTime, Structure targetStructure, int sectionIndex);
|
||||
partial void FixCharacterProjSpecific(Character user, float deltaTime, Character targetCharacter);
|
||||
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem, float prevCondition);
|
||||
|
||||
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
||||
{
|
||||
Gap leak = objective.OperateTarget as Gap;
|
||||
@@ -332,17 +268,24 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
//too far away -> consider this done and hope the AI is smart enough to move closer
|
||||
if (dist > range * 5.0f) return true;
|
||||
|
||||
|
||||
Vector2 gapDiff = leak.WorldPosition - item.WorldPosition;
|
||||
if (!character.AnimController.InWater && character.AnimController is HumanoidAnimController &&
|
||||
Math.Abs(gapDiff.X) < 100.0f && gapDiff.Y < 0.0f && gapDiff.Y > -150.0f)
|
||||
{
|
||||
((HumanoidAnimController)character.AnimController).Crouching = true;
|
||||
}
|
||||
|
||||
//steer closer if almost in range
|
||||
if (dist > range)
|
||||
{
|
||||
Vector2 standPos = leak.IsHorizontal ?
|
||||
new Vector2(Math.Sign(item.WorldPosition.X - leak.WorldPosition.X), 0.0f)
|
||||
: new Vector2(0.0f, Math.Sign(item.WorldPosition.Y - leak.WorldPosition.Y));
|
||||
new Vector2(Math.Sign(-gapDiff.X), 0.0f)
|
||||
: new Vector2(0.0f, Math.Sign(-gapDiff.Y) * 0.5f);
|
||||
|
||||
standPos = leak.WorldPosition + standPos * range;
|
||||
|
||||
character.AIController.SteeringManager.SteeringManual(deltaTime, (standPos - character.WorldPosition) / 1000.0f);
|
||||
character.AIController.SteeringManager.SteeringManual(deltaTime, (standPos - character.WorldPosition) / 1000.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -355,7 +298,21 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Use(deltaTime, character);
|
||||
|
||||
return leak.Open <= 0.0f;
|
||||
bool leakFixed = leak.Open <= 0.0f || leak.Removed;
|
||||
|
||||
if (leakFixed && leak.FlowTargetHull != null)
|
||||
{
|
||||
if (!leak.FlowTargetHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.Open > 0.0f))
|
||||
{
|
||||
character.Speak(TextManager.Get("DialogLeaksFixed").Replace("[roomname]", leak.FlowTargetHull.RoomName), null, 0.0f, "leaksfixed", 10.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
character.Speak(TextManager.Get("DialogLeakFixed").Replace("[roomname]", leak.FlowTargetHull.RoomName), null, 0.0f, "leakfixed", 10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
return leakFixed;
|
||||
}
|
||||
|
||||
private void ApplyStatusEffectsOnTarget(float deltaTime, ActionType actionType, List<ISerializableEntity> targets)
|
||||
@@ -367,7 +324,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
{
|
||||
if (effect.Targets.HasFlag(StatusEffect.TargetType.UseTarget))
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.UseTarget))
|
||||
{
|
||||
effect.Apply(actionType, deltaTime, item, targets);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ namespace Barotrauma.Items.Components
|
||||
: base(item, element)
|
||||
{
|
||||
//throwForce = ToolBox.GetAttributeFloat(element, "throwforce", 1.0f);
|
||||
if (aimPos == Vector2.Zero)
|
||||
{
|
||||
aimPos = new Vector2(0.6f, 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
@@ -77,22 +81,21 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (picker.IsKeyDown(InputType.Aim))
|
||||
{
|
||||
throwPos = (float)System.Math.Min(throwPos + deltaTime * 5.0f, MathHelper.Pi * 0.7f);
|
||||
|
||||
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, -0.0f), new Vector2(-0.3f, 0.2f), false, throwPos);
|
||||
throwPos = MathUtils.WrapAnglePi(System.Math.Min(throwPos + deltaTime * 5.0f, MathHelper.PiOver2));
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, false, throwPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, aimPos, false, holdAngle);
|
||||
throwPos = 0;
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, Vector2.Zero, false, holdAngle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throwPos -= deltaTime * 15.0f;
|
||||
throwPos = MathUtils.WrapAnglePi(throwPos - deltaTime * 15.0f);
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, false, throwPos);
|
||||
|
||||
ac.HoldItem(deltaTime, item, handlePos, new Vector2(0.6f, 0.0f), new Vector2(-0.3f, 0.2f), false, throwPos);
|
||||
|
||||
if (throwPos < -0.0)
|
||||
if (throwPos < 0)
|
||||
{
|
||||
Vector2 throwVector = Vector2.Normalize(picker.CursorWorldPosition - picker.WorldPosition);
|
||||
//throw upwards if cursor is at the position of the character
|
||||
@@ -108,6 +111,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Limb rightHand = ac.GetLimb(LimbType.RightHand);
|
||||
item.body.AngularVelocity = rightHand.body.AngularVelocity;
|
||||
throwPos = 0;
|
||||
throwDone = true;
|
||||
ApplyStatusEffects(ActionType.OnSecondaryUse, deltaTime, picker); //Stun grenades, flares, etc. all have their throw-related things handled in "onSecondaryUse"
|
||||
throwing = false;
|
||||
|
||||
Reference in New Issue
Block a user