v0.19.0.0 (unstable)

This commit is contained in:
Regalis11
2022-07-20 18:47:07 +03:00
parent 2e2663a175
commit 6b55adcdd9
170 changed files with 2769 additions and 1634 deletions
@@ -73,6 +73,11 @@ namespace Barotrauma
}
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 80.0f, State.ToString(), stateColor, Color.Black);
if (State == AIState.Attack && selectedTargetingParams != null && selectedTargetingParams.AttackPattern == AttackPattern.Circle)
{
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 100.0f, CirclePhase.ToString(), stateColor, Color.Black);
}
if (LatchOntoAI != null && (State == AIState.Idle || LatchOntoAI.IsAttachedToSub))
{
foreach (Joint attachJoint in LatchOntoAI.AttachJoints)
@@ -1,15 +1,14 @@
using Barotrauma.Items.Components;
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using Barotrauma.Particles;
using Barotrauma.SpriteDeformations;
using Barotrauma.Extensions;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Linq;
using System.Collections.Generic;
using Barotrauma.Particles;
using System.Linq;
namespace Barotrauma
{
@@ -55,21 +54,34 @@ namespace Barotrauma
if (character.MemState[0].SelectedItem == null || character.MemState[0].SelectedItem.Removed)
{
character.SelectedConstruction = null;
character.SelectedItem = null;
}
else
else if (character.SelectedItem != character.MemState[0].SelectedItem)
{
if (character.SelectedConstruction != character.MemState[0].SelectedItem)
foreach (var ic in character.MemState[0].SelectedItem.Components)
{
foreach (var ic in character.MemState[0].SelectedItem.Components)
if (ic.CanBeSelected)
{
if (ic.CanBeSelected)
{
ic.Select(character);
}
ic.Select(character);
}
}
character.SelectedConstruction = character.MemState[0].SelectedItem;
character.SelectedItem = character.MemState[0].SelectedItem;
}
if (character.MemState[0].SelectedSecondaryItem == null || character.MemState[0].SelectedSecondaryItem.Removed)
{
character.SelectedSecondaryItem = null;
}
else if (character.SelectedSecondaryItem != character.MemState[0].SelectedSecondaryItem)
{
foreach (var ic in character.MemState[0].SelectedSecondaryItem.Components)
{
if (ic.CanBeSelected)
{
ic.Select(character);
}
}
character.SelectedSecondaryItem = character.MemState[0].SelectedSecondaryItem;
}
if (character.MemState[0].Animation == AnimController.Animation.CPR)
@@ -201,15 +213,24 @@ namespace Barotrauma
{
if (serverPos.SelectedItem == null || serverPos.SelectedItem.Removed)
{
character.SelectedConstruction = null;
character.SelectedItem = null;
}
else if (serverPos.SelectedItem != null)
else if (character.SelectedItem != serverPos.SelectedItem)
{
if (character.SelectedConstruction != serverPos.SelectedItem)
{
serverPos.SelectedItem.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true);
}
character.SelectedConstruction = serverPos.SelectedItem;
serverPos.SelectedItem.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true);
character.SelectedItem = serverPos.SelectedItem;
}
}
if (localPos.SelectedSecondaryItem != serverPos.SelectedSecondaryItem)
{
if (serverPos.SelectedSecondaryItem == null || serverPos.SelectedSecondaryItem.Removed)
{
character.SelectedSecondaryItem = null;
}
else if (character.SelectedSecondaryItem != serverPos.SelectedSecondaryItem)
{
serverPos.SelectedSecondaryItem.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true);
character.SelectedSecondaryItem = serverPos.SelectedSecondaryItem;
}
}
@@ -496,12 +517,11 @@ namespace Barotrauma
float maxDepth = 0.0f;
float minDepth = 1.0f;
float depthOffset = 0.0f;
var ladder = character.SelectedConstruction?.GetComponent<Ladder>();
if (ladder != null)
if (character.SelectedSecondaryItem?.GetComponent<Ladder>() is Ladder ladder)
{
CalculateLimbDepths();
if (character.WorldPosition.X < character.SelectedConstruction.WorldPosition.X)
if (character.WorldPosition.X < character.SelectedSecondaryItem.WorldPosition.X)
{
//at the left side of the ladder, needs to be drawn in front of the rungs
if (maxDepth > ladder.BackgroundSpriteDepth)
@@ -522,16 +542,21 @@ namespace Barotrauma
else
{
CalculateLimbDepths();
var controller = character.SelectedConstruction?.GetComponent<Controller>();
if (controller != null && controller.ControlCharacterPose && controller.User == character && controller.UserInCorrectPosition)
AdjustDepthOffset(character.SelectedItem);
AdjustDepthOffset(character.SelectedSecondaryItem);
void AdjustDepthOffset(Item item)
{
if (controller.Item.SpriteDepth <= maxDepth || controller.DrawUserBehind)
if (item?.GetComponent<Controller>() is { ControlCharacterPose: true, UserInCorrectPosition: true } controller && controller.User == character)
{
depthOffset = Math.Max(controller.Item.GetDrawDepth() + 0.0001f - minDepth, -minDepth);
}
else
{
depthOffset = Math.Max(controller.Item.GetDrawDepth() - 0.0001f - maxDepth, 0.0f);
if (controller.Item.SpriteDepth <= maxDepth || controller.DrawUserBehind)
{
depthOffset = Math.Max(controller.Item.GetDrawDepth() + 0.0001f - minDepth, -minDepth);
}
else
{
depthOffset = Math.Max(controller.Item.GetDrawDepth() - 0.0001f - maxDepth, 0.0f);
}
}
}
}
@@ -9,7 +9,6 @@ using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
namespace Barotrauma
@@ -323,8 +322,8 @@ namespace Barotrauma
{
cam.OffsetAmount = targetOffsetAmount = item.Prefab.OffsetOnSelected * item.OffsetOnSelectedMultiplier;
}
else if (SelectedConstruction != null && ViewTarget == null &&
SelectedConstruction.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this)))
else if (SelectedItem != null && ViewTarget == null &&
SelectedItem.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this)))
{
cam.OffsetAmount = targetOffsetAmount = 0.0f;
cursorPosition =
@@ -368,21 +367,20 @@ namespace Barotrauma
if (!GUI.InputBlockingMenuOpen)
{
if (SelectedConstruction != null &&
(SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect)) ||
if (SelectedItem != null &&
(SelectedItem.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect)) ||
((ViewTarget as Item)?.Prefab.FocusOnSelected ?? false) && PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)))
{
if (GameMain.Client != null)
{
//emulate a Select input to get the character to deselect the item server-side
//keys[(int)InputType.Select].Hit = true;
keys[(int)InputType.Deselect].Hit = true;
//emulate a Deselect input to get the character to deselect the item server-side
EmulateInput(InputType.Deselect);
}
//reset focus to prevent us from accidentally interacting with another entity
focusedItem = null;
FocusedCharacter = null;
findFocusedTimer = 0.2f;
SelectedConstruction = null;
SelectedItem = null;
}
}
@@ -425,6 +423,11 @@ namespace Barotrauma
}
}
}
public void EmulateInput(InputType input)
{
keys[(int)input].Hit = true;
}
partial void OnAttackedProjSpecific(Character attacker, AttackResult attackResult, float stun)
{
@@ -518,7 +521,7 @@ namespace Barotrauma
//reduce the amount of aim assist if an item has been selected
//= can't switch selection to another item without deselecting the current one first UNLESS the cursor is directly on the item
//otherwise it would be too easy to accidentally switch the selected item when rewiring items
float aimAssistAmount = SelectedConstruction == null ? 100.0f * aimAssistModifier : 1.0f;
float aimAssistAmount = SelectedItem == null ? 100.0f * aimAssistModifier : 1.0f;
Vector2 displayPosition = ConvertUnits.ToDisplayUnits(simPosition);
@@ -623,12 +626,12 @@ namespace Barotrauma
{
if (this != controlled) { return false; }
if (GameMain.GameSession?.Campaign != null && GameMain.GameSession.Campaign.ShowCampaignUI) { return true; }
var controller = SelectedConstruction?.GetComponent<Controller>();
var controller = SelectedItem?.GetComponent<Controller>();
//lock if using a controller, except if we're also using a connection panel in the same item
return
SelectedConstruction != null &&
SelectedItem != null &&
controller?.User == this && controller.HideHUD &&
SelectedConstruction?.GetComponent<ConnectionPanel>()?.User != this;
SelectedItem?.GetComponent<ConnectionPanel>()?.User != this;
}
@@ -900,7 +903,14 @@ namespace Barotrauma
if (info != null)
{
LocalizedString name = Info.DisplayName;
if (controlled == null && name != Info.Name) { name += " " + TextManager.Get("Disguised"); }
if (controlled == null && name != Info.Name)
{
name += " " + TextManager.Get("Disguised");
}
else if (Info.Title != null)
{
name += '\n' + Info.Title;
}
Vector2 nameSize = GUIStyle.Font.MeasureString(name);
Vector2 namePos = new Vector2(pos.X, pos.Y - 10.0f - (5.0f / cam.Zoom)) - nameSize * 0.5f / cam.Zoom;
@@ -108,7 +108,7 @@ namespace Barotrauma
private static bool ShouldDrawInventory(Character character)
{
var controller = character.SelectedConstruction?.GetComponent<Controller>();
var controller = character.SelectedItem?.GetComponent<Controller>();
return
character?.Inventory != null &&
@@ -417,13 +417,17 @@ namespace Barotrauma
visibleRange = new Range<float>(-100f, 500f);
}
float dist = Vector2.Distance(character.WorldPosition, npc.WorldPosition);
float distFactor = 1.0f - MathUtils.InverseLerp(1000.0f, 3000.0f, dist);
float alpha = MathHelper.Lerp(0.3f, 1.0f, distFactor);
GUI.DrawIndicator(
spriteBatch,
npc.WorldPosition,
cam,
visibleRange,
iconStyle.GetDefaultSprite(),
iconStyle.Color);
iconStyle.Color * alpha,
label: npc.Info?.Title);
}
foreach (Item item in Item.ItemList)
@@ -436,10 +440,10 @@ namespace Barotrauma
}
}
if (character.SelectedConstruction != null &&
(character.CanInteractWith(character.SelectedConstruction) || Screen.Selected == GameMain.SubEditorScreen))
if (character.SelectedItem != null &&
(character.CanInteractWith(character.SelectedItem) || Screen.Selected == GameMain.SubEditorScreen))
{
character.SelectedConstruction.DrawHUD(spriteBatch, cam, character);
character.SelectedItem.DrawHUD(spriteBatch, cam, character);
}
if (character.Inventory != null)
{
@@ -561,9 +565,15 @@ namespace Barotrauma
Color nameColor = character.FocusedCharacter.GetNameColor();
GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2, GUIStyle.SubHeadingFont, ForceUpperCase.No);
textPos.X += 10.0f * GUI.Scale;
textPos.Y += GUIStyle.SubHeadingFont.MeasureString(focusName).Y;
if (character.FocusedCharacter.Info?.Title != null && !character.FocusedCharacter.Info.Title.IsNullOrEmpty())
{
GUI.DrawString(spriteBatch, textPos, character.FocusedCharacter.Info.Title, nameColor, Color.Black * 0.7f, 2, GUIStyle.SubHeadingFont, ForceUpperCase.No);
textPos.Y += GUIStyle.SubHeadingFont.MeasureString(character.FocusedCharacter.Info.Title.Value).Y;
}
textPos.X += 10.0f * GUI.Scale;
if (!character.FocusedCharacter.IsIncapacitated && character.FocusedCharacter.IsPet)
{
GUI.DrawString(spriteBatch, textPos, GetCachedHudText("PlayHint", InputType.Use),
@@ -102,7 +102,7 @@ namespace Barotrauma
if (PersonalityTrait != null)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform),
TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + PersonalityTrait.Name.Replace(" ".ToIdentifier(), "".ToIdentifier()))),
TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), PersonalityTrait.DisplayName),
font: font)
{
Padding = Vector4.Zero
@@ -523,22 +523,20 @@ namespace Barotrauma
Color facialHairColor = inc.ReadColorR8G8B8();
string ragdollFile = inc.ReadString();
string jobIdentifier = inc.ReadString();
uint jobIdentifier = inc.ReadUInt32();
int variant = inc.ReadByte();
JobPrefab jobPrefab = null;
Dictionary<Identifier, float> skillLevels = new Dictionary<Identifier, float>();
if (!string.IsNullOrEmpty(jobIdentifier))
{
jobPrefab = JobPrefab.Get(jobIdentifier);
byte skillCount = inc.ReadByte();
for (int i = 0; i < skillCount; i++)
if (jobIdentifier > 0)
{
jobPrefab = JobPrefab.Prefabs.Find(jp => jp.UintIdentifier == jobIdentifier);
foreach (SkillPrefab skillPrefab in jobPrefab.Skills.OrderBy(s => s.Identifier))
{
Identifier skillIdentifier = inc.ReadIdentifier();
float skillLevel = inc.ReadSingle();
skillLevels.Add(skillIdentifier, skillLevel);
}
}
skillLevels.Add(skillPrefab.Identifier, skillLevel);
}
}
// TODO: animations
CharacterInfo ch = new CharacterInfo(speciesName, newName, originalName, jobPrefab, ragdollFile, variant)
@@ -777,7 +775,21 @@ namespace Barotrauma
createColorSelector($"Customization.{nameof(info.Head.SkinColor)}".ToIdentifier(), info.SkinColors, () => info.Head.SkinColor,
(color) => info.Head.SkinColor = color);
#if DEBUG
new GUIButton(new RectTransform(Vector2.One * 0.12f,
parentComponent.RectTransform,
anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest)
{ RelativeOffset = new Vector2(0.01f, 0.005f) }, style: "SaveButton", color: Color.Magenta)
{
ToolTip = "DEBUG ONLY: copy the character info XML to clipboard",
OnClicked = (button, o) =>
{
XElement element = info.Save(null);
Clipboard.SetText(element.ToString());
return false;
}
};
#endif
RandomizeButton = new GUIButton(new RectTransform(Vector2.One * 0.12f,
parentComponent.RectTransform,
anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest)
@@ -1,5 +1,4 @@
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using Barotrauma.Items.Components;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
@@ -44,7 +43,8 @@ namespace Barotrauma
LastNetworkUpdateID,
AnimController.TargetDir,
SelectedCharacter,
SelectedConstruction,
SelectedItem,
SelectedSecondaryItem,
AnimController.Anim);
memLocalState.Add(posInfo);
@@ -219,15 +219,17 @@ namespace Barotrauma
bool entitySelected = msg.ReadBoolean();
Character selectedCharacter = null;
Item selectedItem = null;
Item selectedItem = null, selectedSecondaryItem = null;
AnimController.Animation animation = AnimController.Animation.None;
if (entitySelected)
{
ushort characterID = msg.ReadUInt16();
ushort itemID = msg.ReadUInt16();
ushort secondaryItemID = msg.ReadUInt16();
selectedCharacter = FindEntityByID(characterID) as Character;
selectedItem = FindEntityByID(itemID) as Item;
selectedSecondaryItem = FindEntityByID(secondaryItemID) as Item;
if (characterID != NullEntityID)
{
bool doingCpr = msg.ReadBoolean();
@@ -274,7 +276,7 @@ namespace Barotrauma
pos, rotation,
networkUpdateID,
facingRight ? Direction.Right : Direction.Left,
selectedCharacter, selectedItem, animation);
selectedCharacter, selectedItem, selectedSecondaryItem, animation);
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
index++;
@@ -286,7 +288,7 @@ namespace Barotrauma
pos, rotation,
linearVelocity, angularVelocity,
sendingTime, facingRight ? Direction.Right : Direction.Left,
selectedCharacter, selectedItem, animation);
selectedCharacter, selectedItem, selectedSecondaryItem, animation);
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
index++;
@@ -375,9 +377,15 @@ namespace Barotrauma
if (attackLimbIndex == 255 || Removed) { break; }
if (attackLimbIndex >= AnimController.Limbs.Length)
{
string errorMsg = $"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})";
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:AttackLimbOutOfBounds", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
//it's possible to get these errors when mid-round syncing, as the client may not
//yet know about afflictions that have given the character extra limbs (e.g. spineling genes)
//ignoring the error should be safe though, not executing the attack should not cause any further issues
if (!GameMain.Client.MidRoundSyncing)
{
string errorMsg = $"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})";
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:AttackLimbOutOfBounds", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
}
break;
}
Limb attackLimb = AnimController.Limbs[attackLimbIndex];
@@ -673,16 +681,17 @@ namespace Barotrauma
AfflictionPrefab causeOfDeathAffliction = null;
if (causeOfDeathType == CauseOfDeathType.Affliction)
{
string afflictionName = msg.ReadString();
if (!AfflictionPrefab.Prefabs.ContainsKey(afflictionName))
uint afflictionId = msg.ReadUInt32();
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs.Find(p => p.UintIdentifier == afflictionId);
if (afflictionPrefab == null)
{
string errorMsg = $"Error in CharacterNetworking.ReadStatus: affliction not found ({afflictionName})";
string errorMsg = $"Error in CharacterNetworking.ReadStatus: affliction not found (id {afflictionId})";
causeOfDeathType = CauseOfDeathType.Unknown;
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:AfflictionIndexOutOfBounts", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ReadStatus:AfflictionNotFound", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
}
else
{
causeOfDeathAffliction = AfflictionPrefab.Prefabs[afflictionName];
causeOfDeathAffliction = afflictionPrefab;
}
}
bool containsAfflictionData = msg.ReadBoolean();
@@ -162,11 +162,7 @@ namespace Barotrauma
openHealthWindow.characterName.Text = value.Character.Info.DisplayName;
value.Character.Info.CheckDisguiseStatus(false);
}
if (Character.Controlled.SelectedConstruction != null && Character.Controlled.SelectedConstruction.GetComponent<Ladder>() == null)
{
Character.Controlled.SelectedConstruction = null;
}
Character.Controlled.SelectedItem = null;
}
HintManager.OnShowHealthInterface();
@@ -724,7 +720,7 @@ namespace Barotrauma
//emulate a Health input to get the character to deselect the item server-side
if (GameMain.Client != null)
{
Character.Controlled.Keys[(int)InputType.Health].Hit = true;
Character.Controlled.EmulateInput(InputType.Health);
}
OpenHealthWindow = null;
}
@@ -2014,7 +2010,7 @@ namespace Barotrauma
FaceTint = DefaultFaceTint;
BodyTint = Color.TransparentBlack;
if (!(Character?.Params?.Health.ApplyAfflictionColors ?? false)) { return; }
if (!Character.Params.Health.ApplyAfflictionColors) { return; }
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
{
@@ -2031,15 +2027,21 @@ namespace Barotrauma
foreach (Limb limb in Character.AnimController.Limbs)
{
if (limb.HealthIndex < 0 || limb.HealthIndex >= limbHealths.Count) { continue; }
limb.BurnOverlayStrength = 0.0f;
limb.DamageOverlayStrength = 0.0f;
foreach (KeyValuePair<Affliction, LimbHealth> kvp in afflictions)
{
if (kvp.Value != limbHealths[limb.HealthIndex]) { continue; }
var affliction = kvp.Key;
limb.BurnOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.BurnOverlayAlpha;
limb.DamageOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.DamageOverlayAlpha;
float burnStrength = affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.BurnOverlayAlpha;
if (kvp.Value == limbHealths[limb.HealthIndex])
{
limb.BurnOverlayStrength += burnStrength;
limb.DamageOverlayStrength += affliction.Strength / Math.Min(affliction.Prefab.MaxStrength, 100) * affliction.Prefab.DamageOverlayAlpha;
}
else
{
limb.BurnOverlayStrength += burnStrength / 2;
}
}
}
}
@@ -481,7 +481,7 @@ namespace Barotrauma
{
ContentPath texturePath =
character.Params.VariantFile?.Root?.GetAttributeContentPath("texture", character.Prefab.ContentPackage)
?? ContentPath.FromRaw(character.Prefab.ContentPackage, spriteParams.GetTexturePath());
?? ContentPath.FromRaw(spriteParams.Element.ContentPackage ?? character.Prefab.ContentPackage, spriteParams.GetTexturePath());
path = GetSpritePath(texturePath);
}
else