Unstable 0.1500.5.0 (almost forgor edition 💀)
This commit is contained in:
@@ -79,6 +79,13 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, false, description: "Use the hand rotation instead of torso rotation for the item hold angle. Enable this if you want the item just to follow with the arm when not aiming instead of forcing the arm to a hold pose.")]
|
||||
public bool UseHandRotationForHoldAngle
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, false, description: "Can the item be attached to walls.")]
|
||||
public bool Attachable
|
||||
{
|
||||
@@ -93,6 +100,13 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, false, description: "Can the item only be attached in limited amount? Uses permanent stat values to check for legibility.")]
|
||||
public bool LimitedAttachable
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, false, description: "Should the item be attached to a wall by default when it's placed in the submarine editor.")]
|
||||
public bool AttachedByDefault
|
||||
{
|
||||
@@ -154,7 +168,8 @@ namespace Barotrauma.Items.Components
|
||||
BodyType = BodyType.Dynamic,
|
||||
CollidesWith = Physics.CollisionCharacter,
|
||||
CollisionCategories = Physics.CollisionItemBlocking,
|
||||
Enabled = false
|
||||
Enabled = false,
|
||||
UserData = "Holdable.Pusher"
|
||||
};
|
||||
Pusher.FarseerBody.OnCollision += OnPusherCollision;
|
||||
Pusher.FarseerBody.FixedRotation = false;
|
||||
@@ -205,7 +220,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
characterUsable = element.GetAttributeBool("characterusable", true);
|
||||
}
|
||||
|
||||
@@ -247,6 +261,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void Drop(bool dropConnectedWires, Character dropper)
|
||||
{
|
||||
GetRope()?.Snap();
|
||||
if (dropConnectedWires)
|
||||
{
|
||||
DropConnectedWires(dropper);
|
||||
@@ -558,6 +573,15 @@ namespace Barotrauma.Items.Components
|
||||
PickKey = InputType.Select;
|
||||
}
|
||||
|
||||
public override void ParseMsg()
|
||||
{
|
||||
base.ParseMsg();
|
||||
if (Attachable)
|
||||
{
|
||||
prevMsg = DisplayMsg;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (!attachable || item.body == null) { return character == null || (character.IsKeyDown(InputType.Aim) && characterUsable); }
|
||||
@@ -567,6 +591,25 @@ namespace Barotrauma.Items.Components
|
||||
if (!character.IsKeyDown(InputType.Aim)) { return false; }
|
||||
if (!CanBeAttached(character)) { return false; }
|
||||
|
||||
if (LimitedAttachable)
|
||||
{
|
||||
if (character?.Info == null)
|
||||
{
|
||||
DebugConsole.AddWarning("Character without CharacterInfo attempting to attach a limited attachable item!");
|
||||
return false;
|
||||
}
|
||||
int maxAttachableCount = (int)character.Info.GetSavedStatValue(StatTypes.MaxAttachableCount, item.Prefab.Identifier);
|
||||
int currentlyAttachedCount = Item.ItemList.Count(
|
||||
i => i.Submarine == item.Submarine && i.GetComponent<Holdable>() is Holdable holdable && holdable.Attached && i.Prefab.Identifier == item.prefab.Identifier);
|
||||
if (currentlyAttachedCount >= maxAttachableCount)
|
||||
{
|
||||
#if CLIENT
|
||||
GUI.AddMessage($"{TextManager.Get("itemmsgtotalnumberlimited")} ({currentlyAttachedCount}/{maxAttachableCount})", Color.Red);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
if (character != Character.Controlled)
|
||||
@@ -666,6 +709,20 @@ namespace Barotrauma.Items.Components
|
||||
Update(deltaTime, cam);
|
||||
}
|
||||
|
||||
public Rope GetRope()
|
||||
{
|
||||
var rangedWeapon = Item.GetComponent<RangedWeapon>();
|
||||
if (rangedWeapon != null)
|
||||
{
|
||||
var lastProjectile = rangedWeapon.LastProjectile;
|
||||
if (lastProjectile != null)
|
||||
{
|
||||
return lastProjectile.Item.GetComponent<Rope>();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (attachTargetCell != null)
|
||||
@@ -720,9 +777,18 @@ namespace Barotrauma.Items.Components
|
||||
scaledHandlePos[1] = handlePos[1] * item.Scale;
|
||||
bool aim = picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero && picker.CanAim;
|
||||
picker.AnimController.HoldItem(deltaTime, item, scaledHandlePos, holdPos + swing, aimPos + swing, aim, holdAngle);
|
||||
if (!aim)
|
||||
{
|
||||
var rope = GetRope();
|
||||
if (rope != null && rope.SnapWhenNotAimed)
|
||||
{
|
||||
rope.Snap();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetRope()?.Snap();
|
||||
Limb equipLimb = null;
|
||||
if (picker.Inventory.IsInLimbSlot(item, InvSlotType.Headset) || picker.Inventory.IsInLimbSlot(item, InvSlotType.Head))
|
||||
{
|
||||
@@ -792,7 +858,7 @@ namespace Barotrauma.Items.Components
|
||||
attachTargetCell = null;
|
||||
if (Pusher != null)
|
||||
{
|
||||
GameMain.World.Remove(Pusher.FarseerBody);
|
||||
Pusher.Remove();
|
||||
Pusher = null;
|
||||
}
|
||||
body = null;
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void Initialize(CharacterInfo info)
|
||||
{
|
||||
if (info == null) return;
|
||||
if (info == null) { return; }
|
||||
|
||||
if (info.Job?.Prefab != null)
|
||||
{
|
||||
@@ -42,20 +42,22 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
var head = info.Head;
|
||||
|
||||
if (info != null && head != null)
|
||||
{
|
||||
item.AddTag("gender:" + head.gender.ToString().ToLowerInvariant());
|
||||
item.AddTag("race:" + head.race.ToString());
|
||||
item.AddTag("headspriteid:" + info.HeadSpriteId.ToString());
|
||||
item.AddTag("hairindex:" + head.HairIndex);
|
||||
item.AddTag("beardindex:" + head.BeardIndex);
|
||||
item.AddTag("moustacheindex:" + head.MoustacheIndex);
|
||||
item.AddTag("faceattachmentindex:" + head.FaceAttachmentIndex);
|
||||
if (head == null) { return; }
|
||||
|
||||
if (info.HasGenders) { item.AddTag($"gender:{head.gender.ToString().ToLowerInvariant()}"); }
|
||||
if (info.HasRaces) { item.AddTag($"race:{head.race}"); }
|
||||
item.AddTag($"headspriteid:{info.HeadSpriteId}");
|
||||
item.AddTag($"hairindex:{head.HairIndex}");
|
||||
item.AddTag($"beardindex:{head.BeardIndex}");
|
||||
item.AddTag($"moustacheindex:{head.MoustacheIndex}");
|
||||
item.AddTag($"faceattachmentindex:{head.FaceAttachmentIndex}");
|
||||
item.AddTag($"haircolor:{head.HairColor.ToStringHex()}");
|
||||
item.AddTag($"facialhaircolor:{head.FacialHairColor.ToStringHex()}");
|
||||
item.AddTag($"skincolor:{head.SkinColor.ToStringHex()}");
|
||||
|
||||
if (head.SheetIndex != null)
|
||||
{
|
||||
item.AddTag("sheetindex:" + head.SheetIndex.Value.X + ";" + head.SheetIndex.Value.Y);
|
||||
}
|
||||
if (head.SheetIndex != null)
|
||||
{
|
||||
item.AddTag($"sheetindex:{head.SheetIndex.Value.X};{head.SheetIndex.Value.Y}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,16 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Editable, Serialize(true, false)]
|
||||
public bool Swing { get; set; }
|
||||
|
||||
[Editable, Serialize("2.0, 0.0", false)]
|
||||
public Vector2 SwingPos { get; set; }
|
||||
|
||||
[Editable, Serialize("3.0, -1.0", false)]
|
||||
public Vector2 SwingForce { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defines items that boost the weapon functionality, like battery cell for stun batons.
|
||||
/// </summary>
|
||||
@@ -67,8 +77,6 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
}
|
||||
item.IsShootable = true;
|
||||
// TODO: should define this in xml if we have melee weapons that don't require aim to use
|
||||
item.RequireAimToUse = true;
|
||||
PreferredContainedItems = element.GetAttributeStringArray("preferredcontaineditems", new string[0], convertToLowerInvariant: true);
|
||||
}
|
||||
|
||||
@@ -82,6 +90,9 @@ namespace Barotrauma.Items.Components
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == null || reloadTimer > 0.0f) { return false; }
|
||||
#if CLIENT
|
||||
if (!Item.RequireAimToUse && character.IsPlayer && (GUI.MouseOn != null || character.Inventory.visualSlots.Any(s => s.MouseOn()) || Inventory.DraggingItems.Any())) { return false; }
|
||||
#endif
|
||||
if (Item.RequireAimToUse && !character.IsKeyDown(InputType.Aim) || hitting) { return false; }
|
||||
|
||||
//don't allow hitting if the character is already hitting with another weapon
|
||||
@@ -94,7 +105,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
SetUser(character);
|
||||
|
||||
if (hitPos < MathHelper.PiOver4) { return false; }
|
||||
if (Item.RequireAimToUse && hitPos < MathHelper.PiOver4) { return false; }
|
||||
|
||||
ActivateNearbySleepingCharacters();
|
||||
reloadTimer = reload / (1 + character.GetStatValue(StatTypes.MeleeAttackSpeed));
|
||||
@@ -105,20 +116,28 @@ namespace Barotrauma.Items.Components
|
||||
item.body.FarseerBody.IsBullet = true;
|
||||
item.body.PhysEnabled = true;
|
||||
|
||||
if (!character.AnimController.InWater)
|
||||
if (Swing && !character.AnimController.InWater)
|
||||
{
|
||||
foreach (Limb l in character.AnimController.Limbs)
|
||||
{
|
||||
if (l.IsSevered) { continue; }
|
||||
if (l.type == LimbType.LeftFoot || l.type == LimbType.LeftThigh || l.type == LimbType.LeftLeg) { continue; }
|
||||
if (l.type == LimbType.Head || l.type == LimbType.Torso)
|
||||
Vector2 force = new Vector2(character.AnimController.Dir * SwingForce.X, SwingForce.Y) * l.Mass;
|
||||
switch (l.type)
|
||||
{
|
||||
l.body.ApplyLinearImpulse(new Vector2(character.AnimController.Dir * 7.0f, -4.0f));
|
||||
case LimbType.Torso:
|
||||
force *= 2;
|
||||
break;
|
||||
case LimbType.Legs:
|
||||
case LimbType.LeftFoot:
|
||||
case LimbType.LeftThigh:
|
||||
case LimbType.LeftLeg:
|
||||
case LimbType.RightFoot:
|
||||
case LimbType.RightThigh:
|
||||
case LimbType.RightLeg:
|
||||
force = Vector2.Zero;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
l.body.ApplyLinearImpulse(new Vector2(character.AnimController.Dir * 5.0f, -2.0f));
|
||||
}
|
||||
l.body.ApplyLinearImpulse(force);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,9 +173,16 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (!item.body.Enabled) { impactQueue.Clear(); return; }
|
||||
if (picker == null && !picker.HeldItems.Contains(item)) { impactQueue.Clear(); IsActive = false; }
|
||||
|
||||
if (!item.body.Enabled)
|
||||
{
|
||||
impactQueue.Clear();
|
||||
return;
|
||||
}
|
||||
if (picker == null && !picker.HeldItems.Contains(item))
|
||||
{
|
||||
impactQueue.Clear();
|
||||
IsActive = false;
|
||||
}
|
||||
while (impactQueue.Count > 0)
|
||||
{
|
||||
var impact = impactQueue.Dequeue();
|
||||
@@ -164,37 +190,47 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
//in case handling the impact does something to the picker
|
||||
if (picker == null) { return; }
|
||||
|
||||
reloadTimer -= deltaTime;
|
||||
if (reloadTimer < 0) { reloadTimer = 0; }
|
||||
|
||||
if (!picker.IsKeyDown(InputType.Aim) && !hitting) { hitPos = 0.0f; }
|
||||
|
||||
if (reloadTimer < 0)
|
||||
{
|
||||
reloadTimer = 0;
|
||||
}
|
||||
if (!picker.IsKeyDown(InputType.Aim) && !hitting)
|
||||
{
|
||||
hitPos = 0.0f;
|
||||
}
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, picker);
|
||||
|
||||
if (item.body.Dir != picker.AnimController.Dir) { item.FlipX(relativeToSub: false); }
|
||||
|
||||
if (item.body.Dir != picker.AnimController.Dir)
|
||||
{
|
||||
item.FlipX(relativeToSub: false);
|
||||
}
|
||||
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)
|
||||
{
|
||||
bool aim = picker.AllowInput && picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && picker.CanAim;
|
||||
bool aim = item.RequireAimToUse && picker.AllowInput && picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && picker.CanAim;
|
||||
if (aim)
|
||||
{
|
||||
hitPos = MathUtils.WrapAnglePi(Math.Min(hitPos + deltaTime * 5f, MathHelper.PiOver4));
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, false, hitPos, holdAngle + hitPos, aimingMelee: true);
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, aim: false, hitPos, holdAngle + hitPos, aimMelee: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
hitPos = 0;
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, Vector2.Zero, false, holdAngle);
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, Vector2.Zero, aim: false, holdAngle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: We might want to make this configurable
|
||||
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 (Swing)
|
||||
{
|
||||
ac.HoldItem(deltaTime, item, handlePos, SwingPos, Vector2.Zero, aim: false, hitPos, holdAngle + hitPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, Vector2.Zero, aim: false, holdAngle);
|
||||
}
|
||||
if (hitPos < -MathHelper.PiOver2)
|
||||
{
|
||||
RestoreCollision();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Barotrauma.Abilities;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
@@ -80,6 +79,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Projectile LastProjectile { get; private set; }
|
||||
|
||||
private float currentChargeTime;
|
||||
private bool tryingToCharge;
|
||||
|
||||
@@ -196,6 +198,7 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 barrelPos = TransformedBarrelPos + item.body.SimPosition;
|
||||
float rotation = (Item.body.Dir == 1.0f) ? Item.body.Rotation : Item.body.Rotation - MathHelper.Pi;
|
||||
float spread = GetSpread(character) * Rand.Range(-0.5f, 0.5f);
|
||||
LastProjectile?.Item.GetComponent<Rope>()?.Snap();
|
||||
float damageMultiplier = 1f + item.GetQualityModifier(Quality.StatType.AttackMultiplier);
|
||||
projectile.Shoot(character, character.AnimController.AimSourceSimPos, barrelPos, rotation + spread, ignoredBodies: limbBodies.ToList(), createNetworkEvent: false, damageMultiplier);
|
||||
projectile.Item.GetComponent<Rope>()?.Attach(Item, projectile.Item);
|
||||
@@ -206,6 +209,7 @@ namespace Barotrauma.Items.Components
|
||||
projectile.Item.body.ApplyTorque(projectile.Item.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
|
||||
Item.RemoveContained(projectile.Item);
|
||||
}
|
||||
LastProjectile = projectile;
|
||||
}
|
||||
|
||||
LaunchProjSpecific();
|
||||
|
||||
@@ -123,18 +123,18 @@ namespace Barotrauma.Items.Components
|
||||
if (aim)
|
||||
{
|
||||
throwPos = MathUtils.WrapAnglePi(System.Math.Min(throwPos + deltaTime * 5.0f, MathHelper.PiOver2));
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, false, throwPos);
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, aim: false, throwPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
throwPos = 0;
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, Vector2.Zero, false, holdAngle);
|
||||
ac.HoldItem(deltaTime, item, handlePos, holdPos, Vector2.Zero, aim: false, holdAngle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throwPos = MathUtils.WrapAnglePi(throwPos - deltaTime * 15.0f);
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, false, throwPos);
|
||||
ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, aim: false, throwPos);
|
||||
|
||||
if (throwPos < 0)
|
||||
{
|
||||
@@ -169,8 +169,8 @@ namespace Barotrauma.Items.Components
|
||||
item.body.FarseerBody.IsBullet = true;
|
||||
midAir = true;
|
||||
|
||||
ac.GetLimb(LimbType.Head).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
ac.GetLimb(LimbType.Torso).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
ac.GetLimb(LimbType.Head)?.body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
ac.GetLimb(LimbType.Torso)?.body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
|
||||
Limb rightHand = ac.GetLimb(LimbType.RightHand);
|
||||
item.body.AngularVelocity = rightHand.body.AngularVelocity;
|
||||
|
||||
Reference in New Issue
Block a user