Merge branch 'master' into moStuff

This commit is contained in:
Joonas Rikkonen
2018-01-09 10:38:06 +02:00
committed by GitHub
179 changed files with 116633 additions and 3529 deletions
@@ -1,29 +1,63 @@
using Barotrauma.Items.Components;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
namespace Barotrauma
{
class AIObjectiveContainItem: AIObjective
{
private string itemName;
public int MinContainedAmount = 1;
private string[] itemNames;
private ItemContainer container;
bool isCompleted;
private bool isCompleted;
public bool IgnoreAlreadyContainedItems;
public Func<Item, float> GetItemPriority;
private AIObjectiveGetItem getItemObjective;
private AIObjectiveGoTo goToObjective;
public AIObjectiveContainItem(Character character, string itemName, ItemContainer container)
: this(character, new string[] { itemName }, container)
{
}
public AIObjectiveContainItem(Character character, string[] itemNames, ItemContainer container)
: base (character, "")
{
this.itemName = itemName;
this.itemNames = itemNames;
this.container = container;
}
public override bool IsCompleted()
{
return isCompleted || container.Inventory.FindItem(itemName)!=null;
if (isCompleted) return true;
int containedItemCount = 0;
foreach (Item item in container.Inventory.Items)
{
if (item != null && itemNames.Any(name => item.Prefab.NameMatches(name) || item.HasTag(name))) containedItemCount++;
}
return containedItemCount >= MinContainedAmount;
}
public override bool CanBeCompleted
{
get
{
if (goToObjective != null)
{
return goToObjective.CanBeCompleted;
}
return getItemObjective == null || !getItemObjective.CanBeCompleted;
}
}
public override float GetPriority(AIObjectiveManager objectiveManager)
@@ -41,12 +75,13 @@ namespace Barotrauma
if (isCompleted) return;
//get the item that should be contained
var itemToContain = character.Inventory.FindItem(itemName);
var itemToContain = character.Inventory.FindItem(itemNames);
if (itemToContain == null)
{
var getItem = new AIObjectiveGetItem(character, itemName);
getItem.IgnoreContainedItems = IgnoreAlreadyContainedItems;
AddSubObjective(getItem);
getItemObjective = new AIObjectiveGetItem(character, itemNames);
getItemObjective.GetItemPriority = GetItemPriority;
getItemObjective.IgnoreContainedItems = IgnoreAlreadyContainedItems;
AddSubObjective(getItemObjective);
return;
}
@@ -63,9 +98,10 @@ namespace Barotrauma
else
{
if (Vector2.Distance(character.Position, container.Item.Position) > container.Item.InteractDistance
&& !container.Item.IsInsideTrigger(character.Position))
&& !container.Item.IsInsideTrigger(character.WorldPosition))
{
AddSubObjective(new AIObjectiveGoTo(container.Item, character));
goToObjective = new AIObjectiveGoTo(container.Item, character);
AddSubObjective(goToObjective);
return;
}
@@ -79,8 +115,15 @@ namespace Barotrauma
{
AIObjectiveContainItem objective = otherObjective as AIObjectiveContainItem;
if (objective == null) return false;
if (objective.container != container) return false;
if (objective.itemNames.Length != itemNames.Length) return false;
return objective.itemName == itemName && objective.container == container;
for (int i = 0; i < itemNames.Length; i++)
{
if (objective.itemNames[i] != itemNames[i]) return false;
}
return true;
}
@@ -11,12 +11,20 @@ namespace Barotrauma
public override bool IsCompleted()
{
var item = character.Inventory.FindItem(gearName);
if (item == null) return false;
for (int i = 0; i < character.Inventory.Items.Length; i++)
{
if (CharacterInventory.limbSlots[i] == InvSlotType.Any || character.Inventory.Items[i] == null) continue;
if (character.Inventory.Items[i].Prefab.NameMatches(gearName) || character.Inventory.Items[i].HasTag(gearName))
{
var containedItems = character.Inventory.Items[i].ContainedItems;
if (containedItems == null) continue;
var containedItems = item.ContainedItems;
var oxygenTank = Array.Find(containedItems, i => i.Prefab.NameMatches("Oxygen Tank") && i.Condition > 0.0f);
return oxygenTank != null;
var oxygenTank = Array.Find(containedItems, it => (it.Prefab.NameMatches("Oxygen Tank") || it.HasTag("oxygensource")) && it.Condition > 0.0f);
if (oxygenTank != null) return true;
}
}
return false;
}
public AIObjectiveFindDivingGear(Character character, bool needDivingSuit)
@@ -41,25 +49,24 @@ namespace Barotrauma
var containedItems = item.ContainedItems;
if (containedItems == null) return;
//check if there's an oxygen tank in the mask
var oxygenTank = Array.Find(containedItems, i => i.Prefab.NameMatches("Oxygen Tank"));
if (oxygenTank != null)
//check if there's an oxygen tank in the mask/suit
foreach (Item containedItem in containedItems)
{
if (oxygenTank.Condition > 0.0f)
if (containedItem == null) continue;
if (containedItem.Condition <= 0.0f)
{
containedItem.Drop();
}
else if (containedItem.Prefab.NameMatches("Oxygen Tank") || containedItem.HasTag("oxygensource"))
{
//we've got an oxygen source inside the mask/suit, all good
return;
}
else
{
oxygenTank.Drop();
}
}
if (!(subObjective is AIObjectiveContainItem) || subObjective.IsCompleted())
{
subObjective = new AIObjectiveContainItem(character, "Oxygen Tank", item.GetComponent<ItemContainer>());
subObjective = new AIObjectiveContainItem(character, new string[] { "Oxygen Tank", "oxygensource" }, item.GetComponent<ItemContainer>());
}
}
@@ -106,6 +106,9 @@ namespace Barotrauma
if (gap.ConnectedWall == null) continue;
if (gap.ConnectedDoor != null || gap.Open <= 0.0f) continue;
//TODO: prevent the AI characters from fixing leaks in the enemy sub in sub-vs-sub missions if/when multiplayer bots are implemented
if (gap.Submarine == null) continue;
float gapPriority = GetGapFixPriority(gap);
int index = 0;
@@ -1,14 +1,16 @@
using Barotrauma.Items.Components;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System;
namespace Barotrauma
{
class AIObjectiveGetItem : AIObjective
{
private string itemName;
public Func<Item, float> GetItemPriority;
private string[] itemNames;
private Item targetItem, moveToTarget;
@@ -20,6 +22,8 @@ namespace Barotrauma
private AIObjectiveGoTo goToObjective;
private float currItemPriority;
private bool equip;
public override bool CanBeCompleted
@@ -49,24 +53,33 @@ namespace Barotrauma
this.targetItem = targetItem;
}
public AIObjectiveGetItem(Character character, string itemName, bool equip=false)
: base (character, "")
public AIObjectiveGetItem(Character character, string itemName, bool equip = false)
: this(character, new string[] { itemName }, equip)
{
}
public AIObjectiveGetItem(Character character, string[] itemNames, bool equip = false)
: base(character, "")
{
canBeCompleted = true;
this.equip = equip;
currSearchIndex = 0;
this.itemName = itemName;
this.itemNames = itemNames;
}
protected override void Act(float deltaTime)
{
FindTargetItem();
if (targetItem == null || moveToTarget == null) return;
if (targetItem == null || moveToTarget == null)
{
character?.AIController?.SteeringManager?.Reset();
return;
}
if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.InteractDistance*2.0f)
if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.InteractDistance * 2.0f)
{
int targetSlot = -1;
if (equip)
@@ -82,8 +95,8 @@ namespace Barotrauma
foreach (InvSlotType slots in pickable.AllowedSlots)
{
if (slots.HasFlag(InvSlotType.Any)) continue;
for (int i = 0; i<character.Inventory.Items.Length; i++)
for (int i = 0; i < character.Inventory.Items.Length; i++)
{
//slot not needed by the item, continue
if (!slots.HasFlag(CharacterInventory.limbSlots[i])) continue;
@@ -111,15 +124,19 @@ namespace Barotrauma
}
else
{
if (goToObjective == null)
if (goToObjective == null || moveToTarget != goToObjective.Target)
{
bool gettingDivingGear = itemName == "diving" || itemName == "Diving Gear";
//check if we're already looking for a diving gear
bool gettingDivingGear = (targetItem != null && targetItem.Prefab.NameMatches("Diving Gear") || targetItem.HasTag("diving")) ||
(itemNames != null && (itemNames.Contains("diving") || itemNames.Contains("Diving Gear")));
//don't attempt to get diving gear to reach the destination if the item we're trying to get is diving gear
goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear);
}
goToObjective.TryComplete(deltaTime);
}
}
/// <summary>
@@ -127,14 +144,14 @@ namespace Barotrauma
/// </summary>
private void FindTargetItem()
{
if (itemName == null)
if (itemNames == null)
{
if (targetItem == null) canBeCompleted = false;
return;
}
float currDist = moveToTarget == null ? 0.0f : Vector2.DistanceSquared(moveToTarget.Position, character.Position);
for (int i = 0; i < 10 && currSearchIndex < Item.ItemList.Count - 2; i++)
{
currSearchIndex++;
@@ -143,21 +160,38 @@ namespace Barotrauma
if (item.CurrentHull == null || item.Condition <= 0.0f) continue;
if (IgnoreContainedItems && item.Container != null) continue;
if (item.Name != itemName && !item.HasTag(itemName)) continue;
if (!itemNames.Any(name => item.Prefab.NameMatches(name) || item.HasTag(name))) continue;
//if the item is inside a character's inventory, don't steal it
if (item.ParentInventory is CharacterInventory) continue;
//if the item is inside an item, which is inside a character's inventory, don't steal it
if (item.ParentInventory != null && item.ParentInventory.Owner is Item)
//if the item is inside a character's inventory, don't steal it unless the character is dead
if (item.ParentInventory is CharacterInventory)
{
if (((Item)item.ParentInventory.Owner).ParentInventory is CharacterInventory) continue;
Character owner = item.ParentInventory.Owner as Character;
if (owner != null && !owner.IsDead) continue;
}
//ignore if item is further away than the currently targeted item
//if the item is inside an item, which is inside a character's inventory, don't steal it
Item rootContainer = item.GetRootContainer();
if (moveToTarget != null && Vector2.DistanceSquared((rootContainer ?? item).Position, character.Position) > currDist) continue;
if (rootContainer != null && rootContainer.ParentInventory is CharacterInventory)
{
Character owner = rootContainer.ParentInventory.Owner as Character;
if (owner != null && !owner.IsDead) continue;
}
float itemPriority = 0.0f;
if (GetItemPriority != null)
{
//ignore if the item has zero priority
itemPriority = GetItemPriority(item);
if (itemPriority <= 0.0f) continue;
}
itemPriority = itemPriority - Vector2.Distance((rootContainer ?? item).Position, character.Position) * 0.01f;
//ignore if the item has a lower priority than the currently selected one
if (moveToTarget != null && itemPriority < currItemPriority) continue;
currItemPriority = itemPriority;
targetItem = item;
moveToTarget = rootContainer ?? item;
}
@@ -165,23 +199,44 @@ namespace Barotrauma
//if searched through all the items and a target wasn't found, can't be completed
if (currSearchIndex >= Item.ItemList.Count && targetItem == null) canBeCompleted = false;
}
public override bool IsDuplicate(AIObjective otherObjective)
{
AIObjectiveGetItem getItem = otherObjective as AIObjectiveGetItem;
if (getItem == null) return false;
return (getItem.itemName == itemName);
if (getItem.equip != equip) return false;
if (getItem.itemNames != null && itemNames != null)
{
if (getItem.itemNames.Length != itemNames.Length) return false;
for (int i = 0; i < getItem.itemNames.Length; i++)
{
if (getItem.itemNames[i] != itemNames[i]) return false;
}
return true;
}
else if (getItem.itemNames == null && itemNames == null)
{
return getItem.targetItem == targetItem;
}
return false;
}
public override bool IsCompleted()
{
if (itemName!=null)
if (itemNames != null)
{
return character.Inventory.FindItem(itemName) != null;
foreach (string itemName in itemNames)
{
var matchingItem = character.Inventory.FindItem(itemName);
if (matchingItem != null && (!equip || character.HasEquippedItem(matchingItem))) return true;
}
return false;
}
else if (targetItem!= null)
else if (targetItem != null)
{
return character.Inventory.Items.Contains(targetItem);
return character.Inventory.Items.Contains(targetItem) && (!equip || character.HasEquippedItem(targetItem));
}
else
{
@@ -78,7 +78,7 @@ namespace Barotrauma
}
//re-enable collider
if (!Collider.FarseerBody.Enabled)
if (!Collider.Enabled)
{
var lowestLimb = FindLowestLimb();
@@ -87,7 +87,7 @@ namespace Barotrauma
Math.Max(lowestLimb.SimPosition.Y + (Collider.radius + Collider.height / 2), Collider.SimPosition.Y)),
0.0f);
Collider.FarseerBody.Enabled = true;
Collider.Enabled = true;
}
ResetPullJoints();
@@ -105,7 +105,7 @@ namespace Barotrauma
//re-enable collider
if (!Collider.FarseerBody.Enabled)
if (!Collider.Enabled)
{
var lowestLimb = FindLowestLimb();
@@ -115,7 +115,7 @@ namespace Barotrauma
Collider.Rotation);
Collider.FarseerBody.ResetDynamics();
Collider.FarseerBody.Enabled = true;
Collider.Enabled = true;
}
if (swimming)
@@ -1034,7 +1034,8 @@ namespace Barotrauma
{
Limb targetLimb = target.AnimController.GetLimb(GrabLimb);
if (targetLimb == null || targetLimb.IsSevered)
//grab hands if GrabLimb is not specified (or torso if the character has no hands)
if (GrabLimb == LimbType.None || targetLimb.IsSevered)
{
targetLimb = target.AnimController.GetLimb(LimbType.Torso);
if (i == 0)
@@ -527,7 +527,7 @@ namespace Barotrauma
public void SeverLimbJoint(LimbJoint limbJoint)
{
if (!limbJoint.CanBeSevered)
if (!limbJoint.CanBeSevered || limbJoint.IsSevered)
{
return;
}
@@ -541,12 +541,29 @@ namespace Barotrauma
GetConnectedLimbs(connectedLimbs, checkedJoints, MainLimb);
foreach (Limb limb in Limbs)
{
if (!connectedLimbs.Contains(limb))
if (connectedLimbs.Contains(limb)) continue;
limb.IsSevered = true;
}
#if CLIENT
if (character.UseBloodParticles)
{
foreach (Limb limb in new Limb[] { limbJoint.LimbA, limbJoint.LimbB })
{
limb.IsSevered = true;
for (int i = 0; i < MathHelper.Clamp(limb.Mass * 2.0f, 1.0f, 50.0f); i++)
{
GameMain.ParticleManager.CreateParticle("gib", limb.WorldPosition, Rand.Range(0.0f, MathHelper.TwoPi), Rand.Range(200.0f, 700.0f), character.CurrentHull);
}
for (int i = 0; i < MathHelper.Clamp(limb.Mass * 2.0f, 1.0f, 10.0f); i++)
{
GameMain.ParticleManager.CreateParticle("heavygib", limb.WorldPosition, Rand.Range(0.0f, MathHelper.TwoPi), Rand.Range(50.0f, 250.0f), character.CurrentHull);
}
}
}
#endif
if (GameMain.Server != null)
{
GameMain.Server.CreateEntityEvent(character, new object[] { NetEntityEvent.Type.Status });
@@ -1469,5 +1486,12 @@ namespace Barotrauma
list.Remove(this);
}
public static void RemoveAll()
{
for (int i = list.Count - 1; i >= 0; i--)
{
list[i].Remove();
}
}
}
}
@@ -21,6 +21,12 @@ namespace Barotrauma
Any = Blunt | Slash | Burn
}
public enum HitDetection
{
Distance,
Contact
}
struct AttackResult
{
public readonly float Damage;
@@ -39,90 +45,87 @@ namespace Barotrauma
partial class Attack
{
public readonly float Range;
public readonly float DamageRange;
public readonly float Duration;
[Serialize(HitDetection.Distance, false)]
public HitDetection HitDetectionType { get; private set; }
public readonly DamageType DamageType;
[Serialize(0.0f, false)]
public float Range { get; private set; }
private readonly float structureDamage;
private readonly float damage;
private readonly float bleedingDamage;
[Serialize(0.0f, false)]
public float DamageRange { get; private set; }
private readonly bool onlyHumans;
[Serialize(0.0f, false)]
public float Duration { get; private set; }
private readonly List<StatusEffect> statusEffects;
[Serialize(DamageType.None, false)]
public DamageType DamageType { get; private set; }
public readonly float Force;
[Serialize(0.0f, false)]
public float StructureDamage { get; private set; }
public readonly float Torque;
[Serialize(0.0f, false)]
public float Damage { get; private set; }
public readonly float TargetForce;
[Serialize(0.0f, false)]
public float BleedingDamage { get; private set; }
public readonly float SeverLimbsProbability;
[Serialize(0.0f, false)]
public float Stun { get; private set; }
[Serialize(false, false)]
public bool OnlyHumans { get; private set; }
[Serialize(0.0f, false)]
public float Force { get; private set; }
[Serialize(0.0f, false)]
public float Torque { get; private set; }
[Serialize(0.0f, false)]
public float TargetForce { get; private set; }
[Serialize(0.0f, false)]
public float SeverLimbsProbability { get; set; }
[Serialize(0.0f, false)]
public float Priority { get; private set; }
//the indices of the limbs Force is applied on
//(if none, force is applied only to the limb the attack is attached to)
public readonly List<int> ApplyForceOnLimbs;
public readonly float Stun;
private float priority;
private readonly List<StatusEffect> statusEffects;
public float GetDamage(float deltaTime)
{
return (Duration == 0.0f) ? damage : damage * deltaTime;
return (Duration == 0.0f) ? Damage : Damage * deltaTime;
}
public float GetBleedingDamage(float deltaTime)
{
return (Duration == 0.0f) ? bleedingDamage : bleedingDamage * deltaTime;
return (Duration == 0.0f) ? BleedingDamage : BleedingDamage * deltaTime;
}
public float GetStructureDamage(float deltaTime)
{
return (Duration == 0.0f) ? structureDamage : structureDamage * deltaTime;
return (Duration == 0.0f) ? StructureDamage : StructureDamage * deltaTime;
}
public Attack(float damage, float structureDamage, float bleedingDamage, float range = 0.0f)
{
Range = range;
DamageRange = range;
this.damage = damage;
this.structureDamage = structureDamage;
this.bleedingDamage = bleedingDamage;
this.Damage = damage;
this.StructureDamage = structureDamage;
this.BleedingDamage = bleedingDamage;
}
public Attack(XElement element)
{
try
{
DamageType = (DamageType)Enum.Parse(typeof(DamageType), element.GetAttributeString("damagetype", "None"), true);
}
catch
{
DamageType = DamageType.None;
}
damage = element.GetAttributeFloat("damage", 0.0f);
structureDamage = element.GetAttributeFloat("structuredamage", 0.0f);
bleedingDamage = element.GetAttributeFloat("bleedingdamage", 0.0f);
Stun = element.GetAttributeFloat("stun", 0.0f);
SeverLimbsProbability = element.GetAttributeFloat("severlimbsprobability", 0.0f);
Force = element.GetAttributeFloat("force", 0.0f);
TargetForce = element.GetAttributeFloat("targetforce", 0.0f);
Torque = element.GetAttributeFloat("torque", 0.0f);
Range = element.GetAttributeFloat("range", 0.0f);
SerializableProperty.DeserializeProperties(this, element);
DamageRange = element.GetAttributeFloat("damagerange", Range);
Duration = element.GetAttributeFloat("duration", 0.0f);
priority = element.GetAttributeFloat("priority", 1.0f);
onlyHumans = element.GetAttributeBool("onlyhumans", false);
InitProjSpecific(element);
string limbIndicesStr = element.GetAttributeString("applyforceonlimbs", "");
@@ -158,7 +161,7 @@ namespace Barotrauma
public AttackResult DoDamage(Character attacker, IDamageable target, Vector2 worldPosition, float deltaTime, bool playSound = true)
{
if (onlyHumans)
if (OnlyHumans)
{
Character character = target as Character;
if (character != null && character.ConfigPath != Character.HumanConfigFile) return new AttackResult();
@@ -189,7 +192,7 @@ namespace Barotrauma
{
if (targetLimb == null) return new AttackResult();
if (onlyHumans)
if (OnlyHumans)
{
if (targetLimb.character != null && targetLimb.character.ConfigPath != Character.HumanConfigFile) return new AttackResult();
}
@@ -344,18 +344,18 @@ namespace Barotrauma
if (GameMain.Client != null) return;
float newHealth = MathHelper.Clamp(value, minHealth, maxHealth);
if (newHealth == health) return;
//if (newHealth == health) return;
health = newHealth;
if (GameMain.Server != null)
/*if (GameMain.Server != null)
{
if (Math.Abs(health - lastSentHealth) > (maxHealth - minHealth) / 255.0f || Math.Sign(health) != Math.Sign(lastSentHealth))
{
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
lastSentHealth = health;
}
}
}*/
}
}
@@ -374,12 +374,12 @@ namespace Barotrauma
if (!DoesBleed) return;
float newBleeding = MathHelper.Clamp(value, 0.0f, 5.0f);
if (newBleeding == bleeding) return;
//if (newBleeding == bleeding) return;
bleeding = newBleeding;
if (GameMain.Server != null)
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
/*if (GameMain.Server != null)
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });*/
}
}
@@ -426,6 +426,12 @@ namespace Barotrauma
private set;
}
public bool UseBloodParticles
{
get;
private set;
}
public float BleedingDecreaseSpeed
{
get;
@@ -634,6 +640,7 @@ namespace Barotrauma
health = maxHealth;
DoesBleed = doc.Root.GetAttributeBool("doesbleed", true);
UseBloodParticles = doc.Root.GetAttributeBool("usebloodparticles", true);
BleedingDecreaseSpeed = doc.Root.GetAttributeFloat("bleedingdecreasespeed", 0.05f);
needsAir = doc.Root.GetAttributeBool("needsair", false);
@@ -1046,6 +1053,17 @@ namespace Barotrauma
return !inventory.IsInLimbSlot(item, InvSlotType.Any);
}
public bool HasEquippedItem(string itemName)
{
for (int i = 0; i < inventory.Items.Length; i++)
{
if (CharacterInventory.limbSlots[i] == InvSlotType.Any || inventory.Items[i] == null) continue;
if (inventory.Items[i].Prefab.NameMatches(itemName) || inventory.Items[i].HasTag(itemName)) return true;
}
return false;
}
public bool HasSelectedItem(Item item)
{
return selectedItems.Contains(item);
@@ -1541,11 +1559,11 @@ namespace Barotrauma
if (stunTimer > 0.0f)
{
stunTimer -= deltaTime;
if (stunTimer < 0.0f && GameMain.Server != null)
/*if (stunTimer < 0.0f && GameMain.Server != null)
{
//stun ended -> notify clients
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
}
} */
}
//Skip health effects as critical health handles it differently
@@ -1575,8 +1593,8 @@ namespace Barotrauma
if (IsRagdolled)
{
if (AnimController is HumanoidAnimController) ((HumanoidAnimController)AnimController).Crouching = false;
if(GameMain.Server != null)
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
/*if(GameMain.Server != null)
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });*/
AnimController.ResetPullJoints();
selectedConstruction = null;
return;
@@ -1831,11 +1849,11 @@ namespace Barotrauma
if ((newStun <= stunTimer && !allowStunDecrease) || !MathUtils.IsValid(newStun)) return;
if (GameMain.Server != null &&
/*if (GameMain.Server != null &&
(Math.Sign(newStun) != Math.Sign(stunTimer) || Math.Abs(newStun - stunTimer) > 0.1f))
{
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
}
}*/
if (Math.Sign(newStun) != Math.Sign(stunTimer)) AnimController.ResetPullJoints();
@@ -1894,11 +1912,11 @@ namespace Barotrauma
return;
}
if (GameMain.NetworkMember != null)
/*if (GameMain.NetworkMember != null)
{
if (GameMain.Server != null)
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
}
}*/
AnimController.Frozen = false;
@@ -332,6 +332,7 @@ namespace Barotrauma
inventory.ServerRead(type, msg, c);
break;
case 1:
bool doingCPR = msg.ReadBoolean();
if (c.Character != this)
{
#if DEBUG
@@ -340,7 +341,6 @@ namespace Barotrauma
return;
}
bool doingCPR = msg.ReadBoolean();
AnimController.Anim = doingCPR ? AnimController.Animation.CPR : AnimController.Animation.None;
break;
case 2:
@@ -358,7 +358,15 @@ namespace Barotrauma
}
break;
case 3:
AnimController.GrabLimb = (LimbType)msg.ReadUInt16();
LimbType grabLimb = (LimbType)msg.ReadUInt16();
if (c.Character != this)
{
#if DEBUG
DebugConsole.Log("Received a character update message from a client who's not controlling the character");
#endif
return;
}
AnimController.GrabLimb = grabLimb;
break;
}
break;
@@ -384,10 +392,6 @@ namespace Barotrauma
Client owner = ((Client)extraData[1]);
msg.Write(owner == null ? (byte)0 : owner.ID);
break;
case NetEntityEvent.Type.Status:
msg.WriteRangedInteger(0, 2, 2);
WriteStatus(msg);
break;
}
msg.WritePadBits();
}
@@ -474,6 +478,8 @@ namespace Barotrauma
tempBuffer.Write(SimPosition.Y);
tempBuffer.Write(AnimController.Collider.Rotation);
WriteStatus(tempBuffer);
tempBuffer.WritePadBits();
msg.Write((byte)tempBuffer.LengthBytes);
@@ -2,6 +2,7 @@
using Barotrauma.Items.Components;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using System;
@@ -386,23 +387,25 @@ namespace Barotrauma
SoundPlayer.PlayDamageSound(damageSoundType, amount, position);
}
float bloodParticleAmount = bleedingAmount <= 0.0f ? 0 : (int)Math.Min(amount / 5, 10);
float bloodParticleSize = MathHelper.Clamp(amount / 50.0f, 0.1f, 1.0f);
for (int i = 0; i < bloodParticleAmount; i++)
if (character.UseBloodParticles)
{
var blood = GameMain.ParticleManager.CreateParticle(inWater ? "waterblood" : "blood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
if (blood != null)
float bloodParticleAmount = bleedingAmount <= 0.0f ? 0 : (int)Math.Min(amount / 5, 10);
float bloodParticleSize = MathHelper.Clamp(amount / 50.0f, 0.1f, 1.0f);
for (int i = 0; i < bloodParticleAmount; i++)
{
blood.Size *= bloodParticleSize;
var blood = GameMain.ParticleManager.CreateParticle(inWater ? "waterblood" : "blood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
if (blood != null)
{
blood.Size *= bloodParticleSize;
}
}
if (bloodParticleAmount > 0 && character.CurrentHull != null)
{
character.CurrentHull.AddDecal("blood", WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
}
}
if (bloodParticleAmount > 0 && character.CurrentHull != null)
{
character.CurrentHull.AddDecal("blood", WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
}
#endif
if (damageType == DamageType.Burn)
@@ -479,12 +482,69 @@ namespace Barotrauma
body.ApplyTorque(Mass * character.AnimController.Dir * attack.Torque);
if (dist < attack.DamageRange)
bool wasHit = false;
if (damageTarget != null)
{
switch (attack.HitDetectionType)
{
case HitDetection.Distance:
wasHit = dist < attack.DamageRange;
break;
case HitDetection.Contact:
List<Body> targetBodies = new List<Body>();
if (damageTarget is Character)
{
Character targetCharacter = (Character)damageTarget;
foreach (Limb limb in targetCharacter.AnimController.Limbs)
{
if (!limb.IsSevered && limb.body?.FarseerBody != null) targetBodies.Add(limb.body.FarseerBody);
}
}
else if (damageTarget is Structure)
{
Structure targetStructure = (Structure)damageTarget;
if (character.Submarine == null && targetStructure.Submarine != null)
{
targetBodies.Add(targetStructure.Submarine.PhysicsBody.FarseerBody);
}
else
{
targetBodies.AddRange(targetStructure.Bodies);
}
}
else if (damageTarget is Item)
{
Item targetItem = damageTarget as Item;
if (targetItem.body?.FarseerBody != null) targetBodies.Add(targetItem.body.FarseerBody);
}
if (targetBodies != null)
{
ContactEdge contactEdge = body.FarseerBody.ContactList;
while (contactEdge != null)
{
if (contactEdge.Contact != null &&
contactEdge.Contact.IsTouching &&
targetBodies.Any(b => b == contactEdge.Contact.FixtureA?.Body || b == contactEdge.Contact.FixtureB?.Body))
{
wasHit = true;
break;
}
contactEdge = contactEdge.Next;
}
}
break;
}
}
if (wasHit)
{
if (AttackTimer >= attack.Duration && damageTarget != null)
{
attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, (SoundTimer <= 0.0f));
SoundTimer = SoundInterval;
}
}