-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSH2_KeepGettingRings.py
More file actions
174 lines (133 loc) · 4.71 KB
/
SH2_KeepGettingRings.py
File metadata and controls
174 lines (133 loc) · 4.71 KB
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
from ReadWriteMemory import ReadWriteMemory
import pydirectinput
import time
import pygame
import win32api
import win32con
import win32gui
import win32process
import GetBaseAddr as BA
# -----------------------------------
AMMOUNT_TIME = 5.00 #secs
# -----------------------------------
PROCESS_NAME = 'retroarch.exe'
BASE_ADDRESS_DLL = BA.GetRetroArc_DLL_Address()
RING_ADDRESS_OFFSET = 2887296
MILLS_ADDRESS_OFFSET = 2887299
LEVEL_ADDRESS_OFFSET = 2887268
RING_ADDRESS_POINTER = BASE_ADDRESS_DLL+RING_ADDRESS_OFFSET
MILLS_ADDRESS_POINTER = BASE_ADDRESS_DLL+MILLS_ADDRESS_OFFSET
LEVEL_TICK_POINTER = BASE_ADDRESS_DLL+LEVEL_ADDRESS_OFFSET
# SECS_ADDRESS_POINTER = 0x16380E85
# MIN_ADDRESS_POINTER = 0x16380E82
# Overlay Init ---------------
pygame.init()
screen = pygame.display.set_mode((800, 600), pygame.RESIZABLE) # For borderless, use pygame.NOFRAME
# Set Window to always be top
hwnd = win32gui.GetForegroundWindow()
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 600, 300, 0, 0, win32con.SWP_NOSIZE)
# Set window transparency color
fuchsia = (115, 115, 115)
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*fuchsia), 0, win32con.LWA_COLORKEY)
# Text Outline Code ---------
_circle_cache = {}
def _circlepoints(r):
r = int(round(r))
if r in _circle_cache:
return _circle_cache[r]
x, y, e = r, 0, 1 - r
_circle_cache[r] = points = []
while x >= y:
points.append((x, y))
y += 1
if e < 0:
e += 2 * y - 1
else:
x -= 1
e += 2 * (y - x) - 1
points += [(y, x) for x, y in points if x > y]
points += [(-x, y) for x, y in points if x]
points += [(x, -y) for x, y in points if y]
points.sort()
return points
def render(text, font, gfcolor=(239, 239, 0), ocolor=(0, 0, 0), opx=4):
textsurface = font.render(text, True, gfcolor).convert_alpha()
w = textsurface.get_width() + 2 * opx
h = font.get_height()
osurf = pygame.Surface((w, h + 2 * opx)).convert_alpha()
osurf.fill((0, 0, 0, 0))
surf = osurf.copy()
osurf.blit(font.render(text, True, ocolor).convert_alpha(), (0, 0))
for dx, dy in _circlepoints(opx):
surf.blit(osurf, (dx + opx, dy + opx))
surf.blit(textsurface, (opx, opx))
return surf
# Read Game Memory Init ----------------
rwm = ReadWriteMemory()
process = rwm.get_process_by_name(PROCESS_NAME)
process.open()
rings_pointer = process.get_pointer(RING_ADDRESS_POINTER)
mills_pointer = process.get_pointer(MILLS_ADDRESS_POINTER)
level_tick_pointer = process.get_pointer(LEVEL_TICK_POINTER)
levelStartFlagSet = False
rings = process.read(rings_pointer)
pre_value_rings = rings
print("Rings: " + str(rings))
# Game Logic ----------
def resetlevel():
pydirectinput.press('f4')
time.sleep(0.2)
print("Reset Level")
def levelStart():
pydirectinput.press('f2')
levelStartFlagSet = True
print("Level Start")
def gameTimeTickInMills():
return process.read(mills_pointer)
class TimeLeft:
def __init__(self):
self.reset_time()
self.ammount_of_time = AMMOUNT_TIME
self.ammount_left = 0
self.pre_game_time_mills = 0;
def reset_time(self):
self.last_reset_time = time.time()
def tick_time(self):
#Level Start
if process.read(level_tick_pointer) == 1:
levelStart()
# Time Left Tick
if gameTimeTickInMills() != self.pre_game_time_mills:
self.ammount_left = (time.time() - self.last_reset_time)
if self.ammount_left > self.ammount_of_time:
self.ammount_left = self.ammount_of_time
self.reset_time()
resetlevel()
else:
self.reset_time()
self.pre_game_time_mills = gameTimeTickInMills()
return self.ammount_left
time_left = 0.0
time_tracker = TimeLeft()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
screen.fill(fuchsia) # Transparent background
pre_value_rings = rings
rings = process.read(rings_pointer)
if rings != pre_value_rings:
print("Rings: " + str(rings))
if rings > pre_value_rings:
time_tracker.reset_time()
preTime_left = time_left
time_left = time_tracker.tick_time()
t = AMMOUNT_TIME
if preTime_left != time_left:
t = round(AMMOUNT_TIME - time_left, 1)
font = pygame.font.SysFont(None, 50)
screen.blit(render("Time Left: " + str(t), font), (850, 90))
time.sleep(0.02) # magic number to sync with the MILLS_ADDRESS update speed
pygame.display.flip()
#65536 //vlaue when nothing is happening