├── .gitignore
├── .idea
├── .gitignore
├── Maple Controller.iml
├── inspectionProfiles
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── other.xml
├── runConfigurations
│ └── _template__of_Python.xml
├── vcs.xml
└── webResources.xml
├── Bot
├── .gitignore
├── Bot.py
└── compile.py
├── Controller
├── Controllers
│ ├── BaseController.py
│ ├── GameController.py
│ ├── MovementController.py
│ ├── PlayerController.py
│ ├── PotionsController.py
│ └── SettingsController.py
├── Elite boss.png
├── MapleMoveMode.py
├── MapleState.py
├── docs
│ ├── Controller Settings.md
│ └── images
│ │ ├── Download folder.png
│ │ ├── Json selection.png
│ │ ├── Resolution.png
│ │ ├── Smart direction example.png
│ │ ├── UAC1.png
│ │ └── UAC2.png
├── funcs.py
└── refs
│ ├── EXP digits
│ ├── 0.png
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ ├── 9.png
│ ├── bracket.png
│ ├── exp.png
│ └── slash.png
│ ├── PIC keys
│ ├── 0.png
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ ├── 9.png
│ ├── a.png
│ ├── b.png
│ ├── c.png
│ ├── d.png
│ ├── e.png
│ ├── f.png
│ ├── g.png
│ ├── h.png
│ ├── i.png
│ ├── j.png
│ ├── k.png
│ ├── l.png
│ ├── m.png
│ ├── n.png
│ ├── o.png
│ ├── p.png
│ ├── q.png
│ ├── r.png
│ ├── s.png
│ ├── t.png
│ ├── u.png
│ ├── v.png
│ ├── w.png
│ ├── x.png
│ ├── y.png
│ └── z.png
│ ├── bars
│ ├── EXP bar.png
│ └── World map.png
│ ├── buttons
│ ├── Cash shop button.png
│ ├── Change channel button.png
│ ├── Close button.png
│ ├── Create character button.png
│ ├── Login news buttons.png
│ ├── Ok.png
│ └── World menu channels button.png
│ ├── curses
│ ├── No potions curse.png
│ └── Rune cooldown.png
│ ├── map
│ └── Location mark.png
│ ├── menus
│ └── Settings menu E.png
│ ├── messages
│ ├── Death message.png
│ ├── Missing hyper rock.png
│ ├── Rune cooldown.png
│ ├── Rune message 1.png
│ ├── Select a world.png
│ ├── Unable to change channel dialog.png
│ └── World map teleport message.png
│ ├── mini map
│ ├── Left edge.png
│ ├── Npc.png
│ ├── Other player.png
│ ├── Player.png
│ ├── Portal.png
│ ├── Right edge.png
│ ├── Rune.png
│ └── World.png
│ ├── rune keys
│ ├── Down.png
│ ├── Left.png
│ ├── Right.png
│ └── Up.png
│ └── worlds
│ ├── aurora.png
│ ├── bera.png
│ ├── burning.png
│ ├── elysium.png
│ ├── reboot.png
│ └── scania.png
├── Dependencies
├── __pycache__
│ ├── NotebookLoader.cpython-39.pyc
│ └── admin.cpython-39.pyc
└── admin.py
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | compile
2 | compile/*
3 | deaths
4 | deaths/*
5 | log.txt
6 | *.json
7 | __pycache__
8 | __pycache__/*
9 | .ipynb_checkpoints
10 | .ipynb_checkpoints/*
11 | overlay
12 | overlay/*
13 | bot.exe
14 | *.exe
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /../../../../../../../../../../:\Users\Tomer\Desktop\Projects\Practice\Python\Maplestory\Maple Controller\.idea/dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/Maple Controller.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/other.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/_template__of_Python.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/webResources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Bot/.gitignore:
--------------------------------------------------------------------------------
1 | compile
2 | compile/*
3 | deaths
4 | deaths/*
5 | log.txt
6 | *.json
7 | __pycache__
8 | __pycache__/*
9 | .ipynb_checkpoints
10 | .ipynb_checkpoints/*
11 | overlay
12 | overlay/*
13 |
--------------------------------------------------------------------------------
/Bot/Bot.py:
--------------------------------------------------------------------------------
1 | import collections
2 | import sys
3 |
4 | from Controller.MapleMoveMode import MapleMoveMode
5 |
6 | sys.path.append('..')
7 | sys.path.append('..\\Dependencies')
8 | sys.path.append('..\\Controller')
9 |
10 | from Dependencies import admin
11 | from Controller.Controllers.PlayerController import PlayerController
12 | from Controller.funcs import *
13 |
14 | print("Created by tomergt45 (Tomergt89@gmail.com or github.com/tomergt45) ")
15 |
16 | if not admin.isUserAdmin():
17 | print("Note: You must run this application as administrator")
18 | admin.runAsAdmin(wait=False)
19 | sys.exit()
20 |
21 | print("Note: You must play on windowed 800x600 (4:3)")
22 | print(
23 | "Note: You must change your windows UAC settings to 'Never Notify' (don't forget to turn it back after using the bot!)")
24 |
25 |
26 | def get_json_files(path='.'):
27 | return [f for f in os.listdir(".") if f.endswith(".json")]
28 |
29 |
30 | files = get_json_files()
31 |
32 | if len(files) == 0:
33 | raise Exception('No settings.json file was found.')
34 | elif len(files) == 1:
35 | settingsPath = files[0]
36 | else:
37 | print('Found multiple .json files, please select the one you want to use:')
38 | for i, file in enumerate(files):
39 | print(str(i + 1) + ')', file)
40 | selection = int(input("I select: "))
41 | settingsPath = files[selection - 1]
42 |
43 | if os.path.isdir("refs"):
44 | resources_path = "refs"
45 | elif os.path.isdir("../Controller/refs"):
46 | resources_path = "../Controller/refs"
47 | else:
48 | raise Exception("Unable to locate the refs directory.")
49 |
50 | controller = PlayerController(settingsPath, resources_path=resources_path)
51 |
52 | start_time = datetime.datetime.now()
53 | maxlen = 10
54 | history = {
55 | 'last_verbose': time.time(),
56 | 'exp_per_minute_history': collections.deque(maxlen=maxlen),
57 | }
58 | controller.restart_cooldown('change_channel')
59 |
60 | def clear():
61 | os.system("cls")
62 |
63 | def refresh_exp_history(current_exp, t_diff):
64 | if current_exp < history.get('last_exp', current_exp):
65 | history['last_exp'] = 0
66 | history['exp_per_minute_history'] = collections.deque(maxlen=maxlen)
67 | current_exp_diff = current_exp - history.get('last_exp', current_exp) # Gained EXP
68 | current_exp_per_minute = current_exp_diff * (1 / t_diff) * 60
69 | current_exp_per_hour = current_exp_per_minute * 60
70 | history['exp_per_minute_history'].append(current_exp_per_minute)
71 | history['last_exp'] = current_exp
72 |
73 | def verbose():
74 | if controller.check_black_screen():
75 | sleep(1)
76 | return False
77 |
78 | t_diff = time.time() - history['last_verbose']
79 |
80 | # Calculate EXP
81 | if not controller.pause_state:
82 | current_exp = controller.get_exp_precent()
83 | refresh_exp_history(current_exp, t_diff)
84 | exp_per_minute = np.mean(history['exp_per_minute_history'])
85 | exp_per_hour = exp_per_minute * 60
86 | exp_diff = exp_per_minute / 60 * t_diff
87 | estimated_time_rankup = pretty_delta(datetime.timedelta(
88 | minutes=(100 - current_exp) / exp_per_minute)) if exp_per_minute != 0 else "Gain more EXP for estimation"
89 | else:
90 | current_exp = history['last_exp']
91 | exp_diff = exp_per_minute = exp_per_hour = 0
92 | estimated_time_rankup = 'Unable to estimate while paused'
93 |
94 | clear()
95 | print(f"""
96 | Elapsed time:\t\t {str((datetime.datetime.now() - start_time))}
97 | Paused:\t\t\t {controller.pause_state}
98 | Deaths:\t\t\t {controller.deaths}
99 | HP Potions used:\t\t {controller.hp_potions_used}
100 | MP Potions used:\t\t {controller.mp_potions_used}
101 | EXP per {round(t_diff, 1)}s/1m/1h: \t {str(round(exp_diff, 2))}% / {str(round(exp_per_minute, 2))}% / {str(round(exp_per_hour, 2))}%
102 | Estimated time till rankup:\t {estimated_time_rankup}
103 | """)
104 | history['last_verbose'] = time.time()
105 |
106 | def login_bot():
107 | close_news = select_character = select_world = False
108 | controller.restart_cooldown('wait_for_ingame_view')
109 |
110 | if controller.get_status() != MapleState.ACTIVE:
111 | log('Launching maplestory', console=True)
112 | controller.launch_maple()
113 | sleep(30) # Give at least 30 seconds for maple to launch
114 | while 1:
115 | if controller.pause_state:
116 | continue
117 | try:
118 | if controller.check_world_menu_open() or controller.check_cooldown('wait_for_ingame_view', 180):
119 | break
120 | except Exception as e:
121 | log(str(e), console=True)
122 | sleep(5)
123 |
124 | while not controller.check_cooldown('wait_for_ingame_view', 60 * 5):
125 | if controller.pause_state:
126 | continue
127 | if controller.get_status() == MapleState.ACTIVE:
128 | if controller.check_world_menu_open() and not select_world:
129 | log('Maplestory launched and detected', console=True)
130 | select_world = True
131 | controller.select_world(controller.world)
132 | sleep(3)
133 |
134 | elif controller.check_characters_menu_open() and not select_character:
135 | log('Entered characters menu', console=True)
136 | select_character = True
137 | press_and_release('enter')
138 | controller.enter_PIC(controller.PIC)
139 | sleep(3)
140 |
141 | elif controller.check_news_window_open() and not close_news:
142 | sleep(1)
143 | log('Closing annoying news window', console=True)
144 | close_news = True
145 | press_and_release('esc')
146 | sleep(2)
147 |
148 | elif controller.check_exp_bar_inview():
149 | log('Player spawned', console=True)
150 | if not close_news:
151 | log('Pressing safeguard ESC', console=True)
152 | press_and_release('esc')
153 | sleep(.5)
154 | if controller.check_settings_menu_open():
155 | press_and_release('esc')
156 | sleep(1)
157 | if select_world or select_character:
158 | sleep(1)
159 | controller.use_spawn_skills()
160 | return True
161 | return False
162 |
163 | def afk_bot():
164 | if controller.hold_up_state:
165 | controller.press_up()
166 | if controller.move_mode == MapleMoveMode.HOLD:
167 | controller.press_move()
168 |
169 | # Check that maplestory is running and that the cashshop button is in view (indicating that you are in game)
170 | while controller.get_status() == 1:
171 | try: # Sanity check: Failing to grab frame means app is not running properly
172 | verbose()
173 |
174 | if controller.pause_state:
175 | continue
176 | if controller.check_unable_change_channel_dialog_open():
177 | press_and_release('enter')
178 | if controller.check_dead():
179 | controller.on_death()
180 | sleep(1)
181 | break
182 |
183 | controller.check_health_and_heal()
184 | controller.close_tabs()
185 |
186 | if controller.check_mana():
187 | controller.fill_mana()
188 | sleep(.15)
189 | controller.check_direction_and_change()
190 |
191 | if controller.check_cooldown("pet_food", controller.pet_food_period):
192 | controller.feed_pet()
193 | controller.restart_cooldown('pet_food')
194 |
195 | if controller.pause_state:
196 | continue
197 | controller.check_health_and_heal()
198 |
199 | # Attempt to activate rune only if not on cooldown
200 | if not controller.check_rune_cooldown_buff() and controller.attempt_rune():
201 | pass
202 |
203 | # Change channel if:
204 | # Faild to activate rune / Rune is blocking EXP / Another player in map / Channel timeout exceeded
205 | elif controller.check_channel():
206 | # Release move / up keys if on hold
207 | if controller.hold_up_state:
208 | controller.release_up()
209 | if controller.move_mode == MapleMoveMode.HOLD:
210 | controller.release_move()
211 |
212 | status = controller.move_channel()
213 | if not status: # Exit bot if faild to change channel
214 | break
215 |
216 | sleep(2)
217 | controller.restart_cooldown('change_channel')
218 |
219 | # Press move / up keys if on hold
220 | if controller.hold_up_state:
221 | controller.press_up()
222 | if controller.move_mode == MapleMoveMode.HOLD:
223 | controller.press_move()
224 |
225 | while controller.check_no_potion_curse():
226 | controller.check_direction_and_change()
227 | controller.jump_or_doublejump()
228 | controller.attack()
229 | controller.check_direction_and_change()
230 | sleep(.5)
231 |
232 | if controller.pause_state:
233 | continue
234 | controller.check_health_and_heal()
235 |
236 | if controller.check_cooldown('buffs', controller.buffs_period):
237 | controller.attack()
238 | controller.use_buffs()
239 | controller.restart_cooldown('buffs')
240 | # Periodical HP check
241 | if controller.check_cooldown('period hp', 30):
242 | controller.heal()
243 | controller.restart_cooldown('period hp')
244 | if controller.pause_state:
245 | continue
246 |
247 | if controller.ascend_key and controller.check_cooldown("ascend", controller.ascend_period):
248 | controller.restart_cooldown("ascend")
249 | controller.ascend()
250 |
251 | if controller.move_mode == MapleMoveMode.TELEPORT:
252 | controller.grab_frame()
253 | if controller.check_cooldown('teleport down', controller.teleport_down_period):
254 | controller.restart_cooldown('teleport down')
255 | controller.teleport_down()
256 | sleep(.25)
257 | elif controller.check_cooldown('teleport up', controller.teleport_up_period):
258 | controller.restart_cooldown('teleport up')
259 | controller.teleport_up()
260 | sleep(.25)
261 | controller.move()
262 |
263 | controller.check_direction_and_change()
264 | controller.jump_or_doublejump()
265 | controller.check_health_and_heal()
266 | controller.use_uncooldowned_skills()
267 | controller.check_health_and_heal()
268 | controller.check_direction_and_change()
269 | controller.attack()
270 | except:
271 | import traceback
272 | log('AFK Bot crashed attempting restart')
273 | log(''.join(traceback.format_exception(*sys.exc_info())), console=True)
274 | break
275 |
276 | # Release keys left pressed
277 | if controller.hold_up_state:
278 | controller.release_up()
279 | if controller.move_mode == MapleMoveMode.HOLD:
280 | controller.release_move()
281 |
282 | while 1:
283 | if controller.pause_state:
284 | continue
285 | if controller.get_status() == MapleState.CRASHED: # Check if maple crashed
286 | if controller.attempt_restart_after_crash_state: # Close crashed maple
287 | clear()
288 | log('Maplestory has crashed... closing program', console=True)
289 | controller.close_maple()
290 | log('Maplestory closed, waiting 10 seconds and then launching back', console=True)
291 | sleep(10) # Wait a bit for maplestory to close properly
292 | else:
293 | log(
294 | 'Maplestory has crashed, exiting program... (If you want to auto restart maple in future crashes, set "attempt_restart_after_crash=true" in the settings.json file)',
295 | console=True)
296 |
297 | # launch the game, select world, enter PIC and conddddinue fighting
298 | status = login_bot()
299 | try:
300 | if status:
301 | afk_bot()
302 | clear()
303 | else:
304 | log(
305 | 'Maplestory attempt to launch and login has faild after 5 minutes of wait time (this includes attempting to launch the game, select a world, channel, character and enter PIC).',
306 | console=True)
307 | break
308 | except:
309 | import traceback
310 | log(''.join(traceback.format_exception(*sys.exc_info())), console=True)
311 |
--------------------------------------------------------------------------------
/Bot/compile.py:
--------------------------------------------------------------------------------
1 | import os, shutil
2 | import sys
3 |
4 | sys.path.append('..')
5 | sys.path.append('..\\Dependencies')
6 | from Dependencies import admin
7 |
8 | if not admin.isUserAdmin():
9 | admin.runAsAdmin(wait=False)
10 | sys.exit()
11 |
12 | hiddenimports = [
13 | 'numpy',
14 | 'os',
15 | 'subprocess',
16 | 'itertools',
17 | 'ctypes',
18 | 'win32gui',
19 | 'win32com',
20 | 'pyautogui',
21 | 'keyboard',
22 | 'json',
23 | 'datetime',
24 | 'psutil',
25 | 'time',
26 | 'PIL',
27 | "mss",
28 | "cv2",
29 | "shutil",
30 | "re"
31 | ]
32 |
33 |
34 |
35 |
36 | os.makedirs('../compile', exist_ok=True)
37 | with open('../compile/controller imports.py', 'w') as fd:
38 | fd.write('hiddenimports = ' + str(hiddenimports))
39 |
40 | shutil.copyfile("../Dependencies/admin.py", '../compile/admin.py')
41 | shutil.copyfile("Bot.py", '../compile/Bot.py')
42 |
43 | os.system('pyinstaller "../compile/bot.py" --onefile --specpath="../compile/" --distpath="../compile/" --workpath="../compile/" --additional-hooks-dir="../compile/hook-data.py"')
44 |
45 | shutil.copyfile('../compile/bot.exe', 'bot.exe')
46 | shutil.rmtree('../compile')
47 | #
--------------------------------------------------------------------------------
/Controller/Controllers/BaseController.py:
--------------------------------------------------------------------------------
1 | import collections
2 | import subprocess
3 |
4 | from Controller.Controllers.SettingsController import SettingsController
5 | from Controller.funcs import *
6 |
7 | pyautogui.FAILSAFE = False
8 |
9 | nexon_launch_target = "nxl://launch/10100"
10 | steam_launch_target = "steam://rungameid/216150"
11 |
12 | class BaseController(SettingsController):
13 | def __init__(self, settings_path, log_path='log.txt'):
14 | super().__init__(settings_path)
15 | clearlog(path=log_path)
16 |
17 | # Settings variables
18 | self.pause_key = self.get('pause', 'f5')
19 | self.install_origin = self.get('install_origin')
20 |
21 | # Default variables
22 | self.log_path = log_path
23 | self.frames = collections.deque(maxlen=600)
24 | self.cooldowns = {}
25 |
26 | # Keyboard events
27 | self.pause_state = False
28 |
29 | def onpause(e):
30 | self.pause_state = not self.pause_state
31 | log('Paused' if self.pause_state else 'Unpaused')
32 | print('Paused' if self.pause_state else 'Unpaused')
33 |
34 | keyboard.unhook_all()
35 | keyboard.on_release_key(self.pause_key, onpause)
36 |
37 | def grab_frame(self, focus=True):
38 | if self.get_status() == MapleState.ACTIVE:
39 | self.frame_pil, self.box = grab_maple(focus=(focus and not self.pause_state))
40 | self.frame_arr = np.asarray(self.frame_pil)
41 | self.frames.append(self.frame_arr)
42 | return self.frame_pil, self.frame_arr, self.box
43 | else:
44 | raise Exception('Unable to grab a screenshot from maplestory because maplestory isn\'t running.')
45 |
46 | def get_status(self):
47 | return get_maple_status()
48 |
49 | def launch_maple(self):
50 | launch_target = steam_launch_target if self.install_origin == 'steam' else nexon_launch_target
51 | subprocess.run("start {}".format(launch_target), shell=True)
52 |
53 | def close_maple(self):
54 | for process in psutil.process_iter():
55 | name = process.name().lower()
56 | if 'werfault' in name.lower() or 'maplestory' in name.lower():
57 | process.kill()
58 |
59 | def toggle_fullscreen(self):
60 | focus_maple()
61 | press_and_release('alt+enter')
62 |
63 | def focus_maple(self):
64 | focus_maple()
65 |
66 | def restart_cooldown(self, key):
67 | self.cooldowns[key] = time.time()
68 |
69 | def check_cooldown(self, key, cooldown):
70 | if cooldown == -1 or cooldown is None:
71 | return False
72 | if key in self.cooldowns:
73 | return True if time.time() - self.cooldowns[key] > cooldown else False
74 | else:
75 | return True
76 |
--------------------------------------------------------------------------------
/Controller/Controllers/GameController.py:
--------------------------------------------------------------------------------
1 | import pathlib
2 |
3 | from Controller.Controllers.BaseController import BaseController
4 | from Controller.funcs import *
5 |
6 |
7 | class GameController(BaseController):
8 | def __init__(self, settings_path, log_path='log.txt', resources_path="refs"):
9 | super().__init__(settings_path, log_path)
10 |
11 | self.world = self.get('world')
12 | self.PIC = self.get('PIC')
13 | self.world_map_key = self.get('world_map', 'w')
14 | self.channel_period = self.get('change_channel_period', 600)
15 |
16 | # Default variables
17 | self.resources_path = pathlib.Path(resources_path)
18 | if not self.resources_path.exists():
19 | raise Exception("Unable to locate the refs folder at '" + resources_path + "'")
20 |
21 | def select_world(self, world, channel=1):
22 | self.grab_frame()
23 | if self.check_world_menu_open():
24 | if not locate_on_screen(self.get_resource_path("worlds/{}.png".format(world))):
25 | self.grab_frame()
26 | press_and_release('up')
27 | sleep(.25)
28 | press_and_release('up')
29 | sleep(.25)
30 | if locate_on_screen_and_click(self.get_resource_path("worlds/{}.png".format(world)), duration=1):
31 | sleep(.5)
32 | if self.check_world_menu_channels_menu_open():
33 | for i in range(channel - 1):
34 | press_and_release('right')
35 | sleep(.3)
36 | press_and_release('enter')
37 | sleep(1)
38 | else:
39 | raise Exception('Faild selecting world {}, channels menu was not detected.'.format(world))
40 | else:
41 | raise Exception('Faild selecting world {}, world button was not detected.'.format(world))
42 |
43 | def enter_PIC(self, PIC):
44 | self.grab_frame()
45 | for key in PIC:
46 | if not locate_on_screen_and_click(self.get_resource_path('PIC keys/{}.png'.format(key)), duration=.5):
47 | raise Exception('Faild entering PIC, unable to find the key for `{}`.'.format(key))
48 | press_and_release('enter')
49 |
50 | def get_player_position(self, confidence=.9, minimap=None):
51 | if not minimap:
52 | minimap = self.get_mini_map()
53 | return locate(self.get_resource_path('mini map/Player.png'), minimap, confidence=confidence)
54 |
55 | def get_rune_position(self, confidence=.9, minimap=None):
56 | if not minimap:
57 | minimap = self.get_mini_map()
58 | return locate(self.get_resource_path('mini map/Rune.png'), minimap, confidence=confidence)
59 |
60 | def get_mini_map(self, padding=5, confidence=.98):
61 | self.grab_frame()
62 |
63 | left_edge = locate(self.get_resource_path("mini map/Left edge.png"), self.frame_pil, confidence=confidence)
64 | right_edge = locate(self.get_resource_path("mini map/Right edge.png"), self.frame_pil, confidence=confidence)
65 |
66 | try:
67 | return self.frame_pil.crop((left_edge.left, left_edge.top, right_edge.left + padding, right_edge.top + padding))
68 | except:
69 | print("Faild to find minimap")
70 | button = self.get_npc_button()
71 | if not button:
72 | button = self.get_world_button()
73 | if button:
74 | width, height = self.frame_pil.size
75 | return self.frame_pil.crop((0, 0, button.left + button.width + 10, height))
76 | else:
77 | return self.frame_pil
78 |
79 | def get_world_button(self):
80 | self.grab_frame()
81 | return locate(self.get_resource_path("mini map/World.png"), self.frame_pil)
82 |
83 | def get_npc_button(self):
84 | self.grab_frame()
85 | return locate(self.get_resource_path("mini map/Npc.png"), self.frame_pil)
86 |
87 | def click_ok_button(self, duration=1):
88 | self.grab_frame()
89 | button = locate_on_screen(self.get_resource_path('buttons/Ok.png'), confidence=.95)
90 | if button:
91 | pyautogui.click(button, duration=duration)
92 |
93 | def close_tabs(self):
94 | self.grab_frame()
95 | i = 1
96 | while locate_and_click(self.get_resource_path('buttons/Close button.png'), self.frame_pil, self.box, duration=.5,
97 | confidence=.8) and not self.pause_state:
98 | self.grab_frame()
99 | log('Closed tab num. ' + str(i))
100 | press_and_release('enter')
101 | sleep(.25)
102 | i += 1
103 |
104 | def open_world_map(self):
105 | press_and_release(self.world_map_key)
106 |
107 | def get_resource_path(self, resource):
108 | path = self.resources_path / resource
109 | if not path.exists():
110 | raise Exception("Unable to locate resource at " + str(path))
111 | return str(path)
112 |
113 | def check_frame_for_resource(self, resource, confidence=.99):
114 | path = self.get_resource_path(resource)
115 | return True if locate(path, self.frame_pil, confidence=confidence) else False
116 |
117 | def check_world_menu_open(self):
118 | self.grab_frame()
119 | return self.check_frame_for_resource("messages/Select a world.png")
120 |
121 | def check_rune_message_open(self):
122 | self.grab_frame()
123 | return self.check_frame_for_resource("messages/Rune message 1.png")
124 |
125 | def check_settings_menu_open(self):
126 | self.grab_frame()
127 | return self.check_frame_for_resource("menus/Settings menu E.png")
128 |
129 | def check_ingame_channel_menu_open(self):
130 | self.grab_frame()
131 | return self.check_frame_for_resource("buttons/Change channel button.png")
132 |
133 | def check_unable_change_channel_dialog_open(self):
134 | self.grab_frame()
135 | return self.check_frame_for_resource("messages/Unable to change channel dialog.png")
136 |
137 | def check_news_window_open(self):
138 | self.grab_frame()
139 | return self.check_frame_for_resource("buttons/Login news buttons.png")
140 |
141 | def check_world_menu_channels_menu_open(self):
142 | self.grab_frame()
143 | return self.check_frame_for_resource("buttons/World menu channels button.png")
144 |
145 | def check_characters_menu_open(self):
146 | self.grab_frame()
147 | return self.check_frame_for_resource("buttons/Create character button.png")
148 |
149 | def check_cashshop_button_inview(self):
150 | self.grab_frame()
151 | return self.check_frame_for_resource("buttons/Cash shop button.png")
152 |
153 | def check_black_screen(self):
154 | self.grab_frame()
155 | return np.all(self.frame_arr[100:500, 100:500] == 0)
156 |
157 | def check_dead(self):
158 | self.grab_frame()
159 | return self.check_frame_for_resource("messages/Death message.png")
160 |
161 | def check_exp_bar_inview(self):
162 | self.grab_frame()
163 | return self.check_frame_for_resource("bars/EXP bar.png")
164 |
165 | def check_other_player_in_map(self, minimap=None):
166 | if not minimap:
167 | minimap = self.get_mini_map()
168 | return locate(self.get_resource_path("mini map/Other player.png"), minimap)
169 |
170 | def check_no_potion_curse(self):
171 | self.grab_frame()
172 | return self.check_frame_for_resource("curses/No potions curse.png")
173 |
174 | def check_rune_cooldown_message(self):
175 | self.grab_frame()
176 | return self.check_frame_for_resource("messages/Rune cooldown.png", confidence=.5)
177 |
178 | def check_rune_cooldown_buff(self):
179 | self.grab_frame()
180 | return self.check_frame_for_resource("curses/Rune cooldown.png", confidence=.75)
181 |
182 | def check_world_map_open(self):
183 | self.grab_frame()
184 | return self.check_frame_for_resource('bars/World map.png', confidence=.9)
185 |
186 | def check_world_map_teleport_message(self):
187 | self.grab_frame()
188 | return self.check_frame_for_resource('messages/World map teleport message.png', confidence=.75)
189 |
190 | def check_missing_hyper_message(self):
191 | self.grab_frame()
192 | return self.check_frame_for_resource('messages/Missing hyper rock.png', confidence=.75)
193 |
194 | def check_channel(self):
195 | return self.check_rune_message_open() \
196 | or self.check_other_player_in_map() \
197 | or self.check_cooldown('change_channel', self.channel_period)
198 |
199 |
--------------------------------------------------------------------------------
/Controller/Controllers/MovementController.py:
--------------------------------------------------------------------------------
1 | from Controller.Controllers.GameController import GameController
2 | from Controller.MapleMoveMode import MapleMoveMode
3 | from Controller.funcs import *
4 |
5 |
6 | class MovementController(GameController):
7 | def __init__(self, settings_path, log_path='log.txt', resources_path="refs"):
8 | super().__init__(settings_path, log_path=log_path, resources_path=resources_path)
9 |
10 | self.move_mode = self.get('move_mode', 'hold')
11 | self.right_key = self.get('right')
12 | self.left_key = self.get('left')
13 | self.up_key = self.get('up')
14 | self.down_key = self.get('down')
15 | self.jump_key = self.get('jump', None)
16 | self.doublejump_state = self.get('doublejump', True)
17 | self.ascend_key = self.get('ascend', None)
18 | self.ascend_period = self.get('ascend_period', -1)
19 | self.hold_up_state = self.get('hold_up', True)
20 | self.direction_period = self.get('change_direction_period', 10)
21 | self.smart_direction_state = self.get('smart_direction', True)
22 |
23 | # Load TELEPORT settings
24 | if self.move_mode == MapleMoveMode.TELEPORT:
25 | self.teleport_up_period = self.get('teleport_up_period', 10)
26 | self.teleport_down_period = self.get('teleport_down_period', 30)
27 | self.teleport_up_key = self.get('teleport_up')
28 | self.teleport_down_key = self.get('teleport_down')
29 | self.teleport_right_key = self.get('teleport_right')
30 | self.teleport_left_key = self.get('teleport_left')
31 | self.hold_up_state = False
32 |
33 | if self.smart_direction_state:
34 | self.direction_period = 0
35 |
36 | # Default variables
37 | self.move_key = self.teleport_right_key if self.move_mode == MapleMoveMode.TELEPORT else self.right_key
38 | self.move_locked = False
39 | self.moving = False
40 | self.last_smart_direction = None
41 |
42 | def jump(self):
43 | press_and_release(self.jump_key)
44 |
45 | def doublejump(self):
46 | press_and_release(self.jump_key, repeat=2)
47 |
48 | def press_right(self):
49 | press(self.right_key)
50 |
51 | def release_right(self):
52 | release(self.right_key)
53 |
54 | def right(self):
55 | press_and_release(self.right_key)
56 |
57 | def press_left(self):
58 | press(self.left_key)
59 |
60 | def release_left(self):
61 | release(self.left_key)
62 |
63 | def left(self):
64 | press_and_release(self.left_key)
65 |
66 | def press_up(self):
67 | press(self.up_key)
68 |
69 | def release_up(self):
70 | release(self.up_key)
71 |
72 | def up(self):
73 | press_and_release(self.up_key)
74 |
75 | def press_down(self):
76 | press(self.down_key)
77 |
78 | def release_down(self):
79 | release(self.down_key)
80 |
81 | def down(self):
82 | press_and_release(self.down_key)
83 |
84 | def teleport_right(self):
85 | press_and_release(self.teleport_right_key)
86 |
87 | def teleport_left(self):
88 | press_and_release(self.teleport_left_key)
89 |
90 | def teleport_up(self):
91 | press_and_release(self.teleport_up_key)
92 |
93 | def teleport_down(self):
94 | press_and_release(self.teleport_down_key)
95 |
96 | def press_move(self):
97 | press(self.move_key)
98 | self.moving = True
99 |
100 | def release_move(self):
101 | self.focus_maple()
102 | release(self.move_key)
103 | self.moving = False
104 |
105 | def move(self):
106 | self.moving = True
107 | press_and_release(self.move_key)
108 | self.moving = False
109 |
110 | def toggle_move_direction(self):
111 | if self.move_mode == MapleMoveMode.HOLD:
112 | self.move_key = self.left_key if self.move_key == self.right_key else self.right_key
113 | elif self.move_mode == MapleMoveMode.TELEPORT:
114 | self.move_key = self.teleport_left_key if self.move_key == self.teleport_right_key else self.teleport_right_key
115 |
116 | def set_move_direction(self, direction_num, force_mode=None):
117 | if abs(direction_num) != 1:
118 | return
119 | elif self.move_mode == MapleMoveMode.HOLD or force_mode == MapleMoveMode.HOLD:
120 | self.move_key = self.left_key if direction_num == -1 else self.right_key
121 | elif self.move_mode == MapleMoveMode.TELEPORT or force_mode == MapleMoveMode.TELEPORT:
122 | self.move_key = self.teleport_left_key if direction_num == -1 else self.teleport_right_key
123 | log("Move direction key changed to: " + self.move_key)
124 |
125 | def change_move_direction(self):
126 | if self.smart_direction_state:
127 | direction = self.get_smart_direction()
128 | self.set_move_direction(direction)
129 | else:
130 | self.toggle_move_direction()
131 |
132 | def lock_move(self):
133 | self.move_locked = True
134 |
135 | def unlock_move(self):
136 | self.move_locked = False
137 |
138 | def is_move_locked(self):
139 | return self.move_locked
140 |
141 | def check_direction_and_change(self):
142 | log("Checking direction")
143 | if self.check_cooldown("change_direction", self.direction_period) and not self.is_move_locked():
144 | self.change_direction()
145 | self.restart_cooldown("change_direction")
146 |
147 | def change_direction(self):
148 | moving = self.moving
149 | if moving and self.move_mode == MapleMoveMode.HOLD:
150 | self.release_move()
151 | self.change_move_direction()
152 | if moving and self.move_mode == MapleMoveMode.HOLD:
153 | self.press_move()
154 |
155 | def get_smart_direction(self, winPrecent=.5):
156 | minimap = self.get_mini_map()
157 |
158 | max_left = minimap.size[0]
159 | center_left = max_left // 2
160 | win_size = round(center_left * winPrecent)
161 | xMin, xMax = center_left - win_size, center_left + win_size
162 |
163 | try:
164 | player_left = self.get_player_position(minimap=minimap).left
165 |
166 | if player_left < xMin:
167 | direction = 1
168 | elif player_left > xMax:
169 | direction = -1
170 | else:
171 | return 0
172 | except:
173 | print("Couldn't find player")
174 | return np.random.choice([-1, 1])
175 |
176 | self.last_smart_direction = direction
177 | return direction
178 |
179 | def ascend(self):
180 | press_and_release(self.ascend_key)
181 |
182 | def jump_or_doublejump(self):
183 | if self.doublejump_state:
184 | self.doublejump()
185 | else:
186 | self.jump()
187 |
188 |
--------------------------------------------------------------------------------
/Controller/Controllers/PlayerController.py:
--------------------------------------------------------------------------------
1 | import re
2 | import sys
3 |
4 | import cv2
5 |
6 | from Controller.MapleMoveMode import MapleMoveMode
7 | from Controller.funcs import *
8 | from Controller.Controllers.PotionsController import PotionsController
9 | from Controller.Controllers.MovementController import MovementController
10 |
11 |
12 | class PlayerController(MovementController, PotionsController):
13 | def __init__(self, settings_path, log_path='log.txt', resources_path="refs", deathsfolder='deaths'):
14 | PotionsController.__init__(self, settings_path, log_path=log_path)
15 | MovementController.__init__(self, settings_path, log_path=log_path, resources_path=resources_path)
16 |
17 | # Settings variables
18 | self.attack_key = self.get('attack')
19 | self.attack_interval = self.get('attack_interval', .25)
20 | self.attack_repeat = self.get('attack_repeat', 5)
21 | self.buffs_key = self.get('buffs', [])
22 | self.buffs_period = self.get('buffs_period', 50)
23 | self.buffs_interval = self.get('buffs_interval', .5)
24 | self.skills = self.get('skills', [])
25 | self.skills_interval = self.get('skills_interval', .25)
26 | self.spawn_skills = self.get('spawn_skills', [])
27 | self.spawn_skills_interval = self.get('spawn_skills_interval', .25)
28 | self.interact_key = self.get('interact', 'space')
29 | self.hyper_teleport_state = self.get('hyper_teleport', True)
30 | self.attempt_restart_after_crash_state = self.get('attempt_restart_after_crash', True)
31 | self.console_update_period = self.get('console_update_period', 60)
32 |
33 | # Default variables
34 | self.deaths = 0
35 | self.deathsfolder = deathsfolder
36 |
37 | def get_exp_precent(self):
38 | try:
39 | box = get_maple_windows()[0].box
40 | images = ["slash.png", "bracket.png"] + [str(i) + '.png' for i in range(10)]
41 | pyautogui.moveTo(box.left + 5, box.top + box.height - 5, _pause=False)
42 | self.grab_frame()
43 | img = Image.fromarray(self.frame_arr[-30:-5, 5:500])
44 |
45 | if locate(self.get_resource_path('EXP digits/exp.png'), img, confidence=.85):
46 | results = locate_all_multiple_images(img,
47 | self.get_resource_path('EXP digits/'),
48 | images,
49 | confidence=.85,
50 | key=lambda x: x[1].left)
51 | results = re.split('slash|bracket', ''.join(results[:, 0]))[:2]
52 | results = np.asarray(results, dtype=np.int64)
53 | exp, max_exp = results
54 | return exp / max_exp * 100
55 | else:
56 | return 0
57 | except:
58 | return 0
59 |
60 | def attack(self):
61 | log('Attacking')
62 | for i in range(self.attack_repeat):
63 | if self.pause_state or self.check_channel():
64 | break
65 | press_and_release(self.attack_key)
66 | self.check_direction_and_change()
67 | sleep(self.attack_interval)
68 |
69 | def interact(self):
70 | press_and_release(self.interact_key)
71 |
72 | def use_buffs(self):
73 | self.release_move()
74 |
75 | for key in self.buffs_key:
76 | if self.pause_state or self.check_channel():
77 | break
78 | self.check_health_and_heal()
79 | self.check_direction_and_change()
80 | sleep(self.buffs_interval)
81 | press_and_release(key)
82 |
83 | if self.move_mode == MapleMoveMode.HOLD:
84 | self.press_move()
85 |
86 | def use_skill(self, skill_settings):
87 | log('Using skill:' + str(skill_settings))
88 | for i in range(5):
89 | if self.pause_state:
90 | break
91 | press(skill_settings['key'])
92 | sleep(skill_settings.get('hold', .1) / 5)
93 | release(skill_settings['key'])
94 |
95 | def use_uncooldowned_skills(self):
96 | if any(self.check_cooldown(skill['key'], skill['period']) for skill in self.skills):
97 | sleep(0.75) # Wait for any active animations to end
98 | for skill in self.skills:
99 | if self.pause_state or self.check_channel():
100 | break
101 | if self.check_cooldown(skill['key'], skill['period']):
102 | self.check_health_and_heal()
103 | self.check_direction_and_change()
104 | self.use_skill(skill)
105 | self.restart_cooldown(skill['key'])
106 | sleep(self.skills_interval)
107 |
108 | def use_spawn_skills(self):
109 | for skill in self.spawn_skills:
110 | self.use_skill(skill)
111 | sleep(self.spawn_skills_interval)
112 |
113 | def save_last_frames(self, path, fps=10, fourcc='H264'):
114 | fourcc = cv2.VideoWriter_fourcc(*fourcc)
115 | writer = cv2.VideoWriter(path, fourcc, fps, self.frames[0].shape[1::-1])
116 |
117 | for frame in self.frames:
118 | frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
119 | writer.write(frame)
120 |
121 | writer.release()
122 |
123 | def move_channel(self):
124 | while self.get_status() == MapleState.ACTIVE and not self.pause_state:
125 | # Make sure player wont die during channel change
126 | self.check_health_and_heal()
127 |
128 | if self.check_dead():
129 | log('Player died while trying to change channel')
130 | self.on_death()
131 | return False
132 |
133 | while self.check_no_potion_curse():
134 | if self.pause_state:
135 | break
136 | self.check_direction_and_change()
137 | self.attack()
138 | sleep(.5)
139 |
140 | press_and_release('esc')
141 | sleep(.15)
142 |
143 | if self.check_settings_menu_open():
144 | log('Change channel - Settings menu opened')
145 | press_and_release('enter')
146 | sleep(.15)
147 |
148 | if self.check_ingame_channel_menu_open():
149 | log('Change channel - Channel menu opened')
150 | press_and_release('right')
151 | sleep(.15)
152 |
153 | # Make sure player wont die during channel change
154 | if self.check_health():
155 | log('Change channel - Heal')
156 | press_and_release('esc')
157 | self.attack()
158 | self.heal()
159 | sleep(.15)
160 | continue
161 |
162 | press_and_release('enter')
163 | sleep(1)
164 |
165 | if self.check_unable_change_channel_dialog_open():
166 | log('Change channel - Unable to change channel dialog')
167 | press_and_release('enter')
168 | continue
169 |
170 | # Random pixel turns black must mean success
171 | # Or if all screen turned black
172 | if self.check_black_screen():
173 | log('Change channel - Successfully changed channel')
174 | if self.move_mode == MapleMoveMode.HOLD:
175 | self.check_direction_and_change()
176 | self.press_move()
177 |
178 | return True
179 |
180 | def attempt_rune(self):
181 | minimap = self.get_mini_map()
182 | player = self.get_player_position(.8, minimap=minimap)
183 | rune = self.get_rune_position(minimap=minimap)
184 |
185 | if player and rune: # If player and rune are visible in the minimap
186 | reached_rune = self.reach_rune()
187 |
188 | if reached_rune:
189 | # Maximum of 10 seconds to attempt activating the rune
190 | self.restart_cooldown('attempt rune')
191 | while not self.check_cooldown('attempt rune', 30) and not self.pause_state:
192 | log('Moving towards rune - ' + str(abs(player.left - rune.left)) + 'px left')
193 | self.check_health_and_heal()
194 | self.release_move()
195 | self.move() # Move towards rune
196 |
197 | activated = self.activate_rune(rune)
198 | if activated:
199 | log('Activated rune')
200 | break
201 |
202 | self.unlock_move()
203 | return False
204 |
205 | def reach_rune(self):
206 | log('Attempting to reach rune')
207 |
208 | minimap = self.get_mini_map()
209 | player = self.get_player_position(minimap=minimap)
210 | if not player:
211 | return False
212 | rune = self.get_rune_position(minimap=minimap)
213 | direction = -1 if player.left - rune.left > 0 else 1
214 |
215 | self.release_move()
216 | self.lock_move()
217 | self.set_move_direction(direction, force_mode=MapleMoveMode.HOLD)
218 |
219 | # Maximum of 10 seconds to reach rune x axis
220 | self.restart_cooldown('reach rune x axis')
221 |
222 | while not self.check_cooldown('reach rune x axis', 15) and not self.pause_state:
223 | self.check_health_and_heal()
224 |
225 | player = self.get_player_position()
226 |
227 | if not player:
228 | continue
229 |
230 | currentDirection = -1 if player.left - rune.left > 0 else 1
231 |
232 | if currentDirection == direction:
233 | self.press_move()
234 | if self.doublejump_state:
235 | self.doublejump()
236 | continue
237 | else:
238 | self.unlock_move()
239 | self.release_move()
240 | self.set_move_direction(currentDirection, force_mode=MapleMoveMode.HOLD)
241 | self.press_move()
242 |
243 | while not self.check_cooldown('reach rune x axis', 15) and not self.pause_state:
244 | self.check_health_and_heal()
245 | player = self.get_player_position()
246 |
247 | if abs(player.left - rune.left) <= 3:
248 | self.release_move()
249 | break
250 |
251 | player = self.get_player_position()
252 |
253 | if player.top > rune.top: # Player below rune
254 | while not self.check_cooldown('reach rune x axis', 15) and not self.pause_state:
255 | self.check_health_and_heal()
256 | player = self.get_player_position()
257 |
258 | if not player:
259 | continue
260 |
261 | if rune.top - 3 <= player.top <= rune.top + 3: # Check if player reached rune
262 | return True
263 |
264 | self.ascend()
265 | sleep(.5)
266 | else: # Player above rune
267 | while not self.check_cooldown('reach rune x axis', 15) and not self.pause_state:
268 | self.check_health_and_heal()
269 | player = self.get_player_position()
270 |
271 | if not player:
272 | continue
273 |
274 | if rune.top - 3 <= player.top <= rune.top + 3: # Check if player reached rune
275 | return True
276 |
277 | press_and_release(self.down_key + "+" + self.jump_key)
278 | sleep(.5)
279 |
280 | return False
281 |
282 | def activate_rune(self, rune):
283 | log('Attempting to activate rune')
284 |
285 | # Help function
286 | def filter_rune_results(results):
287 | results = list(results)
288 | if len(results) == 0: return []
289 | current_result = results[0]
290 | yield (current_result[0], current_result[1].left)
291 | for result in results:
292 | if not (current_result[1].left - 10 <= result[1].left <= current_result[1].left + 10):
293 | current_result = result
294 | yield (current_result[0], current_result[1].left)
295 |
296 | player = self.get_player_position()
297 |
298 | if not player:
299 | return False
300 | elif rune.left - 3 <= player.left <= rune.left + 3: # Check if player reached rune
301 | self.restart_cooldown('activate rune')
302 | while not self.check_cooldown('activate rune', 15) and not self.pause_state:
303 | sleep(1.5)
304 | self.interact()
305 |
306 | sleep(.5)
307 | self.grab_frame(focus=False)
308 |
309 | rune_keys_pil = self.frame_pil.crop((150, 150, 650, 400))
310 | keys = locate_all_multiple_images(rune_keys_pil,
311 | self.get_resource_path('rune keys/'),
312 | ["Up.png", "Down.png", "Right.png", "Left.png"],
313 | confidence=.7,
314 | key=lambda x: x[1].left)
315 |
316 | keys = list(filter_rune_results(keys))
317 |
318 | if len(keys) == 0:
319 | return True
320 |
321 | for key, x in keys:
322 | press_and_release(key)
323 | sleep(.25)
324 |
325 | return False
326 |
327 | def mark_world_map_location(self):
328 | self.focus_maple()
329 | if not self.check_world_map_open():
330 | self.open_world_map()
331 | sleep(.5)
332 | self.grab_frame(focus=False)
333 | if self.check_world_map_open():
334 | mark = locate(self.get_resource_path('map/Location mark.png'), self.frame_pil, confidence=.85)
335 | self.open_world_map() # Press world map key to close it
336 | sleep(.5)
337 | return mark
338 |
339 | def teleport_to_mark(self, mark):
340 | if mark:
341 | self.focus_maple()
342 | self.open_world_map()
343 | sleep(.5)
344 | for i in range(10):
345 | pyautogui.doubleClick(self.box.left + mark.left + mark.width // 2,
346 | self.box.top + mark.top + mark.height + i, duration=1 / 3)
347 | if self.check_world_map_teleport_message():
348 | press_and_release('enter')
349 | return True
350 | elif self.check_missing_hyper_message():
351 | return False
352 | return False
353 |
354 | def on_death(self, save_vid=True):
355 | log('Player died, saving death video')
356 | if save_vid:
357 | if not os.path.exists(self.deathsfolder):
358 | os.makedirs(self.deathsfolder)
359 | self.save_last_frames(
360 | self.deathsfolder + '\\' + datetime.datetime.now().strftime("%m-%d-%Y %H-%M-%S") + '.mp4')
361 | self.deaths += 1
362 | if self.hyper_teleport_state:
363 | sleep(2)
364 | mark = self.mark_world_map_location()
365 | sleep(1)
366 | self.click_ok_button()
367 | sleep(5)
368 | self.check_health_and_heal()
369 | if mark:
370 | if self.teleport_to_mark(mark):
371 | sleep(3)
372 | self.use_spawn_skills()
373 | else:
374 | raise Exception('Faild respawning after death')
375 | else:
376 | sys.exit()
377 |
378 | controller = PlayerController("Shade Settings.json", resources_path="../Controller/refs")
--------------------------------------------------------------------------------
/Controller/Controllers/PotionsController.py:
--------------------------------------------------------------------------------
1 | from Controller.Controllers.BaseController import BaseController
2 | from Controller.funcs import *
3 |
4 |
5 | class PotionsController(BaseController):
6 | def __init__(self, settings_path, log_path='log.txt'):
7 | super().__init__(settings_path, log_path)
8 |
9 | self.hp_potion_key = self.get('hp_potion', None)
10 | self.min_potion_hp = self.get('min_potion_hp', 50)
11 | self.mana_potion_key = self.get('mana_potion', None)
12 | self.min_potion_mp = self.get('min_potion_mp', 50)
13 | self.potions_per_use = self.get('potions_per_use', 1)
14 | self.delay_per_potion = self.get('delay_per_potion', 0)
15 | self.pet_food_key = self.get('pet_food', None)
16 | self.pet_food_period = self.get('pet_food_period', 100)
17 |
18 | self.hp_potions_used = 0
19 | self.mp_potions_used = 0
20 |
21 | def get_hp_precent(self):
22 | try:
23 | self.grab_frame()
24 | img = self.frame_arr[575:586, 441:571]
25 | img = img.copy()
26 | img[np.where(img < 200)] = 0
27 | imax = 0
28 | for row in img:
29 | r, g, b = row.T
30 | cond = (r > 240) & (g == 0) & (b == 0)
31 | i = np.where(cond)[0].max()
32 | if i > imax:
33 | imax = i
34 | return imax / img.shape[1] * 100
35 | except:
36 | return 0
37 |
38 | def get_mp_precent(self):
39 | self.grab_frame()
40 | img = self.frame_arr[591:602, 441:578]
41 | img = img.copy()
42 | r, g, b = img.T
43 | cond = (r < 200) & (g > 200) & (b > 200)
44 | try:
45 | mp = np.where(cond)[0].max()
46 | except:
47 | mp = 0
48 | return mp / img.shape[1] * 100
49 |
50 | def check_health(self):
51 | return self.get_hp_precent() < self.min_potion_hp
52 |
53 | def check_health_and_heal(self, after_delay=0):
54 | if self.check_health():
55 | self.heal()
56 | sleep(after_delay)
57 |
58 | def check_mana(self):
59 | return self.get_mp_precent() < self.min_potion_mp
60 |
61 | def heal(self):
62 | self.grab_frame()
63 | for i in range(self.potions_per_use):
64 | press_and_release(self.hp_potion_key)
65 | self.hp_potions_used += 1
66 | log('Healing')
67 | if i > 0: sleep(self.delay_per_potion)
68 |
69 | def fill_mana(self, delay_per_fill=.25):
70 | self.grab_frame()
71 | for i in range(self.potions_per_use):
72 | press_and_release(self.mana_potion_key)
73 | self.mp_potions_used += 1
74 | log('Filling mana')
75 | if i > 0: sleep(self.delay_per_potion)
76 |
77 | def feed_pet(self):
78 | press_and_release(self.pet_food_key)
79 |
--------------------------------------------------------------------------------
/Controller/Controllers/SettingsController.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 |
4 | class SettingsController:
5 | DEFAULT_VAL = "~SETTINGS_CONTROLLER_DEFAULT_VALUE~"
6 |
7 | def __init__(self, settings_path):
8 | self.settings = SettingsController.load_settings(settings_path)
9 |
10 | @staticmethod
11 | def load_settings(path):
12 | with open(path) as fd:
13 | return json.load(fd)
14 |
15 | def get(self, key, default_value=DEFAULT_VAL):
16 | if key not in self.settings:
17 | if default_value == SettingsController.DEFAULT_VAL:
18 | raise ValueError("The .json file does not contain the key '" + key + "'")
19 | else:
20 | return default_value
21 | else:
22 | return self.settings[key]
23 |
--------------------------------------------------------------------------------
/Controller/Elite boss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/Elite boss.png
--------------------------------------------------------------------------------
/Controller/MapleMoveMode.py:
--------------------------------------------------------------------------------
1 | class MapleMoveMode:
2 | HOLD = 'hold'
3 | TELEPORT = 'teleport'
4 |
--------------------------------------------------------------------------------
/Controller/MapleState.py:
--------------------------------------------------------------------------------
1 | class MapleState:
2 | CLOSED = 0
3 | ACTIVE = 1
4 | CRASHED = 2
5 |
--------------------------------------------------------------------------------
/Controller/docs/Controller Settings.md:
--------------------------------------------------------------------------------
1 | # Settings.json
2 | The `settings.json` file is used to contain the settings of the `MapleController` class, below you can find all the optional parameters that can be used within it.
3 |
4 | Notes:
5 | 1. The names are case sensitive.
6 | 2. An empty default cell means required.
7 |
8 | ### General
9 | Name | Type | Description | Default
10 | ---- | ---- | ---- | ----
11 | `install_origin` | String | The source of your installation, can be either `steam` or `nexon` |
12 | `world` | String | The world your character is in (use this only if you want to use the auto restart system) |
13 | `PIC` | String | Your character's PIC (use this only if you want to use the auto restart system) |
14 | `toggle_pause` | Boolean | The key used to toggle in and out of pause mode | `f5`
15 | `attempt_restart_after_crash` | Boolean | Indication if to attempt restart when the game crashes | `true`
16 | `hyper_teleport` | Boolean | Indication if to attempt to teleport back to the training region after death (using an hyper teleport rock) | `true`
17 |
18 | ### Movement
19 | Name | Type | Description | Default
20 | ---- | ---- | ---- | ----
21 | `move_mode` | String | The mode of the movement, can be either `hold` or `teleport` | `hold`
22 | `smart_direction` | Boolean | Indicates if the direction of the player is smartly decided (more info below) or is constantly switching between right and left | `true`
23 | `right` | String | The key of your right movement |
24 | `left` | String | The key of your left movement |
25 | `up` | String | The key of your up movement |
26 | `down` | String | The key of your down movement |
27 | `teleport_right` | String | The key (or key combination, i.e. `right+shift`) used to teleport right (use this only when `move_mode=teleport`) | `None`
28 | `teleport_left` | String | The key (or key combination, i.e. `right+shift`) used to teleport left (use this only when `move_mode=teleport`) | `None`
29 | `teleport_up` | String | The key (or key combination, i.e. `right+shift`) used to teleport up (use this only when `move_mode=teleport`) | `None`
30 | `teleport_down` | String | The key (or key combination, i.e. `right+shift`) used to teleport down (use this only when `move_mode=teleport`) | `None`
31 | `teleport_up_period` | Number | The period of which to teleport up (use this only when `move_mode=teleport`) | 10
32 | `teleport_down_period` | Number | The period of which to teleport down (use this only when `move_mode=teleport`) | 30
33 | `hold_up` | Boolean | Indication if to keep the up key pressed the entire time | `true`
34 | `jump` | String | The key of your character's jump |
35 | `doublejump` | Boolean | Indication if to double jump (press the jump key twice) everytime you jump | `true`
36 | `change_direction_period` | Number | The period of which to change direction | 10 (seconds)
37 |
38 | ### Attack
39 | Name | Type | Description | Default
40 | ---- | ---- | ---- | ----
41 | `attack` | String | The key of your main attack |
42 | `attack_repeat` | Number | The number of attacks (key presses) to perform each time you attack | 5
43 | `attack_interval` | Number | The delay (in seconds) between each of the key presses | 0.25
44 |
45 | ### Misc
46 | Name | Type | Description | Default
47 | ---- | ---- | ---- | ----
48 | `interact` | String | The key used to activate runes / interact with stuff | `space`
49 | `world_map` | String | The key used to open the world map | `w`
50 |
51 | ### Potions
52 | Name | Type | Description | Default
53 | ---- | ---- | ---- | ----
54 | `hp_potion` | String | The key of your HP potion | `None`
55 | `min_potion_hp` | Number | Minimum HP required to take a potion in precent | 50
56 | `mana_potion` | String | The key of your MP potion | `None`
57 | `min_potion_mp` | Number | Minimum MP required to take a potion in precent | 50
58 | `potions_per_use` | Number | The number of potions to take each time (this applies to both HP and MP) | 1
59 | `delay_per_potion` | Number | Delay (in seconds) per potion take | 0
60 | `pet_food` | String | The key of your pet food | `None`
61 | `pet_food_period` | Number | The period of which to take the pet food | 100 (1.4 minutes)
62 |
63 | ### Channel
64 | Name | Type | Description | Default
65 | ---- | ---- | ---- | ----
66 | `change_channel_period` | Number | The period of which to change channel | 600 (10 minutes)
67 |
68 | ### Buffs
69 | Name | Type | Description | Default
70 | ---- | ---- | ---- | ----
71 | `buffs` | List\ | A list of strings where each string is a key for a buff | `[]` (empty list)
72 | `buffs_interval` | Number | The delay (in seconds) between each buff's keypress | 0.5
73 | `buffs_period` | Number | The period of which to activate the buffs | 50 (seconds)
74 |
75 | ### Skills
76 | Name | Type | Description | Default
77 | ---- | ---- | ---- | ----
78 | `skills` | List<{}> | A list of dicts where each dict is a skills containing `key`, `period` and (optional) `hold` | `[]`
79 | `skills_interval` | Number | The delay between skill keypress | 0.25
80 | `spawn_skills` | List<{}> | A list of skills to activate on spawn (death respawn or crash) | `[]`
81 | `spawn_skills_interval` | Number | The delay between skill keypresses | 0.25
82 |
83 | ### Misc skills
84 | Name | Type | Description | Default
85 | ---- | ---- | ---- | ----
86 | `ascend` | String | Key used to quickly ascend to the platform above you (For example the skill `Rope Lift`) | `None`
87 | `ascend_period` | Number | The period of which to ascend upwards | -1 (seconds)
88 |
89 | # Move mode
90 | Move mode dictates the mode of which to move the player, currently the available modes are:
91 | - `hold`: Leaving the direction key pressed until direction change to keep the player constantly moving.
92 | - `teleport`: Constantly teleports the player, make sure to set all teleportation keys (i.e. if `up+shift` teleport you up than set this as your `teleport_up` key). this would also overwrite `hold_up` to `false`.
93 |
94 | # Smart direction
95 | When smart direction is enabled the player will be constantly guided into the center of the map, this feature will overwrite `change_direction_period` to 0.
96 |
97 | 
98 |
--------------------------------------------------------------------------------
/Controller/docs/images/Download folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/docs/images/Download folder.png
--------------------------------------------------------------------------------
/Controller/docs/images/Json selection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/docs/images/Json selection.png
--------------------------------------------------------------------------------
/Controller/docs/images/Resolution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/docs/images/Resolution.png
--------------------------------------------------------------------------------
/Controller/docs/images/Smart direction example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/docs/images/Smart direction example.png
--------------------------------------------------------------------------------
/Controller/docs/images/UAC1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/docs/images/UAC1.png
--------------------------------------------------------------------------------
/Controller/docs/images/UAC2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/docs/images/UAC2.png
--------------------------------------------------------------------------------
/Controller/funcs.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import os
3 | import time
4 |
5 | import keyboard
6 | import mss
7 | import numpy as np
8 | import psutil
9 | import pyautogui
10 | import win32gui
11 | from PIL import Image
12 | from win32com.client import Dispatch
13 | from Controller.MapleState import MapleState
14 |
15 |
16 | def get_maple_hwnd():
17 | return win32gui.FindWindowEx(None, None, None, 'MapleStory')
18 |
19 |
20 | def get_maple_processes():
21 | for proc in psutil.process_iter():
22 | if 'maplestory' in proc.name().lower():
23 | yield proc
24 |
25 |
26 | def convert_psutil_status(status):
27 | if status == psutil.STATUS_RUNNING:
28 | return MapleState.ACTIVE
29 | else:
30 | return MapleState.CRASHED
31 |
32 |
33 | def get_maple_status():
34 | mprocesses = list(get_maple_processes())
35 | if len(mprocesses) == 0:
36 | return MapleState.CLOSED
37 | else:
38 | for mproc in mprocesses:
39 | status = convert_psutil_status(mproc.status())
40 | if status != MapleState.ACTIVE:
41 | return status
42 | return MapleState.ACTIVE
43 |
44 |
45 | def focus_maple():
46 | hwnd = get_maple_hwnd()
47 | shell = Dispatch("WScript.Shell")
48 | shell.SendKeys('%')
49 | try:
50 | win32gui.SetForegroundWindow(hwnd)
51 | except:
52 | pass
53 |
54 |
55 | def get_maple_windows():
56 | wins = pyautogui.getWindowsWithTitle("MapleStory")
57 | if get_maple_status() == MapleState.ACTIVE and len(wins) > 0:
58 | return list(filter(lambda x: x.title == 'MapleStory', wins))
59 | else:
60 | raise Exception("Unable to get maplestory, maplestory is not running")
61 |
62 |
63 | def grab_maple(focus=True):
64 | wins = get_maple_windows()
65 | box = wins[0].box
66 | if len(wins) == 0:
67 | return None
68 |
69 | if focus:
70 | focus_maple()
71 |
72 | with mss.mss() as sct:
73 | mon = sct.monitors[1]
74 | monitor = {
75 | "top": mon["top"] + box.top, # 100px from the top
76 | "left": mon["left"] + box.left, # 100px from the left
77 | "width": box.width,
78 | "height": box.height,
79 | "mon": 1,
80 | }
81 | img = sct.grab(monitor)
82 | img = Image.frombytes("RGB", img.size, img.bgra, "raw", "BGRX")
83 |
84 | return img, box
85 |
86 |
87 | def press_and_release(key, release_delay=.1, repeat=1):
88 | if key:
89 | for i in range(repeat):
90 | press(key)
91 | sleep(release_delay)
92 | release(key)
93 |
94 |
95 | def press(key):
96 | if key:
97 | keyboard.press(key)
98 |
99 |
100 | def release(key):
101 | if key:
102 | keyboard.release(key)
103 |
104 |
105 | def click(x=None, y=None, duration=0, clicks=1, interval=0):
106 | pyautogui.click(x, y, duration=duration, interval=interval, clicks=clicks)
107 |
108 |
109 | def locate(img_path, source, confidence=.999):
110 | return pyautogui.locate(img_path, source, confidence=confidence)
111 |
112 |
113 | def locate_all(img_path, source, confidence=.999):
114 | return pyautogui.locateAll(img_path, source, confidence=confidence)
115 |
116 |
117 | def locate_all_multiple_images(source, path, imgnames, confidence=.99, key=None):
118 | results = []
119 | for img in imgnames:
120 | img_path = os.path.join(path, img)
121 | img = img.split('.')[0]
122 | for result in locate_all(img_path, source, confidence):
123 | results.append((img, result))
124 | results = sorted(results, key=key) if key else results
125 | return np.asarray(results, dtype=tuple)
126 |
127 |
128 | def locate_on_screen(img_path, confidence=.999):
129 | return pyautogui.locateOnScreen(img_path, confidence=confidence)
130 |
131 |
132 | def locate_all_on_screen(img_path, confidence=.999):
133 | return pyautogui.locateAllOnScreen(img_path, confidence=confidence)
134 |
135 |
136 | def locate_on_screen_and_click(img_path, clicks=1, clicks_interval=0, duration=0, confidence=.999):
137 | box = locate_on_screen(img_path, confidence=confidence)
138 | if box:
139 | click(box, duration=duration, clicks=clicks, interval=clicks_interval)
140 | return True
141 | return False
142 |
143 |
144 | def locate_and_click(img_path, source, source_box, clicks=1, clicks_interval=0, duration=0, confidence=.999):
145 | box = locate(img_path, source, confidence=confidence)
146 | if box:
147 | click(source_box.left + box.left, source_box.top + box.top, duration=duration, clicks=clicks,
148 | interval=clicks_interval)
149 | return True
150 | return False
151 |
152 |
153 | def sleep(seconds):
154 | time.sleep(seconds)
155 |
156 |
157 | def log(message, path='log.txt', console=False):
158 | with open(path, 'a') as fd:
159 | message = '[{}] {}\n'.format(str(datetime.datetime.now()), message)
160 | fd.write(message)
161 | if console:
162 | print(message)
163 |
164 |
165 | def clearlog(path='log.txt'):
166 | with open(path, 'w') as fd:
167 | fd.seek(0)
168 | fd.truncate()
169 |
170 | def pretty_delta(delta, granularity=2):
171 | result = []
172 | intervals = (('weeks', 604800), ('days', 86400), ('hours', 3600), ('minutes', 60), ('seconds', 1))
173 | seconds = delta.seconds
174 | for name, count in intervals:
175 | value = seconds // count
176 | if value:
177 | seconds -= value * count
178 | if value == 1:
179 | name = name.rstrip('s')
180 | result.append("{} {}".format(value, name))
181 | return ', '.join(result[:granularity])
182 |
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/0.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/1.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/2.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/3.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/4.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/5.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/6.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/7.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/8.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/9.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/bracket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/bracket.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/exp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/exp.png
--------------------------------------------------------------------------------
/Controller/refs/EXP digits/slash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/EXP digits/slash.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/0.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/1.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/2.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/3.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/4.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/5.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/6.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/7.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/8.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/9.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/a.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/b.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/c.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/d.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/e.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/f.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/g.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/g.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/h.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/i.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/i.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/j.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/j.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/k.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/k.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/l.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/l.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/m.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/m.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/n.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/o.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/o.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/p.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/p.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/q.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/q.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/r.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/r.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/s.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/t.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/t.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/u.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/u.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/v.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/w.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/x.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/y.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/y.png
--------------------------------------------------------------------------------
/Controller/refs/PIC keys/z.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/PIC keys/z.png
--------------------------------------------------------------------------------
/Controller/refs/bars/EXP bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/bars/EXP bar.png
--------------------------------------------------------------------------------
/Controller/refs/bars/World map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/bars/World map.png
--------------------------------------------------------------------------------
/Controller/refs/buttons/Cash shop button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/buttons/Cash shop button.png
--------------------------------------------------------------------------------
/Controller/refs/buttons/Change channel button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/buttons/Change channel button.png
--------------------------------------------------------------------------------
/Controller/refs/buttons/Close button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/buttons/Close button.png
--------------------------------------------------------------------------------
/Controller/refs/buttons/Create character button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/buttons/Create character button.png
--------------------------------------------------------------------------------
/Controller/refs/buttons/Login news buttons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/buttons/Login news buttons.png
--------------------------------------------------------------------------------
/Controller/refs/buttons/Ok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/buttons/Ok.png
--------------------------------------------------------------------------------
/Controller/refs/buttons/World menu channels button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/buttons/World menu channels button.png
--------------------------------------------------------------------------------
/Controller/refs/curses/No potions curse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/curses/No potions curse.png
--------------------------------------------------------------------------------
/Controller/refs/curses/Rune cooldown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/curses/Rune cooldown.png
--------------------------------------------------------------------------------
/Controller/refs/map/Location mark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/map/Location mark.png
--------------------------------------------------------------------------------
/Controller/refs/menus/Settings menu E.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/menus/Settings menu E.png
--------------------------------------------------------------------------------
/Controller/refs/messages/Death message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/messages/Death message.png
--------------------------------------------------------------------------------
/Controller/refs/messages/Missing hyper rock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/messages/Missing hyper rock.png
--------------------------------------------------------------------------------
/Controller/refs/messages/Rune cooldown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/messages/Rune cooldown.png
--------------------------------------------------------------------------------
/Controller/refs/messages/Rune message 1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/messages/Rune message 1.png
--------------------------------------------------------------------------------
/Controller/refs/messages/Select a world.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/messages/Select a world.png
--------------------------------------------------------------------------------
/Controller/refs/messages/Unable to change channel dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/messages/Unable to change channel dialog.png
--------------------------------------------------------------------------------
/Controller/refs/messages/World map teleport message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/messages/World map teleport message.png
--------------------------------------------------------------------------------
/Controller/refs/mini map/Left edge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/mini map/Left edge.png
--------------------------------------------------------------------------------
/Controller/refs/mini map/Npc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/mini map/Npc.png
--------------------------------------------------------------------------------
/Controller/refs/mini map/Other player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/mini map/Other player.png
--------------------------------------------------------------------------------
/Controller/refs/mini map/Player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/mini map/Player.png
--------------------------------------------------------------------------------
/Controller/refs/mini map/Portal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/mini map/Portal.png
--------------------------------------------------------------------------------
/Controller/refs/mini map/Right edge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/mini map/Right edge.png
--------------------------------------------------------------------------------
/Controller/refs/mini map/Rune.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/mini map/Rune.png
--------------------------------------------------------------------------------
/Controller/refs/mini map/World.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/mini map/World.png
--------------------------------------------------------------------------------
/Controller/refs/rune keys/Down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/rune keys/Down.png
--------------------------------------------------------------------------------
/Controller/refs/rune keys/Left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/rune keys/Left.png
--------------------------------------------------------------------------------
/Controller/refs/rune keys/Right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/rune keys/Right.png
--------------------------------------------------------------------------------
/Controller/refs/rune keys/Up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/rune keys/Up.png
--------------------------------------------------------------------------------
/Controller/refs/worlds/aurora.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/worlds/aurora.png
--------------------------------------------------------------------------------
/Controller/refs/worlds/bera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/worlds/bera.png
--------------------------------------------------------------------------------
/Controller/refs/worlds/burning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/worlds/burning.png
--------------------------------------------------------------------------------
/Controller/refs/worlds/elysium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/worlds/elysium.png
--------------------------------------------------------------------------------
/Controller/refs/worlds/reboot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/worlds/reboot.png
--------------------------------------------------------------------------------
/Controller/refs/worlds/scania.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Controller/refs/worlds/scania.png
--------------------------------------------------------------------------------
/Dependencies/__pycache__/NotebookLoader.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Dependencies/__pycache__/NotebookLoader.cpython-39.pyc
--------------------------------------------------------------------------------
/Dependencies/__pycache__/admin.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomerh2001/MapleController/e0dbdca616cd56fcf242bcd1f6390b77de1f45e5/Dependencies/__pycache__/admin.cpython-39.pyc
--------------------------------------------------------------------------------
/Dependencies/admin.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
3 | # vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4
4 |
5 | # (C) COPYRIGHT © Preston Landers 2010
6 | # Released under the same license as Python 2.6.5
7 |
8 |
9 | import sys, os, traceback, types
10 |
11 | def isUserAdmin():
12 |
13 | if os.name == 'nt':
14 | import ctypes
15 | # WARNING: requires Windows XP SP2 or higher!
16 | try:
17 | return ctypes.windll.shell32.IsUserAnAdmin()
18 | except:
19 | traceback.print_exc()
20 | print("Admin check failed, assuming not an admin.")
21 | return False
22 | elif os.name == 'posix':
23 | # Check for root on Posix
24 | return os.getuid() == 0
25 | else:
26 | raise( RuntimeError, "Unsupported operating system for this module: %s" % (os.name,))
27 |
28 | def runAsAdmin(cmdLine=None, wait=True):
29 |
30 | if os.name != 'nt':
31 | raise( RuntimeError, "This function is only implemented on Windows.")
32 |
33 | import win32api, win32con, win32event, win32process
34 | from win32com.shell.shell import ShellExecuteEx
35 | from win32com.shell import shellcon
36 |
37 | python_exe = sys.executable
38 |
39 | if cmdLine is None:
40 | cmdLine = [python_exe] + sys.argv
41 | elif type(cmdLine) not in (types.TupleType,types.ListType):
42 | raise( ValueError, "cmdLine is not a sequence.")
43 | cmd = '"%s"' % (cmdLine[0],)
44 | # XXX TODO: isn't there a function or something we can call to massage command line params?
45 | params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]])
46 | cmdDir = ''
47 | showCmd = win32con.SW_SHOWNORMAL
48 | #showCmd = win32con.SW_HIDE
49 | lpVerb = 'runas' # causes UAC elevation prompt.
50 |
51 | # print("Running", cmd, params
52 |
53 | # ShellExecute() doesn't seem to allow us to fetch the PID or handle
54 | # of the process, so we can't get anything useful from it. Therefore
55 | # the more complex ShellExecuteEx() must be used.
56 |
57 | # procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)
58 |
59 | procInfo = ShellExecuteEx(nShow=showCmd,
60 | fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
61 | lpVerb=lpVerb,
62 | lpFile=cmd,
63 | lpParameters=params)
64 |
65 | if wait:
66 | procHandle = procInfo['hProcess']
67 | obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
68 | rc = win32process.GetExitCodeProcess(procHandle)
69 | #print("Process handle %s returned code %s" % (procHandle, rc)
70 | else:
71 | rc = None
72 |
73 | return rc
74 |
75 | def test():
76 | rc = 0
77 | if not isUserAdmin():
78 | print("You're not an admin.", os.getpid(), "params: ", sys.argv)
79 | #rc = runAsAdmin(["c:\\Windows\\notepad.exe"])
80 | rc = runAsAdmin()
81 | else:
82 | print("You are an admin!", os.getpid(), "params: ", sys.argv)
83 | rc = 0
84 | x = raw_input('Press Enter to exit.')
85 | return rc
86 |
87 |
88 | if __name__ == "__main__":
89 | sys.exit(test())
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AFK Bot
2 | A less-detectable, easy to use MapleStory bot using fancy computer vision and clever coding. Train while you're AFK, farm mesos, boost main/secondary characters and more!
3 |
4 | **Note: this is not cheats by any means, this bot does not access the game's memory data or files.**
5 |
6 | ## Download
7 | https://mega.nz/file/c4lSRTxJ#YZZcqvFK_nOaXrVCdNz0AQaoHrQtv1slaSwNbFNYLY8
8 |
9 | ## Features
10 | - Auto crash detection, restart & login
11 | - Move & attack
12 | - Use skills
13 | - Predict time to rankup
14 | - Activate buffs periodically
15 | - Take potions (HP, MP & Pet)
16 | - Change channels
17 | - Avoid players (by changing channel, to ensure not getting reported)
18 | - Activate ruins
19 | - Teleport back after death (using hyper teleport rock)
20 | - Settings per character
21 |
22 | ### Upcoming features
23 | - Kanna follower
24 | - In-game overlay
25 | - Email notifications
26 | - And much, much more!
27 |
28 | ## Setup
29 | 1. Download the files using the download link above and extract all of them into the same folder
30 |
31 |
32 |
33 | - Open the `settings.json` file, this file will contain all the insutrctions for the bot, make sure to adjust everything according to your character, if you plan on using the bot with multiple characters then create a `.json` file for each character and name it accordingly, for example `Kanna Settings.json`, `Shade Settings.json`, etc...
34 |
35 | - By default the `settings.json` that you download will contain only the default parameters and would look something like that:
36 |
37 | ```
38 | {
39 | "install_origin": "steam",
40 | "world": "bera",
41 | "PIC": "password",
42 | "hold_up": false,
43 | "right": "right",
44 | "left": "left",
45 | "up": "up",
46 | "down": "down",
47 | "jump": "alt",
48 | "hp_potion": "delete",
49 | "mana_potion": "insert",
50 | "pet_food": "end",
51 | "attack": "d",
52 | "buffs": [],
53 | "skills": []
54 | }
55 | ```
56 |
57 | - You can add more parameters to customize the bot's behavior, for example add periodic skills, spawn skills, interval between attacks, num. of attacks, and MUCH MORE.
58 | You can find all the other parameters here: https://github.com/tomergt45/MapleController/blob/main/docs/Controller%20Settings.md
59 |
60 | - Make sure to edit all the parameters according to your character keys and behavior (i.e. animation time, etc...)
61 |
62 | 2. While using the bot, maplestory MUST be on 800x600 (4:3) windowed
63 |
64 |
65 | 3. Disable UAC (only if you use the auto restart feature).
66 | This is because when maplestory is launched, you are prompted with an admin privileges dialog, this dialog cannot be accepeted via code so in order to automate the process you'll need to disable it while using the bot.
67 |
68 | - Search "UAC" in the windows search
69 |
70 |
71 |
72 | - Set it to "Never notify me ..."
73 |
74 |
75 |
76 | 4. After you finish with your `.json` files and steps 2 & 3, launch the `bot.exe` file as administrator and wait for it to load
77 |
78 | - If you have have mutliple `.json` files, you'll be prompted to select which file you wanna use
79 |
80 |
81 |
82 | - Otherwise, if you only have one `.json` file in that folder then this file will automatically be selected
83 |
84 | - After selecting the `.json` file the bot will take control over your PC and start playing MapleStory
85 |
86 | - You can now go to sleep, good night :)
87 | "# MapleAfkBot"
88 |
--------------------------------------------------------------------------------