(1da783d84) RepairTool fixes. Closes #1486 - Fixed Submarine.PickBodies only returning the closest body it hits (and the body the ray is inside, if any). - Welding tool raycasts can go through walls, but not fix other types of entities behind the walls. Now it's possible to weld multiple overlapping walls at the same time, but not doors/characters behind the wall. - Made the welding & plasma particles bigger to match the increased range of the tools better.
This commit is contained in:
@@ -615,7 +615,7 @@ namespace Barotrauma
|
||||
NewMessage(Hull.EditWater ? "Water editing on" : "Water editing off", Color.White);
|
||||
}, isCheat: true));
|
||||
|
||||
commands.Add(new Command("eventmanager", "eventmanager: Toggle event manager on/off. No new random events are created when the event manager is disabled.", (string[] args) =>
|
||||
commands.Add(new Command("fire|editfire", "fire/editfire: Allows putting up fires by left clicking.", (string[] args) =>
|
||||
{
|
||||
Hull.EditFire = !Hull.EditFire;
|
||||
NewMessage(Hull.EditFire ? "Fire spawning on" : "Fire spawning off", Color.White);
|
||||
|
||||
@@ -40,6 +40,9 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(false, false)]
|
||||
public bool RepairThroughWalls { get; set; }
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool RepairMultiple { get; set; }
|
||||
|
||||
public Vector2 TransformedBarrelPos
|
||||
{
|
||||
get
|
||||
@@ -158,12 +161,22 @@ namespace Barotrauma.Items.Components
|
||||
private void Repair(Vector2 rayStart, Vector2 rayEnd, float deltaTime, Character user, float degreeOfSuccess, List<Body> ignoredBodies)
|
||||
{
|
||||
var collisionCategories = Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionRepair;
|
||||
if (RepairThroughWalls)
|
||||
if (RepairMultiple)
|
||||
{
|
||||
var bodies = Submarine.PickBodies(rayStart, rayEnd, ignoredBodies, collisionCategories, ignoreSensors: false, allowInsideFixture: true);
|
||||
Type lastHitType = null;
|
||||
foreach (Body body in bodies)
|
||||
{
|
||||
FixBody(user, deltaTime, degreeOfSuccess, body);
|
||||
Type bodyType = body.UserData?.GetType();
|
||||
if (!RepairThroughWalls && bodyType != null && bodyType != lastHitType)
|
||||
{
|
||||
//stop the ray if it already hit a door/wall and is now about to hit some other type of entity
|
||||
if (lastHitType == typeof(Item) || lastHitType == typeof(Structure)) { break; }
|
||||
}
|
||||
if (FixBody(user, deltaTime, degreeOfSuccess, body))
|
||||
{
|
||||
if (bodyType != null) { lastHitType = bodyType; }
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -202,19 +215,19 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private void FixBody(Character user, float deltaTime, float degreeOfSuccess, Body targetBody)
|
||||
private bool FixBody(Character user, float deltaTime, float degreeOfSuccess, Body targetBody)
|
||||
{
|
||||
if (targetBody?.UserData == null) { return; }
|
||||
if (targetBody?.UserData == null) { return false; }
|
||||
|
||||
pickedPosition = Submarine.LastPickedPosition;
|
||||
|
||||
if (targetBody.UserData is Structure targetStructure)
|
||||
{
|
||||
if (!fixableEntities.Contains("structure") && !fixableEntities.Contains(targetStructure.Prefab.Identifier)) return;
|
||||
if (targetStructure.IsPlatform) return;
|
||||
if (!fixableEntities.Contains("structure") && !fixableEntities.Contains(targetStructure.Prefab.Identifier)) { return false; }
|
||||
if (targetStructure.IsPlatform) { return false; }
|
||||
|
||||
int sectionIndex = targetStructure.FindSectionIndex(ConvertUnits.ToDisplayUnits(pickedPosition));
|
||||
if (sectionIndex < 0) return;
|
||||
if (sectionIndex < 0) { return false; }
|
||||
|
||||
FixStructureProjSpecific(user, deltaTime, targetStructure, sectionIndex);
|
||||
targetStructure.AddDamage(sectionIndex, -StructureFixAmount * degreeOfSuccess, user);
|
||||
@@ -232,18 +245,21 @@ namespace Barotrauma.Items.Components
|
||||
targetStructure.AddDamage(sectionIndex + i, -StructureFixAmount * degreeOfSuccess);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (targetBody.UserData is Character targetCharacter)
|
||||
{
|
||||
targetCharacter.LastDamageSource = item;
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, new List<ISerializableEntity>() { targetCharacter });
|
||||
FixCharacterProjSpecific(user, deltaTime, targetCharacter);
|
||||
return true;
|
||||
}
|
||||
else if (targetBody.UserData is Limb targetLimb)
|
||||
{
|
||||
targetLimb.character.LastDamageSource = item;
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, new List<ISerializableEntity>() { targetLimb.character, targetLimb });
|
||||
FixCharacterProjSpecific(user, deltaTime, targetLimb.character);
|
||||
return true;
|
||||
}
|
||||
else if (targetBody.UserData is Item targetItem)
|
||||
{
|
||||
@@ -268,7 +284,9 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
}
|
||||
FixItemProjSpecific(user, deltaTime, targetItem, prevCondition);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
partial void FixStructureProjSpecific(Character user, float deltaTime, Structure targetStructure, int sectionIndex);
|
||||
|
||||
@@ -730,7 +730,15 @@ namespace Barotrauma
|
||||
return closestBody;
|
||||
}
|
||||
|
||||
public static List<Body> PickBodies(Vector2 rayStart, Vector2 rayEnd, IEnumerable<Body> ignoredBodies = null, Category? collisionCategory = null, bool ignoreSensors = true, Predicate<Fixture> customPredicate = null, bool allowInsideFixture = false)
|
||||
private static readonly Dictionary<Body, float> bodyDist = new Dictionary<Body, float>();
|
||||
private static readonly List<Body> bodies = new List<Body>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of physics bodies the ray intersects with, sorted according to distance (the closest body is at the beginning of the list).
|
||||
/// </summary>
|
||||
/// <param name="customPredicate">Can be used to filter the bodies based on some condition. If the predicate returns false, the body isignored.</param>
|
||||
/// <param name="allowInsideFixture">Should fixtures that the start of the ray is inside be returned</param>
|
||||
public static IEnumerable<Body> PickBodies(Vector2 rayStart, Vector2 rayEnd, IEnumerable<Body> ignoredBodies = null, Category? collisionCategory = null, bool ignoreSensors = true, Predicate<Fixture> customPredicate = null, bool allowInsideFixture = false)
|
||||
{
|
||||
if (Vector2.DistanceSquared(rayStart, rayEnd) < 0.00001f)
|
||||
{
|
||||
@@ -738,20 +746,25 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
float closestFraction = 1.0f;
|
||||
List<Body> bodies = new List<Body>();
|
||||
bodies.Clear();
|
||||
bodyDist.Clear();
|
||||
GameMain.World.RayCast((fixture, point, normal, fraction) =>
|
||||
{
|
||||
if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return -1; }
|
||||
|
||||
if (fixture.Body != null) { bodies.Add(fixture.Body); }
|
||||
if (fixture.Body != null)
|
||||
{
|
||||
bodies.Add(fixture.Body);
|
||||
bodyDist[fixture.Body] = fraction;
|
||||
}
|
||||
if (fraction < closestFraction)
|
||||
{
|
||||
lastPickedPosition = rayStart + (rayEnd - rayStart) * fraction;
|
||||
lastPickedFraction = fraction;
|
||||
lastPickedNormal = normal;
|
||||
}
|
||||
|
||||
return fraction;
|
||||
//continue
|
||||
return -1;
|
||||
}, rayStart, rayEnd);
|
||||
|
||||
if (allowInsideFixture)
|
||||
@@ -770,10 +783,12 @@ namespace Barotrauma
|
||||
lastPickedFraction = 0.0f;
|
||||
lastPickedNormal = Vector2.Normalize(rayEnd - rayStart);
|
||||
bodies.Add(fixture.Body);
|
||||
bodyDist[fixture.Body] = 0.0f;
|
||||
return false;
|
||||
}, ref aabb);
|
||||
}
|
||||
|
||||
bodies.Sort((b1, b2) => { return bodyDist[b1].CompareTo(bodyDist[b2]); });
|
||||
return bodies;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user