(6f4bea467) Updated doors

This commit is contained in:
Joonas Rikkonen
2019-05-03 13:43:47 +03:00
parent aef95740d3
commit fb21005258
84 changed files with 1514 additions and 1136 deletions
@@ -12,6 +12,7 @@
<Item file="Content/Items/Jobgear/Assistant/assistant_gear.xml" />
<Item file="Content/Items/Jobgear/Watchman/watchman_gear.xml" />
<Item file="Content/Items/Jobgear/Security/securityofficer_gear.xml" />
<Item file="Content/Items/Jobgear/Clown/clown.xml" />
<Item file="Content/Items/Jobgear/misc.xml" />
<Item file="Content/Items/CreatureLoot/creatureloot.xml" />
<Item file="Content/Items/Diving/divinggear.xml" />
@@ -73,14 +74,11 @@
<Character file="Content/Characters/Hammerhead/Hammerhead.xml" />
<Outpost file="Content/Map/Outposts/Outpost.sub" />
<Submarine file="Submarines/Orca.sub" />
<Submarine file="Submarines/Berilia.sub" />
<Submarine file="Submarines/Typhon.sub" />
<Submarine file="Submarines/Selkie.sub" />
<Submarine file="Submarines/Bunyip.sub" />
<Submarine file="Submarines/Humpback.sub" />
<Submarine file="Submarines/Dugong.sub" />
<Submarine file="Submarines/Remora.sub" />
<Submarine file="Submarines/RemoraDrone.sub" />
<Submarine file="Submarines/Venture.sub" />
<Text file="Content/Texts/EnglishVanilla.xml" />
<UIStyle file="Content/UI/style.xml"/>
@@ -364,10 +364,16 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Assemblies\airlock doors.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Assemblies\AutoDoor.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Assemblies\AutoHatch.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Assemblies\Automatic Bilge Pump.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Command\NavUI.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Assemblies\WindowedAutoDoor.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Door\door2.png">
@@ -382,6 +388,18 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Assistant\assistant_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Clown\clown_legs_female.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Clown\clown_legs_male.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Clown\clown_torso_female.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Clown\clown_torso_male.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -412,6 +430,12 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_torso_male_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Clown\clown.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Old\clownshirt.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -466,33 +490,6 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Map\OutpostWall_C.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\1_CommandReactor\BaroTutorial_CommandReactor.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\2_NavConsole\BaroTutorial_NavConsole.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\3_Flood\BaroTutorial_Flood.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\4_Reactor\BaroTutorial_Reactor.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\5_EnemyOnSonar\BaroTutorial_EnemyOnSonar.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\6_Degrading2\BaroTutorial_Degrading.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\7_Medical\BaroTutorial_Medical.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\BaroTutorial_Approach.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\9_SwitchCharacter\BaroTutorial_SwitchCharacter.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\TutorialVideos\tutorial_command.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1210,6 +1207,9 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Lights\pointlight_falloff.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Lights\light_fluorescent_L2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Map\AlienBackground1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1701,15 +1701,6 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Captain\captain_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\clownmask.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\clownpants.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\clownshirt.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Medic\medic_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2175,15 +2166,19 @@
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Impact\SoftImpact3.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Berilia.sub">
<None Include="$(MSBuildThisFileDirectory)Content\Tutorials\Dugong_Tutorial.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Tutorials\TutorialOutpost.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Berilia.sub">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Dugong_Tutorial.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\TutorialOutpost.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\TutorialOutpost.sub" />
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)Content\Characters\Carrier\CARRIER_alarmLoop.ogg">
@@ -3138,9 +3133,6 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Water\SplashLoop.ogg" />
<None Include="$(MSBuildThisFileDirectory)Content\Tutorials\TutorialSub.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Ambient\Ambient1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -3337,10 +3329,10 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Remora.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\RemoraDrone.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Selkie.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -320,8 +320,9 @@ namespace Barotrauma
{
State = AIState.Idle;
}
else if (Character.Health < fleeHealthThreshold)
else if (Character.Health < fleeHealthThreshold && SwarmBehavior == null)
{
// Don't flee from damage if in a swarm.
State = AIState.Escape;
}
else if (targetingPriority != null)
@@ -330,8 +331,6 @@ namespace Barotrauma
}
}
LatchOntoAI?.Update(this, deltaTime);
if (SelectedAiTarget != null && (SelectedAiTarget.Entity == null || SelectedAiTarget.Entity.Removed))
{
State = AIState.Idle;
@@ -369,8 +368,15 @@ namespace Barotrauma
default:
throw new NotImplementedException();
}
SwarmBehavior?.Update(deltaTime);
LatchOntoAI?.Update(this, deltaTime);
IsSteeringThroughGap = false;
if (SwarmBehavior != null)
{
SwarmBehavior.IsActive = State == AIState.Idle && Character.CurrentHull == null;
SwarmBehavior.Refresh();
SwarmBehavior.UpdateSteering(deltaTime);
}
steeringManager.Update(Character.AnimController.GetCurrentSpeed(run));
}
@@ -493,7 +499,7 @@ namespace Barotrauma
}
else
{
if (!IsProperlyLatchedOnSub)
if (!IsLatchedOnSub)
{
UpdateWallTarget();
}
@@ -552,7 +558,7 @@ namespace Barotrauma
{
WallSection section = wallTarget.Structure.GetSection(wallTarget.SectionIndex);
Vector2 targetPos = wallTarget.Structure.SectionPosition(wallTarget.SectionIndex, true);
if (section?.gap != null && section.gap.IsRoomToRoom && SteerThroughGap(wallTarget.Structure, section, targetPos, deltaTime))
if (section?.gap != null && SteerThroughGap(wallTarget.Structure, section, targetPos, deltaTime))
{
return;
}
@@ -794,9 +800,21 @@ namespace Barotrauma
return false;
}
public bool IsSteeringThroughGap { get; private set; }
private bool SteerThroughGap(Structure wall, WallSection section, Vector2 targetWorldPos, float deltaTime)
{
IsSteeringThroughGap = true;
SelectedAiTarget = wall.AiTarget;
wallTarget = null;
LatchOntoAI?.DeattachFromBody();
Character.AnimController.ReleaseStuckLimbs();
Hull targetHull = section.gap?.FlowTargetHull;
float distance = Vector2.Distance(Character.WorldPosition, targetWorldPos);
float maxDistance = Math.Min(wall.Rect.Width, wall.Rect.Height);
if (distance > maxDistance)
{
return false;
}
if (targetHull != null)
{
if (wall.IsHorizontal)
@@ -807,16 +825,7 @@ namespace Barotrauma
{
targetWorldPos.X = targetHull.WorldRect.Center.X;
}
LatchOntoAI?.DeattachFromBody();
Character.AnimController.ReleaseStuckLimbs();
if (steeringManager is IndoorsSteeringManager)
{
steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetWorldPos - Character.WorldPosition));
}
else
{
steeringManager.SteeringSeek(ConvertUnits.ToSimUnits(targetWorldPos));
}
steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetWorldPos - Character.WorldPosition));
return true;
}
return false;
@@ -1048,43 +1057,43 @@ namespace Barotrauma
#region Targeting
private bool IsLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
//goes through all the AItargets, evaluates how preferable it is to attack the target,
//whether the Character can see/hear the target and chooses the most preferable target within
//sight/hearing range
public AITarget UpdateTargets(Character character, out TargetingPriority priority)
{
if (IsProperlyLatchedOnSub)
if ((SelectedAiTarget != null || wallTarget != null) && IsLatchedOnSub)
{
// If attached to a valid target, just keep the target.
// Priority not used in this case.
priority = null;
return SelectedAiTarget;
var wall = SelectedAiTarget.Entity as Structure;
if (wall == null)
{
wall = wallTarget?.Structure;
}
// The target is not a wall or it's not the same as we are attached to -> release
bool releaseTarget = wall == null || !wall.Bodies.Contains(LatchOntoAI.AttachJoints[0].BodyB);
if (!releaseTarget)
{
for (int i = 0; i < wall.Sections.Length; i++)
{
if (CanPassThroughHole(wall, i))
{
releaseTarget = true;
}
}
}
if (releaseTarget)
{
SelectedAiTarget = null;
wallTarget = null;
LatchOntoAI.DeattachFromBody();
}
else if (SelectedAiTarget?.Entity == wallTarget?.Structure)
{
// If attached to a valid target, just keep the target.
// Priority not used in this case.
priority = null;
return SelectedAiTarget;
}
}
AITarget newTarget = null;
priority = null;
@@ -1167,7 +1176,7 @@ namespace Barotrauma
else if (target.Entity != null)
{
//skip the target if it's a room and the character is already inside a sub
if (character.CurrentHull != null && target.Entity is Hull) continue;
if (character.CurrentHull != null && target.Entity is Hull) { continue; }
Door door = null;
if (target.Entity is Item item)
@@ -1196,23 +1205,37 @@ namespace Barotrauma
// Ignore structures that doesn't have a body (not walls)
continue;
}
// Ignore walls when inside.
valueModifier = character.CurrentHull == null ? 1 : 0;
if (s.IsPlatform)
{
continue;
}
if (character.CurrentHull != null)
{
// Ignore walls when inside.
continue;
}
valueModifier = 1;
float wallMaxHealth = 400; // Anything more than this is ignored -> 200 = 1
// Prefer weaker targets.
valueModifier *= MathHelper.Lerp(1.5f, 0.5f, MathUtils.InverseLerp(0, 1, s.Health / wallMaxHealth));
if (aggressiveBoarding)
{
var hulls = s.Submarine.GetHulls(false);
for (int i = 0; i < s.Sections.Length; i++)
{
var section = s.Sections[i];
if (CanPassThroughHole(s, i))
if (section.gap != null)
{
// Ignore walls that can be passed through
valueModifier = 0;
break;
}
else if (section.gap != null)
{
// up to 100% priority increase for every gap in the wall
valueModifier *= 1 + section.gap.Open;
if (CanPassThroughHole(s, i))
{
bool leadsInside = !section.gap.IsRoomToRoom && section.gap.FlowTargetHull != null && hulls.Any(h => h.Rect.Intersects(section.rect));
valueModifier *= leadsInside ? 5 : 0;
}
else
{
// up to 100% priority increase for every gap in the wall
valueModifier *= 1 + section.gap.Open;
}
}
}
}
@@ -223,8 +223,10 @@ namespace Barotrauma
}
}
bool isDiving = character.AnimController.InWater && character.AnimController.HeadInWater;
//only humanoids can climb ladders
if (character.AnimController is HumanoidAnimController && IsNextLadderSameAsCurrent)
if (!isDiving && character.AnimController is HumanoidAnimController && IsNextLadderSameAsCurrent)
{
if (character.SelectedConstruction != currentPath.CurrentNode.Ladders.Item &&
currentPath.CurrentNode.Ladders.Item.IsInsideTrigger(character.WorldPosition))
@@ -234,7 +236,7 @@ namespace Barotrauma
}
var collider = character.AnimController.Collider;
if (character.IsClimbing)
if (character.IsClimbing && !isDiving)
{
Vector2 diff = currentPath.CurrentNode.SimPosition - pos;
bool nextLadderSameAsCurrent = IsNextLadderSameAsCurrent;
@@ -278,6 +280,12 @@ namespace Barotrauma
}
else if (character.AnimController.InWater)
{
// If the character is underwater, we don't need the ladders anymore
if (character.IsClimbing && isDiving)
{
character.AnimController.Anim = AnimController.Animation.None;
character.SelectedConstruction = null;
}
if (Vector2.DistanceSquared(pos, currentPath.CurrentNode.SimPosition) < MathUtils.Pow(collider.radius * 3, 2))
{
currentPath.SkipToNextNode();
@@ -54,7 +54,7 @@ namespace Barotrauma
get { return attachJoints.Count > 0; }
}
public bool IsAttachedToSub => IsAttached && attachTargetBody?.UserData is Entity entity && (entity is Submarine sub || entity?.Submarine != null);
public bool IsAttachedToSub => IsAttached && (attachTargetBody?.UserData is Submarine || attachTargetBody?.UserData is Entity entity && entity.Submarine != null);
public LatchOntoAI(XElement element, EnemyAIController enemyAI)
{
@@ -190,7 +190,7 @@ namespace Barotrauma
case AIController.AIState.Attack:
if (enemyAI.AttackingLimb != null)
{
if (attachToSub && wallAttachPos != Vector2.Zero && attachTargetBody != null)
if (attachToSub && !enemyAI.IsSteeringThroughGap && wallAttachPos != Vector2.Zero && attachTargetBody != null)
{
// is not attached or is attached to something else
if (!IsAttached || IsAttached && attachJoints[0].BodyB == attachTargetBody)
@@ -14,11 +14,16 @@ namespace Barotrauma
private float maxDistFromCenter;
private float cohesion;
private List<AICharacter> members = new List<AICharacter>();
public List<AICharacter> Members { get; private set; } = new List<AICharacter>();
public HashSet<AICharacter> ActiveMembers { get; private set; } = new HashSet<AICharacter>();
private AIController ai;
private EnemyAIController ai;
public SwarmBehavior(XElement element, AIController ai)
public bool IsActive { get; set; }
public bool IsEnoughMembers => ActiveMembers.Count > 1;
public SwarmBehavior(XElement element, EnemyAIController ai)
{
this.ai = ai;
minDistFromClosest = ConvertUnits.ToSimUnits(element.GetAttributeFloat("mindistfromclosest", 10.0f));
@@ -32,21 +37,36 @@ namespace Barotrauma
{
if (character.AIController is EnemyAIController enemyAI && enemyAI.SwarmBehavior != null)
{
enemyAI.SwarmBehavior.members = swarm.ToList();
enemyAI.SwarmBehavior.Members = swarm.ToList();
}
}
}
public void Update(float deltaTime)
public void Refresh()
{
members.RemoveAll(m => m.IsDead || m.Removed);
if (members.Count < 2) { return; }
Members.RemoveAll(m => m.IsDead || m.Removed);
foreach (var member in Members)
{
if (!member.AIController.Enabled && member.IsRemotePlayer || Character.Controlled == member || !((EnemyAIController)member.AIController).SwarmBehavior.IsActive)
{
ActiveMembers.Remove(member);
}
else
{
ActiveMembers.Add(member);
}
}
}
public void UpdateSteering(float deltaTime)
{
if (!IsActive) { return; }
if (!IsEnoughMembers) { return; }
//calculate the "center of mass" of the swarm and the distance to the closest character in the swarm
float closestDistSqr = float.MaxValue;
Vector2 center = Vector2.Zero;
AICharacter closest = null;
foreach (AICharacter member in members)
foreach (AICharacter member in Members)
{
center += member.SimPosition;
if (member == ai.Character) { continue; }
@@ -57,7 +77,7 @@ namespace Barotrauma
closest = member;
}
}
center /= members.Count;
center /= Members.Count;
if (closest == null) { return; }
@@ -83,11 +103,11 @@ namespace Barotrauma
if (cohesion > 0.0f)
{
Vector2 avgVel = Vector2.Zero;
foreach (AICharacter member in members)
foreach (AICharacter member in Members)
{
avgVel += member.AnimController.TargetMovement;
}
avgVel /= members.Count;
avgVel /= Members.Count;
ai.SteeringManager.SteeringManual(deltaTime, avgVel * cohesion);
}
}
@@ -293,6 +293,27 @@ namespace Barotrauma
return;
}
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
{
//stop dragging if there's something between the pull limb and the target
Vector2 sourceSimPos = mouthLimb.SimPosition;
Vector2 targetSimPos = target.SimPosition;
if (character.Submarine != null && character.SelectedCharacter.Submarine == null)
{
targetSimPos -= character.Submarine.SimPosition;
}
else if (character.Submarine == null && character.SelectedCharacter.Submarine != null)
{
sourceSimPos -= character.SelectedCharacter.Submarine.SimPosition;
}
var body = Submarine.CheckVisibility(sourceSimPos, targetSimPos, ignoreSubs: true);
if (body != null)
{
character.DeselectCharacter();
return;
}
}
Character targetCharacter = target;
float eatSpeed = character.Mass / targetCharacter.Mass * 0.1f;
eatTimer += deltaTime * eatSpeed;
@@ -712,6 +733,12 @@ namespace Barotrauma
limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength, maxVelocity: 10.0f);
}
while (referenceLimb.Rotation - angle < -MathHelper.TwoPi)
{
angle -= MathHelper.TwoPi;
}
limb?.body.SmoothRotate(angle, torque, wrapAngle: false);
}
private void SmoothRotateWithoutWrapping(Limb limb, float angle, Limb referenceLimb, float torque)
@@ -560,7 +560,8 @@ namespace Barotrauma
//TODO: take into account that the feet aren't necessarily in CurrentHull
//full slowdown (1.5f) when water is up to the torso
surfaceY = ConvertUnits.ToSimUnits(currentHull.Surface);
slowdownAmount = MathHelper.Clamp((surfaceY - colliderPos.Y) / TorsoPosition.Value, 0.0f, 1.0f) * 1.5f;
float bottomPos = Math.Max(colliderPos.Y, currentHull.Rect.Y - currentHull.Rect.Height);
slowdownAmount = MathHelper.Clamp((surfaceY - bottomPos) / TorsoPosition.Value, 0.0f, 1.0f) * 1.5f;
}
float maxSpeed = Math.Max(TargetMovement.Length() - slowdownAmount, 1.0f);
@@ -853,7 +853,7 @@ namespace Barotrauma
{
if (characterConfigFiles == null)
{
characterConfigFiles = GameMain.Instance.GetFilesOfType(ContentType.Character);
characterConfigFiles = GameMain.Instance.GetFilesOfType(ContentType.Character, searchAllContentPackages: true);
}
return characterConfigFiles;
}
@@ -2551,64 +2551,14 @@ namespace Barotrauma
if (info != null) { info.Remove(); }
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
CharacterList.Remove(this);
if (Controlled == this) { Controlled = null; }
if (Inventory != null)
{
foreach (Item item in Inventory.Items)
@@ -217,6 +217,7 @@ namespace Barotrauma
{
return corePackageRequiredFiles.All(fileType => Files.Any(file => file.Type == fileType));
}
public bool ContainsRequiredCorePackageFiles(out List<ContentType> missingContentTypes)
{
missingContentTypes = new List<ContentType>();
@@ -230,6 +231,25 @@ namespace Barotrauma
return missingContentTypes.Count == 0;
}
/// <summary>
/// Make sure all the files defined in the content package are present
/// </summary>
/// <returns></returns>
public bool VerifyFiles(out List<string> errorMessages)
{
errorMessages = new List<string>();
foreach (ContentFile file in Files)
{
if (!File.Exists(file.Path))
{
errorMessages.Add("File \"" + file.Path + "\" not found.");
continue;
}
}
return errorMessages.Count == 0;
}
public static ContentPackage CreatePackage(string name, string path, bool corePackage)
{
ContentPackage newPackage = new ContentPackage()
@@ -398,6 +418,13 @@ namespace Barotrauma
return path == "Mods";
}
}
/// <summary>
/// Are mods allowed to install a file into the specified path. If a content package XML includes files
/// with a prohibited path, they are treated as references to external files. For example, a mod could include
/// some vanilla files in the XML, in which case the game will simply use the vanilla files present in the game folder.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static bool IsModFilePathAllowed(string path)
{
while (true)
@@ -422,16 +449,6 @@ namespace Barotrauma
return contentPackages.SelectMany(f => f.Files).Where(f => f.Type == type).Select(f => f.Path);
}
public IEnumerable<string> GetFilesOfType(ContentType type)
{
return Files.Where(f => f.Type == type).Select(f => f.Path);
}
public static IEnumerable<string> GetFilesOfType(IEnumerable<ContentPackage> contentPackages, ContentType type)
{
return contentPackages.SelectMany(f => f.Files).Where(f => f.Type == type).Select(f => f.Path);
}
public IEnumerable<string> GetFilesOfType(ContentType type)
{
return Files.Where(f => f.Type == type).Select(f => f.Path);
@@ -34,14 +34,33 @@ namespace Barotrauma
{
Level.Loaded.TryGetInterestingPosition(true, Level.PositionType.MainPath, Level.Loaded.Size.X * 0.3f, out Vector2 spawnPos);
bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
//bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
//for (int i = 0; i < monsterCount; i++)
//{
// monsters.Add(Character.Create(monsterFile, spawnPos, ToolBox.RandomSeed(8), null, isClient, true, false));
//}
//monsters.ForEach(m => m.Enabled = false);
//SwarmBehavior.CreateSwarm(monsters.Cast<AICharacter>());
//sonarPositions.Add(spawnPos);
float offsetAmount = 500;
for (int i = 0; i < monsterCount; i++)
{
monsters.Add(Character.Create(monsterFile, spawnPos, ToolBox.RandomSeed(8), null, isClient, true, false));
CoroutineManager.InvokeAfter(() =>
{
bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
var monster = Character.Create(monsterFile, spawnPos + Rand.Vector(offsetAmount, Rand.RandSync.Server), i.ToString(), null, isClient, true, true);
monster.Enabled = false;
monsters.Add(monster);
if (monsters.Count == monsterCount)
{
//this will do nothing if the monsters have no swarm behavior defined,
//otherwise it'll make the spawned characters act as a swarm
SwarmBehavior.CreateSwarm(monsters.Cast<AICharacter>());
sonarPositions.Add(spawnPos);
}
}, Rand.Range(0f, monsterCount / 2, Rand.RandSync.Server));
}
monsters.ForEach(m => m.Enabled = false);
SwarmBehavior.CreateSwarm(monsters.Cast<AICharacter>());
sonarPositions.Add(spawnPos);
}
public override void Update(float deltaTime)
@@ -604,13 +604,14 @@ namespace Barotrauma
}
foreach (ContentPackage contentPackage in SelectedContentPackages)
{
bool packageOk = contentPackage.VerifyFiles(out List<string> errorMessages);
if (!packageOk)
{
DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\":\n" + string.Join("\n", errorMessages));
continue;
}
foreach (ContentFile file in contentPackage.Files)
{
if (!System.IO.File.Exists(file.Path))
{
DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\" - file \"" + file.Path + "\" not found.");
continue;
}
ToolBox.IsProperFilenameCase(file.Path);
}
}
@@ -970,13 +971,14 @@ namespace Barotrauma
foreach (ContentPackage contentPackage in SelectedContentPackages)
{
bool packageOk = contentPackage.VerifyFiles(out List<string> errorMessages);
if (!packageOk)
{
DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\":\n" + string.Join("\n", errorMessages));
continue;
}
foreach (ContentFile file in contentPackage.Files)
{
if (!System.IO.File.Exists(file.Path))
{
DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\" - file \"" + file.Path + "\" not found.");
continue;
}
ToolBox.IsProperFilenameCase(file.Path);
}
}
@@ -293,10 +293,35 @@ namespace Barotrauma.Items.Components
//steer closer if almost in range
if (dist > Range)
{
Vector2 standPos = leak.IsHorizontal ? new Vector2(Math.Sign(-fromItemToLeak.X), 0.0f) : new Vector2(0.0f, Math.Sign(-fromItemToLeak.Y) * 0.5f);
standPos = leak.WorldPosition + standPos * Range;
Vector2 dir = Vector2.Normalize(standPos - character.WorldPosition);
character.AIController.SteeringManager.SteeringManual(deltaTime, dir / 2);
Vector2 standPos = new Vector2(Math.Sign(-fromItemToLeak.X), Math.Sign(-fromItemToLeak.Y)) / 2;
if (!character.AnimController.InWater)
{
if (leak.IsHorizontal)
{
standPos.X *= 2;
standPos.Y = 0;
}
else
{
standPos.X = 0;
}
}
if (character.AIController.SteeringManager is IndoorsSteeringManager indoorSteering)
{
if (indoorSteering.CurrentPath != null && !indoorSteering.IsPathDirty && indoorSteering.CurrentPath.Unreachable)
{
Vector2 dir = Vector2.Normalize(standPos - character.WorldPosition);
character.AIController.SteeringManager.SteeringManual(deltaTime, dir / 2);
}
else
{
character.AIController.SteeringManager.SteeringSeek(standPos);
}
}
else
{
character.AIController.SteeringManager.SteeringSeek(standPos);
}
}
else
{
@@ -305,30 +330,29 @@ namespace Barotrauma.Items.Components
// Too close -> steer away
character.AIController.SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(character.SimPosition - leak.SimPosition) / 2);
}
else
else if (dist <= Range)
{
// In range
character.AIController.SteeringManager.Reset();
}
else
{
return false;
}
}
sinTime += deltaTime;
character.CursorPosition = leak.Position + VectorExtensions.Forward(Item.body.TransformedRotation + (float)Math.Sin(sinTime), dist);
if (item.RequireAimToUse)
{
character.SetInput(InputType.Aim, false, true);
}
// Press the trigger only when the tool is approximately facing the target.
// If the character is climbing, ignore the check, because we cannot aim while climbing.
if (VectorExtensions.Angle(VectorExtensions.Forward(item.body.TransformedRotation), fromItemToLeak) < MathHelper.PiOver4)
var angle = VectorExtensions.Angle(VectorExtensions.Forward(item.body.TransformedRotation), fromItemToLeak);
if (angle < MathHelper.PiOver4)
{
character.SetInput(InputType.Shoot, false, true);
Use(deltaTime, character);
}
else
{
sinTime -= deltaTime * 2;
}
bool leakFixed = (leak.Open <= 0.0f || leak.Removed) &&
(leak.ConnectedWall == null || leak.ConnectedWall.Sections.Average(s => s.damage) < 1);
@@ -47,9 +47,8 @@ namespace Barotrauma.Items.Components
//was the last ping sent with directional pinging
private bool isLastPingDirectional;
private Sprite pingCircle, directionalPingCircle, screenOverlay, screenBackground;
private Sprite sonarBlip;
private Sprite lineSprite;
private readonly Sprite pingCircle, directionalPingCircle, screenOverlay, screenBackground;
private readonly Sprite sonarBlip;
private bool aiPingCheckPending;
@@ -87,16 +86,6 @@ namespace Barotrauma.Items.Components
get { return zoom; }
}
//TODO: remove, only for testing
#if DEBUG
[Serialize(false, false), Editable]
public bool DynamicDockingIndicator
{
get;
set;
}
#endif
public override bool IsActive
{
get
@@ -122,7 +111,29 @@ namespace Barotrauma.Items.Components
: base(item, element)
{
connectedTransducers = new List<ConnectedTransducer>();
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "pingcircle":
pingCircle = new Sprite(subElement);
break;
case "directionalpingcircle":
directionalPingCircle = new Sprite(subElement);
break;
case "screenoverlay":
screenOverlay = new Sprite(subElement);
break;
case "screenbackground":
screenBackground = new Sprite(subElement);
break;
case "blip":
sonarBlip = new Sprite(subElement);
break;
}
}
IsActive = false;
InitProjSpecific(element);
}
@@ -194,7 +205,6 @@ namespace Barotrauma.Items.Components
directionalPingCircle?.Remove();
screenOverlay?.Remove();
screenBackground?.Remove();
lineSprite?.Remove();
}
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
@@ -249,24 +259,15 @@ namespace Barotrauma.Items.Components
int clockDir = (int)Math.Round((angle / MathHelper.TwoPi) * 12);
if (clockDir == 0) clockDir = 12;
return TextManager.Get("SubDirOClock").Replace("[dir]", clockDir.ToString());
return TextManager.Get("roomname.subdiroclock").Replace("[dir]", clockDir.ToString());
}
private Vector2 GetTransducerPos()
private Vector2 GetTransducerCenter()
{
if (!UseTransducers || connectedTransducers.Count == 0)
{
//use the position of the sub if the item is static (no body) and inside a sub
return item.Submarine != null && item.body == null ? item.Submarine.WorldPosition : item.WorldPosition;
}
if (!UseTransducers || connectedTransducers.Count == 0) return Vector2.Zero;
Vector2 transducerPosSum = Vector2.Zero;
foreach (ConnectedTransducer transducer in connectedTransducers)
{
if (transducer.Transducer.Item.Submarine != null)
{
return transducer.Transducer.Item.Submarine.WorldPosition;
}
transducerPosSum += transducer.Transducer.Item.WorldPosition;
}
return transducerPosSum / connectedTransducers.Count;
@@ -172,6 +172,19 @@ namespace Barotrauma.Items.Components
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void Update(float deltaTime, Camera cam)
{
networkUpdateTimer -= deltaTime;
@@ -474,9 +487,7 @@ namespace Barotrauma.Items.Components
if (!posToMaintain.HasValue)
{
unsentChanges = true;
posToMaintain = controlledSub != null ?
controlledSub.WorldPosition :
item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition;
posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition;
}
if (!AutoPilot || !MaintainPos) unsentChanges = true;
@@ -1149,6 +1149,10 @@ namespace Barotrauma
{
body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation);
}
else if (Submarine != null && prevSub != null && Submarine != prevSub)
{
body.SetTransform(body.SimPosition + prevSub.SimPosition - Submarine.SimPosition, body.Rotation);
}
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
@@ -1265,7 +1269,7 @@ namespace Barotrauma
if (recursive)
{
HashSet<Connection> alreadySearched = new HashSet<Connection>();
List<Item> alreadySearched = new List<Item>() { this };
GetConnectedComponentsRecursive(alreadySearched, connectedComponents);
return connectedComponents;
@@ -1287,7 +1291,7 @@ namespace Barotrauma
return connectedComponents;
}
private void GetConnectedComponentsRecursive<T>(HashSet<Connection> alreadySearched, List<T> connectedComponents) where T : ItemComponent
private void GetConnectedComponentsRecursive<T>(List<Item> alreadySearched, List<T> connectedComponents) where T : ItemComponent
{
ConnectionPanel connectionPanel = GetComponent<ConnectionPanel>();
if (connectionPanel == null) { return; }
@@ -1332,14 +1336,28 @@ namespace Barotrauma
new Pair<string, string>("signal_in2", "signal_out")
};
private void GetConnectedComponentsRecursive<T>(Connection c, HashSet<Connection> alreadySearched, List<T> connectedComponents) where T : ItemComponent
recipient.Item.GetConnectedComponentsRecursive<T>(alreadySearched, connectedComponents);
}
}
}
public List<T> GetConnectedComponentsRecursive<T>(Connection c) where T : ItemComponent
{
alreadySearched.Add(c);
List<T> connectedComponents = new List<T>();
List<Item> alreadySearched = new List<Item>() { this };
GetConnectedComponentsRecursive(c, alreadySearched, connectedComponents);
return connectedComponents;
}
private void GetConnectedComponentsRecursive<T>(Connection c, List<Item> alreadySearched, List<T> connectedComponents) where T : ItemComponent
{
alreadySearched.Add(this);
var recipients = c.Recipients;
foreach (Connection recipient in recipients)
{
if (alreadySearched.Contains(recipient)) { continue; }
if (alreadySearched.Contains(recipient.Item)) continue;
var component = recipient.Item.GetComponent<T>();
if (component != null)
@@ -1348,29 +1366,7 @@ namespace Barotrauma
}
recipient.Item.GetConnectedComponentsRecursive(recipient, alreadySearched, connectedComponents);
}
foreach (Pair<string, string> connectionPair in connectionPairs)
{
if (connectionPair.First == c.Name)
{
var pairedConnection = c.Item.Connections.FirstOrDefault(c2 => c2.Name == connectionPair.Second);
if (pairedConnection != null)
{
if (alreadySearched.Contains(pairedConnection)) { continue; }
GetConnectedComponentsRecursive(pairedConnection, alreadySearched, connectedComponents);
}
}
else if (connectionPair.Second == c.Name)
{
var pairedConnection = c.Item.Connections.FirstOrDefault(c2 => c2.Name == connectionPair.First);
if (pairedConnection != null)
{
if (alreadySearched.Contains(pairedConnection)) { continue; }
GetConnectedComponentsRecursive(pairedConnection, alreadySearched, connectedComponents);
}
}
}
}
}
@@ -635,24 +635,6 @@ namespace Barotrauma
var character = ((Limb)f2.Body.UserData).character;
if (character.DisableImpactDamageTimer > 0.0f || ((Limb)f2.Body.UserData).Mass < 100.0f) return true;
}
if (!Prefab.Platform && Prefab.StairDirection == Direction.None)
{
Vector2 pos = ConvertUnits.ToDisplayUnits(f2.Body.Position);
int section = FindSectionIndex(pos);
if (section > -1)
{
Vector2 normal = contact.Manifold.LocalNormal;
float impact = Vector2.Dot(f2.Body.LinearVelocity, -normal) * f2.Body.Mass * 0.1f;
if (impact < 10.0f) return true;
#if CLIENT
SoundPlayer.PlayDamageSound("StructureBlunt", impact, SectionPosition(section, true), tags: Tags);
#endif
AddDamage(section, impact);
}
}
OnImpactProjSpecific(f1, f2, contact);
@@ -432,7 +432,7 @@ namespace Barotrauma
{
//prevent picking up (or deattaching) items
#if CLIENT
if (GameMain.GameSession.GameMode is TutorialMode)
if (GameMain.GameSession?.GameMode is TutorialMode)
{
continue;
}
@@ -468,7 +468,7 @@ namespace Barotrauma
var gaps = newHull?.ConnectedGaps ?? Gap.GapList.Where(g => g.Submarine == submarine);
targetPos = character.WorldPosition;
Gap adjacentGap = Gap.FindAdjacent(gaps, targetPos, 200.0f);
Gap adjacentGap = Gap.FindAdjacent(gaps, targetPos, 500.0f);
if (adjacentGap == null) return true;
if (newHull != null)
@@ -102,7 +102,7 @@ namespace Barotrauma
{
string errorMsg = "Attempted to add a null item to entity spawn queue.\n" + Environment.StackTrace;
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue1:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return;
}
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, condition));
@@ -115,7 +115,7 @@ namespace Barotrauma
{
string errorMsg = "Attempted to add a null item to entity spawn queue.\n" + Environment.StackTrace;
DebugConsole.ThrowError(errorMsg);
GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue2:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return;
}
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, condition));
@@ -401,7 +401,7 @@ namespace Barotrauma.Networking
public bool AllowRagdollButton
{
get;
private set;
set;
}
[Serialize(true, true)]
@@ -795,18 +795,6 @@ namespace Barotrauma
return new Vector2((float)x, (float)y);
}
/// <summary>
/// Rotates a point in 2d space around the origin
/// </summary>
public static Vector2 RotatePoint(Vector2 point, float radians)
{
var sin = Math.Sin(radians);
var cos = Math.Cos(radians);
var x = (cos * point.X) - (sin * point.Y);
var y = (sin * point.X) + (cos * point.Y);
return new Vector2((float)x, (float)y);
}
/// <summary>
/// Returns the corners of an imaginary rectangle.
/// Unlike the XNA rectangle, this can be rotated with the up parameter.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+59
View File
@@ -1,3 +1,62 @@
---------------------------------------------------------------------------------------------------------
v0.8.10.0
---------------------------------------------------------------------------------------------------------
Additions and changes:
- Completely remade tutorials (separate tutorial for each job).
- Added a door and hatch variants with integrated buttons.
- New outpost graphics.
- Added swarm behavior to crawlers.
- Added a new mission where you have to kill a swarm of crawlers.
- Numerous crew AI improvements.
- Balanced item deterioration values.
- Mineral sprites change when collected from the environment.
- Added an option to disable directional voice chat.
- Added automatic submarine repair option to the campaign.
- Added "all" tab to the entity list in the submarine editor.
- Hide the crew area, chat box and server buttons when operating a turret or searchlight.
- Doors can be repaired with a wrench.
- Some new lamp variants.
- Display a progress bar when welding doors shut.
- Items that don't give any materials when deconstructed cannot be deconstructed.
- Added a console command that resets selected items and structures to prefab values ("resetselected").
- Option to toggle structure drop shadows and edit the position of the shadow in the sub editor.
- Minor physics optimizations.
- Disable background music & ambience in the character editor.
- More pronounced limping animation when a character's legs are injured.
- The inventory slots next to the character portrait (ID card, uniform, etc) can be hidden.
- Some new sound effects and background music.
- All walls can be scaled in the submarine editor.
- Structure damage is visualized when using debugdraw.
- Improved font scaling on different resolutions.
- Added Steam overlay support to Workshop.
- Server list shows which servers have voice chat enabled.
- Show a message box notifying respawning traitors that they're no longer a traitor.
- Added a search bar to the store menu.
- Added search bars to sub lists in campaign setup UI and sub editor.
Bugfixes:
- Don't allow rewiring and deattaching an item at the same time (happened when interacting with an item
while holding both a screwdriver and a wrench).
- Fixed bots being unable to complete almost any task in the multiplayer due to a bug that caused
them to interpret the sub as another crew's submarine.
- When spawning multiple monsters at the same time, spread them around a bit to prevent the players
from getting attacked by a ball of overlapping crawlers.
- Fixed huge lag spikes when a character tries to escape from an enemy but can't find a path away from it.
- Fixed file transfer progress bars not being visible in the server lobby.
- Fixed crashing when attempting to start a mission round with mission type set to None.
- Fixed ElectricalDischarger electricity effect staying visible if the item breaks or the component
is deactivated from outside (e.g. via a StatusEffect or the parent component).
- Fixed specular maps being rendered on top of characters when outside the sub.
- Fixed excessively bright lights around sonar flora and lava vents.
- Fixes to item collider sizes.
- Fixed inability to scroll through long texts in the sub editor's textboxes.
- Fixed clients not being able to see other characters in spectator if they've died far away from the sub.
- Fixed non-latin characters not being displayed correctly in Workshop item texts.
- Don't prevent selecting items in the sub editor when the cursor is on a wire node, because it makes it
very difficult (or impossible) to select small items in the wiring mode.
- Fixed crashing when attempting to use the "spawnitem" command when a round is not running.
---------------------------------------------------------------------------------------------------------
v0.8.9.10
---------------------------------------------------------------------------------------------------------