Hitscan weapons can hit targets outside the sub when firing from the inside and vice versa. Closes #639
This commit is contained in:
@@ -12,6 +12,22 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
class Projectile : ItemComponent
|
class Projectile : ItemComponent
|
||||||
{
|
{
|
||||||
|
struct HitscanResult
|
||||||
|
{
|
||||||
|
public Fixture Fixture;
|
||||||
|
public Vector2 Point;
|
||||||
|
public Vector2 Normal;
|
||||||
|
public float Fraction;
|
||||||
|
|
||||||
|
public HitscanResult(Fixture fixture, Vector2 point, Vector2 normal, float fraction)
|
||||||
|
{
|
||||||
|
Fixture = fixture;
|
||||||
|
Point = point;
|
||||||
|
Normal = normal;
|
||||||
|
Fraction = fraction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//continuous collision detection is used while the projectile is moving faster than this
|
//continuous collision detection is used while the projectile is moving faster than this
|
||||||
const float ContinuousCollisionThreshold = 5.0f;
|
const float ContinuousCollisionThreshold = 5.0f;
|
||||||
|
|
||||||
@@ -183,39 +199,41 @@ namespace Barotrauma.Items.Components
|
|||||||
Vector2 rayStart = item.SimPosition;
|
Vector2 rayStart = item.SimPosition;
|
||||||
Vector2 rayEnd = item.SimPosition + dir * 1000.0f;
|
Vector2 rayEnd = item.SimPosition + dir * 1000.0f;
|
||||||
|
|
||||||
List<Tuple<Fixture, Vector2, Vector2>> hits = new List<Tuple<Fixture, Vector2, Vector2>>();
|
List<HitscanResult> hits = new List<HitscanResult>();
|
||||||
GameMain.World.RayCast((fixture, point, normal, fraction) =>
|
|
||||||
|
hits.AddRange(DoRayCast(rayStart, rayEnd));
|
||||||
|
|
||||||
|
if (item.Submarine != null)
|
||||||
{
|
{
|
||||||
if (fixture == null || fixture.IsSensor) return -1;
|
//shooting indoors, do a hitscan outside as well
|
||||||
|
hits.AddRange(DoRayCast(rayStart + item.Submarine.SimPosition, rayEnd + item.Submarine.SimPosition));
|
||||||
if (fixture.UserData is Item) return -1;
|
}
|
||||||
|
else
|
||||||
if (!fixture.CollisionCategories.HasFlag(Physics.CollisionCharacter) &&
|
{
|
||||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) &&
|
//shooting outdoors, see if we can hit anything inside a sub
|
||||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) return -1;
|
foreach (Submarine submarine in Submarine.Loaded)
|
||||||
|
|
||||||
/*item.body.SetTransform(point, rotation);
|
|
||||||
if (OnProjectileCollision(fixture, normal))
|
|
||||||
{
|
{
|
||||||
Character.Controlled.AnimController.Teleport(point - Character.Controlled.SimPosition, Vector2.Zero);
|
var inSubHits = DoRayCast(rayStart - submarine.SimPosition, rayEnd - submarine.SimPosition);
|
||||||
hitSomething = true;
|
//transform back to world coordinates
|
||||||
return 0;
|
for (int i = 0; i < inSubHits.Count; i++)
|
||||||
}*/
|
{
|
||||||
|
inSubHits[i] = new HitscanResult(
|
||||||
|
inSubHits[i].Fixture,
|
||||||
|
inSubHits[i].Point + submarine.SimPosition,
|
||||||
|
inSubHits[i].Normal,
|
||||||
|
inSubHits[i].Fraction);
|
||||||
|
}
|
||||||
|
|
||||||
hits.Add(new Tuple<Fixture, Vector2, Vector2>(fixture,point,normal));
|
hits.AddRange(inSubHits);
|
||||||
|
}
|
||||||
return hits.Count<25 ? 1 : 0;
|
}
|
||||||
}, rayStart, rayEnd);
|
|
||||||
|
|
||||||
bool hitSomething = false;
|
bool hitSomething = false;
|
||||||
hits = hits.OrderBy(t => Vector2.DistanceSquared(rayStart, t.Item2)).ToList();
|
hits = hits.OrderBy(h => h.Fraction).ToList();
|
||||||
foreach (Tuple<Fixture, Vector2, Vector2> t in hits)
|
foreach (HitscanResult h in hits)
|
||||||
{
|
{
|
||||||
Fixture fixture = t.Item1;
|
item.body.SetTransform(h.Point, rotation);
|
||||||
Vector2 point = t.Item2;
|
if (OnProjectileCollision(h.Fixture, h.Normal))
|
||||||
Vector2 normal = t.Item3;
|
|
||||||
item.body.SetTransform(point, rotation);
|
|
||||||
if (OnProjectileCollision(fixture, normal))
|
|
||||||
{
|
{
|
||||||
hitSomething = true;
|
hitSomething = true;
|
||||||
break;
|
break;
|
||||||
@@ -229,6 +247,27 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<HitscanResult> DoRayCast(Vector2 rayStart, Vector2 rayEnd)
|
||||||
|
{
|
||||||
|
List<HitscanResult> hits = new List<HitscanResult>();
|
||||||
|
GameMain.World.RayCast((fixture, point, normal, fraction) =>
|
||||||
|
{
|
||||||
|
if (fixture == null || fixture.IsSensor) return -1;
|
||||||
|
|
||||||
|
if (fixture.UserData is Item) return -1;
|
||||||
|
|
||||||
|
if (!fixture.CollisionCategories.HasFlag(Physics.CollisionCharacter) &&
|
||||||
|
!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) &&
|
||||||
|
!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) return -1;
|
||||||
|
|
||||||
|
hits.Add(new HitscanResult(fixture, point, normal, fraction));
|
||||||
|
|
||||||
|
return hits.Count < 25 ? 1 : 0;
|
||||||
|
}, rayStart, rayEnd);
|
||||||
|
|
||||||
|
return hits;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Update(float deltaTime, Camera cam)
|
public override void Update(float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||||
@@ -309,7 +348,7 @@ namespace Barotrauma.Items.Components
|
|||||||
item.Move(-submarine.Position);
|
item.Move(-submarine.Position);
|
||||||
item.Submarine = submarine;
|
item.Submarine = submarine;
|
||||||
item.body.Submarine = submarine;
|
item.body.Submarine = submarine;
|
||||||
return true;
|
return !Hitscan;
|
||||||
}
|
}
|
||||||
|
|
||||||
Structure structure;
|
Structure structure;
|
||||||
|
|||||||
Reference in New Issue
Block a user