private bool ArcHit(ushort zoneId, Point3D pinPos, Point3D worldPos) { if (_weapon.LOSHit(zoneId, pinPos)) { return(true); } #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Direct LOS check failed, checking arc..."); #endif WarZoneLib.Vector3 playnice = new WarZoneLib.Vector3(); int maxZDisplacement = Math.Min(_Owner.Z, pinPos.Z) + 100 * 12; // check 100 feet upwards Point3D weaponTopPoint = new Point3D(); Point3D destPoint = new Point3D(); Vector2 toTarget = new Vector2(worldPos.X - _weapon.WorldPosition.X, worldPos.Y - _weapon.WorldPosition.Y); toTarget.Normalize(); weaponTopPoint.SetCoordsFrom(_weapon); destPoint.SetCoordsFrom(_weapon); #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Weapon location: " + weaponTopPoint); #endif // Check LOS between weapon and close apex (if applicable) if (weaponTopPoint.Z < maxZDisplacement) { destPoint.Z = maxZDisplacement; // Check 50 feet in front of the weapon destPoint.X += (int)(toTarget.X * 50 * 12); destPoint.Y += (int)(toTarget.Y * 50 * 12); #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Checking weapon to destination point: " + destPoint); #endif RegionData.OcclusionResult arc1Result = RegionData.OcclusionQuery( zoneId, weaponTopPoint.X, weaponTopPoint.Y, weaponTopPoint.Z + 120, zoneId, destPoint.X, destPoint.Y, destPoint.Z, ref playnice); if (arc1Result == RegionData.OcclusionResult.Occluded) { #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Arc check failed (obstruction between cannon and arc apex 1)"); foreach (var player in Players) { player.Key.ZoneTeleport((ushort)destPoint.X, (ushort)destPoint.Y, (ushort)destPoint.Z, 0); } #endif return(false); } weaponTopPoint.SetCoordsFrom(destPoint); } // Check LOS between target and far apex (if applicable) destPoint.SetCoordsFrom(pinPos); #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Target location: " + pinPos); #endif if (pinPos.Z < maxZDisplacement) { destPoint.Z = maxZDisplacement; // Much more lenient on drop - 10ft destPoint.X -= (int)(toTarget.X * 10 * 12); destPoint.Y -= (int)(toTarget.Y * 10 * 12); #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Checking target location to destination point: " + destPoint); #endif RegionData.OcclusionResult arc2Result = RegionData.OcclusionQuery( zoneId, pinPos.X, pinPos.Y, pinPos.Z + 120, zoneId, destPoint.X, destPoint.Y, destPoint.Z, ref playnice); if (arc2Result == RegionData.OcclusionResult.Occluded) { #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Arc check failed (obstruction between target point and arc apex 2)"); foreach (var player in Players) { player.Key.ZoneTeleport((ushort)destPoint.X, (ushort)destPoint.Y, (ushort)destPoint.Z, 0); } #endif return(false); } pinPos.SetCoordsFrom(destPoint); } #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Checking apex 1 " + weaponTopPoint + " to apex 2 " + pinPos); #endif // Check LOS between two apex points RegionData.OcclusionResult result = RegionData.OcclusionQuery( zoneId, weaponTopPoint.X, weaponTopPoint.Y, weaponTopPoint.Z + 120, zoneId, pinPos.X, pinPos.Y, pinPos.Z + 120, ref playnice); if (result == RegionData.OcclusionResult.Occluded) { #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Arc check failed (obstruction between arc apexes)"); //foreach (var player in Players) // player.Key.ZoneTeleport((ushort)weaponTopPoint.X, (ushort)weaponTopPoint.Y, (ushort)weaponTopPoint.Z, 0); foreach (var player in Players) { player.Key.ZoneTeleport((ushort)pinPos.X, (ushort)pinPos.Y, (ushort)pinPos.Z, 0); } #endif return(false); } #if DEBUG && ARTILLERY_ARC_DEBUG Log.Info("Artillery", "Arc check passed"); #endif return(true); }