/// <summary> /// Add hitscan position to coordinates /// </summary> /// <param name="result"></param> /// <returns></returns> public static PointF GetHitscanPoint(HitscanResult result) { switch (result) { case HitscanResult.Center: return(new PointF(0, 0)); case HitscanResult.Top: return(new PointF(0, 0 - ScanRange)); case HitscanResult.Bottom: return(new PointF(0, 0 + ScanRange)); case HitscanResult.Left: return(new PointF(0 - ScanRange, 0)); case HitscanResult.Right: return(new PointF(0 + ScanRange, 0)); case HitscanResult.TopLeft: return(new PointF(0 - ScanRange, 0 - ScanRange)); case HitscanResult.TopRight: return(new PointF(0 + ScanRange, 0 - ScanRange)); case HitscanResult.BottomLeft: return(new PointF(0 - ScanRange, 0 + ScanRange)); case HitscanResult.BottomRight: return(new PointF(0 + ScanRange, 0 + ScanRange)); } return(new PointF(0, 0)); }
private void DoHitscan(Vector2 dir) { float rotation = item.body.Rotation; Vector2 simPositon = item.SimPosition; item.Drop(null); item.body.Enabled = true; //set the velocity of the body because the OnProjectileCollision method //uses it to determine the direction from which the projectile hit item.body.LinearVelocity = dir; IsActive = true; Vector2 rayStart = simPositon; Vector2 rayEnd = simPositon + dir * 1000.0f; List <HitscanResult> hits = new List <HitscanResult>(); hits.AddRange(DoRayCast(rayStart, rayEnd)); if (item.Submarine != null) { //shooting indoors, do a hitscan outside as well hits.AddRange(DoRayCast(rayStart + item.Submarine.SimPosition, rayEnd + item.Submarine.SimPosition)); } else { //shooting outdoors, see if we can hit anything inside a sub foreach (Submarine submarine in Submarine.Loaded) { var inSubHits = DoRayCast(rayStart - submarine.SimPosition, rayEnd - submarine.SimPosition); //transform back to world coordinates 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.AddRange(inSubHits); } } bool hitSomething = false; hits = hits.OrderBy(h => h.Fraction).ToList(); foreach (HitscanResult h in hits) { item.body.SetTransform(h.Point, rotation); if (OnProjectileCollision(h.Fixture, h.Normal)) { hitSomething = true; break; } } //the raycast didn't hit anything -> the projectile flew somewhere outside the level and is permanently lost if (!hitSomething) { if (Entity.Spawner == null) { item.Remove(); } else { Entity.Spawner.AddToRemoveQueue(item); } } }
private void DoHitscan(Vector2 dir) { float rotation = item.body.Rotation; Vector2 simPositon = item.SimPosition; item.Drop(null); item.body.Enabled = true; //set the velocity of the body because the OnProjectileCollision method //uses it to determine the direction from which the projectile hit item.body.LinearVelocity = dir; IsActive = true; Vector2 rayStart = simPositon; Vector2 rayEnd = simPositon + dir * 500.0f; List <HitscanResult> hits = new List <HitscanResult>(); hits.AddRange(DoRayCast(rayStart, rayEnd, submarine: item.Submarine)); if (item.Submarine != null) { //shooting indoors, do a hitscan outside as well hits.AddRange(DoRayCast(rayStart + item.Submarine.SimPosition, rayEnd + item.Submarine.SimPosition, submarine: null)); //also in the coordinate space of docked subs foreach (Submarine dockedSub in item.Submarine.DockedTo) { if (dockedSub == item.Submarine) { continue; } hits.AddRange(DoRayCast(rayStart + item.Submarine.SimPosition - dockedSub.SimPosition, rayEnd + item.Submarine.SimPosition - dockedSub.SimPosition, dockedSub)); } } else { //shooting outdoors, see if we can hit anything inside a sub foreach (Submarine submarine in Submarine.Loaded) { var inSubHits = DoRayCast(rayStart - submarine.SimPosition, rayEnd - submarine.SimPosition, submarine); //transform back to world coordinates 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.AddRange(inSubHits); } } bool hitSomething = false; hits = hits.OrderBy(h => h.Fraction).ToList(); foreach (HitscanResult h in hits) { item.SetTransform(h.Point, rotation); if (HandleProjectileCollision(h.Fixture, h.Normal, Vector2.Zero)) { hitSomething = true; break; } } //the raycast didn't hit anything -> the projectile flew somewhere outside the level and is permanently lost if (!hitSomething) { if (Entity.Spawner == null) { item.Remove(); } else { if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { //clients aren't allowed to remove items by themselves, so lets hide the projectile until the server tells us to remove it item.HiddenInGame = Hitscan; } else { Entity.Spawner.AddToRemoveQueue(item); } } } }
private void DoHitscan(Vector2 dir) { float rotation = item.body.Rotation; Vector2 simPositon = item.SimPosition; item.Drop(null); item.body.Enabled = true; //set the velocity of the body because the OnProjectileCollision method //uses it to determine the direction from which the projectile hit item.body.LinearVelocity = dir; IsActive = true; Vector2 rayStart = simPositon; Vector2 rayEnd = rayStart + dir * 500.0f; Vector2 rayStartWorld = item.WorldPosition; float worldDist = 1000.0f; #if CLIENT worldDist = Screen.Selected?.Cam?.WorldView.Width ?? GameMain.GraphicsWidth; #endif Vector2 rayEndWorld = rayStartWorld + dir * worldDist; List <HitscanResult> hits = new List <HitscanResult>(); hits.AddRange(DoRayCast(rayStart, rayEnd, submarine: item.Submarine)); if (item.Submarine != null) { //shooting indoors, do a hitscan outside as well hits.AddRange(DoRayCast(rayStart + item.Submarine.SimPosition, rayEnd + item.Submarine.SimPosition, submarine: null)); //also in the coordinate space of docked subs foreach (Submarine dockedSub in item.Submarine.DockedTo) { if (dockedSub == item.Submarine) { continue; } hits.AddRange(DoRayCast(rayStart + item.Submarine.SimPosition - dockedSub.SimPosition, rayEnd + item.Submarine.SimPosition - dockedSub.SimPosition, dockedSub)); } } else { //shooting outdoors, see if we can hit anything inside a sub foreach (Submarine submarine in Submarine.Loaded) { var inSubHits = DoRayCast(rayStart - submarine.SimPosition, rayEnd - submarine.SimPosition, submarine); //transform back to world coordinates 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.AddRange(inSubHits); } } int hitCount = 0; Vector2 lastHitPos = item.WorldPosition; hits = hits.OrderBy(h => h.Fraction).ToList(); for (int i = 0; i < hits.Count; i++) { var h = hits[i]; item.SetTransform(h.Point, rotation); if (HandleProjectileCollision(h.Fixture, h.Normal, Vector2.Zero)) { hitCount++; if (hitCount >= MaxTargetsToHit || i == hits.Count - 1) { LaunchProjSpecific(rayStartWorld, item.WorldPosition); break; } } } //the raycast didn't hit anything (or didn't hit enough targets to stop the projectile) -> the projectile flew somewhere outside the level and is permanently lost if (hitCount < MaxTargetsToHit) { item.body.SetTransformIgnoreContacts(item.body.SimPosition, rotation); LaunchProjSpecific(rayStartWorld, rayEndWorld); if (Entity.Spawner == null) { item.Remove(); } else { if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { //clients aren't allowed to remove items by themselves, so lets hide the projectile until the server tells us to remove it item.HiddenInGame = Hitscan; } else { Entity.Spawner.AddToRemoveQueue(item); } } } }