Unstable v0.9.707.0

This commit is contained in:
Juan Pablo Arce
2020-02-11 16:07:21 -03:00
parent 8324d20464
commit 2783125162
68 changed files with 1460 additions and 1219 deletions
@@ -20,13 +20,7 @@ namespace Barotrauma
class Order
{
public static Dictionary<string, Order> Prefabs { get; private set; }
public static Dictionary<OrderCategory, Sprite> OrderCategoryIcons { get; private set; }
public static Sprite StartNode { get; private set; }
public static Sprite ShortcutNode { get; private set; }
public static Sprite ExpandNode { get; private set; }
public static Sprite NodeContainer { get; private set; }
public static Sprite HotkeyContainer { get; private set; }
public static Sprite CommandBackground { get; private set; }
public static Dictionary<OrderCategory, Tuple<Sprite, Color>> OrderCategoryIcons { get; private set; }
public static List<Order> PrefabList { get; private set; }
public static Order GetPrefab(string identifier)
{
@@ -52,7 +46,30 @@ namespace Barotrauma
public readonly string Identifier;
public readonly Color Color;
private Color? color;
public Color Color
{
get
{
if (color.HasValue)
{
return color.Value;
}
else if (OrderCategoryIcons.TryGetValue(Category, out Tuple<Sprite, Color> sprite))
{
return sprite.Item2;
}
else
{
return Color.White;
}
}
private set
{
color = value;
}
}
//if true, the order is issued to all available characters
public bool TargetAllCharacters;
@@ -80,7 +97,7 @@ namespace Barotrauma
static Order()
{
Prefabs = new Dictionary<string, Order>();
OrderCategoryIcons = new Dictionary<OrderCategory, Sprite>();
OrderCategoryIcons = new Dictionary<OrderCategory, Tuple<Sprite, Color>>();
foreach (ContentFile file in GameMain.Instance.GetFilesOfType(ContentType.Orders))
{
@@ -125,7 +142,7 @@ namespace Barotrauma
else if (name.Equals("ordercategory", StringComparison.OrdinalIgnoreCase))
{
var category = (OrderCategory)Enum.Parse(typeof(OrderCategory), element.GetAttributeString("category", "undefined"), true);
if (OrderCategoryIcons.TryGetValue(category, out Sprite duplicate))
if (OrderCategoryIcons.ContainsKey(category))
{
if (allowOverriding || sourceElement.IsOverride())
{
@@ -142,35 +159,8 @@ namespace Barotrauma
if (spriteElement != null)
{
var sprite = new Sprite(spriteElement, lazyLoad: true);
OrderCategoryIcons.Add(category, sprite);
}
}
else
{
var spriteElement = element.GetChildElement("sprite");
if (spriteElement != null)
{
switch (name.ToLowerInvariant())
{
case "startnode":
StartNode = new Sprite(spriteElement, lazyLoad: true);
break;
case "shortcutnode":
ShortcutNode = new Sprite(spriteElement, lazyLoad: true);
break;
case "expandnode":
ExpandNode = new Sprite(spriteElement, lazyLoad: true);
break;
case "nodecontainer":
NodeContainer = new Sprite(spriteElement, lazyLoad: true);
break;
case "hotkeycontainer":
HotkeyContainer = new Sprite(spriteElement, lazyLoad: true);
break;
case "commandbackground":
CommandBackground = new Sprite(spriteElement, lazyLoad: true);
break;
}
var color = element.GetAttributeColor("color", Color.White);
OrderCategoryIcons.Add(category, new Tuple<Sprite, Color>(sprite, color));
}
}
}
@@ -201,7 +191,7 @@ namespace Barotrauma
}
ItemIdentifiers = orderElement.GetAttributeStringArray("targetitemidentifiers", new string[0], trim: true, convertToLowerInvariant: true);
Color = orderElement.GetAttributeColor("color", Color.White);
color = orderElement.GetAttributeColor("color");
FadeOutTime = orderElement.GetAttributeFloat("fadeouttime", 0.0f);
UseController = orderElement.GetAttributeBool("usecontroller", false);
TargetAllCharacters = orderElement.GetAttributeBool("targetallcharacters", false);
@@ -271,6 +261,7 @@ namespace Barotrauma
AppropriateJobs = prefab.AppropriateJobs;
FadeOutTime = prefab.FadeOutTime;
Weight = prefab.Weight;
Category = prefab.Category;
OrderGiver = orderGiver;
TargetEntity = targetEntity;
@@ -300,22 +291,22 @@ namespace Barotrauma
}
for (int i = 0; i < AppropriateJobs.Length; i++)
{
if (character.Info.Job.Prefab.Identifier.ToLowerInvariant() == AppropriateJobs[i].ToLowerInvariant()) return true;
if (character.Info.Job.Prefab.Identifier.ToLowerInvariant() == AppropriateJobs[i].ToLowerInvariant()) { return true; }
}
return false;
}
public string GetChatMessage(string targetCharacterName, string targetRoomName, bool givingOrderToSelf, string orderOption = "")
{
orderOption = orderOption ?? "";
orderOption ??= "";
string messageTag = (givingOrderToSelf && !TargetAllCharacters ? "OrderDialogSelf." : "OrderDialog.") + Identifier;
if (!string.IsNullOrEmpty(orderOption)) messageTag += "." + orderOption;
if (!string.IsNullOrEmpty(orderOption)) { messageTag += "." + orderOption; }
if (targetCharacterName == null) targetCharacterName = "";
if (targetRoomName == null) targetRoomName = "";
if (targetCharacterName == null) { targetCharacterName = ""; }
if (targetRoomName == null) { targetRoomName = ""; }
string msg = TextManager.GetWithVariables(messageTag, new string[2] { "[name]", "[roomname]" }, new string[2] { targetCharacterName, targetRoomName }, new bool[2] { false, true }, true);
if (msg == null) return "";
if (msg == null) { return ""; }
return msg;
}
@@ -78,8 +78,12 @@ namespace Barotrauma
if (frozen == value) return;
frozen = value;
Collider.PhysEnabled = !frozen;
Collider.FarseerBody.LinearDamping = frozen ? (1.5f / (float)Timing.Step) : 0.0f;
Collider.FarseerBody.AngularDamping = frozen ? (1.5f / (float)Timing.Step) : 0.0f;
Collider.FarseerBody.IgnoreGravity = frozen;
//Collider.PhysEnabled = !frozen;
if (frozen && MainLimb != null) MainLimb.PullJointWorldAnchorB = MainLimb.SimPosition;
}
}
@@ -312,15 +312,7 @@ namespace Barotrauma
selectedCharacter.selectedBy = null;
selectedCharacter = value;
if (selectedCharacter != null)
{
selectedCharacter.selectedBy = this;
#if CLIENT
if (Inventory != null)
{
Inventory.ToggleInventory(true);
}
#endif
}
}
}
@@ -1269,7 +1269,7 @@ namespace Barotrauma
{
//if the command is not defined client-side, we'll relay it anyway because it may be a custom command at the server's side
GameMain.Client.SendConsoleCommand(command);
NewMessage("Server command: " + command, Color.White);
NewMessage("Server command: " + command, Color.Cyan);
return;
}
else if (GameMain.Client.HasConsoleCommandPermission(splitCommand[0].ToLowerInvariant()))
@@ -1277,7 +1277,7 @@ namespace Barotrauma
if (matchingCommand.RelayToServer)
{
GameMain.Client.SendConsoleCommand(command);
NewMessage("Server command: " + command, Color.White);
NewMessage("Server command: " + command, Color.Cyan);
}
else
{
@@ -1424,8 +1424,6 @@ namespace Barotrauma
var variant = job != null ? Rand.Range(0, job.Variants, Rand.RandSync.Server) : 0;
CharacterInfo characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: job, variant: variant);
spawnedCharacter = Character.Create(characterInfo, spawnPosition, ToolBox.RandomSeed(8));
spawnedCharacter.GiveJobItems(spawnPoint);
if (GameMain.GameSession != null)
{
if (GameMain.GameSession.GameMode != null && !GameMain.GameSession.GameMode.IsSinglePlayer)
@@ -1437,6 +1435,7 @@ namespace Barotrauma
GameMain.GameSession.CrewManager.AddCharacter(spawnedCharacter);
#endif
}
spawnedCharacter.GiveJobItems(spawnPoint);
}
else
{
@@ -56,7 +56,7 @@ namespace Barotrauma
get { return activeEvents; }
}
public EventManager(GameSession session)
public EventManager()
{
isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
}
@@ -70,21 +70,9 @@ namespace Barotrauma
pendingEventSets.Clear();
selectedEvents.Clear();
var suitableSettings = EventManagerSettings.List.FindAll(s =>
level.Difficulty >= s.MinLevelDifficulty &&
level.Difficulty <= s.MaxLevelDifficulty);
if (suitableSettings.Count == 0)
{
DebugConsole.ThrowError("No suitable event manager settings found for the selected level (difficulty " + level.Difficulty + ")");
settings = EventManagerSettings.List[Rand.Int(EventManagerSettings.List.Count, Rand.RandSync.Server)];
}
else
{
settings = suitableSettings[Rand.Int(suitableSettings.Count, Rand.RandSync.Server)];
}
this.level = level;
SelectSettings();
var initialEventSet = SelectRandomEvents(ScriptedEventSet.List);
if (initialEventSet != null)
{
@@ -102,6 +90,32 @@ namespace Barotrauma
eventCoolDown = 0.0f;
}
private void SelectSettings()
{
if (EventManagerSettings.List.Count == 0)
{
throw new InvalidOperationException("Could not select EventManager settings (no settings loaded).");
}
if (level == null)
{
throw new InvalidOperationException("Could not select EventManager settings (level not set).");
}
var suitableSettings = EventManagerSettings.List.FindAll(s =>
level.Difficulty >= s.MinLevelDifficulty &&
level.Difficulty <= s.MaxLevelDifficulty);
if (suitableSettings.Count == 0)
{
DebugConsole.ThrowError("No suitable event manager settings found for the selected level (difficulty " + level.Difficulty + ")");
settings = EventManagerSettings.List[Rand.Int(EventManagerSettings.List.Count, Rand.RandSync.Server)];
}
else
{
settings = suitableSettings[Rand.Int(suitableSettings.Count, Rand.RandSync.Server)];
}
}
public IEnumerable<ContentFile> GetFilesToPreload()
{
foreach (List<ScriptedEvent> eventList in selectedEvents.Values)
@@ -310,6 +324,18 @@ namespace Barotrauma
roundDuration += deltaTime;
if (settings == null)
{
DebugConsole.ThrowError("Event settings not set before updating EventManager. Attempting to select...");
SelectSettings();
if (settings == null)
{
DebugConsole.ThrowError("Could not select EventManager settings. Disabling EventManager for the round...");
Enabled = false;
return;
}
}
eventThreshold += settings.EventThresholdIncrease * deltaTime;
if (eventCoolDown > 0.0f)
{
@@ -17,9 +17,18 @@ namespace Barotrauma.Extensions
/// <summary>
/// Randomizes the list in place.
/// </summary>
public static void RandomizeList<T>(this List<T> source)
public static void RandomizeList<T>(this List<T> list)
{
source.Sort((x, y) => Rand.Value().CompareTo(Rand.Value()));
//Fisher-Yates shuffle
int n = list.Count;
while (n > 1)
{
n--;
int k = Rand.Int(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
public static T GetRandom<T>(this IEnumerable<T> source, Func<T, bool> predicate, Rand.RandSync randSync = Rand.RandSync.Unsynced)
@@ -82,7 +82,8 @@ namespace Barotrauma
// Another pass for items with containers because also they can spawn inside other items (like smg magazine)
prefabsWithContainer.ForEach(i => SpawnItems(i));
// Spawn items that don't have containers last
prefabsWithoutContainer.Randomize().ForEach(i => SpawnItems(i));
prefabsWithoutContainer.RandomizeList();
prefabsWithoutContainer.ForEach(i => SpawnItems(i));
if (OutputDebugInfo)
{
@@ -91,7 +91,7 @@ namespace Barotrauma
Submarine.MainSub = submarine;
this.Submarine = submarine;
GameMain.GameSession = this;
EventManager = new EventManager(this);
EventManager = new EventManager();
this.SavePath = savePath;
}
@@ -16,7 +16,6 @@ namespace Barotrauma
partial class CharacterInventory : Inventory
{
private const int hotkeyCount = 5;
private Character character;
public InvSlotType[] SlotTypes
@@ -53,7 +52,16 @@ namespace Barotrauma
{
DebugConsole.ThrowError("Error in the inventory config of \"" + character.SpeciesName + "\" - " + slotTypeNames[i] + " is not a valid inventory slot type.");
}
SlotTypes[i] = parsedSlotType;
SlotTypes[i] = parsedSlotType;
switch (SlotTypes[i])
{
//case InvSlotType.Head:
//case InvSlotType.OuterClothes:
case InvSlotType.LeftHand:
case InvSlotType.RightHand:
hideEmptySlot[i] = true;
break;
}
}
InitProjSpecific(element);
@@ -122,25 +130,25 @@ namespace Barotrauma
/// <summary>
/// If there is no room in the generic inventory (InvSlotType.Any), check if the item can be auto-equipped into its respective limbslot
/// </summary>
public bool TryPutItemWithAutoEquipCheck(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true, bool preferNonHotkeys = false)
public bool TryPutItemWithAutoEquipCheck(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
{
// Does not auto-equip the item if specified and no suitable any slot found (for example handcuffs are not auto-equipped)
if (item.AllowedSlots.Contains(InvSlotType.Any))
{
var wearable = item.GetComponent<Wearable>();
if (wearable != null && !wearable.AutoEquipWhenFull && CheckIfAnySlotAvailable(item, false, preferNonHotkeys) == -1)
if (wearable != null && !wearable.AutoEquipWhenFull && CheckIfAnySlotAvailable(item, false) == -1)
{
return false;
}
}
return TryPutItem(item, user, allowedSlots, createNetworkEvent, preferNonHotkeys);
return TryPutItem(item, user, allowedSlots, createNetworkEvent);
}
/// <summary>
/// If there is room, puts the item in the inventory and returns true, otherwise returns false
/// </summary>
public override bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true, bool preferNonHotkeys = false)
public override bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
{
if (allowedSlots == null || !allowedSlots.Any()) return false;
@@ -164,7 +172,7 @@ namespace Barotrauma
//try to place the item in a LimbSlot.Any slot if that's allowed
if (allowedSlots.Contains(InvSlotType.Any) && item.AllowedSlots.Contains(InvSlotType.Any))
{
int freeIndex = CheckIfAnySlotAvailable(item, inWrongSlot, preferNonHotkeys);
int freeIndex = CheckIfAnySlotAvailable(item, inWrongSlot);
if (freeIndex > -1)
{
PutItem(item, freeIndex, user, true, createNetworkEvent);
@@ -207,7 +215,12 @@ namespace Barotrauma
#if CLIENT
if (PersonalSlots.HasFlag(SlotTypes[i])) { hidePersonalSlots = false; }
#endif
bool removeFromOtherSlots = item.ParentInventory != this || (placedInSlot == -1 && inWrongSlot);
bool removeFromOtherSlots = item.ParentInventory != this;
if (placedInSlot == -1 && inWrongSlot)
{
if (!hideEmptySlot[i] || SlotTypes[currentSlot] != InvSlotType.Any) removeFromOtherSlots = true;
}
PutItem(item, i, user, removeFromOtherSlots, createNetworkEvent);
item.Equip(character);
placedInSlot = i;
@@ -219,19 +232,16 @@ namespace Barotrauma
return placedInSlot > -1;
}
public int CheckIfAnySlotAvailable(Item item, bool inWrongSlot, bool preferNonHotkeys)
public int CheckIfAnySlotAvailable(Item item, bool inWrongSlot)
{
for (int i = 0; i < capacity; i++)
{
if (SlotTypes[i] != InvSlotType.Any) continue;
if (Items[i] == item)
for (int i = 0; i < capacity; i++)
{
return i;
if (SlotTypes[i] != InvSlotType.Any) continue;
if (Items[i] == item)
{
return i;
}
}
}
if (!preferNonHotkeys)
{
for (int i = 0; i < capacity; i++)
{
if (SlotTypes[i] != InvSlotType.Any) continue;
@@ -246,45 +256,11 @@ namespace Barotrauma
return i;
}
}
else
{
int hotkeysCounted = 0;
// First go through non-hotkeyed slots
for (int i = 0; i < capacity; i++)
{
if (SlotTypes[i] != InvSlotType.Any) continue;
hotkeysCounted++;
if (hotkeysCounted <= hotkeyCount) continue;
if (inWrongSlot)
{
if (Items[i] != item && Items[i] != null) continue;
}
else
{
if (Items[i] != null) continue;
}
#if CLIENT
if (!inventoryOpen)
{
ToggleInventory();
}
#endif
return i;
}
// Then redo with no preference
return CheckIfAnySlotAvailable(item, inWrongSlot, false);
}
return -1;
}
public override bool TryPutItem(Item item, int index, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true, bool avoidHotkeys = false)
public override bool TryPutItem(Item item, int index, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
{
if (index < 0 || index >= Items.Length)
{
@@ -82,7 +82,7 @@ namespace Barotrauma.Items.Components
public virtual bool OnPicked(Character picker)
{
if (picker.Inventory.TryPutItemWithAutoEquipCheck(item, picker, allowedSlots, true, true))
if (picker.Inventory.TryPutItemWithAutoEquipCheck(item, picker, allowedSlots))
{
if (!picker.HasSelectedItem(item) && item.body != null) item.body.Enabled = false;
this.picker = picker;
@@ -19,7 +19,7 @@ namespace Barotrauma.Items.Components
private string prevSignal;
[Serialize(Character.TeamType.None, false, description: "WiFi components can only communicate with components that have the same Team ID.")]
[Serialize(Character.TeamType.None, true, description: "WiFi components can only communicate with components that have the same Team ID.")]
public Character.TeamType TeamID { get; set; }
[Editable, Serialize(20000.0f, false, description: "How close the recipient has to be to receive a signal from this WiFi component.")]
@@ -190,7 +190,7 @@ namespace Barotrauma.Items.Components
}
}
if (newNodeIndex == 0)
if (newNodeIndex == 0 && nodes.Count > 1)
{
nodes.Insert(0, nodePos);
}
@@ -499,7 +499,7 @@ namespace Barotrauma.Items.Components
}
}
private void ClearConnections(Character user = null)
public void ClearConnections(Character user = null)
{
nodes.Clear();
sections.Clear();
@@ -14,6 +14,7 @@ namespace Barotrauma
protected readonly int capacity;
public Item[] Items;
protected bool[] hideEmptySlot;
public bool Locked;
@@ -31,6 +32,7 @@ namespace Barotrauma
this.Owner = owner;
Items = new Item[capacity];
hideEmptySlot = new bool[capacity];
#if CLIENT
this.slotsPerRow = slotsPerRow;
@@ -39,8 +41,15 @@ namespace Barotrauma
{
DraggableIndicator = GUI.Style.GetComponentStyle("GUIDragIndicator").Sprites[GUIComponent.ComponentState.None][0].Sprite;
EquipIndicator = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(137, 10, 112, 25), new Vector2(0.5f, 1f), 0);
EquipIndicator.size = new Vector2(EquipIndicator.SourceRect.Width * 0.682f, EquipIndicator.SourceRect.Height * 0.682f);
slotHotkeySprite = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(258, 7, 120, 120), null, 0);
EquippedIndicator = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(550, 137, 87, 16), new Vector2(0.5f, 0.5f), 0);
EquippedHoverIndicator = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(550, 157, 87, 16), new Vector2(0.5f, 0.5f), 0);
EquippedClickedIndicator = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(550, 177, 87, 16), new Vector2(0.5f, 0.5f), 0);
UnequippedIndicator = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(550, 197, 87, 16), new Vector2(0.5f, 0.5f), 0);
UnequippedHoverIndicator = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(550, 217, 87, 16), new Vector2(0.5f, 0.5f), 0);
UnequippedClickedIndicator = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(550, 237, 87, 16), new Vector2(0.5f, 0.5f), 0);
}
#endif
}
@@ -102,7 +111,7 @@ namespace Barotrauma
/// <summary>
/// If there is room, puts the item in the inventory and returns true, otherwise returns false
/// </summary>
public virtual bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true, bool avoidHotkeys = false)
public virtual bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
{
int slot = FindAllowedSlot(item);
if (slot < 0) return false;
@@ -111,7 +120,7 @@ namespace Barotrauma
return true;
}
public virtual bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true, bool avoidHotkeys = false)
public virtual bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
{
if (i < 0 || i >= Items.Length)
{
@@ -1986,7 +1986,14 @@ namespace Barotrauma
body.ResetDynamics();
if (dropper != null)
{
body.SetTransform(dropper.SimPosition, 0.0f);
if (body.Removed)
{
DebugConsole.ThrowError("Failed to drop the item \"" + Name + "\" (body has been removed).");
}
else
{
body.SetTransform(dropper.SimPosition, 0.0f);
}
}
}
@@ -47,9 +47,9 @@ namespace Barotrauma
return (item != null && Items[i] == null && container.CanBeContained(item));
}
public override bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true, bool preferNonHotkeys = false)
public override bool TryPutItem(Item item, Character user, List<InvSlotType> allowedSlots = null, bool createNetworkEvent = true)
{
bool wasPut = base.TryPutItem(item, user, allowedSlots, createNetworkEvent, preferNonHotkeys);
bool wasPut = base.TryPutItem(item, user, allowedSlots, createNetworkEvent);
if (wasPut)
{
@@ -68,9 +68,9 @@ namespace Barotrauma
return wasPut;
}
public override bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true, bool preferNonHotkeys = false)
public override bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
{
bool wasPut = base.TryPutItem(item, i, allowSwapping, allowCombine, user, createNetworkEvent, preferNonHotkeys);
bool wasPut = base.TryPutItem(item, i, allowSwapping, allowCombine, user, createNetworkEvent);
if (wasPut)
{
@@ -60,6 +60,7 @@ namespace Barotrauma.Networking
QUERY_STARTGAME, //ask the clients whether they're ready to start
STARTGAME, //start a new round
STARTGAMEFINALIZE, //finalize round initialization
ENDGAME,
TRAITOR_MESSAGE,
@@ -88,14 +88,13 @@ namespace Barotrauma
Circle, Rectangle, Capsule, HorizontalCapsule
};
private static List<PhysicsBody> list = new List<PhysicsBody>();
private static readonly List<PhysicsBody> list = new List<PhysicsBody>();
public static List<PhysicsBody> List
{
get { return list; }
}
//the farseer physics body of the item
private Body body;
protected Vector2 prevPosition;
protected float prevRotation;
@@ -105,6 +104,12 @@ namespace Barotrauma
private Vector2 drawPosition;
private float drawRotation;
public bool Removed
{
get;
private set;
}
public Vector2 LastSentPosition
{
get;
@@ -114,7 +119,7 @@ namespace Barotrauma
private Shape bodyShape;
public float height, width, radius;
private float density;
private readonly float density;
//the direction the item is facing (for example, a gun has to be
//flipped horizontally if the Character holding it turns around)
@@ -198,7 +203,7 @@ namespace Barotrauma
isEnabled = value;
try
{
if (isEnabled) body.Enabled = isPhysEnabled; else body.Enabled = false;
if (isEnabled) FarseerBody.Enabled = isPhysEnabled; else FarseerBody.Enabled = false;
}
catch (Exception e)
{
@@ -206,7 +211,7 @@ namespace Barotrauma
if (UserData != null) DebugConsole.NewMessage("PhysicsBody UserData: " + UserData.GetType().ToString(), Color.Red);
if (GameMain.World.ContactManager == null) DebugConsole.NewMessage("ContactManager is null!", Color.Red);
else if (GameMain.World.ContactManager.BroadPhase == null) DebugConsole.NewMessage("Broadphase is null!", Color.Red);
if (body.FixtureList == null) DebugConsole.NewMessage("FixtureList is null!", Color.Red);
if (FarseerBody.FixtureList == null) DebugConsole.NewMessage("FixtureList is null!", Color.Red);
if (UserData is Entity entity)
{
@@ -218,18 +223,18 @@ namespace Barotrauma
public bool PhysEnabled
{
get { return body.Enabled; }
set { isPhysEnabled = value; if (Enabled) body.Enabled = value; }
get { return FarseerBody.Enabled; }
set { isPhysEnabled = value; if (Enabled) FarseerBody.Enabled = value; }
}
public Vector2 SimPosition
{
get { return body.Position; }
get { return FarseerBody.Position; }
}
public Vector2 Position
{
get { return ConvertUnits.ToDisplayUnits(body.Position); }
get { return ConvertUnits.ToDisplayUnits(FarseerBody.Position); }
}
public Vector2 PrevPosition
@@ -239,7 +244,7 @@ namespace Barotrauma
public float Rotation
{
get { return body.Rotation; }
get { return FarseerBody.Rotation; }
}
/// <summary>
@@ -249,27 +254,27 @@ namespace Barotrauma
public Vector2 LinearVelocity
{
get { return body.LinearVelocity; }
get { return FarseerBody.LinearVelocity; }
set
{
if (!IsValidValue(value, "velocity", -1000.0f, 1000.0f)) return;
body.LinearVelocity = value;
FarseerBody.LinearVelocity = value;
}
}
public float AngularVelocity
{
get { return body.AngularVelocity; }
get { return FarseerBody.AngularVelocity; }
set
{
if (!IsValidValue(value, "angular velocity", -1000f, 1000f)) return;
body.AngularVelocity = value;
FarseerBody.AngularVelocity = value;
}
}
public float Mass
{
get { return body.Mass; }
get { return FarseerBody.Mass; }
}
public float Density
@@ -277,36 +282,33 @@ namespace Barotrauma
get { return density; }
}
public Body FarseerBody
{
get { return body; }
}
public Body FarseerBody { get; private set; }
public object UserData
{
get { return body.UserData; }
set { body.UserData = value; }
get { return FarseerBody.UserData; }
set { FarseerBody.UserData = value; }
}
public float Friction
{
set { body.Friction = value; }
set { FarseerBody.Friction = value; }
}
public BodyType BodyType
{
get { return body.BodyType; }
set { body.BodyType = value; }
get { return FarseerBody.BodyType; }
set { FarseerBody.BodyType = value; }
}
public Category CollisionCategories
{
set { body.CollisionCategories = value; }
set { FarseerBody.CollisionCategories = value; }
}
public Category CollidesWith
{
set { body.CollidesWith = value; }
set { FarseerBody.CollidesWith = value; }
}
public PhysicsBody(XElement element, float scale = 1.0f) : this(element, Vector2.Zero, scale) { }
@@ -316,15 +318,15 @@ namespace Barotrauma
public PhysicsBody(float width, float height, float radius, float density)
{
CreateBody(width, height, radius, density);
LastSentPosition = body.Position;
LastSentPosition = FarseerBody.Position;
list.Add(this);
}
public PhysicsBody(Body farseerBody)
{
body = farseerBody;
if (body.UserData == null) body.UserData = this;
LastSentPosition = body.Position;
FarseerBody = farseerBody;
if (FarseerBody.UserData == null) FarseerBody.UserData = this;
LastSentPosition = FarseerBody.Position;
list.Add(this);
}
@@ -335,13 +337,13 @@ namespace Barotrauma
float width = ConvertUnits.ToSimUnits(colliderParams.Width) * colliderParams.Ragdoll.LimbScale;
density = 10;
CreateBody(width, height, radius, density);
body.BodyType = BodyType.Dynamic;
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
body.CollisionCategories = Physics.CollisionCharacter;
body.AngularDamping = 5.0f;
body.FixedRotation = true;
body.Friction = 0.05f;
body.Restitution = 0.05f;
FarseerBody.BodyType = BodyType.Dynamic;
FarseerBody.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
FarseerBody.CollisionCategories = Physics.CollisionCharacter;
FarseerBody.AngularDamping = 5.0f;
FarseerBody.FixedRotation = true;
FarseerBody.Friction = 0.05f;
FarseerBody.Restitution = 0.05f;
SetTransformIgnoreContacts(position, 0.0f);
LastSentPosition = position;
list.Add(this);
@@ -354,13 +356,13 @@ namespace Barotrauma
float width = ConvertUnits.ToSimUnits(limbParams.Width) * limbParams.Ragdoll.LimbScale;
density = limbParams.Density;
CreateBody(width, height, radius, density);
body.BodyType = BodyType.Dynamic;
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
body.CollisionCategories = Physics.CollisionItem;
body.Friction = limbParams.Friction;
body.Restitution = limbParams.Restitution;
body.AngularDamping = limbParams.AngularDamping;
body.UserData = this;
FarseerBody.BodyType = BodyType.Dynamic;
FarseerBody.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
FarseerBody.CollisionCategories = Physics.CollisionItem;
FarseerBody.Friction = limbParams.Friction;
FarseerBody.Restitution = limbParams.Restitution;
FarseerBody.AngularDamping = limbParams.AngularDamping;
FarseerBody.UserData = this;
SetTransformIgnoreContacts(position, 0.0f);
LastSentPosition = position;
list.Add(this);
@@ -374,12 +376,12 @@ namespace Barotrauma
density = element.GetAttributeFloat("density", 10.0f);
CreateBody(width, height, radius, density);
//Enum.TryParse(element.GetAttributeString("bodytype", "Dynamic"), out BodyType bodyType);
body.BodyType = BodyType.Dynamic;
body.CollisionCategories = Physics.CollisionItem;
body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionPlatform;
body.Friction = element.GetAttributeFloat("friction", 0.3f);
body.Restitution = element.GetAttributeFloat("restitution", 0.05f);
body.UserData = this;
FarseerBody.BodyType = BodyType.Dynamic;
FarseerBody.CollisionCategories = Physics.CollisionItem;
FarseerBody.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionPlatform;
FarseerBody.Friction = element.GetAttributeFloat("friction", 0.3f);
FarseerBody.Restitution = element.GetAttributeFloat("restitution", 0.05f);
FarseerBody.UserData = this;
SetTransformIgnoreContacts(position, 0.0f);
LastSentPosition = position;
list.Add(this);
@@ -393,16 +395,16 @@ namespace Barotrauma
switch (bodyShape)
{
case Shape.Capsule:
body = GameMain.World.CreateCapsule(height, radius, density);
FarseerBody = GameMain.World.CreateCapsule(height, radius, density);
break;
case Shape.HorizontalCapsule:
body = GameMain.World.CreateCapsuleHorizontal(width, radius, density);
FarseerBody = GameMain.World.CreateCapsuleHorizontal(width, radius, density);
break;
case Shape.Circle:
body = GameMain.World.CreateCircle(radius, density);
FarseerBody = GameMain.World.CreateCircle(radius, density);
break;
case Shape.Rectangle:
body = GameMain.World.CreateRectangle(width, height, density);
FarseerBody = GameMain.World.CreateRectangle(width, height, density);
break;
default:
throw new NotImplementedException(bodyShape.ToString());
@@ -567,15 +569,15 @@ namespace Barotrauma
public void ResetDynamics()
{
body.ResetDynamics();
FarseerBody.ResetDynamics();
}
public void ApplyLinearImpulse(Vector2 impulse)
{
if (!IsValidValue(impulse / body.Mass, "new velocity", -1000f, 1000f)) return;
if (!IsValidValue(impulse / FarseerBody.Mass, "new velocity", -1000f, 1000f)) return;
if (!IsValidValue(impulse, "impulse", -1e10f, 1e10f)) return;
body.ApplyLinearImpulse(impulse);
FarseerBody.ApplyLinearImpulse(impulse);
}
/// <summary>
@@ -587,24 +589,24 @@ namespace Barotrauma
if (!IsValidValue(maxVelocity, "max velocity")) return;
Vector2 velocityAddition = impulse / Mass;
Vector2 newVelocity = body.LinearVelocity + velocityAddition;
Vector2 newVelocity = FarseerBody.LinearVelocity + velocityAddition;
float newSpeedSqr = newVelocity.LengthSquared();
if (newSpeedSqr > maxVelocity * maxVelocity)
{
newVelocity = newVelocity.ClampLength(maxVelocity);
}
if (!IsValidValue((newVelocity - body.LinearVelocity), "new velocity", -1000.0f, 1000.0f)) return;
if (!IsValidValue((newVelocity - FarseerBody.LinearVelocity), "new velocity", -1000.0f, 1000.0f)) return;
body.ApplyLinearImpulse((newVelocity - body.LinearVelocity) * Mass);
FarseerBody.ApplyLinearImpulse((newVelocity - FarseerBody.LinearVelocity) * Mass);
}
public void ApplyLinearImpulse(Vector2 impulse, Vector2 point)
{
if (!IsValidValue(impulse, "impulse", -1e10f, 1e10f)) return;
if (!IsValidValue(point, "point")) return;
if (!IsValidValue(impulse / body.Mass, "new velocity", -1000.0f, 1000.0f)) return;
body.ApplyLinearImpulse(impulse, point);
if (!IsValidValue(impulse / FarseerBody.Mass, "new velocity", -1000.0f, 1000.0f)) return;
FarseerBody.ApplyLinearImpulse(impulse, point);
}
/// <summary>
@@ -617,18 +619,18 @@ namespace Barotrauma
if (!IsValidValue(maxVelocity, "max velocity")) return;
Vector2 velocityAddition = impulse / Mass;
Vector2 newVelocity = body.LinearVelocity + velocityAddition;
Vector2 newVelocity = FarseerBody.LinearVelocity + velocityAddition;
float newSpeedSqr = newVelocity.LengthSquared();
if (newSpeedSqr > maxVelocity * maxVelocity)
{
newVelocity = newVelocity.ClampLength(maxVelocity);
}
if (!IsValidValue((newVelocity - body.LinearVelocity), "new velocity", -1000.0f, 1000.0f)) return;
if (!IsValidValue((newVelocity - FarseerBody.LinearVelocity), "new velocity", -1000.0f, 1000.0f)) return;
body.ApplyLinearImpulse((newVelocity - body.LinearVelocity) * Mass, point);
body.AngularVelocity = MathHelper.Clamp(
body.AngularVelocity,
FarseerBody.ApplyLinearImpulse((newVelocity - FarseerBody.LinearVelocity) * Mass, point);
FarseerBody.AngularVelocity = MathHelper.Clamp(
FarseerBody.AngularVelocity,
-NetConfig.MaxPhysicsBodyAngularVelocity,
NetConfig.MaxPhysicsBodyAngularVelocity);
}
@@ -636,7 +638,7 @@ namespace Barotrauma
public void ApplyForce(Vector2 force)
{
if (!IsValidValue(force, "force", -1e10f, 1e10f)) return;
body.ApplyForce(force);
FarseerBody.ApplyForce(force);
}
/// <summary>
@@ -647,10 +649,10 @@ namespace Barotrauma
if (!IsValidValue(maxVelocity, "max velocity")) return;
Vector2 velocityAddition = force / Mass * (float)Timing.Step;
Vector2 newVelocity = body.LinearVelocity + velocityAddition;
Vector2 newVelocity = FarseerBody.LinearVelocity + velocityAddition;
float newSpeedSqr = newVelocity.LengthSquared();
if (newSpeedSqr > maxVelocity * maxVelocity && Vector2.Dot(body.LinearVelocity, force) > 0.0f)
if (newSpeedSqr > maxVelocity * maxVelocity && Vector2.Dot(FarseerBody.LinearVelocity, force) > 0.0f)
{
float newSpeed = (float)Math.Sqrt(newSpeedSqr);
float maxVelAddition = maxVelocity - newSpeed;
@@ -659,20 +661,20 @@ namespace Barotrauma
}
if (!IsValidValue(force, "clamped force", -1e10f, 1e10f)) return;
body.ApplyForce(force);
FarseerBody.ApplyForce(force);
}
public void ApplyForce(Vector2 force, Vector2 point)
{
if (!IsValidValue(force, "force", -1e10f, 1e10f)) return;
if (!IsValidValue(point, "point")) return;
body.ApplyForce(force, point);
FarseerBody.ApplyForce(force, point);
}
public void ApplyTorque(float torque)
{
if (!IsValidValue(torque, "torque")) return;
body.ApplyTorque(torque);
FarseerBody.ApplyTorque(torque);
}
public bool SetTransform(Vector2 simPosition, float rotation, bool setPrevTransform = true)
@@ -684,7 +686,7 @@ namespace Barotrauma
if (!IsValidValue(simPosition, "position", -1e10f, 1e10f)) return false;
if (!IsValidValue(rotation, "rotation")) return false;
body.SetTransform(simPosition, rotation);
FarseerBody.SetTransform(simPosition, rotation);
if (setPrevTransform) { SetPrevTransform(simPosition, rotation); }
return true;
}
@@ -698,7 +700,7 @@ namespace Barotrauma
if (!IsValidValue(simPosition, "position", -1e10f, 1e10f)) return false;
if (!IsValidValue(rotation, "rotation")) return false;
body.SetTransformIgnoreContacts(ref simPosition, rotation);
FarseerBody.SetTransformIgnoreContacts(ref simPosition, rotation);
if (setPrevTransform) { SetPrevTransform(simPosition, rotation); }
return true;
}
@@ -718,9 +720,9 @@ namespace Barotrauma
if (lerp)
{
if (Vector2.DistanceSquared((Vector2)targetPosition, body.Position) < 10.0f * 10.0f)
if (Vector2.DistanceSquared((Vector2)targetPosition, FarseerBody.Position) < 10.0f * 10.0f)
{
drawOffset = -((Vector2)targetPosition - (body.Position + drawOffset));
drawOffset = -((Vector2)targetPosition - (FarseerBody.Position + drawOffset));
prevPosition = (Vector2)targetPosition;
}
else
@@ -729,26 +731,26 @@ namespace Barotrauma
}
if (targetRotation.HasValue)
{
rotationOffset = -MathUtils.GetShortestAngle(body.Rotation + rotationOffset, targetRotation.Value);
rotationOffset = -MathUtils.GetShortestAngle(FarseerBody.Rotation + rotationOffset, targetRotation.Value);
}
}
SetTransformIgnoreContacts((Vector2)targetPosition, targetRotation == null ? body.Rotation : (float)targetRotation);
SetTransformIgnoreContacts((Vector2)targetPosition, targetRotation == null ? FarseerBody.Rotation : (float)targetRotation);
targetPosition = null;
targetRotation = null;
}
public void MoveToPos(Vector2 simPosition, float force, Vector2? pullPos = null)
{
if (pullPos == null) pullPos = body.Position;
if (pullPos == null) pullPos = FarseerBody.Position;
if (!IsValidValue(simPosition, "position", -1e10f, 1e10f)) return;
if (!IsValidValue(force, "force")) return;
Vector2 vel = body.LinearVelocity;
Vector2 vel = FarseerBody.LinearVelocity;
Vector2 deltaPos = simPosition - (Vector2)pullPos;
deltaPos *= force;
body.ApplyLinearImpulse((deltaPos - vel * 0.5f) * body.Mass, (Vector2)pullPos);
FarseerBody.ApplyLinearImpulse((deltaPos - vel * 0.5f) * FarseerBody.Mass, (Vector2)pullPos);
}
/// <summary>
@@ -774,7 +776,7 @@ namespace Barotrauma
}
ApplyForce(dragForce + buoyancy, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
ApplyTorque(body.AngularVelocity * body.Mass * -0.08f);
ApplyTorque(FarseerBody.AngularVelocity * FarseerBody.Mass * -0.08f);
}
public void Update()
@@ -789,9 +791,9 @@ namespace Barotrauma
public void UpdateDrawPosition()
{
drawPosition = Timing.Interpolate(prevPosition, body.Position);
drawPosition = Timing.Interpolate(prevPosition, FarseerBody.Position);
drawPosition = ConvertUnits.ToDisplayUnits(drawPosition + drawOffset);
drawRotation = Timing.InterpolateRotation(prevRotation, body.Rotation) + rotationOffset;
drawRotation = Timing.InterpolateRotation(prevRotation, FarseerBody.Rotation) + rotationOffset;
}
public void CorrectPosition<T>(List<T> positionBuffer,
@@ -827,27 +829,29 @@ namespace Barotrauma
/// <param name="wrapAngle">Should the angles be wrapped. Set to false if it makes a difference whether the angle of the body is 0.0f or 360.0f.</param>
public void SmoothRotate(float targetRotation, float force = 10.0f, bool wrapAngle = true)
{
float nextAngle = body.Rotation + body.AngularVelocity * (float)Timing.Step;
float nextAngle = FarseerBody.Rotation + FarseerBody.AngularVelocity * (float)Timing.Step;
float angle = wrapAngle ?
MathUtils.GetShortestAngle(nextAngle, targetRotation) :
MathHelper.Clamp(targetRotation - nextAngle, -MathHelper.Pi, MathHelper.Pi);
float torque = angle * 60.0f * (force / 100.0f);
if (body.BodyType == BodyType.Kinematic)
if (FarseerBody.BodyType == BodyType.Kinematic)
{
if (!IsValidValue(torque, "torque")) return;
body.AngularVelocity = torque;
FarseerBody.AngularVelocity = torque;
}
else
{
ApplyTorque(body.Mass * torque);
ApplyTorque(FarseerBody.Mass * torque);
}
}
public void Remove()
{
list.Remove(this);
GameMain.World.Remove(body);
GameMain.World.Remove(FarseerBody);
Removed = true;
DisposeProjSpecific();
}
@@ -399,6 +399,12 @@ namespace Barotrauma
return ParseColor(element.Attribute(name).Value);
}
public static Color? GetAttributeColor(this XElement element, string name)
{
if (element == null || element.Attribute(name) == null) { return null; }
return ParseColor(element.Attribute(name).Value);
}
public static Color[] GetAttributeColorArray(this XElement element, string name, Color[] defaultValue)
{
if (element?.Attribute(name) == null) return defaultValue;