(63916eda9) Unstable v0.9.1001.0
This commit is contained in:
@@ -210,7 +210,7 @@ namespace Barotrauma
|
||||
public void SelectTarget(AITarget target, float priority)
|
||||
{
|
||||
SelectedAiTarget = target;
|
||||
selectedTargetMemory = GetTargetMemory(target);
|
||||
selectedTargetMemory = GetTargetMemory(target, true);
|
||||
selectedTargetMemory.Priority = priority;
|
||||
}
|
||||
|
||||
@@ -439,7 +439,10 @@ namespace Barotrauma
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
LatchOntoAI?.Update(this, deltaTime);
|
||||
if (!Character.AnimController.SimplePhysicsEnabled)
|
||||
{
|
||||
LatchOntoAI?.Update(this, deltaTime);
|
||||
}
|
||||
IsSteeringThroughGap = false;
|
||||
if (SwarmBehavior != null)
|
||||
{
|
||||
@@ -478,7 +481,7 @@ namespace Barotrauma
|
||||
if (target?.Entity != null && !target.Entity.Removed && PreviousState == AIState.Attack && Character.CurrentHull == null)
|
||||
{
|
||||
// Keep heading to the last known position of the target
|
||||
var memory = GetTargetMemory(target);
|
||||
var memory = GetTargetMemory(target, false);
|
||||
if (memory != null)
|
||||
{
|
||||
var location = memory.Location;
|
||||
@@ -908,7 +911,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (!Character.AnimController.SimplePhysicsEnabled && SelectedAiTarget.Entity.Submarine != null && Character.Submarine == null && (!canAttackDoors || !canAttackWalls || !AIParams.TargetOuterWalls))
|
||||
{
|
||||
if (Vector2.Distance(Character.WorldPosition, attackWorldPos) < 2000 * 2000)
|
||||
if (Vector2.DistanceSquared(Character.WorldPosition, attackWorldPos) < 2000 * 2000)
|
||||
{
|
||||
// Check that we are not bumping into a door or a wall
|
||||
Vector2 rayStart = SimPosition;
|
||||
@@ -916,8 +919,8 @@ namespace Barotrauma
|
||||
{
|
||||
rayStart -= SelectedAiTarget.Entity.Submarine.SimPosition;
|
||||
}
|
||||
Vector2 toTarget = SelectedAiTarget.WorldPosition - WorldPosition;
|
||||
Vector2 rayEnd = rayStart + toTarget.ClampLength(Character.AnimController.Collider.GetLocalFront().Length() * 2);
|
||||
Vector2 dir = SelectedAiTarget.WorldPosition - WorldPosition;
|
||||
Vector2 rayEnd = rayStart + dir.ClampLength(Character.AnimController.Collider.GetLocalFront().Length() * 2);
|
||||
Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd, ignoreSubs: true);
|
||||
if (Submarine.LastPickedFraction != 1.0f && closestBody != null &&
|
||||
(!AIParams.TargetOuterWalls || !canAttackWalls && closestBody.UserData is Structure s && s.Submarine != null || !canAttackDoors && closestBody.UserData is Item i && i.Submarine != null && i.GetComponent<Door>() != null))
|
||||
@@ -933,25 +936,30 @@ namespace Barotrauma
|
||||
float distance = 0;
|
||||
Limb attackTargetLimb = null;
|
||||
Character targetCharacter = SelectedAiTarget.Entity as Character;
|
||||
if (canAttack && !Character.AnimController.SimplePhysicsEnabled)
|
||||
if (canAttack)
|
||||
{
|
||||
// Target a specific limb instead of the target center position
|
||||
if (wallTarget == null && targetCharacter != null)
|
||||
if (!Character.AnimController.SimplePhysicsEnabled)
|
||||
{
|
||||
var targetLimbType = AttackingLimb.Params.Attack.Attack.TargetLimbType;
|
||||
attackTargetLimb = GetTargetLimb(AttackingLimb, targetCharacter, targetLimbType);
|
||||
if (attackTargetLimb == null)
|
||||
// Target a specific limb instead of the target center position
|
||||
if (wallTarget == null && targetCharacter != null)
|
||||
{
|
||||
State = AIState.Idle;
|
||||
IgnoreTarget(SelectedAiTarget);
|
||||
ResetAITarget();
|
||||
return;
|
||||
var targetLimbType = AttackingLimb.Params.Attack.Attack.TargetLimbType;
|
||||
attackTargetLimb = GetTargetLimb(AttackingLimb, targetCharacter, targetLimbType);
|
||||
if (attackTargetLimb == null)
|
||||
{
|
||||
State = AIState.Idle;
|
||||
IgnoreTarget(SelectedAiTarget);
|
||||
ResetAITarget();
|
||||
return;
|
||||
}
|
||||
attackWorldPos = attackTargetLimb.WorldPosition;
|
||||
attackSimPos = Character.GetRelativeSimPosition(attackTargetLimb);
|
||||
}
|
||||
attackWorldPos = attackTargetLimb.WorldPosition;
|
||||
attackSimPos = Character.GetRelativeSimPosition(attackTargetLimb);
|
||||
}
|
||||
// Check that we can reach the target
|
||||
Vector2 toTarget = attackWorldPos - (Character.AnimController.SimplePhysicsEnabled ? Character.WorldPosition : AttackingLimb.WorldPosition);
|
||||
|
||||
Vector2 attackLimbPos = Character.AnimController.SimplePhysicsEnabled ? Character.WorldPosition : AttackingLimb.WorldPosition;
|
||||
Vector2 toTarget = attackWorldPos - attackLimbPos;
|
||||
// Add a margin when the target is moving away, because otherwise it might be difficult to reach it (the attack takes some time to perform)
|
||||
if (wallTarget != null)
|
||||
{
|
||||
if (wallTarget.Structure.Submarine != null)
|
||||
@@ -962,7 +970,6 @@ namespace Barotrauma
|
||||
}
|
||||
else if (targetCharacter != null)
|
||||
{
|
||||
// Add a margin when the target is moving away, because otherwise it might be difficult to reach it (the attack takes some time to perform)
|
||||
Vector2 margin = CalculateMargin(targetCharacter.AnimController.Collider.LinearVelocity);
|
||||
toTarget += margin;
|
||||
}
|
||||
@@ -982,6 +989,7 @@ namespace Barotrauma
|
||||
return ConvertUnits.ToDisplayUnits(targetVelocity) * AttackingLimb.attack.Duration * dot;
|
||||
}
|
||||
|
||||
// Check that we can reach the target
|
||||
distance = toTarget.Length();
|
||||
canAttack = distance < AttackingLimb.attack.Range;
|
||||
if (!canAttack && !IsCoolDownRunning)
|
||||
@@ -1366,7 +1374,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
AITargetMemory targetMemory = GetTargetMemory(attacker.AiTarget);
|
||||
AITargetMemory targetMemory = GetTargetMemory(attacker.AiTarget, true);
|
||||
targetMemory.Priority += GetRelativeDamage(attackResult.Damage, Character.Vitality) * AggressionHurt;
|
||||
|
||||
// Only allow to react once. Otherwise would attack the target with only a fraction of a cooldown
|
||||
@@ -1409,7 +1417,7 @@ namespace Barotrauma
|
||||
var aiTarget = wallTarget.Structure.AiTarget;
|
||||
if (aiTarget != null && SelectedAiTarget != aiTarget)
|
||||
{
|
||||
SelectTarget(aiTarget, GetTargetMemory(SelectedAiTarget).Priority);
|
||||
SelectTarget(aiTarget, GetTargetMemory(SelectedAiTarget, true).Priority);
|
||||
}
|
||||
}
|
||||
IDamageable damageTarget = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity as IDamageable;
|
||||
@@ -1857,7 +1865,7 @@ namespace Barotrauma
|
||||
// -> just ignore the distance and attack whatever has the highest priority
|
||||
dist = Math.Max(dist, 100.0f);
|
||||
|
||||
AITargetMemory targetMemory = GetTargetMemory(aiTarget);
|
||||
AITargetMemory targetMemory = GetTargetMemory(aiTarget, true);
|
||||
if (Character.CurrentHull != null && Math.Abs(toTarget.Y) > Character.CurrentHull.Size.Y)
|
||||
{
|
||||
// Inside the sub, treat objects that are up or down, as they were farther away.
|
||||
@@ -1938,12 +1946,15 @@ namespace Barotrauma
|
||||
return SelectedAiTarget;
|
||||
}
|
||||
|
||||
private AITargetMemory GetTargetMemory(AITarget target)
|
||||
private AITargetMemory GetTargetMemory(AITarget target, bool addIfNotFound)
|
||||
{
|
||||
if (!targetMemories.TryGetValue(target, out AITargetMemory memory))
|
||||
{
|
||||
memory = new AITargetMemory(target, 10);
|
||||
targetMemories.Add(target, memory);
|
||||
if (addIfNotFound)
|
||||
{
|
||||
memory = new AITargetMemory(target, 10);
|
||||
targetMemories.Add(target, memory);
|
||||
}
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
@@ -1958,8 +1969,11 @@ namespace Barotrauma
|
||||
}
|
||||
else if (CanPerceive(_selectedAiTarget, distSquared: Vector2.DistanceSquared(Character.WorldPosition, _selectedAiTarget.WorldPosition)))
|
||||
{
|
||||
var memory = GetTargetMemory(_selectedAiTarget);
|
||||
memory.Location = _selectedAiTarget.WorldPosition;
|
||||
var memory = GetTargetMemory(_selectedAiTarget, false);
|
||||
if (memory != null)
|
||||
{
|
||||
memory.Location = _selectedAiTarget.WorldPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -42,6 +42,7 @@ namespace Barotrauma
|
||||
currSearchIndex = -1;
|
||||
this.equip = equip;
|
||||
this.targetItem = targetItem;
|
||||
moveToTarget = targetItem?.GetRootInventoryOwner();
|
||||
}
|
||||
|
||||
public AIObjectiveGetItem(Character character, string itemIdentifier, AIObjectiveManager objectiveManager, bool equip = true, bool checkInventory = true, float priorityModifier = 1)
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ namespace Barotrauma
|
||||
{
|
||||
case "shutdown":
|
||||
var powered = component?.Item.GetComponent<Powered>();
|
||||
if (powered != null && powered.IsActive)
|
||||
if (powered != null && !powered.IsActive)
|
||||
{
|
||||
Priority = 0;
|
||||
return Priority;
|
||||
|
||||
@@ -47,11 +47,15 @@ namespace Barotrauma
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
if (!Enabled) { return; }
|
||||
if (IsDead || Vitality <= 0.0f || Stun > 0.0f || IsIncapacitated) { return; }
|
||||
if (IsDead || Vitality <= 0.0f || Stun > 0.0f || IsIncapacitated)
|
||||
{
|
||||
//don't enable simple physics on dead/incapacitated characters
|
||||
//the ragdoll controls the movement of incapacitated characters instead of the collider,
|
||||
//but in simple physics mode the ragdoll would get disabled, causing the character to not move at all
|
||||
AnimController.SimplePhysicsEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//don't enable simple physics on dead/incapacitated characters
|
||||
//the ragdoll controls the movement of incapacitated characters instead of the collider,
|
||||
//but in simple physics mode the ragdoll would get disabled, causing the character to not move at all
|
||||
if (!IsRemotePlayer && !(AIController is HumanAIController))
|
||||
{
|
||||
float characterDist = float.MaxValue;
|
||||
|
||||
@@ -709,7 +709,7 @@ namespace Barotrauma
|
||||
float impactDamage = Math.Min((impact - ImpactTolerance) * ImpactDamageMultiplayer, character.MaxVitality * MaxImpactDamage);
|
||||
|
||||
character.LastDamageSource = null;
|
||||
character.AddDamage(impactPos, new List<Affliction>() { AfflictionPrefab.InternalDamage.Instantiate(impactDamage) }, 0.0f, true);
|
||||
character.AddDamage(impactPos, AfflictionPrefab.ImpactDamage.Instantiate(impactDamage).ToEnumerable(), 0.0f, true);
|
||||
strongestImpact = Math.Max(strongestImpact, impact - ImpactTolerance);
|
||||
character.ApplyStatusEffects(ActionType.OnImpact, 1.0f);
|
||||
//briefly disable impact damage
|
||||
|
||||
@@ -2469,7 +2469,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private readonly float maxAIRange = 10000;
|
||||
private readonly float maxAIRange = 20000;
|
||||
private readonly float aiTargetChangeSpeed = 5;
|
||||
|
||||
private void UpdateSightRange(float deltaTime)
|
||||
@@ -2741,14 +2741,8 @@ namespace Barotrauma
|
||||
}
|
||||
if (severed)
|
||||
{
|
||||
if (joint.LimbA == targetLimb)
|
||||
{
|
||||
joint.LimbB.body.LinearVelocity += targetLimb.LinearVelocity * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
joint.LimbA.body.LinearVelocity += targetLimb.LinearVelocity * 0.5f;
|
||||
}
|
||||
Limb otherLimb = joint.LimbA == targetLimb ? joint.LimbB : joint.LimbA;
|
||||
otherLimb.body.ApplyLinearImpulse(targetLimb.LinearVelocity * targetLimb.Mass);
|
||||
}
|
||||
}
|
||||
if (wasSevered)
|
||||
|
||||
+7
@@ -189,6 +189,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public static AfflictionPrefab InternalDamage;
|
||||
public static AfflictionPrefab ImpactDamage;
|
||||
public static AfflictionPrefab Bleeding;
|
||||
public static AfflictionPrefab Burn;
|
||||
public static AfflictionPrefab OxygenLow;
|
||||
@@ -291,6 +292,7 @@ namespace Barotrauma
|
||||
{
|
||||
CPRSettings.Unload();
|
||||
InternalDamage = null;
|
||||
ImpactDamage = null;
|
||||
Bleeding = null;
|
||||
Burn = null;
|
||||
OxygenLow = null;
|
||||
@@ -437,6 +439,9 @@ namespace Barotrauma
|
||||
case "internaldamage":
|
||||
InternalDamage = prefab;
|
||||
break;
|
||||
case "blunttrauma":
|
||||
ImpactDamage = prefab;
|
||||
break;
|
||||
case "bleeding":
|
||||
Bleeding = prefab;
|
||||
break;
|
||||
@@ -456,6 +461,8 @@ namespace Barotrauma
|
||||
Stun = prefab;
|
||||
break;
|
||||
}
|
||||
if (ImpactDamage == null) { ImpactDamage = InternalDamage; }
|
||||
|
||||
if (prefab != null)
|
||||
{
|
||||
Prefabs.Add(prefab, isOverride);
|
||||
|
||||
@@ -46,10 +46,10 @@ namespace Barotrauma
|
||||
[Serialize(false, false), Editable]
|
||||
public bool CanSpeak { get; set; }
|
||||
|
||||
[Serialize(100f, true, description: "How much noise the character makes when moving?"), Editable(minValue: 0f, maxValue: 10000f)]
|
||||
[Serialize(100f, true, description: "How much noise the character makes when moving?"), Editable(minValue: 0f, maxValue: 100000f)]
|
||||
public float Noise { get; set; }
|
||||
|
||||
[Serialize(100f, true, description: "How visible the character is?"), Editable(minValue: 0f, maxValue: 10000f)]
|
||||
[Serialize(100f, true, description: "How visible the character is?"), Editable(minValue: 0f, maxValue: 100000f)]
|
||||
public float Visibility { get; set; }
|
||||
|
||||
[Serialize("blood", true), Editable]
|
||||
|
||||
@@ -13,6 +13,9 @@ namespace Barotrauma
|
||||
private readonly int minAmount, maxAmount;
|
||||
private List<Character> monsters;
|
||||
|
||||
private readonly float scatter;
|
||||
private readonly float offset;
|
||||
|
||||
private readonly bool spawnDeep;
|
||||
|
||||
private Vector2? spawnPos;
|
||||
@@ -72,6 +75,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
spawnDeep = prefab.ConfigElement.GetAttributeBool("spawndeep", false);
|
||||
offset = prefab.ConfigElement.GetAttributeFloat("offset", 0);
|
||||
scatter = Math.Clamp(prefab.ConfigElement.GetAttributeFloat("scatter", 1000), 0, 3000);
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
@@ -241,6 +246,28 @@ namespace Barotrauma
|
||||
spawnPos = spawnPoint.WorldPosition;
|
||||
}
|
||||
}
|
||||
else if (chosenPosition.PositionType == Level.PositionType.MainPath && offset > 0)
|
||||
{
|
||||
Vector2 dir;
|
||||
var waypoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine == null);
|
||||
var nearestWaypoint = waypoints.OrderBy(wp => Vector2.DistanceSquared(wp.WorldPosition, spawnPos.Value)).FirstOrDefault();
|
||||
if (nearestWaypoint != null)
|
||||
{
|
||||
int currentIndex = waypoints.IndexOf(nearestWaypoint);
|
||||
var nextWaypoint = waypoints[Math.Min(currentIndex + 20, waypoints.Count - 1)];
|
||||
dir = Vector2.Normalize(nextWaypoint.WorldPosition - nearestWaypoint.WorldPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = new Vector2(1, Rand.Range(-1, 1));
|
||||
}
|
||||
Vector2 targetPos = spawnPos.Value + dir * offset;
|
||||
var targetWaypoint = waypoints.OrderBy(wp => Vector2.DistanceSquared(wp.WorldPosition, targetPos)).FirstOrDefault();
|
||||
if (targetWaypoint != null)
|
||||
{
|
||||
spawnPos = targetWaypoint.WorldPosition;
|
||||
}
|
||||
}
|
||||
spawnPending = true;
|
||||
}
|
||||
}
|
||||
@@ -314,7 +341,7 @@ namespace Barotrauma
|
||||
//+1 because Range returns an integer less than the max value
|
||||
int amount = Rand.Range(minAmount, maxAmount + 1);
|
||||
monsters = new List<Character>();
|
||||
float offsetAmount = spawnPosType == Level.PositionType.MainPath ? 1000 : 100;
|
||||
float offsetAmount = spawnPosType == Level.PositionType.MainPath ? scatter : 100;
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
CoroutineManager.InvokeAfter(() =>
|
||||
@@ -324,7 +351,22 @@ namespace Barotrauma
|
||||
|
||||
System.Diagnostics.Debug.Assert(GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer, "Clients should not create monster events.");
|
||||
|
||||
monsters.Add(Character.Create(speciesName, spawnPos.Value + Rand.Vector(offsetAmount), Level.Loaded.Seed + i.ToString(), null, false, true, true));
|
||||
Vector2 pos = spawnPos.Value + Rand.Vector(offsetAmount);
|
||||
if (spawnPosType == Level.PositionType.MainPath)
|
||||
{
|
||||
if (Submarine.Loaded.Any(s => ToolBox.GetWorldBounds(s.Borders.Center, s.Borders.Size).ContainsWorld(pos)))
|
||||
{
|
||||
// Can't use the offset position, let's use the exact spawn position.
|
||||
pos = spawnPos.Value;
|
||||
}
|
||||
else if (Level.Loaded.Ruins.Any(r => ToolBox.GetWorldBounds(r.Area.Center, r.Area.Size).ContainsWorld(pos)))
|
||||
{
|
||||
// Can't use the offset position, let's use the exact spawn position.
|
||||
pos = spawnPos.Value;
|
||||
}
|
||||
}
|
||||
|
||||
monsters.Add(Character.Create(speciesName, pos, Level.Loaded.Seed + i.ToString(), null, false, true, true));
|
||||
|
||||
if (monsters.Count == amount)
|
||||
{
|
||||
|
||||
@@ -70,6 +70,12 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(false, false, description: "Can the item repair things through holes in walls.")]
|
||||
public bool RepairThroughHoles { get; set; }
|
||||
|
||||
[Serialize(true, false, description: "Can the item hit broken doors.")]
|
||||
public bool HitItems { get; set; }
|
||||
|
||||
[Serialize(false, false, description: "Can the item hit broken doors.")]
|
||||
public bool HitBrokenDoors { get; set; }
|
||||
|
||||
[Serialize(0.0f, false, description: "The probability of starting a fire somewhere along the ray fired from the barrel (for example, 0.1 = 10% chance to start a fire during a second of use).")]
|
||||
public float FireProbability { get; set; }
|
||||
|
||||
@@ -445,7 +451,9 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
else if (targetBody.UserData is Item targetItem)
|
||||
{
|
||||
{
|
||||
if (!HitItems) { return false; }
|
||||
|
||||
var levelResource = targetItem.GetComponent<LevelResource>();
|
||||
if (levelResource != null && levelResource.Attached &&
|
||||
levelResource.requiredItems.Any() &&
|
||||
@@ -463,7 +471,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
if (!targetItem.Prefab.DamagedByRepairTools) { return false; }
|
||||
if (item.GetComponent<Door>() == null && item.Condition <= 0) { return false; }
|
||||
|
||||
if (HitBrokenDoors)
|
||||
{
|
||||
if (targetItem.GetComponent<Door>() == null && targetItem.Condition <= 0) { return false; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targetItem.Condition <= 0) { return false; }
|
||||
}
|
||||
|
||||
targetItem.IsHighlighted = true;
|
||||
|
||||
|
||||
@@ -486,6 +486,10 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (target.Body.UserData is Item item)
|
||||
{
|
||||
if (item.Condition <= 0.0f) { return false; }
|
||||
}
|
||||
|
||||
//ignore character colliders (the projectile only hits limbs)
|
||||
if (target.CollisionCategories == Physics.CollisionCharacter && target.Body.UserData is Character)
|
||||
|
||||
@@ -309,11 +309,10 @@ namespace Barotrauma.Items.Components
|
||||
SkillSettings.Current.SkillIncreasePerRepair / Math.Max(characterSkillLevel, 1.0f),
|
||||
CurrentFixer.WorldPosition + Vector2.UnitY * 100.0f);
|
||||
}
|
||||
|
||||
SteamAchievementManager.OnItemRepaired(item, CurrentFixer);
|
||||
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
|
||||
wasBroken = false;
|
||||
}
|
||||
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
|
||||
wasBroken = false;
|
||||
StopRepairing(CurrentFixer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
|
||||
[Serialize(false, false, description: "Can the component communicate with wifi components in another team's submarine (e.g. enemy sub in Combat missions, respawn shuttle). Needs to be enabled on both the component transmitting the signal and the component receiving it.", alwaysUseInstanceValues: true)]
|
||||
[Editable, Serialize(false, true, description: "Can the component communicate with wifi components in another team's submarine (e.g. enemy sub in Combat missions, respawn shuttle). Needs to be enabled on both the component transmitting the signal and the component receiving it.", alwaysUseInstanceValues: true)]
|
||||
public bool AllowCrossTeamCommunication
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -707,7 +707,8 @@ namespace Barotrauma
|
||||
var brokenSprite = new BrokenItemSprite(
|
||||
new Sprite(subElement, brokenSpriteFolder, lazyLoad: true),
|
||||
subElement.GetAttributeFloat("maxcondition", 0.0f),
|
||||
subElement.GetAttributeBool("fadein", false));
|
||||
subElement.GetAttributeBool("fadein", false),
|
||||
subElement.GetAttributePoint("offset", Point.Zero));
|
||||
|
||||
int spriteIndex = 0;
|
||||
for (int i = 0; i < BrokenSprites.Count && BrokenSprites[i].MaxCondition < brokenSprite.MaxCondition; i++)
|
||||
|
||||
@@ -292,10 +292,10 @@ namespace Barotrauma
|
||||
if (limb.WorldPosition != worldPosition && !MathUtils.NearlyEqual(force, 0.0f))
|
||||
{
|
||||
Vector2 limbDiff = Vector2.Normalize(limb.WorldPosition - worldPosition);
|
||||
if (!MathUtils.IsValid(limbDiff)) limbDiff = Rand.Vector(1.0f);
|
||||
if (!MathUtils.IsValid(limbDiff)) { limbDiff = Rand.Vector(1.0f); }
|
||||
Vector2 impulse = limbDiff * distFactor * force;
|
||||
Vector2 impulsePoint = limb.SimPosition - limbDiff * limbRadius;
|
||||
limb.body.ApplyLinearImpulse(impulse, impulsePoint, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
limb.body.ApplyLinearImpulse(impulse, impulsePoint, maxVelocity: NetConfig.MaxPhysicsBodyVelocity * 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace Barotrauma
|
||||
currentCell.CellType = CellType.Path;
|
||||
pathCells.Add(currentCell);
|
||||
|
||||
int currentTargetIndex = 1;
|
||||
int currentTargetIndex = 0;
|
||||
|
||||
int iterationsLeft = cells.Count;
|
||||
|
||||
|
||||
@@ -1600,6 +1600,7 @@ namespace Barotrauma
|
||||
int attemptsLeft = maxAttempts;
|
||||
bool success = false;
|
||||
Vector2 spawnPoint = Vector2.Zero;
|
||||
var allCells = Loaded.GetAllCells();
|
||||
while (attemptsLeft > 0)
|
||||
{
|
||||
if (attemptsLeft < maxAttempts)
|
||||
@@ -1847,8 +1848,7 @@ namespace Barotrauma
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var cells = Loaded.GetAllCells().Where(c => c.Body != null && Vector2.DistanceSquared(pos, c.Center) <= maxDistance);
|
||||
return cells.Any(c => c.BodyVertices.Any(v => bounds.ContainsWorld(v)));
|
||||
return cells.Any(c => c.Body != null && Vector2.DistanceSquared(pos, c.Center) <= maxDistance && c.BodyVertices.Any(v => bounds.ContainsWorld(v)));
|
||||
}
|
||||
}
|
||||
totalSW.Stop();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Common;
|
||||
@@ -451,7 +452,9 @@ namespace Barotrauma
|
||||
private void UpdateDepthDamage(float deltaTime)
|
||||
{
|
||||
if (Position.Y > DamageDepth) { return; }
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession.GameMode is SubTestMode) { return; }
|
||||
#endif
|
||||
float depth = DamageDepth - Position.Y;
|
||||
|
||||
depthDamageTimer -= deltaTime;
|
||||
@@ -639,7 +642,7 @@ namespace Barotrauma
|
||||
float damageAmount = contactDot * Body.Mass / limb.character.Mass;
|
||||
limb.character.LastDamageSource = submarine;
|
||||
limb.character.DamageLimb(ConvertUnits.ToDisplayUnits(collision.ImpactPos), limb,
|
||||
new List<Affliction>() { AfflictionPrefab.InternalDamage.Instantiate(damageAmount) }, 0.0f, true, 0.0f);
|
||||
AfflictionPrefab.ImpactDamage.Instantiate(damageAmount).ToEnumerable(), 0.0f, true, 0.0f);
|
||||
|
||||
if (limb.character.IsDead)
|
||||
{
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Barotrauma
|
||||
|
||||
if (element.StartTimer > 0.0f) { continue; }
|
||||
|
||||
element.Parent.Apply(1.0f, element.Entity, element.Targets, element.WorldPosition);
|
||||
element.Parent.Apply(deltaTime, element.Entity, element.Targets, element.WorldPosition);
|
||||
DelayList.Remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,44 +193,64 @@ namespace Barotrauma
|
||||
string[] readTags = valStr.Split(',');
|
||||
int matches = 0;
|
||||
foreach (string tag in readTags)
|
||||
if (target is Item item && item.HasTag(tag)) matches++;
|
||||
|
||||
{
|
||||
if (target is Item item && item.HasTag(tag))
|
||||
{
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
//If operator is == then it needs to match everything, otherwise if its != there must be zero matches.
|
||||
return Operator == OperatorType.Equals ? matches >= readTags.Length : matches <= 0;
|
||||
}
|
||||
case ConditionType.HasStatusTag:
|
||||
if (target == null) { return Operator == OperatorType.NotEquals; }
|
||||
|
||||
List<DurationListElement> durations = StatusEffect.DurationList.FindAll(d => d.Targets.Contains(target));
|
||||
List<DelayedListElement> delays = DelayedEffect.DelayList.FindAll(d => d.Targets.Contains(target));
|
||||
|
||||
bool success = false;
|
||||
if (durations.Count > 0 || delays.Count > 0)
|
||||
if (StatusEffect.DurationList.Any(d => d.Targets.Contains(target)) || DelayedEffect.DelayList.Any(d => d.Targets.Contains(target)))
|
||||
{
|
||||
string[] readTags = valStr.Split(',');
|
||||
foreach (DurationListElement duration in durations)
|
||||
foreach (DurationListElement duration in StatusEffect.DurationList)
|
||||
{
|
||||
if (!duration.Targets.Contains(target)) { continue; }
|
||||
int matches = 0;
|
||||
foreach (string tag in readTags)
|
||||
if (duration.Parent.HasTag(tag)) matches++;
|
||||
|
||||
{
|
||||
if (duration.Parent.HasTag(tag))
|
||||
{
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
success = Operator == OperatorType.Equals ? matches >= readTags.Length : matches <= 0;
|
||||
if (cancelStatusEffect > 0 && success)
|
||||
{
|
||||
StatusEffect.DurationList.Remove(duration);
|
||||
if (cancelStatusEffect != 2) //cancelStatusEffect 1 = only cancel once, cancelStatusEffect 2 = cancel all of matching tags
|
||||
}
|
||||
if (cancelStatusEffect != 2)
|
||||
{
|
||||
//cancelStatusEffect 1 = only cancel once, cancelStatusEffect 2 = cancel all of matching tags
|
||||
return success;
|
||||
}
|
||||
}
|
||||
foreach (DelayedListElement delay in delays)
|
||||
foreach (DelayedListElement delay in DelayedEffect.DelayList)
|
||||
{
|
||||
if (!delay.Targets.Contains(target)) { continue; }
|
||||
int matches = 0;
|
||||
foreach (string tag in readTags)
|
||||
if (delay.Parent.HasTag(tag)) matches++;
|
||||
|
||||
{
|
||||
if (delay.Parent.HasTag(tag))
|
||||
{
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
success = Operator == OperatorType.Equals ? matches >= readTags.Length : matches <= 0;
|
||||
if (cancelStatusEffect > 0 && success)
|
||||
{
|
||||
DelayedEffect.DelayList.Remove(delay);
|
||||
if (cancelStatusEffect != 2) //ditto
|
||||
}
|
||||
if (cancelStatusEffect != 2)
|
||||
{
|
||||
//ditto
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Operator == OperatorType.NotEquals)
|
||||
|
||||
@@ -318,7 +318,7 @@ namespace Barotrauma
|
||||
break;
|
||||
case "conditionalcomparison":
|
||||
case "comparison":
|
||||
if (!Enum.TryParse(attribute.Value, out conditionalComparison))
|
||||
if (!Enum.TryParse(attribute.Value, ignoreCase: true, out conditionalComparison))
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid conditional comparison type \"" + attribute.Value + "\" in StatusEffect (" + parentDebugName + ")");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user