Unstable 1.8.4.0
This commit is contained in:
@@ -14,13 +14,15 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Holdable : Pickable, IServerSerializable, IClientSerializable
|
||||
{
|
||||
private readonly struct EventData : IEventData
|
||||
private readonly struct AttachEventData : IEventData
|
||||
{
|
||||
public readonly Vector2 AttachPos;
|
||||
|
||||
public EventData(Vector2 attachPos)
|
||||
public readonly Character Attacher;
|
||||
|
||||
public AttachEventData(Vector2 attachPos, Character attacher)
|
||||
{
|
||||
AttachPos = attachPos;
|
||||
Attacher = attacher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +227,51 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Editable, Serialize("", IsPropertySaveable.Yes, translationTextTag: "ItemMsg", description: "A text displayed next to the item when it's been dropped on the floor (not attached to a wall).")]
|
||||
public string MsgWhenDropped
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For setting the handle positions using status effects
|
||||
/// </summary>
|
||||
public Vector2 Handle1
|
||||
{
|
||||
get { return ConvertUnits.ToDisplayUnits(handlePos[0]); }
|
||||
set
|
||||
{
|
||||
handlePos[0] = ConvertUnits.ToSimUnits(value);
|
||||
if (item.FlippedX)
|
||||
{
|
||||
handlePos[0].X = -handlePos[0].X;
|
||||
}
|
||||
if (!secondHandlePosDefined)
|
||||
{
|
||||
Handle2 = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For setting the handle positions using status effects
|
||||
/// </summary>
|
||||
public Vector2 Handle2
|
||||
{
|
||||
get { return ConvertUnits.ToDisplayUnits(handlePos[1]); }
|
||||
set
|
||||
{
|
||||
handlePos[1] = ConvertUnits.ToSimUnits(value);
|
||||
if (item.FlippedX)
|
||||
{
|
||||
handlePos[1].X = -handlePos[1].X;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool secondHandlePosDefined;
|
||||
|
||||
public Holdable(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -254,9 +301,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
int index = i - 1;
|
||||
string attributeName = "handle" + i;
|
||||
var attribute = element.GetAttribute(attributeName);
|
||||
// If no value is defind for handle2, use the value of handle1.
|
||||
var value = attribute != null ? ConvertUnits.ToSimUnits(XMLExtensions.ParseVector2(attribute.Value)) : previousValue;
|
||||
Vector2 value = previousValue;
|
||||
var attribute = element.GetAttribute(attributeName);
|
||||
if (attribute != null)
|
||||
{
|
||||
secondHandlePosDefined = i > 1;
|
||||
value = ConvertUnits.ToSimUnits(XMLExtensions.ParseVector2(attribute.Value));
|
||||
}
|
||||
handlePos[index] = value;
|
||||
previousValue = value;
|
||||
}
|
||||
@@ -688,7 +740,19 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
//make the item pickable with the default pick key and with no specific tools/items when it's deattached
|
||||
RequiredItems.Clear();
|
||||
DisplayMsg = "";
|
||||
if (MsgWhenDropped.IsNullOrEmpty())
|
||||
{
|
||||
DisplayMsg = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayMsg = TextManager.Get(MsgWhenDropped);
|
||||
DisplayMsg =
|
||||
DisplayMsg.Loaded ?
|
||||
TextManager.ParseInputTypes(DisplayMsg) :
|
||||
MsgWhenDropped;
|
||||
}
|
||||
|
||||
PickKey = InputType.Select;
|
||||
#if CLIENT
|
||||
item.DrawDepthOffset = SpriteDepthWhenDropped - item.SpriteDepth;
|
||||
@@ -755,21 +819,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
if (character != Character.Controlled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if CLIENT
|
||||
if (character == Character.Controlled)
|
||||
{
|
||||
Vector2 attachPos = ConvertUnits.ToSimUnits(GetAttachPosition(character));
|
||||
item.CreateClientEvent(this, new EventData(attachPos));
|
||||
#endif
|
||||
item.CreateClientEvent(this, new AttachEventData(attachPos, character));
|
||||
}
|
||||
#endif
|
||||
//don't attach at this point in MP: instead rely on the network events created above
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -824,9 +881,13 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (user.Submarine != null)
|
||||
{
|
||||
//we must add some "padding" to the raycast to ensure it reaches all the way to a wall
|
||||
//otherwise the cursor might be outside a wall, but the grid cell it's in might be partially inside
|
||||
Vector2 padding = Submarine.GridSize * new Vector2(Math.Sign(mouseDiff.X), Math.Sign(mouseDiff.Y));
|
||||
|
||||
if (Submarine.PickBody(
|
||||
ConvertUnits.ToSimUnits(user.Position),
|
||||
ConvertUnits.ToSimUnits(user.Position + mouseDiff), collisionCategory: Physics.CollisionWall) != null)
|
||||
ConvertUnits.ToSimUnits(user.Position + mouseDiff + padding), collisionCategory: Physics.CollisionWall) != null)
|
||||
{
|
||||
attachPos = userPos + mouseDiff * Submarine.LastPickedFraction + offset;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
@@ -23,7 +23,7 @@ namespace Barotrauma.Items.Components
|
||||
public string OwnerTags
|
||||
{
|
||||
get => string.Join(',', OwnerTagSet);
|
||||
set => OwnerTagSet = value.Split(',').ToIdentifiers().ToImmutableHashSet();
|
||||
set => OwnerTagSet = value.ToIdentifiers().ToImmutableHashSet();
|
||||
}
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
|
||||
@@ -95,6 +95,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
item.AddTag(s);
|
||||
}
|
||||
if (GameMain.GameSession?.GameMode is PvPMode)
|
||||
{
|
||||
item.AddTag($"id_{character.TeamID}".ToIdentifier());
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(spawnPoint.IdCardDesc))
|
||||
{
|
||||
item.Description = Description = spawnPoint.IdCardDesc;
|
||||
|
||||
@@ -52,7 +52,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (holdable.Attached)
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent("ResourceCollected:" + (GameMain.GameSession?.GameMode?.Preset.Identifier.Value ?? "none") + ":" + item.Prefab.Identifier);
|
||||
//we don't need info of every collected resource, we can get a good sample size just by logging a small sample
|
||||
if (GameAnalyticsManager.ShouldLogRandomSample())
|
||||
{
|
||||
GameAnalyticsManager.AddDesignEvent("ResourceCollected:" + (GameMain.GameSession?.GameMode?.Preset.Identifier.Value ?? "none") + ":" + item.Prefab.Identifier);
|
||||
}
|
||||
holdable.DeattachFromWall();
|
||||
}
|
||||
trigger.Enabled = false;
|
||||
|
||||
@@ -174,9 +174,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Drop(Character dropper, bool setTransform = true)
|
||||
{
|
||||
//end hit first (which sets the weapon to the "held" state, with disabled physics and no special collision detection)
|
||||
EndHit();
|
||||
//ensure the physics body is enabled
|
||||
item.body.PhysEnabled = true;
|
||||
base.Drop(dropper, setTransform);
|
||||
hitting = false;
|
||||
hitPos = 0.0f;
|
||||
}
|
||||
|
||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||
@@ -251,10 +253,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (hitPos < -MathHelper.Pi)
|
||||
{
|
||||
RestoreCollision();
|
||||
hitting = false;
|
||||
hitTargets.Clear();
|
||||
hitPos = 0;
|
||||
EndHit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -291,6 +290,14 @@ namespace Barotrauma.Items.Components
|
||||
User = character;
|
||||
}
|
||||
|
||||
private void EndHit()
|
||||
{
|
||||
RestoreCollision();
|
||||
hitting = false;
|
||||
hitTargets.Clear();
|
||||
hitPos = 0;
|
||||
}
|
||||
|
||||
private void RestoreCollision()
|
||||
{
|
||||
impactQueue.Clear();
|
||||
@@ -327,6 +334,7 @@ namespace Barotrauma.Items.Components
|
||||
if (targetLimb.character.IgnoreMeleeWeapons) { return false; }
|
||||
var targetCharacter = targetLimb.character;
|
||||
if (targetCharacter == picker) { return false; }
|
||||
if (HitFriendlyTarget(targetCharacter)) { return false; }
|
||||
if (AllowHitMultiple)
|
||||
{
|
||||
if (hitTargets.Contains(targetCharacter)) { return false; }
|
||||
@@ -341,7 +349,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (targetCharacter == picker || targetCharacter == User) { return false; }
|
||||
if (targetCharacter.IgnoreMeleeWeapons) { return false; }
|
||||
targetLimb = targetCharacter.AnimController.GetLimb(LimbType.Torso); //Otherwise armor can be bypassed in strange ways
|
||||
if (HitFriendlyTarget(targetCharacter)) { return false; }
|
||||
if (AllowHitMultiple)
|
||||
{
|
||||
if (hitTargets.Contains(targetCharacter)) { return false; }
|
||||
@@ -380,6 +388,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else if (f2.Body.UserData is Holdable holdable && holdable.CanPush)
|
||||
{
|
||||
if (holdable.Item.GetRootInventoryOwner() == User) { return false; }
|
||||
hitTargets.Add(holdable.Item);
|
||||
}
|
||||
}
|
||||
@@ -387,10 +396,22 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
impactQueue.Enqueue(f2);
|
||||
|
||||
return true;
|
||||
|
||||
// Prevent bots from hitting friendly targets.
|
||||
bool HitFriendlyTarget(Character target)
|
||||
{
|
||||
if (User.IsPlayer) { return false; }
|
||||
if (User.AIController is HumanAIController { Enabled: true } humanAI)
|
||||
{
|
||||
if (humanAI.ObjectiveManager.CurrentObjective is AIObjectiveCombat combat && combat.Enemy != target)
|
||||
{
|
||||
if (humanAI.IsFriendly(target, onlySameTeam: true)) { return true; }
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private System.Text.StringBuilder serverLogger;
|
||||
@@ -412,7 +433,7 @@ namespace Barotrauma.Items.Components
|
||||
Limb targetLimb = target.UserData as Limb;
|
||||
Character targetCharacter = targetLimb?.character ?? target.UserData as Character;
|
||||
Structure targetStructure = target.UserData as Structure ?? targetFixture.UserData as Structure;
|
||||
Item targetItem = target.UserData as Item ?? targetFixture.UserData as Item;
|
||||
Item targetItem = target.UserData is Holdable h ? h.Item : target.UserData as Item ?? targetFixture.UserData as Item;
|
||||
Entity targetEntity = targetCharacter ?? targetStructure ?? targetItem ?? target.UserData as Entity;
|
||||
if (Attack != null)
|
||||
{
|
||||
@@ -452,10 +473,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (target.UserData is Holdable holdable && holdable.CanPush)
|
||||
else if (target.UserData is Holdable { CanPush: true } holdable)
|
||||
{
|
||||
if (holdable.Item.Removed) { return; }
|
||||
Attack.DoDamage(user, holdable.Item, item.WorldPosition, 1.0f);
|
||||
RestoreCollision();
|
||||
hitting = false;
|
||||
User = null;
|
||||
@@ -475,8 +495,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (GameMain.NetworkMember is { IsServer: true } server && targetEntity != null)
|
||||
{
|
||||
server.CreateEntityEvent(item, new Item.ApplyStatusEffectEventData(conditionalActionType, targetItemComponent: null, targetCharacter, targetLimb, useTarget: targetEntity));
|
||||
server.CreateEntityEvent(item, new Item.ApplyStatusEffectEventData(ActionType.OnUse, targetItemComponent: null, targetCharacter, targetLimb, useTarget: targetEntity));
|
||||
server.CreateEntityEvent(item, new Item.ApplyStatusEffectEventData(conditionalActionType, targetItemComponent: this, targetCharacter, targetLimb, useTarget: targetEntity));
|
||||
server.CreateEntityEvent(item, new Item.ApplyStatusEffectEventData(ActionType.OnUse, targetItemComponent: this, targetCharacter, targetLimb, useTarget: targetEntity));
|
||||
serverLogger ??= new System.Text.StringBuilder();
|
||||
serverLogger.Clear();
|
||||
serverLogger.Append($"{picker?.LogName} used {item.Name}");
|
||||
|
||||
@@ -202,12 +202,26 @@ namespace Barotrauma.Items.Components
|
||||
#if CLIENT
|
||||
if (requiredTime < float.MaxValue && picker == Character.Controlled)
|
||||
{
|
||||
string text = string.Empty;
|
||||
if (!string.IsNullOrWhiteSpace(PickingMsg))
|
||||
{
|
||||
text = PickingMsg;
|
||||
}
|
||||
else if (this is Door door)
|
||||
{
|
||||
text = door.IsClosed ? "progressbar.opening" : "progressbar.closing";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "progressbar.deattaching";
|
||||
}
|
||||
|
||||
Character.Controlled?.UpdateHUDProgressBar(
|
||||
this,
|
||||
item.WorldPosition,
|
||||
pickTimer / requiredTime,
|
||||
GUIStyle.Red, GUIStyle.Green,
|
||||
!string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching");
|
||||
text);
|
||||
}
|
||||
#endif
|
||||
picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
|
||||
|
||||
@@ -243,7 +243,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
IsActive = true;
|
||||
float baseReloadTime = reload;
|
||||
float weaponSkill = character.GetSkillLevel("weapons");
|
||||
float weaponSkill = character.GetSkillLevel(Tags.WeaponsSkill);
|
||||
|
||||
bool applyReloadFailure = ReloadSkillRequirement > 0 && ReloadNoSkill > reload && weaponSkill < ReloadSkillRequirement;
|
||||
if (applyReloadFailure)
|
||||
@@ -291,9 +291,14 @@ namespace Barotrauma.Items.Components
|
||||
var lastProjectile = LastProjectile;
|
||||
if (lastProjectile != projectile)
|
||||
{
|
||||
//Note that we always snap the rope here, unlike when firing a rope from a turret.
|
||||
//That's because handheld RangedWeapons have some special logic for handling the rope,
|
||||
//which doesn't support multiple attached ropes (see Holdable.GetRope and the references to it)
|
||||
lastProjectile?.Item.GetComponent<Rope>()?.Snap();
|
||||
}
|
||||
float damageMultiplier = (1f + item.GetQualityModifier(Quality.StatType.FirepowerMultiplier)) * WeaponDamageModifier;
|
||||
|
||||
float rangedAttackMultiplier = character?.GetStatValue(StatTypes.RangedAttackMultiplier) ?? 0;
|
||||
float damageMultiplier = (1f + item.GetQualityModifier(Quality.StatType.FirepowerMultiplier) + rangedAttackMultiplier) * WeaponDamageModifier;
|
||||
projectile.Launcher = item;
|
||||
|
||||
ignoredBodies.Clear();
|
||||
@@ -303,6 +308,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (l.IsSevered) { continue; }
|
||||
ignoredBodies.Add(l.body.FarseerBody);
|
||||
#if SERVER
|
||||
ignoredBodies.Add(l.LagCompensatedBody.FarseerBody);
|
||||
#endif
|
||||
}
|
||||
|
||||
foreach (Item heldItem in character.HeldItems)
|
||||
@@ -314,6 +322,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
projectile.Item.body.Dir = Item.body.Dir;
|
||||
projectile.Shoot(character, character.AnimController.AimSourceSimPos, barrelPos, rotation + spread, ignoredBodies: ignoredBodies.ToList(), createNetworkEvent: false, damageMultiplier, LaunchImpulse);
|
||||
projectile.Item.GetComponent<Rope>()?.Attach(Item, projectile.Item);
|
||||
if (projectile.Item.body != null)
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace Barotrauma.Items.Components
|
||||
var barrelHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(rayStartWorld), item.CurrentHull, useWorldCoordinates: true);
|
||||
if (barrelHull != null && barrelHull != item.CurrentHull)
|
||||
{
|
||||
if (MathUtils.GetLineRectangleIntersection(ConvertUnits.ToDisplayUnits(sourcePos), ConvertUnits.ToDisplayUnits(rayStart), item.CurrentHull.Rect, out Vector2 hullIntersection))
|
||||
if (MathUtils.GetLineWorldRectangleIntersection(ConvertUnits.ToDisplayUnits(sourcePos), ConvertUnits.ToDisplayUnits(rayStart), item.CurrentHull.Rect, out Vector2 hullIntersection))
|
||||
{
|
||||
if (!item.CurrentHull.ConnectedGaps.Any(g => g.Open > 0.0f && Submarine.RectContains(g.Rect, hullIntersection)))
|
||||
{
|
||||
@@ -320,7 +320,7 @@ namespace Barotrauma.Items.Components
|
||||
private readonly List<FireSource> fireSourcesInRange = new List<FireSource>();
|
||||
private void Repair(Vector2 rayStart, Vector2 rayEnd, float deltaTime, Character user, float degreeOfSuccess, List<Body> ignoredBodies)
|
||||
{
|
||||
var collisionCategories = Physics.CollisionWall | Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionRepairableWall;
|
||||
var collisionCategories = Physics.CollisionWall | Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionRepairableWall | Physics.CollisionItemBlocking;
|
||||
if (!IgnoreCharacters)
|
||||
{
|
||||
collisionCategories |= Physics.CollisionCharacter;
|
||||
@@ -654,8 +654,9 @@ namespace Barotrauma.Items.Components
|
||||
FixCharacterProjSpecific(user, deltaTime, targetLimb.character);
|
||||
return true;
|
||||
}
|
||||
else if (targetBody.UserData is Item targetItem)
|
||||
else if (targetBody.UserData is Barotrauma.Item or Holdable)
|
||||
{
|
||||
Item targetItem = targetBody.UserData is Holdable holdable ? holdable.Item : (Item)targetBody.UserData;
|
||||
if (!HitItems || !targetItem.IsInteractable(user)) { return false; }
|
||||
|
||||
var levelResource = targetItem.GetComponent<LevelResource>();
|
||||
@@ -764,7 +765,7 @@ namespace Barotrauma.Items.Components
|
||||
if (!character.AnimController.InWater && character.AnimController is HumanoidAnimController humanAnim &&
|
||||
Math.Abs(fromCharacterToLeak.X) < 100.0f && fromCharacterToLeak.Y < 0.0f && fromCharacterToLeak.Y > -150.0f)
|
||||
{
|
||||
humanAnim.Crouching = true;
|
||||
humanAnim.Crouch();
|
||||
}
|
||||
}
|
||||
if (!character.IsClimbing)
|
||||
|
||||
Reference in New Issue
Block a user