134 lines
3.9 KiB
C#
134 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
|
using FFXIVClientStructs.FFXIV.Common.Component.BGCollision;
|
|
|
|
namespace LLib.Fishing;
|
|
|
|
public static class WaterSurfaceDetector
|
|
{
|
|
public static bool IsFishable(Vector3 position, float rotation)
|
|
{
|
|
Vector3? hitPoint;
|
|
return CheckFishableAtRotation(position, rotation, out hitPoint);
|
|
}
|
|
|
|
public static (float Rotation, Vector3 HitPoint)? FindFishableRotation(Vector3 position, int searchSteps = 36)
|
|
{
|
|
float num = (float)Math.PI * 2f / (float)searchSteps;
|
|
List<int> list = new List<int>();
|
|
for (int i = 0; i < searchSteps; i++)
|
|
{
|
|
float rotation = (float)i * num;
|
|
if (CheckFishableAtRotation(position, rotation, out var _))
|
|
{
|
|
list.Add(i);
|
|
}
|
|
}
|
|
if (list.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
List<int> list2 = (from g in FindContiguousGroups(list, searchSteps)
|
|
orderby g.Count descending
|
|
select g).First();
|
|
float num2 = ((float)list2[0] + (float)(list2.Count - 1) / 2f) % (float)searchSteps * num;
|
|
if (CheckFishableAtRotation(position, num2, out var hitPoint2) && hitPoint2.HasValue)
|
|
{
|
|
return (num2, hitPoint2.Value);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private unsafe static bool CheckFishableAtRotation(Vector3 position, float rotation, out Vector3? hitPoint)
|
|
{
|
|
hitPoint = null;
|
|
Framework* ptr = Framework.Instance();
|
|
if (ptr == null || ptr->BGCollisionModule == null)
|
|
{
|
|
return false;
|
|
}
|
|
BGCollisionModule* bGCollisionModule = ptr->BGCollisionModule;
|
|
float num = MathF.Cos(rotation);
|
|
float num2 = MathF.Sin(rotation);
|
|
Matrix4x4 matrix = new Matrix4x4
|
|
{
|
|
M11 = num,
|
|
M13 = 0f - num2,
|
|
M22 = 1f,
|
|
M31 = num2,
|
|
M33 = num
|
|
};
|
|
Vector3 vector = Vector3.Transform(new Vector3(0f, 0f, 2f), matrix) + position;
|
|
vector.Y += 2f;
|
|
Vector3 vector2 = new Vector3(position.X, position.Y + 0.87f, position.Z);
|
|
Vector3 vector3 = Vector3.Normalize(vector - vector2);
|
|
float maxDistance = Vector3.Distance(vector2, vector);
|
|
byte* intPtr = stackalloc byte[16];
|
|
ReadOnlySpan<int> readOnlySpan = new int[4] { 16384, 0, 16384, 0 };
|
|
// IL cpblk instruction
|
|
Unsafe.CopyBlockUnaligned(intPtr, ref readOnlySpan[0], 16);
|
|
int* flags = (int*)intPtr;
|
|
RaycastHit raycastHit = default(RaycastHit);
|
|
if (bGCollisionModule->RaycastMaterialFilter(&raycastHit, &vector2, &vector3, maxDistance, 1, flags))
|
|
{
|
|
return false;
|
|
}
|
|
Vector3 vector4 = Vector3.Transform(new Vector3(0f, -80f, 40f), matrix);
|
|
float num3 = vector4.Length();
|
|
Vector3 vector5 = vector4 / num3;
|
|
byte* intPtr2 = stackalloc byte[16];
|
|
readOnlySpan = new int[4] { 32768, 0, 32768, 0 };
|
|
// IL cpblk instruction
|
|
Unsafe.CopyBlockUnaligned(intPtr2, ref readOnlySpan[0], 16);
|
|
int* flags2 = (int*)intPtr2;
|
|
RaycastHit raycastHit2 = default(RaycastHit);
|
|
if (bGCollisionModule->RaycastMaterialFilter(&raycastHit2, &vector, &vector5, num3, 1, flags2))
|
|
{
|
|
hitPoint = raycastHit2.Point;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static List<List<int>> FindContiguousGroups(List<int> angles, int maxSteps)
|
|
{
|
|
if (angles.Count == 0)
|
|
{
|
|
return new List<List<int>>();
|
|
}
|
|
List<int> list = angles.OrderBy((int a) => a).ToList();
|
|
List<List<int>> list2 = new List<List<int>>();
|
|
List<int> list3 = new List<int> { list[0] };
|
|
for (int num = 1; num < list.Count; num++)
|
|
{
|
|
if (list[num] - list[num - 1] == 1)
|
|
{
|
|
list3.Add(list[num]);
|
|
continue;
|
|
}
|
|
list2.Add(list3);
|
|
int num2 = 1;
|
|
List<int> list4 = new List<int>(num2);
|
|
CollectionsMarshal.SetCount(list4, num2);
|
|
CollectionsMarshal.AsSpan(list4)[0] = list[num];
|
|
list3 = list4;
|
|
}
|
|
list2.Add(list3);
|
|
if (list2.Count > 1 && list[0] == 0)
|
|
{
|
|
if (list[list.Count - 1] == maxSteps - 1)
|
|
{
|
|
List<int> item = list2[list2.Count - 1].Concat(list2[0]).ToList();
|
|
list2.RemoveAt(list2.Count - 1);
|
|
list2.RemoveAt(0);
|
|
list2.Add(item);
|
|
}
|
|
}
|
|
return list2;
|
|
}
|
|
}
|