from phBot import * ; from datetime import datetime, timedelta import QtBind, phBotChat, threading, time, struct, os, json, math, webbrowser pName = 'xNsyL-HWT-FGW' pVersion = 'HollyGame-1' # Ayarlar eski klasorden okunmaya devam etsin (xNsyLDungeon ayarlarin kaybolmasin) pConfigName = 'xNsyLDungeon' # ______________________________ ' Initializing ' ______________________________ # # Graphic user interface gui = QtBind.init(__name__,pName) FIXSOUNDPATH = "c:\\Windows\\Media\\chimes.wav" Remaining = AdvancedL = IntermediateL = BeginnerL = Return = MembersReturn = WaitMaster = Done = Move = x = y = last_trace_stop_time = 0 Advanced_remaining = Intermediate_remaining = Beginner_remaining = 4 Finished_HWT = ReturnCommand = DodgeAttackBool = CheckPoint = start_bot_in_town = stop_bot_in_town = dead = check_data = inside_hwt = trace_log = stop_checking_trace_status = False HWT_Entrance = unsucces_fgw = pm_requested = pm_received = dont_move = Alert = False is_in_dungeon = previous_dungeon = dungeon_location = status = resurrection_name = current_profile = remember_last_status = ResetCountActivatedDate = new_profile = '' waiting_thread = converted_time1 = converted_time2 = start_time_entrance = None set_profile_in_town, disconnect_from_fgw, client_disconnect_from_fgw = (False, ''), ('null',0,0), ('null',0,0) last_trace_time, trace_cooldown , dead_time = 0, 3, 0 resurrection_list, disconnect_list, checkbox_states = [], [], {} waitpartymembers_command = movement = True log_message = True # log her zaman acik (arayuzden kaldirildi) # --- Ghost Sereness kacis tekillestirme ------------------------------------- # Sorun: boss'un telegraf paketini partideki HER uye goruyor, her biri partiye # "dodge Sereness" yaziyor, o duyuruyu alan her uye tekrar kacis tetikliyordu. # 8 kisilik partide tek olay 8 kez tetikleniyor, her tetikleme yonu ters cevirip # ayri bir move_to thread'i aciyordu. Karakter sag-sol emri alip yerinde titriyordu. DODGE_COOLDOWN = 6.0 # saniye: bu sure icinde gelen tekrar tetiklemeler yutulur _dodge_lock = threading.Lock() _dodge_last_ts = 0.0 _dodge_epoch = 0 # her yeni kacista artar; eski move_to dongusu kendini iptal eder # --- HWT zamanlayici -------------------------------------------------------- # Girilen saat geldiginde: botu durdur -> HWT profiline gec -> return scroll. # Her gun tekrarlar. Ayni gun icinde bir kez tetiklenir. _timer_target = None # datetime.time | None = kapali/gecersiz _timer_fired_date = '' # 'YYYY-MM-DD' - o gun tetiklendi mi _timer_last_shown = '' # arayuzdeki geri sayimi bosuna guncellememek icin # =========================================================================== # YERLESIM # Sutunlar : SOL 10-270 | ORTA 285-478 | SAG 492-716 # Kural : satir araligi 20-22 px, sayi kutulari sutun sonunda ayni hizada, # bolum basliklari sade renkli metin (cizgi yok - tasiyordu). # Not : arka plan icin createList kullanilmiyor; etiketleri kendi icine # cekip yerlerinden oynatiyordu. # =========================================================================== # --------------------------------------------------------------------------- # =========================================================================== # DIL (TR / EN) # Arayuz phBot acilisinda BIR KEZ kuruluyor, karakter config'i ise oyuna # girildikten sonra okunuyor. Bu yuzden dil tercihi ayri bir dosyada tutulur # ve import aninda okunur. # =========================================================================== def _lang_file(): try: return get_config_dir() + pConfigName + "\\language.txt" except Exception: return '' def _lang_read(): try: p = _lang_file() if p and os.path.exists(p): v = open(p, 'r', encoding='utf-8').read().strip().upper() if v in ('TR', 'EN'): return v except Exception: pass return 'TR' def _lang_write(v): try: p = _lang_file() if not p: return os.makedirs(os.path.dirname(p), exist_ok=True) open(p, 'w', encoding='utf-8').write(v) except Exception as e: log(f'Plugin: Dil tercihi kaydedilemedi: {e}') LANG = _lang_read() # key : (turkce, english) S = { 'settings' : ('AYARLAR', 'SETTINGS'), 'conditions' : ('KOŞULLAR', 'CONDITIONS'), 'general' : ('GENEL', 'GENERAL'), 'timer' : ('ZAMANLAYICI', 'TIMER'), 'hwtEntrance': ('Holy Water Temple girişi', 'Holy Water Temple Entrance'), 'waitParty' : ('Parti üyesi bekle', 'Wait for party members'), 'floorOrder' : ('Kat sırası', 'Floor order'), 'atkRadius' : ('Saldırı yarıçapı', 'Attack radius'), 'sphinxRefl' : ('Sphinx Reflect sayacı', 'Sphinx Reflect counter'), 'ignoreSph' : ('Beginner Sphinx\'i yoksay', 'Ignore Beginner Sphinx'), 'dodgeBridge': ('Köprüden kaçın', 'Dodge bridge'), 'dodgeSer' : ('Ghost Sereness kaçışı', 'Dodge Ghost Sereness'), 'returnDead' : ('Trace master ölünce şehre dön', 'Return town if trace master dies'), 'stopTrace' : ('Işınlanma sonrası takibi durdur', 'Stop trace after teleport'), 'traceMaster': ('Trace master', 'Trace master'), 'partyMaster': ('Party master', 'Party master'), 'profileName': ('Profil adı', 'Profile name'), 'condOn' : ('Koşullar aktif', 'Conditions on'), 'pluginOn' : ('Eklenti aktif', 'Plugin on'), 'traceParty' : ('Parti master takip', 'Trace party master'), 'range' : ('Menzil', 'Range'), 'startTown' : ('Şehirde botu başlat', 'Start bot in town'), 'autoEntr' : ('HWT girişini otomatik aç', 'Auto activate HWT entrance'), 'afterHWT' : ('HWT bitince geç', 'After HWT switch to'), 'afterFGW' : ('FGW bitince geç', 'After FGW switch to'), 'slotToHwt' : ('SLOT → HWT geçişi', 'SLOT → HWT switch'), 'active' : ('Aktif', 'On'), 'clock' : ('Saat', 'Time'), 'save' : (' Kaydet ', ' Save '), 'promo1' : ('Botun artık cebinde', 'Your bot is in your pocket'), 'promo2' : ('Nerede olursan ol, kontrol sende', 'Wherever you are, you are in control'), 'tmrOff' : ('kapalı', 'off'), 'tmrNoTime' : ('saat gir', 'set time'), 'tmrDone' : ('bugün çalıştı', 'ran today'), } def t(key): v = S.get(key) if not v: return key return v[1] if LANG == 'EN' else v[0] # (widget, key) ciftleri: dil degisince anlik yeniden etiketleme denenir _lang_widgets = [] def _reg(widget, key): _lang_widgets.append((widget, key)) return widget lbl = _reg(QtBind.createLabel(gui,''+t('settings')+'',10,8),'settings') lbl = _reg(QtBind.createLabel(gui,''+t('conditions')+'',492,8),'conditions') btnLang = QtBind.createButton(gui,'toggle_language',' EN ' if LANG=='TR' else ' TR ',664,5) # =========================== SOL SUTUN =================================== cbxHolyMolyEntrance = _reg(QtBind.createCheckBox(gui,'HolyWaterTemple_Entrance_checked',t('hwtEntrance'),10,26),'hwtEntrance') lbl = _reg(QtBind.createLabel(gui,t('waitParty'),10,48),'waitParty') txtPartyMembers = QtBind.createLineEdit(gui,"8",235,45,32,19) lbl = _reg(QtBind.createLabel(gui,t('floorOrder'),10,70),'floorOrder') cmbRoute = QtBind.createCombobox(gui,80,67,187,20) lbl = QtBind.createLabel(gui,'HWT',10,94) cbxSafeWay = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('atkRadius'),10,112),'atkRadius') txtRange = QtBind.createLineEdit(gui,"35",235,110,32,19) cbxspinixref = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('sphinxRefl'),10,130),'sphinxRefl') txtRangeSphinx = QtBind.createLineEdit(gui,"40",235,128,32,19) cbxIgnoreSphnix = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('ignoreSph'),10,148),'ignoreSph') lbl = QtBind.createLabel(gui,'FGW',10,172) cbxSafeWay2 = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('dodgeBridge'),10,190),'dodgeBridge') txtRange2 = QtBind.createLineEdit(gui,"45",235,188,32,19) cbxDodgeSereness = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('dodgeSer'),10,208),'dodgeSer') lineedit_range = QtBind.createLineEdit(gui,"20",235,206,32,19) cbxReturn = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('returnDead'),10,226),'returnDead') lbl = _reg(QtBind.createLabel(gui,''+t('general')+'',10,250),'general') cbxNotrace = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('stopTrace'),10,268),'stopTrace') # =========================== ORTA SUTUN ================================== lblStages = QtBind.createLabel(gui,'Adv 4 · Int 4 · Beg 4',285,8) lbl = QtBind.createLabel(gui,'HWT',285,34) lbl = _reg(QtBind.createLabel(gui,t('traceMaster'),290,54),'traceMaster') txtHWTMASTER = QtBind.createLineEdit(gui,'',375,52,103,19) lbl = _reg(QtBind.createLabel(gui,t('profileName'),290,74),'profileName') txtHWTPROFILE = QtBind.createLineEdit(gui,'HWT',375,72,103,19) lbl = QtBind.createLabel(gui,'FGW',285,98) lbl = _reg(QtBind.createLabel(gui,t('traceMaster'),290,118),'traceMaster') txtFGWMASTER = QtBind.createLineEdit(gui,'',375,116,103,19) lbl = _reg(QtBind.createLabel(gui,t('profileName'),290,138),'profileName') txtFGWPROFILE = QtBind.createLineEdit(gui,'FGW',375,136,103,19) lbl = QtBind.createLabel(gui,'SLOT',285,162) lbl = _reg(QtBind.createLabel(gui,t('partyMaster'),290,182),'partyMaster') txtSLOTMASTER = QtBind.createLineEdit(gui,'',375,180,103,19) lbl = _reg(QtBind.createLabel(gui,t('profileName'),290,202),'profileName') txtSLOTPROFILE = QtBind.createLineEdit(gui,'SLOT',375,200,103,19) # --- NsyL Companion tanitimi ---------------------------------------------- lbl = QtBind.createLabel(gui,'NsyL Companion',285,232) lbl = _reg(QtBind.createLabel(gui,''+t('promo1')+'',285,252),'promo1') lbl = _reg(QtBind.createLabel(gui,''+t('promo2')+'',285,270),'promo2') btnNsyLSite = QtBind.createButton(gui,'open_nsyl_site',' nsylcompanion.com ',285,290) # =========================== SAG SUTUN =================================== cbxEnabledConditions = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('condOn'),500,26),'condOn') cbxEnabledEventLoop = _reg(QtBind.createCheckBox(gui,'Enabled_checked',t('pluginOn'),612,26),'pluginOn') cbxTrace = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('traceParty'),500,48),'traceParty') lbl = _reg(QtBind.createLabel(gui,t('range'),618,50),'range') txtMinDistance = QtBind.createLineEdit(gui,'10',658,47,28,19) lbl = QtBind.createLabel(gui,'–',690,50) txtMaxDistance = QtBind.createLineEdit(gui,'70',698,47,28,19) cbxStart = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('startTown'),500,70),'startTown') cbxEntranceON = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('autoEntr'),500,90),'autoEntr') lbl = _reg(QtBind.createLabel(gui,t('afterHWT'),500,114),'afterHWT') cmbAfterHWT = QtBind.createCombobox(gui,606,112,120,20) lbl = _reg(QtBind.createLabel(gui,t('afterFGW'),500,138),'afterFGW') cmbAfterFGW = QtBind.createCombobox(gui,606,136,120,20) cbxChangeProfile2 = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('slotToHwt'),500,162),'slotToHwt') lbl = _reg(QtBind.createLabel(gui,''+t('timer')+'',492,186),'timer') cbxTimer = _reg(QtBind.createCheckBox(gui,'checkbox_changed',t('active'),500,206),'active') lbl = _reg(QtBind.createLabel(gui,t('clock'),558,208),'clock') txtTimerHWT = QtBind.createLineEdit(gui,'',592,205,44,19) lblTimerNext = QtBind.createLabel(gui,'bugün çalıştı',642,208) cbxEnter1 = QtBind.createButton(gui,'ManuelEntrance1_clicked','Beginner',492,232) cbxEnter2 = QtBind.createButton(gui,'ManuelEntrance2_clicked','Intermediate',568,232) cbxEnter3 = QtBind.createButton(gui,'ManuelEntrance3_clicked','Advanced',648,232) txtBuildList = QtBind.createCombobox(gui,492,260,140,20) cbResetCheckboxes = _reg(QtBind.createButton(gui,'reset_checkboxes',t('save'),640,259),'save') #----------------------------------------------Load Configs------------------------------------------------# #---------------------------------------------- Kat sirasi ------------------------------------------------# # Eskiden 6 ayri onay kutusuydu ve hepsi birbirini kapatiyordu (tek secim). # Tek acilir listeye indirildi. Kayitli secim, liste doldurulurken BASA konur; # boylece QtBind.setText combobox'ta calismasa bile ayar geri gelir. # Acilir liste secenekleri dile bagli. Config'e METIN degil ANAHTAR yazilir, # yoksa dil degisince kayitli secim eslesmez. ROUTE_KEYS = ['first','second','third','only_beginner','only_intermediate','only_advanced'] ROUTE_LABELS = { 'TR': [ 'Beginner → Intermediate → Advanced', 'Intermediate → Advanced → Beginner', 'Advanced → Intermediate → Beginner', 'Sadece Beginner', 'Sadece Intermediate', 'Sadece Advanced', ], 'EN': [ 'Beginner → Intermediate → Advanced', 'Intermediate → Advanced → Beginner', 'Advanced → Intermediate → Beginner', 'Beginner only', 'Intermediate only', 'Advanced only', ], } _route_filled = False AFTER_HWT_KEYS = ['', 'fgw', 'slot'] AFTER_FGW_KEYS = ['', 'hwt', 'slot'] NONE_LABEL = {'TR': 'Hiçbiri', 'EN': 'None'} _after_hwt_filled = False _after_fgw_filled = False def _route_labels(): return ROUTE_LABELS.get(LANG, ROUTE_LABELS['TR']) def _after_labels(keys): return [NONE_LABEL.get(LANG, 'Hiçbiri') if k == '' else k.upper() for k in keys] def _key_from_combo(widget, keys, labels): try: v = (QtBind.text(gui, widget) or '').strip() except Exception: return '' if v in labels: return keys[labels.index(v)] return '' def route_key(): """Secili kat sirasi anahtari: first/second/third/only_* veya ''.""" return _key_from_combo(cmbRoute, ROUTE_KEYS, _route_labels()) def after_hwt_key(): """HWT bitince: 'fgw' | 'slot' | ''""" return _key_from_combo(cmbAfterHWT, AFTER_HWT_KEYS, _after_labels(AFTER_HWT_KEYS)) def after_fgw_key(): """FGW bitince: 'hwt' | 'slot' | ''""" return _key_from_combo(cmbAfterFGW, AFTER_FGW_KEYS, _after_labels(AFTER_FGW_KEYS)) def _fill_combo(widget, labels, sel_label, ad): """Secili secenek BASA konur; QtBind.setText combobox'ta calismasa bile ilk oge secili geldigi icin ayar geri gelir.""" order = list(labels) if sel_label in order: order.remove(sel_label) order.insert(0, sel_label) for opt in order: try: QtBind.append(gui, widget, opt) except Exception as e: log(f'Plugin: "{ad}" listesi doldurulamadi: {e}') return if sel_label: try: QtBind.setText(gui, widget, sel_label) except Exception: pass def route_fill(selected_key=''): global _route_filled if _route_filled: return _route_filled = True labels = _route_labels() sel = labels[ROUTE_KEYS.index(selected_key)] if selected_key in ROUTE_KEYS else '' _fill_combo(cmbRoute, labels, sel, 'Kat sirasi') def after_hwt_fill(selected_key=''): global _after_hwt_filled if _after_hwt_filled: return _after_hwt_filled = True labels = _after_labels(AFTER_HWT_KEYS) sel = labels[AFTER_HWT_KEYS.index(selected_key)] if selected_key in AFTER_HWT_KEYS else '' _fill_combo(cmbAfterHWT, labels, sel, 'HWT bitince') def after_fgw_fill(selected_key=''): global _after_fgw_filled if _after_fgw_filled: return _after_fgw_filled = True labels = _after_labels(AFTER_FGW_KEYS) sel = labels[AFTER_FGW_KEYS.index(selected_key)] if selected_key in AFTER_FGW_KEYS else '' _fill_combo(cmbAfterFGW, labels, sel, 'FGW bitince') def update_stage_label(): """Uc kat sayacini tek satirda gosterir: 'Adv 4 · Int 4 · Beg 4'. Kalan 0 ise o kat '✔' olur.""" def g(v): return '✔' if v <= 0 else str(v) try: QtBind.setText(gui, lblStages, f'Adv {g(Advanced_remaining)} · Int {g(Intermediate_remaining)} · Beg {g(Beginner_remaining)}') except Exception: pass def profile_for(key): """Anahtardan gercek profil adini bul: 'hwt'/'fgw'/'slot' -> kutudaki isim.""" if key == 'hwt': return QtBind.text(gui, txtHWTPROFILE).strip() or "HWT" if key == 'fgw': return QtBind.text(gui, txtFGWPROFILE).strip() or "FGW" if key == 'slot': return QtBind.text(gui, txtSLOTPROFILE).strip() or "SLOT" return '' def switch_profile_and_return(key, nereden=''): """Zindan bitisinde: partiye duyur, profili degistir, sehre don, botu baslat. start_bot_in_town bayragi sehre varista botu baslatir.""" global start_bot_in_town yeni = profile_for(key) if not yeni: return False if (get_profile() or '') == yeni: return False st = get_status() or '' if st == "botting": stop_bot() elif st == "tracing": stop_trace() start_bot_in_town = True phBotChat.Party(f"change profile {yeni.lower()}") set_profile(yeni) log(f'Plugin: {nereden} bitti — [ {yeni} ] profiline geçiliyor, şehre dönülüyor.') threading.Timer(1.0, return_town).start() return True #---------------------------------------------- Zamanlayici -----------------------------------------------# def timer_parse(): """Arayuzdeki saati oku. Gecerliyse datetime.time, degilse None.""" global _timer_target txt = (QtBind.text(gui, txtTimerHWT) or '').strip() if not txt: _timer_target = None return None try: _timer_target = datetime.strptime(txt, "%H:%M").time() except ValueError: _timer_target = None log(f'Plugin: Zamanlayici saati gecersiz: "{txt}" — SS:DD yazin (orn. 16:30).') return _timer_target def timer_seconds_left(): """Hedef saate kalan saniye. Saat gectiyse yarinki ayni saate gore hesaplar.""" if not _timer_target: return None now = datetime.now() target = datetime.combine(now.date(), _timer_target) if target <= now: target += timedelta(days=1) return int((target - now).total_seconds()) def timer_update_label(): """Arayuzdeki 'sonraki tetikleme' satirini tazeler. Saniyede bir cagrilir.""" global _timer_last_shown if not QtBind.isChecked(gui, cbxTimer): text = '' + t('tmrOff') + '' elif not _timer_target: text = '' + t('tmrNoTime') + '' else: kalan = timer_seconds_left() if _timer_fired_date == datetime.now().strftime("%Y-%m-%d"): text = '' + t('tmrDone') + '' else: s, dk = divmod(kalan // 60, 60) text = f'{s}sa {dk}dk' if text != _timer_last_shown: _timer_last_shown = text QtBind.setText(gui, lblTimerNext, text) def timer_check(): """event_loop'tan saniyede bir cagrilir. Saat geldiyse HWT'ye gecisi baslatir.""" global _timer_fired_date if not QtBind.isChecked(gui, cbxTimer) or not _timer_target: return now = datetime.now() today = now.strftime("%Y-%m-%d") if _timer_fired_date == today: return if now.time() < _timer_target: return # Saatin cok gerisinde bir anda (orn. gece acilista) tetiklenmesin: 10 dk pencere gecen = (now - datetime.combine(now.date(), _timer_target)).total_seconds() if gecen > 600: _timer_fired_date = today return _timer_fired_date = today threading.Timer(0.1, timer_go_hwt).start() def timer_go_hwt(): """Zamanlayici eylemi: botu durdur, HWT profiline gec, sehre don.""" try: profile_hwt = (QtBind.text(gui, txtHWTPROFILE) or '').strip() or "HWT" current = get_profile() or '' if current == profile_hwt: log(f'Plugin: Zamanlayici — zaten [ {profile_hwt} ] profilindesin, islem yapilmadi.') return log(f'Plugin: Zamanlayici saati geldi. [ {profile_hwt} ] profiline geciliyor.') st = get_status() or '' if st == "botting": stop_bot() elif st == "tracing": stop_trace() set_profile(profile_hwt) threading.Timer(1.0, return_town).start() except Exception as e: log(f'Plugin: Zamanlayici hatasi: {e}') def toggle_language(): """TR <-> EN. Tercihi dosyaya yazar ve arayuzu anlik guncellemeyi dener. QtBind bazi bilesenlerin metnini sonradan degistiremiyorsa, tercih yine de kaydedildigi icin bir sonraki acilista tam olarak uygulanir.""" global LANG LANG = 'EN' if LANG == 'TR' else 'TR' _lang_write(LANG) degisen = 0 for widget, key in _lang_widgets: try: metin = t(key) # renkli/kalin olanlar ayni bicimle yeniden kurulur if key in ('settings', 'conditions'): metin = '' + metin + '' elif key == 'general': metin = '' + metin + '' elif key == 'timer': metin = '' + metin + '' elif key == 'promo1': metin = '' + metin + '' elif key == 'promo2': metin = '' + metin + '' QtBind.setText(gui, widget, metin) degisen += 1 except Exception: pass try: QtBind.setText(gui, btnLang, ' EN ' if LANG == 'TR' else ' TR ') except Exception: pass # Uyari, gecilen dilde yazilir - okuyan kisi o dili kullaniyor. if LANG == 'EN': log(f'Plugin: Language changed to English. ({degisen} labels updated)') log('Plugin: Reload the plugin to apply the language to the drop-down lists and all remaining texts.') else: log(f'Plugin: Dil Türkçe olarak değiştirildi. ({degisen} etiket güncellendi)') log('Plugin: Açılır listelerin ve kalan tüm metinlerin değişmesi için eklentiyi yeniden yükleyin.') def open_nsyl_site(): """Tanitim butonu: web sitesini varsayilan tarayicida acar.""" url = 'https://nsylcompanion.com' try: webbrowser.open(url) log(f'Plugin: {url} tarayicida aciliyor.') except Exception as e: log(f'Plugin: Site acilamadi ({e}). Adres: {url}') def HolyWaterTemple_Entrance_checked(checked) : global HWT_Entrance HWT_Entrance = QtBind.isChecked(gui, cbxHolyMolyEntrance) def checkbox_changed(checked): saveConfigs() def safe_int(text, default): try: return int(text.strip()) except (ValueError, AttributeError): return default def Config_Builds(): Config_Builds_List = [ "Auto Detect", "Wizard / Spear (Attack)", "Warrior", "Cleric / Force", "Bard / Warlock", "Personal Configuration", "Clear Settings" ] if 'QtBind' in globals() and 'gui' in globals() and 'txtBuildList' in globals(): for config in Config_Builds_List: QtBind.append(gui, txtBuildList, config) else: log("Plugin: GUI bileşenleri tanımlı değil.") return Config_Builds_List Config_Builds() def reset_checkboxes(): global HWT_Entrance build = QtBind.text(gui, txtBuildList) checkboxes = [ cbxHolyMolyEntrance, cbxspinixref, cbxSafeWay, cbxSafeWay2, cbxIgnoreSphnix, cbxNotrace, cbxEnabledConditions, cbxTrace, cbxStart, cbxEntranceON, cbxReturn, cbxDodgeSereness, cbxChangeProfile2, cbxEnabledEventLoop ] for checkbox in checkboxes: if not build == "Personal Configuration": QtBind.setChecked(gui, checkbox, False) # Otomatik build algılama if build == "Auto Detect": try: Master = get_party_info().get('leader_name','') if Master != "null" : QtBind.setText(gui, txtHWTMASTER, Master) QtBind.setText(gui, txtFGWMASTER, Master) QtBind.setText(gui, txtSLOTMASTER, Master) inventory = get_inventory() if inventory and 'items' in inventory and len(inventory['items']) >= 7: item = inventory['items'][6] name = item.get('name') if isinstance(name, str): item_info = get_item_string(name) tid3 = item_info.get('tid3', None) if isinstance(tid3, int): if tid3 in {2, 3, 4, 5, 6, 11, 12, 13}: build = "Wizard / Spear (Attack)" elif tid3 in {7, 8, 9}: build = "Warrior" elif tid3 in {10, 14}: build = "Bard / Warlock" else: build = "Cleric / Force" else : log(f'Plugin: Yapılandırma başarısız. Birincil Silah tespit edilemedi.') except Exception as e: log(f"Build algılama hatası: {e}") # Build yapılandırmaları if build == "Wizard / Spear (Attack)": Config = [ cbxSafeWay2, cbxspinixref, cbxSafeWay, cbxNotrace, cbxIgnoreSphnix, cbxEnabledConditions, cbxTrace, cbxStart, cbxEntranceON, cbxReturn, cbxDodgeSereness, cbxEnabledEventLoop ] for checkbox in Config: QtBind.setChecked(gui, checkbox, True) log("Plugin: xDungeonSupporteRx'ın Ayarları [ Wizard / Spear (Attack) ] için düzenlendi.") elif build == "Warrior": Config = [ cbxSafeWay2, cbxspinixref, cbxSafeWay, cbxNotrace, cbxIgnoreSphnix, cbxEnabledConditions, cbxTrace, cbxStart, cbxEntranceON, cbxReturn, cbxDodgeSereness, cbxEnabledEventLoop ] for checkbox in Config: QtBind.setChecked(gui, checkbox, True) log("Plugin: xDungeonSupporteRx'ın Ayarları [ Warrior ] için düzenlendi.") elif build == "Cleric / Force": Config = [ cbxIgnoreSphnix, cbxSafeWay, cbxEnabledConditions, cbxStart, cbxEntranceON, cbxDodgeSereness, cbxEnabledEventLoop ] for checkbox in Config: QtBind.setChecked(gui, checkbox, True) log("Plugin: xDungeonSupporteRx'ın Ayarları [ Cleric / Force ] için düzenlendi.") elif build == "Bard / Warlock": Config = [ cbxSafeWay2, cbxSafeWay, cbxNotrace, cbxIgnoreSphnix, cbxEnabledConditions, cbxTrace, cbxStart, cbxEntranceON, cbxReturn, cbxDodgeSereness, cbxEnabledEventLoop ] for checkbox in Config: QtBind.setChecked(gui, checkbox, True) log("Plugin: xDungeonSupporteRx'ın Ayarları [ Bard / Warlock ] için düzenlendi.") elif build == "Clear Settings": QtBind.setText(gui, txtHWTMASTER, "") QtBind.setText(gui, txtFGWMASTER, "") QtBind.setText(gui, txtSLOTMASTER, "") log("Plugin: Ayarlarınız Sıfırlandı.") else: if build == "Personal Configuration" : log("Plugin: Kişisel Ayarlarınız Kaydedildi.") HWT_Entrance = QtBind.isChecked(gui, cbxHolyMolyEntrance) threading.Timer(0.1, saveConfigs).start() def saveConfigs(): try: if not isJoined(): return # Kaydet'e her basildiginda saat yeniden okunur timer_parse() global checkbox_states, converted_time1, converted_time2, disconnect_from_fgw checkbox_states = {} # önce sıfırla data = {} # Checkbox ve Text alanları (sade gruplandırma) checkboxes = { 'notrace': cbxNotrace, 'reflect': cbxspinixref, 'ignoresph': cbxIgnoreSphnix, 'ignoreNav': cbxSafeWay, 'ignoreNav2': cbxSafeWay2, 'returntown': cbxReturn, 'changeprofile2': cbxChangeProfile2, 'disabledplugin': cbxEnabledEventLoop, 'Enabled': cbxEnabledConditions, 'trace': cbxTrace, 'start': cbxStart, 'EntranceON': cbxEntranceON, 'usedodgeskills': cbxDodgeSereness, 'timer': cbxTimer } textfields = { 'PartyMembers': txtPartyMembers, 'RangeSphinx': txtRangeSphinx, 'Range': txtRange, 'Range2': txtRange2, 'hwtmaster': txtHWTMASTER, 'fgwmaster': txtFGWMASTER, 'slotmaster': txtSLOTMASTER, 'hwtprofile': txtHWTPROFILE, 'fgwprofile': txtFGWPROFILE, 'slotprofile': txtSLOTPROFILE, 'minDistance': txtMinDistance, 'maxDistance': txtMaxDistance, 'radius': lineedit_range, 'timerHWT': txtTimerHWT } for key, checkbox in checkboxes.items(): checked = QtBind.isChecked(gui, checkbox) data[key] = checked checkbox_states[key] = checked for key, field in textfields.items(): text = QtBind.text(gui, field) data[key] = text data['route'] = route_key() data['afterhwt'] = after_hwt_key() data['afterfgw'] = after_fgw_key() data['disconnect_from_where'] = disconnect_from_fgw # Dosyaya yaz with open(getConfig(), "w") as f: json.dump(data, f, indent=4, sort_keys=True) except Exception as e: log(f"{pName}: Ayarlar kaydedilirken bir hata oluştu: {e}") def getPath(): return get_config_dir()+pConfigName+"\\" def connected(): global inGame inGame = None def getConfig(): return getPath()+inGame['server'] + "_" + inGame['name'] + ".json" def resurrection(): global resurrection_name, resurrection_list data = get_character_data() or {} resurrection_name = data.get('name', '').lower() if resurrection_name: if resurrection_name not in resurrection_list: resurrection_list.append(resurrection_name) else: # 3 saniye sonra tekrar dene threading.Timer(3.0, resurrection).start() def isJoined(): global inGame,check_data inGame = get_character_data() or {} if not check_data and inGame : check_data = True if not (inGame and "name" in inGame and inGame["name"]): inGame = None return inGame def loadConfigs(): try: if isJoined(): if not resurrection_list: resurrection() if os.path.exists(getConfig()): with open(getConfig(), "r") as f: data = json.load(f) global checkbox_states, converted_time1, converted_time2, disconnect_from_fgw checkbox_states = {} # Checkbox haritası (anahtar: config adı, değer: QtBind nesnesi) checkboxes = { 'notrace': cbxNotrace, 'reflect': cbxspinixref, 'ignoresph': cbxIgnoreSphnix, 'ignoreNav': cbxSafeWay, 'ignoreNav2': cbxSafeWay2, 'returntown': cbxReturn, 'changeprofile2': cbxChangeProfile2, 'disabledplugin': cbxEnabledEventLoop, 'Enabled': cbxEnabledConditions, 'trace': cbxTrace, 'start': cbxStart, 'EntranceON': cbxEntranceON, 'usedodgeskills': cbxDodgeSereness, 'timer': cbxTimer } textfields = { 'PartyMembers': txtPartyMembers, 'RangeSphinx': txtRangeSphinx, 'Range': txtRange, 'Range2': txtRange2, 'hwtmaster': txtHWTMASTER, 'fgwmaster': txtFGWMASTER, 'slotmaster': txtSLOTMASTER, 'hwtprofile': txtHWTPROFILE, 'fgwprofile': txtFGWPROFILE, 'slotprofile': txtSLOTPROFILE, 'minDistance': txtMinDistance, 'maxDistance': txtMaxDistance, 'radius': lineedit_range, 'timerHWT': txtTimerHWT } # Checkbox'ları yükle ve checkbox_states içine ata for key, checkbox in checkboxes.items(): checked = data.get(key, False) QtBind.setChecked(gui, checkbox, checked) checkbox_states[key] = checked # Text alanlarını yükle for key, field in textfields.items(): if key in data: QtBind.setText(gui, field, str(data[key])) route_fill(str(data.get('route','')).strip()) after_hwt_fill(str(data.get('afterhwt','')).strip()) after_fgw_fill(str(data.get('afterfgw','')).strip()) if 'disconnect_from_where' in data: disconnect_from_fgw = data.get("disconnect_from_where", "") timer_parse() if _timer_target : log(f'Plugin: Zamanlayici yuklendi — HWT saati {_timer_target.strftime("%H:%M")}.') log(f"Plugin Configs : {pName}: Ayarlar başarıyla yüklendi. ✔️ ") else : route_fill() after_hwt_fill() after_fgw_fill() log(f"Plugin Configs : {pName}: Henüz bir yapılandırmaya sahip değil. ❌ ") except Exception as e: route_fill() # hata olsa bile listeler bos kalmasin after_hwt_fill() after_fgw_fill() log(f"{pName}: Ayarlar yüklenirken bir hata oluştu: {e} ⚠️ ") #----------------------------------------------Load Configs------------------------------------------------# def End(): party_info = get_party_info() or {} finished = party_info.get('area','') == "TOWN" in_end_area = 17409 < x < 17540 and 3761 < y < 3885 return finished and in_end_area def change_profile(args): profile = args[1] msg = f'change profile {profile}' phBotChat.Party(msg) return 0 def GetUnique(): gtmonsters = get_monsters() or {} if not gtmonsters: return False unique_names = {"MOB_SD_OSIRIS_3", "Ghost Sereness",} return any(monster['servername'] in unique_names or monster['name'] in unique_names for monster in gtmonsters.values()) def set_dungeon(new_dungeon): global is_in_dungeon, previous_dungeon if is_in_dungeon != new_dungeon: previous_dungeon = is_in_dungeon is_in_dungeon = new_dungeon def CheckInDungeon(): #start_time = time.time() if log_message else None global is_in_dungeon, dungeon_location, status, current_profile, dead, x, y, remember_last_status, dead_time if resurrection_name in resurrection_list : char_data = get_character_data() or {} dungeon_name = char_data.get('zone_name', '').lower() x, y = char_data.get('x',0), char_data.get('y',0) current_profile = get_profile() or '' slot_profile = QtBind.text(gui, txtSLOTPROFILE) or "SLOT" dead = char_data.get('dead','') current_time = time.time() if dead : dead_time = current_time if status != "nothing" : remember_last_status = status else : if remember_last_status != status : if current_time - dead_time >= 15 : remember_last_status = status status = get_status() or "nothing" if dungeon_name in {'constantinople', 'jangan', 'western china donwhang', 'hotan krallığı', 'alexandria', 'hotan kingdom', 'batı çin donwhang', 'samarkand'} : set_dungeon("TOWN") elif dungeon_name in {'gemi enkazı içinde', 'gemi enkazı dışında', 'inside of the shipwreck', 'outside of the shipwreck'} : set_dungeon("FGW") if checkbox_states.get('ignoreNav2') : B1 = 18028 < x < 18158 and 3845 < y < 3918 B2 = 17873 < x < 17964 and 3956 < y < 4135 B3 = 18016 < x < 18186 and 4196 < y < 4252 B4 = 18265 < x < 18424 and 4252 < y < 4299 B5 = 18467 < x < 18520 and 3893 < y < 4089 B6 = 18654 < x < 18680 and 3529 < y < 3769 B7 = 18323 < x < 18556 and 3242 < y < 3401 B8 = 18081 < x < 18189 and 3317 < y < 3473 B9 = 17939 < x < 18103 and 4350 < y < 4474 B10 = 17572 < x < 17755 and 4419 < y < 4453 B11 = 17246 < x < 17421 and 4247 < y < 4357 B12 = 17218 < x < 17274 and 3839 < y < 4069 B13 = 17113 < x < 17167 and 3414 < y < 3674 B14 = 17303 < x < 17452 and 3163 < y < 3288 B15 = 17625 < x < 17794 and 3153 < y < 3177 B16 = 17546 < x < 17577 and 3237 < y < 3396 B17 = 17714 < x < 17825 and 3471 < y < 3689 B18 = 17570 < x < 17718 and 3684 < y < 3790 B19 = 17910 < x < 18005 and 3704 < y < 3833 if B1 or B2 or B3 or B4 or B5 or B6 or B7 or B8 or B9 or B10 or B11 or B12 or B13 or B14 or B15 or B16 or B17 or B18 or B19: if dungeon_location != "OFF_FGW" : dungeon_location = "OFF_FGW" else: if dungeon_location != "ON_FGW" : dungeon_location = "ON_FGW" elif dungeon_name in {'pharaoh mezarı', 'pharaoh tomb'} : set_dungeon("HWT") if checkbox_states.get('ignoreNav') : #-------------------------Advanced--------------------------------------# NephthysOFF = 8547 < x < 8712 and 5656 < y < 5801 SekhmetOFF = 8547 < x < 8712 and 6070 < y < 6219 HorusOFF = 8998 < x < 9118 and 5896 < y < 6063 #----------------------Intermediate-------------------------------------# NephthysOFF2 = 11043 < x < 11208 and 5658 < y < 5804 SekhmetOFF2 = 11043 < x < 11208 and 6072 < y < 6219 HorusOFF2 = 11494 < x < 11618 and 5897 < y < 6065 #----------------------Beginner-----------------------------------------# SphinxOFF3 = 10875 < x < 11113 and 4566 < y < 4620 NephthysOFF3 = 11042 < x < 11213 and 4313 < y < 4460 SekhmetOFF3 = 11042 < x < 11213 and 4728 < y < 4876 HorusOFF3 = 11496 < x < 11624 and 4553 < y < 4719 #----------------------Sphinx--------------------------------# Sphinx3 = 10875 < x < 11042 and 4523 < y < 4664 Sphinx2 = 10875 < x < 11042 and 5865 < y < 6009 Sphinx = 8377 < x < 8545 and 5865 < y < 6009 if NephthysOFF or SekhmetOFF or HorusOFF or NephthysOFF2 or SekhmetOFF2 or HorusOFF2 or NephthysOFF3 or SekhmetOFF3 or HorusOFF3 or (checkbox_states.get('ignoresph') and SphinxOFF3): if dungeon_location != "OFF_HWT" : dungeon_location = "OFF_HWT" elif Sphinx or Sphinx2 or Sphinx3 : if dungeon_location != "PASS" : dungeon_location = "PASS" else : if dungeon_location != "ON_HWT" : dungeon_location = "ON_HWT" elif -11455 < x < -11327 and -3296 < y < -3261: set_dungeon("GATE") elif current_profile == slot_profile : if get_distance_to_training_area() : set_dungeon("SLOT") else : set_dungeon("OUTSLOT") else : set_dungeon("UNKNOWN") if dungeon_location != "PASS" : dungeon_location = "PASS" CheckResetTime() #end_time = time.time() if log_message else None # Bitiş zamanı #elapsed = round((end_time - start_time) * 1000, 2) if log_message else None # ms cinsinden #log(f"[CheckInDungeon] çalışması {elapsed} ms sürdü.") if log_message else None def get_distance_to_training_area(): training_area = get_training_area() or {} training_x = training_area.get('x', 0) training_y = training_area.get('y', 0) training_radius = training_area.get('radius', 50) distance = ( ((x - training_x) ** 2 + (y - training_y) ** 2) ** 0.5 ) return distance <= training_radius def CheckResetTime(): now = datetime.now() if now.hour == 0 and now.minute == 1: if ResetCountDelay(): ResetCount() def DodgeAttack(): global DodgeAttackBool, CheckPoint if DodgeAttackBool : return DodgeAttackBool = True while DodgeAttackBool : AttackRadius= safe_int(QtBind.text(gui,txtRange),35) AttackRadius2 = safe_int(QtBind.text(gui,txtRange2),45) training_area = get_training_area() or {} radius = training_area.get('radius', 0) if is_in_dungeon in {"FGW","HWT"} : if dungeon_location in {"ON_HWT","OFF_HWT"} : if dungeon_location == "ON_HWT" and radius < AttackRadius : CheckPoint = True set_training_radius(AttackRadius) if log_message : log(f'Plugin: Training radius set to "{AttackRadius}" m. [ HWT ] ') elif dungeon_location == "OFF_HWT" and radius > 0 : CheckPoint = False set_training_radius(0) if log_message : log('Plugin: Training radius set to "0" m. [HWT] ') elif dungeon_location in {"ON_FGW","OFF_FGW"} : if dungeon_location == "ON_FGW" and radius < AttackRadius2 : set_training_radius(AttackRadius2) if log_message : log(f'Plugin: Training radius set to "{AttackRadius2}" m. [ FGW ] ') elif dungeon_location == "OFF_FGW" and radius > 0 : set_training_radius(0) if log_message : log('Plugin: Training radius set to "0" m. [ FGW ] ') elif is_in_dungeon not in {"FGW","HWT"} : DodgeAttackBool = False break time.sleep(0.5) def get_party_info(): party = get_party() or {} if not party: return { 'leader_name': "null", 'is_me': False, 'area': "null", 'total_members': 0, 'nearby_count': 1, 'leader_pos': (0,0) } character_data = get_character_data() or {} my_name = character_data.get('name', '') total_members = len(party) nearby_count = 1 for member in party.values(): if member.get('leader'): leader_name = member['name'] is_me = (leader_name == my_name) leader_pos = (member['x'], member['y']) r = member['region'] for other_member in party.values(): if other_member != member: other_pos = (other_member['x'], other_member['y']) distance = math.dist(leader_pos, other_pos) if distance < 25: nearby_count += 1 # Bölge belirleme x, y = leader_pos if 7301 <= x <= 9603 and 5385 <= y <= 6540: area = "Advanced" elif 9790 <= x <= 12095 and 5375 <= y <= 6530: area = "Intermediate" elif 10560 <= x <= 12100 and 4030 <= y <= 5180: area = "Beginner" elif 16317 < x < 19388 and 2298 < y < 4991: area = "FGW" elif r in {23088, 23687, 23603, 25000, 26265, 27244, 26959}: area = "TOWN" elif r == 19019: area = "GATE" else: area = "UNKNOWN" return { 'leader_name': leader_name, 'is_me': is_me, 'area': area, 'total_members': total_members, 'nearby_count': nearby_count, 'leader_pos': leader_pos } return { 'leader_name': "null", 'is_me': False, 'area': "null", 'total_members': 0, 'nearby_count': 1, 'leader_pos': (0,0) } def Entrance(): global Beginner_remaining,Intermediate_remaining,Advanced_remaining,WaitMaster,MembersReturn,Return,ReturnCommand,Finished_HWT,Remaining,Done,inside_hwt party_info_list = get_party_info() or {} lider_durumu = party_info_list.get('is_me',False) lider_konum = party_info_list.get('area','') count = party_info_list.get('total_members',0) nearby_count = party_info_list.get('nearby_count',1) PartyMembers = safe_int(QtBind.text(gui,txtPartyMembers),0) if not ReturnCommand and resurrection_name in resurrection_list : if lider_durumu and nearby_count >= PartyMembers : if route_key() == 'third': if Advanced_remaining > 0 : Advanced() inside_hwt = True if Advanced_remaining > 0 : if Remaining == 0 : Remaining += 1 Advanced_remaining -=1 update_stage_label() elif Intermediate_remaining > 0 : Intermediate() inside_hwt = True if Intermediate_remaining > 0 : if Remaining == 0 : Remaining += 1 Intermediate_remaining -=1 update_stage_label() elif Beginner_remaining > 0 : Beginner() inside_hwt = True if Beginner_remaining > 0 : if Remaining == 0 : Remaining += 1 Beginner_remaining -=1 update_stage_label() else : if Advanced_remaining == 0 and Intermediate_remaining == 0 and Beginner_remaining == 0 : if Remaining == 0 : Done = 3 Finished_HWT = True HWTOFF() elif route_key() == 'second': if Intermediate_remaining > 0 : Intermediate() inside_hwt = True if Intermediate_remaining > 0 : if Remaining == 0 : Remaining += 1 Intermediate_remaining -=1 update_stage_label() elif Advanced_remaining > 0 : Advanced() inside_hwt = True if Advanced_remaining > 0 : if Remaining == 0 : Remaining += 1 Advanced_remaining -=1 update_stage_label() elif Beginner_remaining > 0 : Beginner() inside_hwt = True if Beginner_remaining > 0 : if Remaining == 0 : Remaining += 1 Beginner_remaining -=1 update_stage_label() else : if Advanced_remaining == 0 and Intermediate_remaining == 0 and Beginner_remaining == 0 : if Remaining == 0 : Done = 3 Finished_HWT = True HWTOFF() elif route_key() == 'first': if Beginner_remaining > 0 : Beginner() inside_hwt = True if Beginner_remaining > 0 : if Remaining == 0 : Remaining += 1 Beginner_remaining -=1 update_stage_label() elif Intermediate_remaining > 0 : Intermediate() inside_hwt = True if Intermediate_remaining > 0 : if Remaining == 0 : Remaining += 1 Intermediate_remaining -=1 update_stage_label() elif Advanced_remaining > 0 : Advanced() inside_hwt = True if Advanced_remaining > 0 : if Remaining == 0 : Remaining += 1 Advanced_remaining -=1 update_stage_label() else : if Advanced_remaining == 0 and Intermediate_remaining == 0 and Beginner_remaining == 0 : if Remaining == 0 : Done = 3 Finished_HWT = True HWTOFF() elif not lider_durumu and count >= 2: if lider_konum == "Advanced" : Advanced() if Advanced_remaining == 0 : update_stage_label() elif Advanced_remaining > 0 : if Remaining == 0 : Remaining += 1 Advanced_remaining -=1 update_stage_label() elif lider_konum == "Intermediate" : Intermediate() if Intermediate_remaining == 0 : update_stage_label() elif Intermediate_remaining > 0 : if Remaining == 0 : Remaining += 1 Intermediate_remaining -=1 update_stage_label() elif lider_konum == "Beginner" : Beginner() if Beginner_remaining == 0 : update_stage_label() elif Beginner_remaining > 0 : if Remaining == 0 : Remaining += 1 Beginner_remaining -=1 update_stage_label() elif lider_konum == "TOWN" : if MembersReturn == 0 : MembersReturn += 1 ReturnCommand = True return_town() log('Plugin: Party Lideri Şehirde, Şehre dönülüyor.') elif lider_konum == "GATE" : if WaitMaster == 0 : WaitMaster += 1 log('Plugin: Party Liderinin giriş yapması bekleniyor...') else : pass def Gate(): npcs = get_npcs() or {} return any(npc['servername'] == "GATE_TOMB_GATE_IN" for npc in npcs.values()) if npcs else False def FGW_Gate(): npcs = get_npcs() or {} return any(npc['servername'] == "NPC_FWORLD_RECALL_PARTY" for npc in npcs.values()) if npcs else False def IfCancelSpeed(): npcs = get_npcs() or {} if not npcs: return False target_npcs = { "NPC_FWORLD_RECALL_PARTY", "GATE_TOMB_GATE_IN", "GATE_TOMB_GATE_OUT_1", "GATE_TOMB_GATE_OUT_2", "GATE_TOMB_GATE_OUT_3" } result = any(npc['servername'] in target_npcs for npc in npcs.values()) return result def event_loop(): # Zamanlayici, eklentinin geri kalanindan bagimsiz calisir: # "Eklenti aktif" kapali olsa bile saat gelince profili degistirir. try: timer_check() timer_update_label() except Exception as e: log(f'Plugin: Zamanlayici dongu hatasi: {e}') if checkbox_states.get('disabledplugin') and resurrection_name in resurrection_list and check_data : global ReturnCommand, Finished_HWT, CheckPoint, start_bot_in_town, last_trace_stop_time, start_time_entrance CheckInDungeon() if is_in_dungeon in { "FGW" , "HWT" } : if is_in_dungeon == "HWT" : if checkbox_states.get('ignoreNav') and not DodgeAttackBool : if status in { "tracing", "botting" }: threading.Timer(0.1, DodgeAttack).start() elif is_in_dungeon == "FGW" : if checkbox_states.get('ignoreNav2') and not DodgeAttackBool : if status in { "tracing", "botting" }: threading.Timer(0.1, DodgeAttack).start() elif checkbox_states.get('returntown') : party_info = get_party_info() or {} if party_info.get('area','') == "TOWN" : if not End() and not ReturnCommand: ReturnCommand = True return_town() elif is_in_dungeon == "GATE" : if HWT_Entrance and ReturnCommand == False and Finished_HWT == False: if status == "botting" and Gate() : if start_time_entrance is None: start_time_entrance = time.time() elif time.time() - start_time_entrance >= 30: stop_bot() else: start_time_entrance = None Entrance() elif Finished_HWT and after_hwt_key() and start_bot_in_town == False : hwt_profile = QtBind.text(gui, txtHWTPROFILE) or "HWT" if current_profile == hwt_profile: Finished_HWT = False switch_profile_and_return(after_hwt_key(), 'HWT') if checkbox_states.get('Enabled'): if is_in_dungeon in { "FGW" , "HWT" } and checkbox_states.get('trace') : party_info = get_party_info() or {} lider_durumu = party_info.get('is_me',False) if not lider_durumu and not stop_checking_trace_status : start_trace_for_dungeon() elif is_in_dungeon == "TOWN" : hwt_profile = QtBind.text(gui, txtHWTPROFILE) or "HWT" # FGW bitisi: FGW'den sehre donuldu ve bir hedef secilmis. # Profil degistigi an kosul kendiliginden kapanir, tekrar tetiklenmez. fgw_profile_ = QtBind.text(gui, txtFGWPROFILE).strip() or "FGW" if after_fgw_key() and previous_dungeon == "FGW" and current_profile == fgw_profile_ : switch_profile_and_return(after_fgw_key(), 'FGW') elif checkbox_states.get('changeprofile2') and waitpartymembers_command and current_profile == "FAKE_SLOT" : threading.Timer(0.1,waitpartymembers).start() elif current_profile == hwt_profile and checkbox_states.get('start') : current_time = time.time() if last_trace_stop_time > 0 and (current_time - last_trace_stop_time) < 0.6: return elif status is not None and status not in { 'tracing', 'botting' }: start_bot() log(f'Plugin: Şehirde Holy Water Temple için botu başlattık.') elif status == "tracing": stop_trace() log(f'Plugin: Şehirde botu başlatmak için takibi durdurduk.') last_trace_stop_time = time.time() elif current_profile != hwt_profile and HWT_Entrance and checkbox_states.get('EntranceON') : HWTOFF() elif is_in_dungeon == "GATE" : if not HWT_Entrance : hwt_profile = QtBind.text(gui, txtHWTPROFILE) or "HWT" if current_profile == hwt_profile: if checkbox_states.get('EntranceON'): party_info = get_party_info() or {} lider_durumu = party_info.get('is_me',False) if lider_durumu and Done < 3: HWTON() elif not lider_durumu: HWTON() elif is_in_dungeon == "SLOT" : profile_slot = QtBind.text(gui, txtSLOTPROFILE).strip() or "SLOT" if checkbox_states.get('changeprofile2') and waitpartymembers_command and current_profile == profile_slot : threading.Timer(0.1,waitpartymembers).start() def send_pm_to_dc_chars(args): if disconnect_list : slot_profile = QtBind.text(gui, txtSLOTPROFILE).strip() or "SLOT" pm_message = f"change profile {slot_profile.lower()}" for name in disconnect_list[:]: try: result = phBotChat.Private(name, pm_message) if result: log(f"Plugin: {name} adlı kişiye mesaj gönderildi.") disconnect_list.remove(name) else: log(f"Plugin: {name} adlı kişiye mesaj gönderilemedi.") except Exception as e: log(f"Plugin: {name} için hata oluştu: {e}") if disconnect_list : log(f"Kalanlar: {', '.join(disconnect_list)}") else : log(f'Plugin: Herkese mesaj gönderildi.') time.sleep(1.5) # Flood yememek için bekleme else : log(f'Plugin: Liste temiz.') return 0 target_positions = [ (["alexandria"], [(-16638, -329), (-16117, 54)]), (["hotan krallığı", "hotan kingdom"], (-11454, -3262)), (["jangan"], (6432, 1098)), (["constantinople"], (-10656, 2604)), (["western china donwhang", "batı çin donwhang"], (3551, 2070)), (["samarkand"], (-5155, 2830)), ] def check_positions(): char_data = get_character_data() or {} map_location = char_data.get('zone_name', '').lower() char_pos = (char_data.get('x', 0), char_data.get('y', 0)) for town_names, coords in target_positions: if map_location in [name.lower() for name in town_names]: # Alexandria veya diğerleri if isinstance(coords, list): # Tüm koordinatlar için kontrol all_far = True for x, y in coords: target_range = int(math.dist(char_pos, (x, y))) log(f'{map_location} -> {x},{y} -> Range: {target_range}') if target_range < 10: # biri 30'dan küçükse başarısız all_far = False break if all_far: # hepsi 30 veya daha uzaksa return True else: x, y = coords target_range = int(math.dist(char_pos, (x, y))) log(f'{map_location} -> {x},{y} -> Range: {target_range}') if target_range >= 10: return True return False def handle_chat(t, player, msg) : if not player.lower() == resurrection_name : if t in { 2 , 4 } : if msg.startswith("change profile "): global pm_received, start_bot_in_town, stop_bot_in_town, set_profile_in_town, unsucces_fgw, dont_move, stop_checking_trace_status FGWProfile = QtBind.text(gui, txtFGWPROFILE).strip() or "FGW" HWTProfile = QtBind.text(gui, txtHWTPROFILE).strip() or "HWT" SLOTProfile = QtBind.text(gui, txtSLOTPROFILE).strip() or "SLOT" if not pm_received : pm_received = True if not dont_move : dont_move = True new_profile = msg[len("change profile "):].strip() or '' master_name = QtBind.text(gui, txtSLOTMASTER).strip() or '' if new_profile == FGWProfile.lower() and master_name == player : #change profile fgw if status in { "tracing" , "botting" } : if status == "tracing" : stop_trace() elif status == "botting" : if is_in_dungeon == "TOWN" : stop_bot() else : stop_bot_in_town = True if is_in_dungeon == "TOWN" : if current_profile.lower() != new_profile.lower() : set_profile(FGWProfile) else : if current_profile.lower() != new_profile.lower() : set_profile_in_town = (True,FGWProfile) return_town() if unsucces_fgw : unsucces_fgw = False log(f'Plugin: [ {FGWProfile} ] profiline geçiş kontrolü yapılıyor. ') log(f'Plugin: Durum: {status}, Lokasyon: {is_in_dungeon}, ') log(f'Plugin: Aktif profil: "{current_profile}", Master: {master_name}, ') log(f'Plugin: Profil değiştirilecek mi: {"Evet" if current_profile.lower() != new_profile.lower() else "Hayır"}') elif new_profile == "dc_fgw" and master_name == player : #change profile dc_fgw if status in { "tracing" , "botting" } : if status == "tracing" : stop_trace() elif status == "botting" : if is_in_dungeon == "TOWN" : stop_bot() else : stop_bot_in_town = True if is_in_dungeon == "TOWN" : if current_profile.lower() != new_profile.lower() : set_profile(FGWProfile) else : if current_profile.lower() != new_profile.lower() : set_profile_in_town = (True,FGWProfile) return_town() log(f'Plugin: [ {FGWProfile }] profiline geçiş kontrolü yapılıyor. ') log(f'Plugin: Durum: {status}, Lokasyon: {is_in_dungeon}, ') log(f'Plugin: Aktif profil: "{current_profile}", Master: {master_name}, ') log(f'Plugin: Profil değiştirilecek mi: {"Evet" if current_profile.lower() != FGWProfile.lower() else "Hayır"}') elif new_profile == HWTProfile.lower() and master_name == player : # change profile hwt if status == "tracing" : stop_trace() if Gate() : if current_profile.lower() != new_profile : set_profile(HWTProfile) else: log(f'Plugin: Zaten "{HWTProfile}" profili aktif. Değişiklik yapılmadı.') if status == "botting" : stop_bot() else : if current_profile.lower() != new_profile : set_profile_in_town = (True,HWTProfile) else: log(f'Plugin: Zaten "{HWTProfile}" profili aktif. Değişiklik yapılmadı.') if status == "botting" : stop_bot_in_town = True return_town() log(f'Plugin: [ {HWTProfile} ] profiline geçiş kontrolü yapılıyor. ') log(f'Plugin: Durum: {status}, Lokasyon: {is_in_dungeon}, ') log(f'Plugin: Aktif profil: "{current_profile}", Master: {master_name}, ') log(f'Plugin: Profil değiştirilecek mi: {"Evet" if current_profile.lower() != new_profile.lower() else "Hayır"}') elif new_profile == SLOTProfile.lower() and master_name == player : # change profile slot if status == "tracing" : stop_trace() if current_profile.lower() != new_profile : set_profile(SLOTProfile) if get_distance_to_training_area() : if status != "botting" : start_bot() else : start_bot_in_town = True return_town() log(f'Plugin: [ {SLOTProfile} ] profiline geçiş kontrolü yapılıyor. ') log(f'Plugin: Durum: {status}, Lokasyon: {is_in_dungeon}, ') log(f'Plugin: Aktif profil: "{current_profile}", Master: {master_name}, ') log(f'Plugin: Profil değiştirilecek mi: {"Evet" if current_profile.lower() != new_profile.lower() else "Hayır"}') elif new_profile == "rpr" and master_name == player : # change profile rpr if is_in_dungeon == "FGW" : stop_checking_trace_status = True return_town() if status == "tracing" : stop_trace() if current_profile.lower() == FGWProfile.lower() : set_profile(new_profile.upper()) else: log(f'Plugin: Profil zaten " {new_profile.upper()} " olarak ayarlı. Değişiklik yapılmadı.') elif new_profile == "fake_slot" and master_name == player : if status == "tracing" : stop_trace() if unsucces_fgw : unsucces_fgw = False set_profile("RPR") else : profile_fgw = FGWProfile.upper() if current_profile.upper() != profile_fgw : set_profile(profile_fgw) if status == "botting" : stop_bot_in_town = True return_town() log(f'Plugin: [ {SLOTProfile} ] profiline geçiş kontrolü yapılıyor. ') log(f'Plugin: Durum: {status}, Lokasyon: {is_in_dungeon}, ') log(f'Plugin: Aktif profil: "{current_profile}", Master: {master_name}, ') log(f'Plugin: Profil değiştirilecek mi: {"Evet" if current_profile.lower() != new_profile.lower() else "Hayır"}') else : Master = get_party_info().get('leader_name','') == player if new_profile.lower() not in {'fgw','dc_fgw','hwt','slot','rpr','fake_slot'} and Master : set_profile(new_profile.upper()) elif msg.startswith("dodge "): if is_in_dungeon in { "FGW" , "HWT" } : command = msg[len("dodge "):].strip() if is_in_dungeon == "FGW" and checkbox_states.get('usedodgeskills') : if command == "Sereness": # Kendi paketimizden zaten tetiklendiyse bu cagri yutulur. request_dodge_sereness('parti duyurusu') elif is_in_dungeon == "HWT" and checkbox_states.get('reflect') : if command == "Sphinx Beginner": SpinixReflectCounterStop() threading.Timer(16.0,SpinixReflectCounterStart).start() if log_message : log('Plugin: Beginner Sphinx Reflect Counter') elif command == "Sphinx Intermediate": SpinixReflectCounterStop() threading.Timer(21.0,SpinixReflectCounterStart).start() if log_message : log('Plugin: Intermediate Sphinx Reflect Counter') elif command == "Sphinx Advanced": SpinixReflectCounterStop() threading.Timer(26.0,SpinixReflectCounterStart).start() if log_message : log('Plugin: Advanced Spinix Reflect Counter') elif msg.startswith("give me profile"): if checkbox_states.get('disabledplugin') : if is_in_dungeon == "FGW" : if player not in disconnect_list : disconnect_list.append(player) if disconnect_from_fgw[0] == "FGW" and False : return elif current_profile == "FAKE_SLOT" : phBotChat.Private(player, f'change profile fake_slot') else : profile = current_profile.lower() phBotChat.Private(player, f'change profile {profile}') else : phBotChat.Private(player, f'Plugin: Plugin is Disabled. [ Cannot assign a profile name ] ') def is_close_trace_master(trace_name): char_data = get_character_data() or {} party_members = get_party() or {} char_pos = (char_data.get('x', 0), char_data.get('y', 0)) Range = 299 for member in party_members.values(): if member['name'] == trace_name: member_pos = (member['x'], member['y']) distance = int(math.dist(char_pos, member_pos)) Range = min(Range, distance) return Range if Range != 299 else -1 def start_trace_for_dungeon(): global last_trace_time, trace_log, trace_cooldown party_info = get_party_info() or {} leader_name = party_info.get('leader_name','') if is_in_dungeon == "FGW": trace_name = QtBind.text(gui, txtFGWMASTER) or leader_name elif is_in_dungeon == "HWT": trace_name = QtBind.text(gui, txtHWTMASTER) or leader_name else: return distance = is_close_trace_master(trace_name) if distance >= 0: min_distance = safe_int(QtBind.text(gui, txtMinDistance), 10) max_distance = safe_int(QtBind.text(gui, txtMaxDistance), 70) if distance <= min_distance: if status == "tracing" and trace_log : trace_log = False log(f'Plugin: Trace Master: {trace_name} ({distance} birim uzaklıkta) takip başlatılıyor...') elif status is not None and status not in { "tracing" , "botting" } and not dead and remember_last_status not in { "tracing" , "botting" }: current_time = time.time() if current_time - last_trace_time >= trace_cooldown: last_trace_time = current_time start_trace(trace_name) trace_log = True elif status == "botting": stop_bot() leader_pos = party_info.get('leader_pos','') if leader_pos[0] != 0 and leader_pos[1] != 0 : move_to(leader_pos[0], leader_pos[1], 0) if trace_log : trace_log = False elif distance >= max_distance: file_path = get_training_area().get('path', '') if status is not None and status not in { "tracing" , "botting" } and not dead : set_training_script(file_path) threading.Timer(0.5,start_bot).start() log(f'Plugin: Trace Master: {trace_name} ({distance} birim uzaklıkta) bot başlatılıyor...') if trace_log : trace_log = False elif status == "tracing": set_training_script(file_path) stop_trace() if trace_log : trace_log = False def handle_joymax(opcode, data) : global AdvancedL,IntermediateL,BeginnerL,Done if opcode == 0xB05A and resurrection_name in resurrection_list: if data[:3] == bytes( [ 0x02, 0x27, 0x1C ] ) : if route_key() == 'third': if AdvancedL < 5: AdvancedL = 5 elif IntermediateL < 5 : IntermediateL = 5 elif BeginnerL < 5 : BeginnerL = 5 elif route_key() == 'second': if IntermediateL < 5 : IntermediateL = 5 elif AdvancedL < 5: AdvancedL = 5 elif BeginnerL < 5 : BeginnerL = 5 elif route_key() == 'first': if BeginnerL < 5 : BeginnerL = 5 elif IntermediateL < 5 : IntermediateL = 5 elif AdvancedL < 5: AdvancedL = 5 elif route_key() == 'only_advanced' : if AdvancedL < 5: AdvancedL = 5 elif route_key() == 'only_intermediate' : if IntermediateL < 5 : IntermediateL = 5 elif route_key() == 'only_beginner' : if BeginnerL < 5 : BeginnerL = 5 Done += 1 elif opcode == 0xB070 and resurrection_name in resurrection_list: if is_in_dungeon in { "FGW" , "HWT" } : if is_in_dungeon == "FGW" : if data[:5] == bytes( [ 0x01, 0x00, 0x30, 0x51, 0x80 ] ) : sereness_cast_detected() elif is_in_dungeon == "HWT" : if data[:5] == bytes( [ 0x01, 0x00, 0x30, 0x9D, 0x7A ] ) : phBotChat.Party("dodge Sphinx Beginner") if checkbox_states.get('reflect') : SpinixReflectCounterStop() threading.Timer(16.0,SpinixReflectCounterStart).start() if log_message : log('Plugin: Beginner Sphinx Reflect Counter') elif data[:5] == bytes( [ 0x01, 0x00, 0x30, 0xA4, 0x7A ] ) : phBotChat.Party("dodge Sphinx Intermediate") if checkbox_states.get('reflect') : SpinixReflectCounterStop() threading.Timer(21.0,SpinixReflectCounterStart).start() if log_message : log('Plugin: Intermediate Spinix Reflect Counter') elif data[:5] == bytes( [ 0x01, 0x00, 0x30, 0xAB, 0x7A ] ) : phBotChat.Party("dodge Sphinx Advanced") if checkbox_states.get('reflect') : SpinixReflectCounterStop() threading.Timer(26.0,SpinixReflectCounterStart).start() if log_message : log('Plugin: Advanced Sphinx Reflect Counter') return True def pm_party_master_for_profile_loop(): global pm_requested, pm_received master_name = QtBind.text(gui, txtSLOTMASTER).strip() or '' if pm_received : return if master_name == '' : log("Plugin: Party master ismi boş.") return if pm_requested and not pm_received: log(f"Plugin: PM gönderiliyor → {master_name}") phBotChat.Private(master_name, "give me profile") threading.Timer(30.0,pm_party_master_for_profile_loop).start() def sereness_cast_detected(): """Boss'un telegraf paketi goruldu. Duyuruyu SADECE parti lideri yapar; boylece 8 uyenin ayni anda partiye yazip birbirini tetiklemesi biter.""" started = False if checkbox_states.get('usedodgeskills'): started = request_dodge_sereness('paket') try: if started and get_party_info().get('is_me', False): phBotChat.Party("dodge Sereness") except Exception as e: log(f'Plugin: Sereness duyurusu gonderilemedi: {e}') def request_dodge_sereness(source=''): """Tek olay = tek kacis. Tekrar eden tetiklemeleri yutar. Donen deger: bu cagri gercekten yeni bir kacis baslatti mi.""" global _dodge_last_ts, _dodge_epoch with _dodge_lock: now = time.time() if now - _dodge_last_ts < DODGE_COOLDOWN: return False _dodge_last_ts = now _dodge_epoch += 1 epoch = _dodge_epoch if log_message and source: log(f'Plugin: Kacis tetiklendi [ kaynak: {source} ]') Trigger_Dodge_Sereness(epoch) return True def Trigger_Dodge_Sereness(epoch=None): if epoch is None: # Disaridan dogrudan cagrildiysa tekillestirmeden gecir request_dodge_sereness('direct') return monsters = get_monsters() or {} x_canavar = y_canavar = None if monsters: unique_name = "Ghost Sereness" for mob in monsters.values(): if mob['name'].strip() == unique_name.strip(): x_canavar, y_canavar = mob['x'], mob['y'] break else: log(f'Plugin: Yakınlarda [ {unique_name} ] bulunamadı.') return else: log("Plugin: Yakınlarda Canavar bulunamadı.") return if x_canavar is not None and y_canavar is not None: global movement movement = not movement position = get_position() or {} x_karakter = position.get('x', 0) y_karakter = position.get('y', 0) yaricap = safe_int(QtBind.text(gui, lineedit_range), 20) dx = x_karakter - x_canavar dy = y_karakter - y_canavar mesafe = math.hypot(dx, dy) # sqrt(dx**2 + dy**2) yerine daha okunabilir if mesafe != 0: target_angle = math.atan2(dy, dx) delta_angle = math.radians(20) if movement else math.radians(-20) target_angle += delta_angle x_yeni = x_canavar + yaricap * math.cos(target_angle) y_yeni = y_canavar + yaricap * math.sin(target_angle) else: x_yeni = x_canavar y_yeni = y_canavar if status == "botting" : set_training_position(0, x_yeni, y_yeni, 0) if log_message : log(f"Plugin: Ghost Sereness ' ten kaçılıyor... [ {x_karakter:.0f},{y_karakter:.0f} -> {x_yeni:.0f},{y_yeni:.0f} ]") threading.Timer(0.1, Dodge_Sereness, [x_yeni, y_yeni, 0, epoch]).start() def Dodge_Sereness(x, y, z, epoch=None): for i in range(10): # Daha yeni bir kacis basladiysa bu dongu kendini iptal eder; # boylece iki zit hedefe ayni anda move_to gonderilmez. if epoch is not None and epoch != _dodge_epoch: return move_to(x, y, z) time.sleep(0.2) if log_message : p = get_position() or {} log(f"Plugin: Kacis bitti. Son konum: [ {p.get('x',0):.0f},{p.get('y',0):.0f} ]") def HWTON(): global HWT_Entrance if not HWT_Entrance : QtBind.setChecked(gui,cbxHolyMolyEntrance,True) HWT_Entrance = QtBind.isChecked(gui, cbxHolyMolyEntrance) if log_message : log('Plugin: Active Holy Water Temple (Entrance)') def HWTOFF(): global HWT_Entrance if HWT_Entrance: QtBind.setChecked(gui,cbxHolyMolyEntrance,False) HWT_Entrance = QtBind.isChecked(gui, cbxHolyMolyEntrance) if log_message : log('Plugin: Passive Holy Water Temple (Entrance)') def Beginner(): # 165, 166, 167 npcs = get_npcs() or {} if npcs : for key , npc in npcs.items() : if npc.get('servername', 'GATE_TOMB_GATE_IN') == "GATE_TOMB_GATE_IN" or npc.get('name', 'Krallar Vadisi') == "Krallar Vadisi" or npc.get('name', 'Kings Valley') == "Kings Valley" : eng = get_teleport_data(npc['name'], "Pharaoh tomb (beginner)") tr = get_teleport_data(npc['name'], "Pharaoh'nun mezarı (düşük)") if eng : inject_joymax(0x705A,struct.pack('= 2 : try: if round(float(args[1])) <= 8 : memberCount = round(float(args[1])) else : log(f"Plugin: Geçersiz sayı girdisi, Yakındaki oyuncu sayısı için varsayılan {memberCount} kullanılacak.") except ValueError: log(f"Plugin: Geçersiz sayı girdisi, Yakındaki oyuncu sayısı için varsayılan {memberCount} kullanılacak.") if len(args) >= 3 : try: if round(float(args[2])) : max_range = round(float(args[2])) else : log(f"Plugin: Geçersiz sayı girdisi, Kontrol mesafesi için varsayılan {max_range} kullanılacak.") except ValueError: log(f"Plugin: Geçersiz sayı girdisi, Kontrol mesafesi için varsayılan {max_range} kullanılacak.") current_count, missing_players = GetPartyMembersCount(max_range) if current_count < memberCount: stop_bot() if not waiting_thread or not waiting_thread.is_alive(): waiting_thread = threading.Thread(target=WaitPartyTask, args=(memberCount,max_range)) waiting_thread.start() if missing_players: log('Plugin: Yakında olmayan üyeler: ' + ', '.join(missing_players) + ' bekleniyor...') else : if memberCount > 8 : memberCount = 8 if current_count < memberCount : logged_missing_player = memberCount - current_count log(f'Plugin: Partyde {logged_missing_player} kişi eksik, bekleniyor... ') else : log(f'Plugin: WaitParty script komutu zaten aktif.') return 0 def GetPartyMembersCount(check_range): _, missing_players, _ = everybodyhere() nearby_count = 0 player_data = get_party() or {} if player_data: leader = next((m for m in player_data.values() if m.get('leader')), None) if leader: nearby_count = 1 # lider dahil leader_pos = (leader['x'], leader['y']) for member in player_data.values(): if not member.get('leader'): member_pos = (member['x'], member['y']) dist = math.dist(member_pos, leader_pos) if dist < check_range: nearby_count += 1 if member['name'] in missing_players: missing_players.remove(member['name']) return nearby_count, missing_players def WaitPartyTask(MemberCount,max_range): previous_missing_count = 0 while True: try: result = GetPartyMembersCount(max_range) if result is None or not isinstance(result, tuple) or len(result) != 2: log("Plugin: Grup verisi alınamadı veya hatalı formatta. Beklenmedik sonuç.") time.sleep(1) continue count, missing_players = result if missing_players and len(missing_players) < previous_missing_count: log('Plugin: Bir oyuncu daha geldi! Şu anda beklenen üyeler: ' + ', '.join(missing_players)) previous_missing_count = len(missing_players) if count >= MemberCount: break time.sleep(0.5) except Exception as e: log(f"Plugin: WaitPartyTask hata verdi: {str(e)}") break log('Plugin: Bekleme tamamlandı, herkes hazır!') start_bot() def teleported(): if checkbox_states.get('disabledplugin') : global WaitMaster,MembersReturn,ReturnCommand,Remaining,start_bot_in_town,stop_bot_in_town,movement,set_profile_in_town,dont_move,stop_checking_trace_status party_info = get_party_info() or {} lider_durumu = party_info.get('is_me', False) if set_profile_in_town[0]: set_profile(set_profile_in_town[1]) set_profile_in_town = (False, '') if start_bot_in_town or stop_bot_in_town: if start_bot_in_town : start_bot() start_bot_in_town = False elif stop_bot_in_town : stop_bot() stop_bot_in_town = False if stop_checking_trace_status : stop_checking_trace_status = False if ReturnCommand : ReturnCommand = False if movement == False : movement = True if Remaining > 0 : Remaining = 0 if WaitMaster > 0 : WaitMaster = 0 if MembersReturn > 0 : MembersReturn = 0 if checkbox_states.get('notrace') : if dont_move : dont_move = False inject_joymax(0x7074,b'\x02',False) p = get_position() if p : region, x, y, z = p.get('region', 0), p.get('x', 0), p.get('y', 0), p.get('z', 0) if region in {23088, 23687, 23603, 25000, 26265, 27244, 26959}: def force_movemont(x,y,z): for i in range(3): move_to(x, y, z) time.sleep(0.334) threading.Timer(0.1, force_movemont,[x,y,z]).start() threading.Timer(1.0,stop_trace_if_checked).start() if HWT_Entrance and lider_durumu : threading.Timer(1.0,start_bot_in_hwt).start() def stop_trace_if_checked(): if previous_dungeon in ("FGW", "HWT", "GATE" ): global unsucces_fgw start_time = time.time() while True: if time.time() - start_time > 20.0: break if status in { "tracing" , "botting" } : if is_in_dungeon == "TOWN": if status == "tracing" : stop_trace() log("Plugin: Şehre dönüş yapıldı, takip durduruldu.") if False and previous_dungeon == "FGW" : if not unsucces_fgw : unsucces_fgw = True give_me_profile_name() break else : break elif is_in_dungeon == "GATE": if status == "tracing" : stop_trace() log("Plugin: Holy Water Temple girişindesin, takip durduruldu.") elif status == "botting" : stop_bot() log("Plugin: Holy Water Temple girişindesin, bot durduruldu.") break time.sleep(0.5) def start_bot_in_hwt(): global inside_hwt start_time = time.time() while True: if time.time() - start_time > 1.0: break if inside_hwt: if is_in_dungeon == "HWT": if status != "botting": start_bot() elif status == "botting": stop_bot() threading.Timer(1, start_bot).start() inside_hwt = False break else: if is_in_dungeon == "GATE" and status == "botting": stop_bot() break time.sleep(0.5) def OutCheck(): start_time = time.time() server_name = '' while True: if time.time() - start_time > 1.0: break npcs = get_npcs() or {} training_area = get_training_area() or {} radius = training_area.get('radius', 0) attack_radius = safe_int(QtBind.text(gui, txtRange), 35) attack_radius2 = safe_int(QtBind.text(gui, txtRange2), 45) if not npcs: continue for key, npc in npcs.items(): server_name = npc.get('servername', '') if server_name in ["GATE_TOMB_GATE_OUT_2", "GATE_TOMB_GATE_OUT_3"] and radius < attack_radius: set_training_radius(attack_radius) if log_message: log(f'Plugin: Saldırı Menzilin [ {attack_radius} ] ile değiştirildi. [ HWT ] ') break elif server_name == "GATE_TOMB_GATE_OUT_1" and radius < attack_radius: if not checkbox_states.get('ignoresph') : set_training_radius(attack_radius) if log_message: log(f'Plugin: Saldırı Menzilin [ {attack_radius} ] ile değiştirildi. [ HWT ] ') break elif server_name == "NPC_FWORLD_RECALL_PARTY" and radius < attack_radius2: set_training_radius(attack_radius2) if log_message: log(f'Plugin: Saldırı Menzilin [ {attack_radius2} ] ile değiştirildi. [ FGW ] ') break if server_name in {'NPC_FWORLD_RECALL_PARTY','GATE_TOMB_GATE_OUT_1','GATE_TOMB_GATE_OUT_2','GATE_TOMB_GATE_OUT_3'}: break time.sleep(0.5) def go_hwt(): # Eskiden sabit "hwt" gonderiliyordu; profil adi "HWT-1" oldugu icin # alicida eslesme tutmuyordu. Artik profil adinin kendisi gonderiliyor. hwt_profile = QtBind.text(gui, txtHWTPROFILE).strip() or "HWT" log(f'Plugin: [ {hwt_profile} ] için Profil değiştiriliyor. [ {pName} ]' ) phBotChat.Party(f"change profile {hwt_profile.lower()}") threading.Timer(10.0,self_change_profile_hwt).start() def self_change_profile_hwt(): global waitpartymembers_command profile_hwt = QtBind.text(gui, txtHWTPROFILE).strip() or "HWT" if status == "botting" : stop_bot() set_profile(profile_hwt) waitpartymembers_command = True return_town() def everybodyhere(): path = get_config_dir() or '' CharData = get_character_data() or {} profile = get_profile() or '' ConfigFile = f"{CharData['server']}_{CharData['name']}.{profile}.json" if profile else f"{CharData['server']}_{CharData['name']}.json" cleaned_list = [] party_invite_type = 0 limited_list = 1 full_path = path + ConfigFile if os.path.exists(full_path): with open(full_path, "r", encoding='utf-8') as f: Configdata = json.load(f) party_data = Configdata.get("Party", {}) invite_list = party_data.get("InviteList", []) limited_list += len(invite_list[:7]) cleaned_list = [item[:-1] if item.endswith('$') else item for item in invite_list] party_invite_type = party_data.get("PartyInviteType", 0) return limited_list, cleaned_list, party_invite_type def fgw_party_list(): path = get_config_dir() or '' CharData = get_character_data() or {} profile_fgw = QtBind.text(gui, txtFGWPROFILE).strip() or "FGW" ConfigFile = f"{CharData['server']}_{CharData['name']}.{profile_fgw}.json" if profile_fgw else f"{CharData['server']}_{CharData['name']}.json" full_path = path + ConfigFile cleaned_list = [] if os.path.exists(full_path): with open(full_path, "r", encoding='utf-8') as f: Configdata = json.load(f) if "Party" in Configdata and "InviteList" in Configdata["Party"]: invite_list = Configdata["Party"]["InviteList"] cleaned_list = [item[:-1] if item.endswith('$') else item for item in invite_list] return cleaned_list def disconnected(): if False : global disconnect_from_fgw,client_disconnect_from_fgw if is_in_dungeon == "FGW" and disconnect_from_fgw[0] == 'null' : disconnect_from_fgw = (is_in_dungeon,x,y) client_disconnect_from_fgw = disconnect_from_fgw saveConfigs() def send_message_from_dc(): fgw_players = fgw_party_list() profile_fgw = QtBind.text(gui, txtFGWPROFILE).strip() or "FGW" global start_bot_in_town if fgw_players : pm_message = "change profile dc_fgw" log(f"PM LIST: {', '.join(fgw_players)}") for name in fgw_players[:]: try: result = phBotChat.Private(name, pm_message) if result: log(f"Plugin: {name} adlı kişiye mesaj gönderildi.") fgw_players.remove(name) else: log(f"Plugin: {name} adlı kişiye mesaj gönderilemedi.") except Exception as e: log(f"Plugin: {name} için hata oluştu: {e}") if fgw_players : log(f"Kalanlar: {', '.join(fgw_players)}") else : log(f'Plugin: Herkese mesaj gönderildi.') threading.Timer(0.5,change_rotation).start() if status == "botting" : stop_bot() start_bot_in_town = True return_town() if status == "botting" : stop_bot() if current_profile != profile_fgw : set_profile(profile_fgw) time.sleep(1.5) # Flood yememek için bekleme else : log(f'Plugin: [ {profile_fgw} ] Profilindeki invite listesinde kimse bulunamadı.') return 0 def change_rotation(): x, y = client_disconnect_from_fgw[1], client_disconnect_from_fgw[2] training_area = get_training_area() or {} if is_inside_big_area(x, y): if is_inside_inner_area(x, y): if training_area.get('name','') != 'FGW3' : log(f"Plugin: Ghost Sereness buz dağında dc oldunuz. Komut ona göre düzenlendi.") set_training_area('FGW3') else: log(f'Plugin: İlk gemi rotasyonunda dc tespit edildi. Komut değiştirilmedi.') else: if training_area.get('name','') != 'FGW2' : log(f'Plugin: ikinci gemi rotasyonunda dc tespit edildi. Komut ona göre düzenlendi.') set_training_area('FGW2') def is_inside_big_area(x, y): center_x, center_y = 18618, 3774 radius = 905 dx = x - center_x dy = y - center_y distance_squared = dx**2 + dy**2 return distance_squared <= radius**2 def is_inside_inner_area(x, y): center_x, center_y = 17844, 3754 radius = 120 dx = x - center_x dy = y - center_y distance_squared = dx**2 + dy**2 return distance_squared <= radius**2 def waitpartymembers(): global waitpartymembers_command if waitpartymembers_command : waitpartymembers_command = False party_info = get_party_info() or {} expected_count, _, _ = everybodyhere() current_count = party_info.get('total_members', 0) if current_count >= expected_count: go_hwt() return timeout = time_diff_in_seconds() timeout = timeout if timeout is not None else 7200 start_time = time.time() while current_count < expected_count: profile_slot = QtBind.text(gui, txtSLOTPROFILE).strip() or "SLOT" if current_profile != profile_slot : threading.Timer(5.0, waitpartymembers_command_t).start() break party_info = get_party_info() or {} current_count = party_info.get('total_members', 0) if current_count >= expected_count: go_hwt() break if time.time() - start_time > timeout: log("Plugin: Süre doldu. Beklenen Party üye sayısına ulaşılamadı.") threading.Timer(5.0, waitpartymembers_command_t).start() break time.sleep(0.5) def waitpartymembers_command_t(): global waitpartymembers_command waitpartymembers_command = True def time_diff_in_seconds(): if not (converted_time1 and converted_time2): return None # Saatler tanımlı değilse today = datetime.today().date() dt1 = datetime.combine(today, converted_time1) dt2 = datetime.combine(today, converted_time2) diff = (dt2 - dt1).total_seconds() if diff < 0: diff += 24 * 3600 # gece yarısını geçiyorsa return int(diff) def information_dungeon(args): if len(args) == 1 : if is_in_dungeon in {"FGW", "HWT"}: radius = 50 if is_in_dungeon == "FGW": objects = { "First Treasure Box": (17832, 3195), "Ghost Sereness": (17930, 3735), "Done Forgotten World": (17475, 3825), } elif is_in_dungeon == "HWT": objects = { "Done Beginner": (11765, 4327), "Done Intermediate": (11764, 5700), "Done Advanced": (9268, 5690), } for name, (obj_x, obj_y) in objects.items(): distance = ((x - obj_x) ** 2 + (y - obj_y) ** 2) ** 0.5 if distance <= radius: if is_in_dungeon == "FGW": if name == "First Treasure Box": log("Congratulations, the first Treasure Box has been destroyed.") elif name == "Ghost Sereness": log("Congratulations, Ghost Sereness has been defeated.") elif name == "Done Forgotten World": log("Congratulations, you have successfully completed Forgotten World.") elif is_in_dungeon == "HWT": if name == "Done Beginner": log("Congratulations, you have successfully completed Holy Water Temple - Beginner.") elif name == "Done Intermediate": log("Congratulations, you have successfully completed Holy Water Temple - Intermediate.") elif name == "Done Advanced": log("Congratulations, you have successfully completed Holy Water Temple - Advanced.") else: log("Custom Notice: " + ' '.join(args[1:])) return 0 def give_me_profile_name(): if isJoined() : if False : global pm_requested, pm_received master_name = QtBind.text(gui, txtSLOTMASTER).strip() or '' if master_name.lower() == resurrection_name.lower(): return pm_requested = True pm_received = False if previous_dungeon == 'FGW' and unsucces_fgw : log("Plugin: Forgotten World bitirilemedi. Party master'dan profil bilgisi istenecek.") else : threading.Timer( 1, lambda: log("Plugin: Profil bilgisi isteme açık. Party master'dan profil bilgisi istenecek.") ).start() threading.Timer(5.0, pm_party_master_for_profile_loop).start() elif False : global disconnect_from_fgw if disconnect_from_fgw[0] == "FGW" : disconnect_from_fgw = ('null',0,0) saveConfigs() log("Plugin: Profil bilgisi verme açık. Party üyelerine profil bilgisi verilecek.") threading.Timer(5.0, send_message_from_dc).start() else : threading.Timer(5.0, give_me_profile_name).start() def return_town(): return_scroll_list = [ "Instant Return Scroll", # Anında "Special Return Scroll", # Özel "Return Scroll", # Normal Return ] def get_item(name): items = get_inventory()['items'] for slot, item in enumerate(items): if item and item.get('name') == name: item['slot'] = slot return item return None def use_item(item): if not item: return False ItemInfo = get_item_string(item['name']) tid1, tid2, tid3, slot = ItemInfo['tid1'], ItemInfo['tid2'], ItemInfo['tid3'], item['slot'] p = struct.pack('