77import FFX_memory
88import FFX_Logs
99from math import copysign
10+ import numpy as np
1011
1112FFXC = FFX_Xbox .FFXC
1213
14+ def lineSphereIntersect (start , end , circle , radius = 11 ):
15+ numHits = 0
16+ hits = []
17+
18+ direction = end - start
19+ sphereToStart = start - circle
20+ a = np .dot (direction , direction )
21+ b = 2 * np .dot (sphereToStart , direction )
22+ c = np .dot (sphereToStart , sphereToStart ) - radius ** 2
23+ d = b ** 2 - 4 * a * c
24+ if d < 0 : # no intersection
25+ return (numHits , hits )
26+
27+ d = np .sqrt (d )
28+ # Solve quadratic equation
29+ t1 = (- b - d )/ (2 * a )
30+ t2 = (- b + d )/ (2 * a )
31+
32+ if t1 >= 0 and t1 <= 1 :
33+ numHits += 1
34+ hits .append (start + direction * t1 )
35+ if t2 >= 0 and t2 <= 1 :
36+ numHits += 1
37+ hits .append (start + direction * t2 )
38+ return (numHits , hits )
39+
40+ def pathAround (player , circle , target , radius = 11 ):
41+ line = player - circle
42+ line /= np .linalg .norm (line ) # normalize to length 1
43+ angle = np .arctan2 (line [1 ],line [0 ])
44+
45+ # Create two points rotated 90 degrees from player -> circle intersection
46+ newAngle1 = angle + 0.5 * np .pi
47+ newAngle2 = angle - 0.5 * np .pi
48+ p1 = circle + [radius * np .cos (newAngle1 ), radius * np .sin (newAngle1 )]
49+ p2 = circle + [radius * np .cos (newAngle2 ), radius * np .sin (newAngle2 )]
50+ # Find which of two possible points gives shortest path
51+ p1length = np .linalg .norm (p1 - player ) + np .linalg .norm (target - p1 )
52+ p2length = np .linalg .norm (p2 - player ) + np .linalg .norm (target - p2 )
53+ if p1length < p2length :
54+ return p1
55+ return p2
56+
1357def engage ():
1458 print ("Start egg hunt" )
1559 startTime = time .time ()
@@ -77,9 +121,27 @@ def engage():
77121 else :
78122 #print("Movement happening.")
79123 #target = [-70,-70]
124+ oldTarget = target
80125 player = FFX_memory .getCoords ()
126+ iceArray = FFX_memory .buildIcicles ()
81127 (forward , right ) = FFX_memory .getMovementVectors ()
82128
129+ targetPos = np .array ([target [0 ], target [1 ]])
130+ playerPos = np .array (player )
131+
132+ closestIntersect = 9999
133+ intersectPoint = []
134+ for icicle in iceArray :
135+ numIntersect , hits = lineSphereIntersect (playerPos , targetPos , np .array ([icicle .x , icicle .y ]))
136+ if numIntersect > 0 :
137+ intersectDistance = (player [0 ] - hits [0 ][0 ])** 2 + (player [1 ] - hits [0 ][1 ])** 2
138+ if intersectDistance < closestIntersect :
139+ closestIntersect = intersectDistance
140+ intersectPoint = hits [0 ]
141+
142+ if closestIntersect < 9999 :
143+ target = pathAround (playerPos , np .array (intersectPoint ), targetPos ) # Move around icicle instead
144+
83145 # Calculate forward and right directions relative to camera space
84146 pX = player [0 ]
85147 pY = player [1 ]
@@ -106,15 +168,14 @@ def engage():
106168
107169 FFXC .set_value ('AxisLx' , Lx )
108170 FFXC .set_value ('AxisLy' , Ly )
109-
171+ target = oldTarget
110172
111173 #camCount += 1
112174 #print(camCount)
113175 #if camCount % 20 == 0:
114176 # FFX_Logs.writePlot("TEST")
115177
116178
117-
118179 #Now if we're close, we want to slow down a bit.
119180 if activeEgg != 99 and eggArray [activeEgg ].distance < 15 and eggArray [activeEgg ].eggLife < 130 :
120181 time .sleep (0.15 )
0 commit comments