Merge branch 'master' of https://github.com/Regalis11/Barotrauma
This commit is contained in:
@@ -550,14 +550,14 @@ namespace Barotrauma
|
||||
if (subObjective.IsCompleted)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage($"{character.Name}: Removing SUBobjective {subObjective.DebugTag} of {DebugTag}, because it is completed.", Color.LightGreen);
|
||||
DebugConsole.NewMessage($"{character.Name}: Removing subObjective \"{subObjective.DebugTag}\" of \"{DebugTag}\", because it is completed.", Color.LightGreen);
|
||||
#endif
|
||||
subObjectives.Remove(subObjective);
|
||||
}
|
||||
else if (!subObjective.CanBeCompleted)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage($"{character.Name}: Removing SUBobjective {subObjective.DebugTag} of {DebugTag}, because it cannot be completed.", Color.Red);
|
||||
DebugConsole.NewMessage($"{character.Name}: Removing subObjective \"{subObjective.DebugTag}\" of \"{DebugTag}\", because it cannot be completed.", Color.Red);
|
||||
#endif
|
||||
subObjectives.Remove(subObjective);
|
||||
if (AbandonWhenCannotCompleteSubObjectives)
|
||||
|
||||
+1
@@ -12,6 +12,7 @@ namespace Barotrauma
|
||||
class AIObjectiveGetItem : AIObjective
|
||||
{
|
||||
public override Identifier Identifier { get; set; } = "get item".ToIdentifier();
|
||||
public override string DebugTag => $"{Identifier} ({(IdentifiersOrTags == null || IdentifiersOrTags.None() ? "none" : string.Join(", ", IdentifiersOrTags))})";
|
||||
|
||||
public override bool AbandonWhenCannotCompleteSubObjectives => false;
|
||||
public override bool AllowMultipleInstances => true;
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Barotrauma
|
||||
class AIObjectiveGoTo : AIObjective
|
||||
{
|
||||
public override Identifier Identifier { get; set; } = "go to".ToIdentifier();
|
||||
public override string DebugTag => $"{Identifier} ({Target?.ToString() ?? "none"})";
|
||||
|
||||
public override bool KeepDivingGearOn => GetTargetHull() == null;
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ namespace Barotrauma
|
||||
class AIObjectiveOperateItem : AIObjective
|
||||
{
|
||||
public override Identifier Identifier { get; set; } = "operate item".ToIdentifier();
|
||||
public override string DebugTag => $"{Identifier} {component.Name}";
|
||||
public override string DebugTag => $"{Identifier} ({component.Name})";
|
||||
|
||||
public override bool AllowAutomaticItemUnequipping => true;
|
||||
public override bool AllowMultipleInstances => true;
|
||||
|
||||
+2
@@ -10,6 +10,8 @@ namespace Barotrauma
|
||||
{
|
||||
public override Identifier Identifier { get; set; } = "repair item".ToIdentifier();
|
||||
|
||||
public override string DebugTag => $"{Identifier} ({Item?.Name ?? "null"})";
|
||||
|
||||
protected override bool AllowInFriendlySubs => true;
|
||||
public override bool KeepDivingGearOn => Item?.CurrentHull == null;
|
||||
protected override bool AllowWhileHandcuffed => false;
|
||||
|
||||
@@ -206,19 +206,21 @@ namespace Barotrauma
|
||||
{
|
||||
float xDiff = Math.Abs(start.X - node.TempPosition.X);
|
||||
float yDiff = Math.Abs(start.Y - node.TempPosition.Y);
|
||||
//higher cost for vertical movement when inside the sub
|
||||
if (InsideSubmarine && !(node.Waypoint.Submarine?.Info?.IsRuin ?? false))
|
||||
{
|
||||
//higher cost for vertical movement when inside the sub
|
||||
if (yDiff > 1.0f && node.Waypoint.Ladders == null && node.Waypoint.Stairs == null)
|
||||
{
|
||||
yDiff += 10.0f;
|
||||
}
|
||||
node.TempDistance = xDiff + yDiff * 10.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
node.TempDistance = xDiff + yDiff;
|
||||
//only apply the higher cost for vertical movement if it's more than a meter
|
||||
//(small differences can be caused by non-meaningful variance in the vertical position of the waypoint, we only care about actually going up/down e.g. ladders or stairs)
|
||||
if (Math.Abs(yDiff) > 1.0f)
|
||||
{
|
||||
yDiff *= 10.0f;
|
||||
}
|
||||
}
|
||||
node.TempDistance = xDiff + yDiff;
|
||||
|
||||
//much higher cost to waypoints that are outside
|
||||
if (node.Waypoint.CurrentHull == null && ApplyPenaltyToOutsideNodes) { node.TempDistance *= 10.0f; }
|
||||
|
||||
@@ -2927,7 +2927,7 @@ namespace Barotrauma
|
||||
Entity.Spawner.AddCharacterToSpawnQueue(CharacterPrefab.HumanSpeciesName, spawnPosition, humanPrefab.CreateCharacterInfo(), onSpawn: newCharacter =>
|
||||
{
|
||||
newCharacter.HumanPrefab = humanPrefab;
|
||||
AddToCrew(newCharacter);
|
||||
SetTeamAndCrew(newCharacter);
|
||||
humanPrefab.GiveItems(newCharacter, newCharacter.Submarine, spawnPoint);
|
||||
humanPrefab.InitializeCharacter(newCharacter);
|
||||
#if SERVER
|
||||
@@ -2943,7 +2943,7 @@ namespace Barotrauma
|
||||
CharacterInfo characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: job, variant: variant);
|
||||
Entity.Spawner.AddCharacterToSpawnQueue(CharacterPrefab.HumanSpeciesName, spawnPosition, characterInfo, onSpawn: newCharacter =>
|
||||
{
|
||||
AddToCrew(newCharacter);
|
||||
SetTeamAndCrew(newCharacter);
|
||||
newCharacter.GiveJobItems(isPvPMode: GameMain.GameSession?.GameMode is PvPMode, spawnPoint);
|
||||
newCharacter.GiveIdCardTags(spawnPoint);
|
||||
newCharacter.Info.StartItemsGiven = true;
|
||||
@@ -2951,10 +2951,13 @@ namespace Barotrauma
|
||||
}
|
||||
else if (CharacterPrefab.FindBySpeciesName(args[0].ToIdentifier()) is { } prefab)
|
||||
{
|
||||
Entity.Spawner.AddCharacterToSpawnQueue(args[0].ToIdentifier(), spawnPosition, prefab.HasCharacterInfo ? new CharacterInfo(prefab.Identifier) : null);
|
||||
Entity.Spawner.AddCharacterToSpawnQueue(args[0].ToIdentifier(), spawnPosition, prefab.HasCharacterInfo ? new CharacterInfo(prefab.Identifier) : null, onSpawn: newCharacter =>
|
||||
{
|
||||
SetTeamAndCrew(newCharacter);
|
||||
});
|
||||
}
|
||||
|
||||
void AddToCrew(Character newCharacter)
|
||||
void SetTeamAndCrew(Character newCharacter)
|
||||
{
|
||||
newCharacter.TeamID = teamType;
|
||||
if (addToCrew)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace Barotrauma
|
||||
{
|
||||
/// <summary>
|
||||
/// Makes the event jump to a <see cref="Label"/> somewhere else in the event.
|
||||
/// Makes the event jump to a <see cref="Label"/> somewhere else in the event. Note that using GoTo resets the effects of other, currently active EventActions (e.g. closing conversation prompts and stopping the objectives NPCs were forced to do using actions such as CombatAction or NPCWaitAction).
|
||||
/// </summary>
|
||||
class GoTo : EventAction
|
||||
{
|
||||
|
||||
@@ -635,6 +635,8 @@ namespace Barotrauma.Items.Components
|
||||
autoInjectCooldown -= deltaTime;
|
||||
if (autoInjectCooldown <= 0.0f &&
|
||||
ownerInventory?.Owner is Character ownerCharacter &&
|
||||
//no point in trying to heal if the character is already dead
|
||||
!ownerCharacter.IsDead &&
|
||||
ownerCharacter.HealthPercentage / 100f <= AutoInjectThreshold &&
|
||||
ownerCharacter.HasEquippedItem(item))
|
||||
{
|
||||
|
||||
@@ -399,7 +399,7 @@ namespace Barotrauma.Items.Components
|
||||
LaunchSub = item.Submarine;
|
||||
//set the rotation of the projectile again because dropping the projectile in Use
|
||||
//resets the rotation and moves it to the position of the parent item
|
||||
Item.SetTransform(simPosition, rotation + (Item.body.Dir * LaunchRotationRadians), findNewHull: false);
|
||||
Item.SetTransform(simPosition, GetLaunchRotation(rotation), findNewHull: false);
|
||||
if (DeactivationTime > 0)
|
||||
{
|
||||
deactivationTimer = DeactivationTime;
|
||||
@@ -489,12 +489,7 @@ namespace Barotrauma.Items.Components
|
||||
float modifiedLaunchImpulse = (LaunchImpulse + launchImpulseModifier) * (1 + Rand.Range(-ImpulseSpread, ImpulseSpread));
|
||||
DoLaunch(launchDir * modifiedLaunchImpulse);
|
||||
//needs to be set after DoLaunch, because dropping the item resets the rotation and dir
|
||||
float afterLaunchAngle = launchAngle + (item.body.Dir * LaunchRotationRadians);
|
||||
if (item.body.Dir < 0)
|
||||
{
|
||||
afterLaunchAngle -= MathHelper.Pi;
|
||||
}
|
||||
item.SetTransform(item.body.SimPosition, afterLaunchAngle, findNewHull: false);
|
||||
item.SetTransform(item.body.SimPosition, GetLaunchRotation(launchAngle), findNewHull: false);
|
||||
}
|
||||
}
|
||||
User = character;
|
||||
@@ -502,6 +497,20 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the final rotation of the projectile after being launched, taking <see cref="LaunchRotationRadians"/>
|
||||
/// and the orientation of the projectile's physics body into account.
|
||||
/// </summary>
|
||||
private float GetLaunchRotation(float unmodifiedLaunchRotation)
|
||||
{
|
||||
float launchRotation = unmodifiedLaunchRotation + (item.body.Dir * LaunchRotationRadians);
|
||||
if (item.body.Dir < 0)
|
||||
{
|
||||
launchRotation -= MathHelper.Pi;
|
||||
}
|
||||
return launchRotation;
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null) => Use(character);
|
||||
|
||||
private void DoLaunch(Vector2 impulse)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.Extensions;
|
||||
@@ -19,6 +18,15 @@ namespace Barotrauma
|
||||
const float GrowSpeed = 20.0f;
|
||||
const float MaxDamageRange = 250.0f;
|
||||
|
||||
/// <summary>
|
||||
/// How often the FireSource checks whether it can spread to nearby hulls.
|
||||
/// </summary>
|
||||
const float SpreadToOtherHullsInterval = 5.0f;
|
||||
/// <summary>
|
||||
/// The probability of the fire spreading to a nearby hull when the <see cref="TrySpreadToNearbyHulls"/> check is made.
|
||||
/// </summary>
|
||||
const float SpreadToOtherHullsProbability = 0.15f;
|
||||
|
||||
protected Hull hull;
|
||||
|
||||
protected Vector2 position;
|
||||
@@ -69,6 +77,12 @@ namespace Barotrauma
|
||||
get { return Math.Min((float)Math.Sqrt(size.X) * 10.0f, MaxDamageRange); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Affects how far above the fire source things can get damaged and how far above a gap can be for the fire to spread through it.
|
||||
/// An arbitrary value chosen roughly based on how high the flame particles seem to extend.
|
||||
/// </summary>
|
||||
public float FlameHeight => MathHelper.Clamp(size.X * 3, 50.0f, 400.0f);
|
||||
|
||||
public bool DamagesItems
|
||||
{
|
||||
get;
|
||||
@@ -96,6 +110,8 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public readonly Character SourceCharacter;
|
||||
|
||||
private float spreadToOtherHullsTimer;
|
||||
|
||||
public FireSource(Vector2 worldPosition, Hull spawningHull = null, Character sourceCharacter = null, bool isNetworkMessage = false)
|
||||
{
|
||||
hull = Hull.FindHull(worldPosition, spawningHull);
|
||||
@@ -219,7 +235,7 @@ namespace Barotrauma
|
||||
if (removed) { return; }
|
||||
}
|
||||
|
||||
if (!(this is DummyFireSource))
|
||||
if (this is not DummyFireSource)
|
||||
{
|
||||
ReduceOxygen(deltaTime);
|
||||
}
|
||||
@@ -236,7 +252,14 @@ namespace Barotrauma
|
||||
|
||||
LimitSize();
|
||||
|
||||
if (size.X > 256.0f && !(this is DummyFireSource))
|
||||
spreadToOtherHullsTimer -= deltaTime;
|
||||
if (spreadToOtherHullsTimer <= 0.0f)
|
||||
{
|
||||
TrySpreadToNearbyHulls();
|
||||
spreadToOtherHullsTimer = SpreadToOtherHullsInterval;
|
||||
}
|
||||
|
||||
if (size.X > 256.0f && this is not DummyFireSource)
|
||||
{
|
||||
if (burnDecals.Count == 0)
|
||||
{
|
||||
@@ -262,7 +285,6 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
UpdateProjSpecific(growModifier, deltaTime);
|
||||
|
||||
|
||||
if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
|
||||
{
|
||||
@@ -270,6 +292,57 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the fire source attempt to spread to nearby hulls through gaps the firesource is in contact with.
|
||||
/// The probability of spreading is affected by <see cref="SpreadToOtherHullsProbability"/>.
|
||||
/// </summary>
|
||||
private void TrySpreadToNearbyHulls()
|
||||
{
|
||||
foreach (var gap in hull.ConnectedGaps)
|
||||
{
|
||||
if (!gap.IsRoomToRoom || gap.Open <= 0.0f) { continue; }
|
||||
|
||||
//no need for any syncing here, server lets the clients know if new fire sources spawn
|
||||
if (Rand.Range(0.0f, 1.0f, Rand.RandSync.Unsynced) > SpreadToOtherHullsProbability) { continue; }
|
||||
|
||||
if (gap.linkedTo.Where(h => h != hull).FirstOrDefault() is not Hull otherHull) { continue; }
|
||||
|
||||
//if firesource intersects with the gap
|
||||
if (position.X > gap.Rect.Right) { continue; }
|
||||
if (position.X + size.X < gap.Rect.X) { continue; }
|
||||
if (position.Y + FlameHeight < gap.Rect.Y - gap.Rect.Height) { continue; }
|
||||
if (position.Y - size.Y > gap.Rect.Y) { continue; }
|
||||
|
||||
//how far into the other hull should the firesource spawn
|
||||
float spawnOffset = 20.0f;
|
||||
Vector2 fireSourcePos = gap.WorldPosition;
|
||||
if (gap.IsHorizontal)
|
||||
{
|
||||
if (otherHull.Position.X < hull.Position.X)
|
||||
{
|
||||
fireSourcePos.X = otherHull.WorldRect.Right - spawnOffset;
|
||||
}
|
||||
else if (otherHull.Position.X > hull.Position.X)
|
||||
{
|
||||
fireSourcePos.X = otherHull.WorldRect.X + spawnOffset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fireSourcePos.X = MathHelper.Clamp(fireSourcePos.X, position.X, position.X + size.X);
|
||||
if (otherHull.Position.Y > hull.Position.Y)
|
||||
{
|
||||
fireSourcePos.Y = otherHull.WorldRect.Y - otherHull.WorldRect.Height + spawnOffset;
|
||||
}
|
||||
else if (otherHull.Position.Y < hull.Position.Y)
|
||||
{
|
||||
fireSourcePos.Y = otherHull.WorldRect.Y - spawnOffset;
|
||||
}
|
||||
}
|
||||
new FireSource(fireSourcePos, spawningHull: otherHull);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ReduceOxygen(float deltaTime)
|
||||
{
|
||||
hull.Oxygen -= size.X * deltaTime * OxygenConsumption;
|
||||
@@ -282,16 +355,6 @@ namespace Barotrauma
|
||||
|
||||
partial void UpdateProjSpecific(float growModifier, float deltaTime);
|
||||
|
||||
private void OnChangeHull(Vector2 pos, Hull particleHull)
|
||||
{
|
||||
if (particleHull == hull || particleHull == null) return;
|
||||
|
||||
//hull already has a firesource roughly at the particles position -> don't create a new one
|
||||
if (particleHull.FireSources.Find(fs => pos.X > fs.position.X - 100.0f && pos.X < fs.position.X + fs.size.X + 100.0f) != null) return;
|
||||
|
||||
new FireSource(new Vector2(pos.X, particleHull.WorldRect.Y - particleHull.Rect.Height + 5.0f));
|
||||
}
|
||||
|
||||
private void DamageCharacters(float deltaTime)
|
||||
{
|
||||
if (size.X <= 0.0f) { return; }
|
||||
@@ -304,7 +367,7 @@ namespace Barotrauma
|
||||
if (!IsInDamageRange(c, DamageRange)) { continue; }
|
||||
|
||||
//GetApproximateDistance returns float.MaxValue if there's no path through open gaps between the hulls (e.g. if there's a door/wall in between)
|
||||
if (hull.GetApproximateDistance(Position, c.Position, c.CurrentHull, 10000.0f) > size.X + DamageRange)
|
||||
if (hull.GetApproximateDistance(Position, c.Position, c.CurrentHull, 10000.0f) > size.X + DamageRange + FlameHeight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -330,16 +393,16 @@ namespace Barotrauma
|
||||
|
||||
public bool IsInDamageRange(Character c, float damageRange)
|
||||
{
|
||||
if (c.Position.X < position.X - damageRange || c.Position.X > position.X + size.X + damageRange) return false;
|
||||
if (c.Position.Y < position.Y - size.Y || c.Position.Y > hull.Rect.Y) return false;
|
||||
if (c.Position.X < position.X - damageRange || c.Position.X > position.X + size.X + damageRange) { return false; }
|
||||
if (c.Position.Y < position.Y - size.Y || c.Position.Y > Math.Max(hull.Rect.Y, position.Y + FlameHeight)) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsInDamageRange(Vector2 worldPosition, float damageRange)
|
||||
{
|
||||
if (worldPosition.X < WorldPosition.X - damageRange || worldPosition.X > WorldPosition.X + size.X + damageRange) return false;
|
||||
if (worldPosition.Y < WorldPosition.Y - size.Y || worldPosition.Y > hull.WorldRect.Y) return false;
|
||||
if (worldPosition.X < WorldPosition.X - damageRange || worldPosition.X > WorldPosition.X + size.X + damageRange) { return false; }
|
||||
if (worldPosition.Y < WorldPosition.Y - size.Y || worldPosition.Y > Math.Max(hull.WorldRect.Y, WorldPosition.Y + FlameHeight)) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2283,9 +2283,14 @@ namespace Barotrauma
|
||||
//(otherwise e.g. a character with 1000 vitality would only get a tenth of the strength)
|
||||
float afflictionStrength = affliction.Strength * (newCharacter.MaxVitality / 100.0f);
|
||||
|
||||
Limb afflictionLimb = character.CharacterHealth.GetAfflictionLimb(affliction) ?? character.AnimController.MainLimb;
|
||||
Limb newAfflictionLimb = newCharacter.AnimController.GetLimb(afflictionLimb.type) ?? newCharacter.AnimController.MainLimb;
|
||||
|
||||
Limb newAfflictionLimb = newCharacter.AnimController.MainLimb;
|
||||
//if the character has been already removed (some weird statuseffect setup, one effect removes the character before another tries to replace it with something else?)
|
||||
//we can't find the limbs any more and need go with the main limb
|
||||
if (!character.Removed)
|
||||
{
|
||||
Limb afflictionLimb = character.CharacterHealth.GetAfflictionLimb(affliction) ?? character.AnimController.MainLimb;
|
||||
newAfflictionLimb = newCharacter.AnimController.GetLimb(afflictionLimb.type) ?? newCharacter.AnimController.MainLimb;
|
||||
}
|
||||
newCharacter.CharacterHealth.ApplyAffliction(newAfflictionLimb, affliction.Prefab.Instantiate(afflictionStrength));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user