forked from Hellsing/MasterMind
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUtilities.cs
278 lines (248 loc) · 9.46 KB
/
Utilities.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
using System;
using System.Collections.Generic;
using System.Linq;
using EloBuddy;
using EloBuddy.SDK;
using EloBuddy.SDK.Rendering;
using SharpDX;
using Color = System.Drawing.Color;
namespace MasterMind
{
public static class Utilities
{
// ReSharper disable once InconsistentNaming
public const float PI2 = (float) Math.PI * 2;
public static Rectangle MinimapRectangle { get; private set; }
public static float MinimapMultiplicator { get; private set; }
static Utilities()
{
Initialize();
}
private static void Initialize()
{
Core.DelayAction(() =>
{
var multiplicator = new Vector3(1000, 1000, 0).WorldToMinimap().Distance(new Vector3(2000, 1000, 0).WorldToMinimap()) / 1000f;
if (multiplicator <= float.Epsilon)
{
Initialize();
}
else
{
MinimapMultiplicator = multiplicator;
Vector2 leftUpper;
Vector2 rightLower;
if (Game.MapId == GameMapId.CrystalScar)
{
leftUpper = new Vector3(0, 13800, 0).WorldToMinimap();
rightLower = new Vector3(13800, 0, 0).WorldToMinimap();
}
else
{
leftUpper = new Vector3(0, 14800, 0).WorldToMinimap();
rightLower = new Vector3(14800, 0, 0).WorldToMinimap();
}
MinimapRectangle = new Rectangle((int) leftUpper.X, (int) leftUpper.Y, (int) (rightLower.X - leftUpper.X), (int) (rightLower.Y - leftUpper.Y));
}
}, 1000);
}
public static void DrawArc(Vector2 position, float radius, Color color, float startDegree, float length, float width = 0.6F, int quality = -1)
{
if (quality == -1)
{
quality = (int) (radius / 7 + 11);
}
var points = new Vector2[(int) (Math.Abs(quality * length / PI2) + 1)];
var rad = new Vector2(0, radius);
for (var i = 0; i <= (int) (Math.Abs(quality * length / PI2)); i++)
{
points[i] = (position + rad).RotateAroundPoint(position, startDegree + PI2 * i / quality * (length > 0 ? 1 : -1));
}
Line.DrawLine(color, width, points);
}
public static void DrawCricleMinimap(Vector2 screenPosition, float radius, Color color, float width = 2F, int quality = -1)
{
if (quality == -1)
{
quality = (int) (radius / 3 + 15);
}
var rad = new Vector2(0, radius);
var segments = new List<MinimapCircleSegment>();
var full = true;
for (var i = 0; i <= quality; i++)
{
var pos = (screenPosition + rad).RotateAroundPoint(screenPosition, PI2 * i / quality);
var contains = MinimapRectangle.Contains(pos);
if (!contains)
{
full = false;
}
segments.Add(new MinimapCircleSegment(pos, contains));
}
foreach (var ar in FindArcs(segments, full))
{
Line.DrawLine(color, width, ar);
}
}
private static IEnumerable<Vector2[]> FindArcs(IReadOnlyList<MinimapCircleSegment> points, bool full)
{
var ret = new List<Vector2[]>();
if (full)
{
ret.Add(points.Select(segment => segment.Position).ToArray());
return ret;
}
var pos = 0;
for (var c = 0; c < 3; c++)
{
int start = -1, stop = -1;
for (var i = pos; i < points.Count; i++)
{
if (points[i].IsValid)
{
if (start == -1)
{
start = i;
}
}
else
{
if (stop == -1 && start != -1)
{
stop = i;
pos = i;
if (start != 0)
{
break;
}
for (var j = points.Count - 1; j > 0; j--)
{
if (points[j].IsValid)
{
start = j;
}
else
{
break;
}
}
}
if (i == points.Count - 1)
{
pos = points.Count;
}
}
}
var arc = new List<Vector2>();
if (start == -1 || stop == -1)
{
continue;
}
var pointer = start;
while (true)
{
if (pointer == stop)
{
break;
}
arc.Add(points[pointer].Position);
pointer++;
if (pointer == points.Count)
{
pointer = 0;
}
}
ret.Add(arc.ToArray());
}
return ret;
}
public static RectangleF GetScreenBoudingRectangle(GameObject obj)
{
int minX = 0, maxX = 0, minY = 0, maxY = 0;
foreach (var corner in obj.BBox.GetCorners())
{
var pos = corner.WorldToScreen();
var x = (int) Math.Round(pos.X);
var y = (int) Math.Round(pos.Y);
// Compare current with existing X
if (minX == 0 || x < minX)
{
minX = x;
}
else if (maxX == 0 || x > maxX)
{
maxX = x;
}
// Compare current with existing Y
if (minY == 0 || y < minY)
{
minY = y;
}
else if (maxY == 0 || y > maxY)
{
maxY = y;
}
}
return new RectangleF(minX, minY, maxX - minX, maxY - minY);
}
public static Vector3 GetValidCastSpot(this Vector3 castPosition)
{
// If the position is not a wall then return the input position
var flags = castPosition.ToNavMeshCell().CollFlags;
if (!flags.HasFlag(CollisionFlags.Wall) && !flags.HasFlag(CollisionFlags.Building))
{
return castPosition;
}
const int maxRange = 20;
const double step = 2 * Math.PI / 20;
var start = new Vector2(castPosition.ToNavMeshCell().GridX, castPosition.ToNavMeshCell().GridY);
var checkedCells = new HashSet<Vector2>();
// Get all directions
var directions = new List<Vector2>();
for (var theta = 0d; theta <= 2 * Math.PI + step; theta += step)
{
directions.Add((new Vector2((short) (start.X + Math.Cos(theta)), (short) (start.Y - Math.Sin(theta))) - start).Normalized());
}
var validPositions = new HashSet<Vector3>();
for (var range = 1; range < maxRange; range++)
{
// ReSharper disable once LoopCanBePartlyConvertedToQuery
foreach (var direction in directions)
{
// Get the position to check
var end = start + range * direction;
var testPoint = new Vector2((short) end.X, (short) end.Y);
if (checkedCells.Contains(testPoint))
{
continue;
}
checkedCells.Add(testPoint);
// Check the position for wall flags
flags = new NavMeshCell((short) testPoint.X, (short) testPoint.Y).CollFlags;
if (!flags.HasFlag(CollisionFlags.Wall) && !flags.HasFlag(CollisionFlags.Building))
{
// Add the position to the valid positions set
validPositions.Add(NavMesh.GridToWorld((short) testPoint.X, (short) testPoint.Y));
}
}
if (validPositions.Count > 0)
{
// Return the closest position to the initial wall position
return validPositions.OrderBy(o => o.Distance(start, true)).First();
}
}
// Nothing found return input
return castPosition;
}
}
internal class MinimapCircleSegment
{
internal readonly Vector2 Position;
internal readonly bool IsValid;
internal MinimapCircleSegment(Vector2 position, bool valid)
{
Position = position;
IsValid = valid;
}
}
}