Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from phBot import *
- from threading import Timer
- import QtBind
- import struct
- import json
- import os
- # ------------------------------ xControl ~ by ProjeXNET ------------------------------
- # Character Info
- playerData = None
- # Plugins\xControl path
- folderSave = os.path.dirname(os.path.realpath(__file__))+"\\xControl"
- # Initializing GUI
- gui = QtBind.init(__name__,'xControl (EN)')
- lblControl = QtBind.createLabel(gui,'Plugin usefull for manage partys. one char or group of characters, by #GeneralChat, #PartyChat or #PrivateMessage\n\n The "Leader(s)" is the character that write commands.\n Them that have the Leader(s) into the list and has receive the message with the command, will execute the function of it.\n\n ➤ ENABLE : Enable #ATTACKs mode\n ➤ DISABLE : Disable #ATTACKs mode\n ➤ ATTACK : Attacking with " Normal Attack " what the leader has previously attacked if is into the range\n ➤ ATTACKS : Same attack mode but using skills from the Skill(s) list \n ➤ STOP : Stop attacking any target\n ➤ INJECT #Opcode #Encrypted #Data : Inject a #Packet. Ex: "INJECT 3091 0" or "INJECT 3091 False 0" ( mean greet )\n ➤ STARTB : Start bot\n ➤ STOPB : Stop Bot\n ➤ TRACE : Start #Trace to leader (nick dont required) or another\n ➤ STOPT : Stop #Trace\n ➤ SIT : Sit or Stand up, depends\n ➤ CAPE #Colour : Use PVP Cape. Ex: "CAPE White" or "CAPE Off"\n ➤ USEZERK : Use #Berserker mode if available\n ➤ USERETURN : Use some " Return Scroll " from inventory',21,11)
- cbxEnableAttack = QtBind.createCheckBox(gui, 'cbxEnableAttack_clicked','Enable #ATTACKs',610,10)
- cbxEnableAttack_checked = False
- lblLeaders = QtBind.createLabel(gui,'♯ Leaders list',351,161)
- tbxLeaders = QtBind.createLineEdit(gui,"",351,179,100,20)
- lstLeaders = QtBind.createList(gui,351,200,176,60)
- btnAddLeader = QtBind.createButton(gui,'btnAddLeader_clicked'," Add ",452,178)
- btnRemLeader = QtBind.createButton(gui,'btnRemLeader_clicked'," Remove ",400,259)
- lblSkills = QtBind.createLabel(gui,'♯ Skills list',540,161)
- lstSkills = QtBind.createList(gui,540,200,181,60)
- cbxRecSkills = QtBind.createCheckBox(gui, 'cbxRecSkills_clicked','Record #Skill',542,179)
- cbxRecSkills_checked = False
- btnRemSkills = QtBind.createButton(gui,'btnRemSkills_clicked'," Remove ",645,178)
- lblTarget = QtBind.createLabel(gui,'TargetID : None',540,264)
- cbxDefensive = QtBind.createCheckBox(gui, 'cbxDefensive_clicked','Defensive',654,263)
- cbxDefensive_checked = False
- cbxSkillsOrder = QtBind.createCheckBox(gui,'cbxSkillsOrder_clicked','Orderly.',520,115)
- cbxSkillsRandom = QtBind.createCheckBox(gui,'cbxSkillsRandom_clicked','Random',590,115)
- QtBind.setChecked(gui,cbxSkillsOrder,True) # Use like radiobutton
- cbxSkillsRandom_checked = False
- # Sync Mode #ATTACKs
- SelectedTargetID = None
- ModeAttack = False
- useSkills = False
- dataSkills = []
- log('Plugins: xControl Plugin Successfully loaded ~ by ProjeXNET')
- # Create folder for save configs
- if not os.path.exists(folderSave):
- os.makedirs(folderSave)
- log('xControl: \"xControl\" folder has been created. Please, dont delete for keep configs.')
- # ------------------------------------- Functions -------------------------------------
- # Load the GUI and data for use like default
- def configs_default():
- # Clear data needed to sync attacks
- global SelectedTargetID,ModeAttack,useSkills,dataSkills
- SelectedTargetID = None
- ModeAttack = False
- useSkills = False
- dataSkills = []
- # Checkboxs
- global cbxEnableAttack_checked,cbxRecSkills_checked,cbxDefensive_checked,cbxSkillsRandom_checked
- cbxEnableAttack_checked = False
- QtBind.setChecked(gui,cbxEnableAttack,False)
- cbxRecSkills_checked = False
- QtBind.setChecked(gui,cbxRecSkills,False)
- cbxDefensive_checked = False
- QtBind.setChecked(gui,cbxDefensive,False)
- cbxSkillsRandom_checked = False
- QtBind.setChecked(gui,cbxSkillsOrder,True)
- QtBind.setChecked(gui,cbxSkillsRandom,False)
- # Lists
- QtBind.clear(gui,lstLeaders)
- QtBind.clear(gui,lstSkills)
- # Loads lists with the config file
- def configs_load():
- configs_default()
- # Load configs
- if os.path.exists(get_xcontrol_path()):
- data = {}
- with open(get_xcontrol_path(),"r") as f:
- data = json.load(f)
- if "Leaders" in data:
- for charname in data["Leaders"]:
- QtBind.append(gui,lstLeaders,charname)
- if "Skills" in data:
- for skillID in data["Skills"]:
- lstSkills_add(skillID)
- if "Defensive" in data:
- global cbxDefensive_checked
- cbxDefensive_checked = data["Defensive"]
- QtBind.setChecked(gui,cbxDefensive,data["Defensive"])
- if "SkillsRandom" in data:
- cbxSkillsRandom_checked = data["SkillsRandom"]
- QtBind.setChecked(gui,cbxSkillsRandom,data["SkillsRandom"])
- QtBind.setChecked(gui,cbxSkillsOrder,not data["SkillsRandom"])
- # Return True if nickname exist in the "Leaders" list
- def lstLeaders_exist(nickname):
- players = QtBind.getItems(gui,lstLeaders)
- for i in range(len(players)):
- if players[i].lower() == nickname.lower():
- return True
- return False
- # Add a new Skill into the list of skills
- def lstSkills_add(skillID,save=False):
- skill = get_skill(skillID).copy()
- skill['id'] = skillID
- skill['ready'] = True
- global dataSkills
- dataSkills.append(skill)
- SkillName = skill['name']+" Lv"+str(skill['level'])
- if save:
- # init dictionary
- data = {}
- # load config if exist
- if os.path.exists(get_xcontrol_path()):
- with open(get_xcontrol_path(), 'r') as f:
- data = json.load(f)
- # add new skill
- if not "Skills" in data:
- data['Skills'] = []
- data['Skills'].append(skillID)
- # replace configs
- with open(get_xcontrol_path(),"w") as f:
- f.write(json.dumps(data, indent=4, sort_keys=True))
- log("xControl: #Skill added ["+SkillName+"]")
- QtBind.append(gui,lstSkills,SkillName)
- # Return True if skill ID exist in the list of skills
- def lstSkills_exist(skillID):
- for i in range(len(dataSkills)):
- if dataSkills[i]['id'] == skillID:
- return True
- return False
- # Return the index of Skill ID ready for use
- def lstSkills_useSkill():
- if cbxSkillsRandom_checked:
- if len(dataSkills) > 0:
- import random
- record = []
- while True:
- again = False
- pos = random.randint(0,len(dataSkills)-1)
- for r in range(len(record)):
- if record[r] == pos:
- again = True
- break
- if again:
- continue
- if dataSkills[pos]['ready']:
- return pos
- else:
- record.append(pos)
- else:
- for i in range(len(dataSkills)):
- if dataSkills[i]['ready']:
- return i
- return -1
- # Enable a skill used previously
- def lstSkills_enableSkill(index):
- try:
- global dataSkills
- dataSkills[index]['ready'] = True
- except: # index not found
- pass
- # Click on "Agregar" from leaders clicked
- def btnAddLeader_clicked():
- if playerData:
- player = QtBind.text(gui,tbxLeaders)
- if player and not lstLeaders_exist(player):
- # init dictionary
- data = {}
- # load config if exist
- if os.path.exists(get_xcontrol_path()):
- with open(get_xcontrol_path(), 'r') as f:
- data = json.load(f)
- # add new leader
- if not "Leaders" in data:
- data['Leaders'] = []
- data['Leaders'].append(player)
- # replace configs
- with open(get_xcontrol_path(),"w") as f:
- f.write(json.dumps(data, indent=4, sort_keys=True))
- QtBind.append(gui,lstLeaders,player)
- QtBind.setText(gui, tbxLeaders,"")
- log('xControl: Leader added ['+player+']')
- # Button "Remover" from leaders clicked
- def btnRemLeader_clicked():
- if playerData:
- selectedItem = QtBind.text(gui,lstLeaders)
- if selectedItem:
- if os.path.exists(get_xcontrol_path()):
- data = {"Leaders":[]}
- with open(get_xcontrol_path(), 'r') as f:
- data = json.load(f)
- try:
- # remove leader nickname from file if exists
- data["Leaders"].remove(selectedItem)
- with open(get_xcontrol_path(),"w") as f:
- f.write(json.dumps(data, indent=4, sort_keys=True))
- except:
- pass # just ignore file if don't exist
- QtBind.remove(gui,lstLeaders,selectedItem)
- log('xControl: Leader removed ['+selectedItem+']')
- # Button "Remover" from skills clicked
- def btnRemSkills_clicked():
- if playerData:
- selectedIndex = QtBind.currentIndex(gui,lstSkills)
- if selectedIndex >= 0:
- if os.path.exists(get_xcontrol_path()):
- data = {"Skills":[]}
- with open(get_xcontrol_path(), 'r') as f:
- data = json.load(f)
- try:
- # remove skill id from file if exists
- data["Skills"].pop(selectedIndex)
- with open(get_xcontrol_path(),"w") as f:
- f.write(json.dumps(data, indent=4, sort_keys=True))
- except:
- pass # just ignore if don't exist
- QtBind.removeAt(gui,lstSkills,selectedIndex)
- skill = dataSkills.pop(selectedIndex)
- log('xControl: #Skill removed ['+skill['name']+' Lv'+str(skill['level'])+']')
- # Return the path of the config file
- def get_xcontrol_path():
- return folderSave+"\\"+ playerData['server'] + "_" + playerData['name'] + ".json"
- # Checkbox "Habilitar Attack" clicked
- def cbxEnableAttack_clicked(checked):
- global cbxEnableAttack_checked
- cbxEnableAttack_checked = checked
- # Checkbox "Grabar #Skill" clicked
- def cbxRecSkills_clicked(checked):
- global cbxRecSkills_checked
- cbxRecSkills_checked = checked
- # Checkbox "Aleatoria" clicked
- def cbxSkillsOrder_clicked(checked):
- global cbxSkillsRandom_checked
- cbxSkillsRandom_checked = not checked
- configs_save_key("SkillsRandom",not checked)
- QtBind.setChecked(gui,cbxSkillsRandom,not checked)
- # Checkbox "Random" clicked
- def cbxSkillsRandom_clicked(checked):
- global cbxSkillsRandom_checked
- cbxSkillsRandom_checked = checked
- configs_save_key("SkillsRandom",checked)
- QtBind.setChecked(gui,cbxSkillsOrder,not checked)
- # Checkbox "AutoDefensa" clicked
- def cbxDefensive_clicked(checked):
- global cbxDefensive_checked
- cbxDefensive_checked = checked
- configs_save_key("Defensive",checked)
- # Save data into key json
- def configs_save_key(key,info):
- if playerData:
- data = {}
- if os.path.exists(get_xcontrol_path()):
- with open(get_xcontrol_path(), 'r') as f:
- data = json.load(f)
- data[key] = info
- with open(get_xcontrol_path(),"w") as f:
- f.write(json.dumps(data, indent=4, sort_keys=True))
- # Called when the bot successfully connects to the game server
- def connected():
- global playerData
- playerData = None
- # Called when the character enters the game world
- def joined_game():
- global playerData
- playerData = get_character_data()
- configs_load()
- # Called when the character teleports and right after joined_game()
- def teleported():
- global playerData
- playerData = get_character_data()
- # All packets received from Silkroad will be passed to this function
- # Returning True will keep the packet and False will not forward it to the game server
- def handle_silkroad(opcode, data):
- if opcode == 0x7074 and cbxRecSkills_checked:
- if data[0] == 0x01: # Flag (Success)
- if data[1] == 0x04: # Using skill
- SkillID = struct.unpack_from("<i",data,2)[0]
- # Need to have target & is not be in the skill list
- if data[6] == 0x01 and not lstSkills_exist(SkillID):
- lstSkills_add(SkillID,True)
- return True
- # All packets received from Joymax will be passed to this function
- # Returning True will keep the packet and False will not forward it to the client
- def handle_joymax(opcode, data):
- if opcode == 0x3026: # Chat Message
- # Packet index
- index = 0
- # Message type: All or Party or Private
- if data[index] == 0x01 or data[index] == 0x02 or data[index] == 0x04:
- # Parse nick of character
- Character = ""
- if data[index] == 0x01:
- index += 1
- Character = getNickname(struct.unpack_from("<i",data,index)[0])
- index += 4
- else:
- index += 1
- CharacterLength = struct.unpack_from('H', data, index)[0]
- index += 2
- Character = struct.unpack_from(str(CharacterLength) + 's', data, index)[0].decode('ascii')
- index += CharacterLength
- # Checking nick into the list of leaders
- if lstLeaders_exist(Character):
- # Load and search command message
- MessageLength = struct.unpack_from('H', data, index)[0]
- index += 2
- Message = struct.unpack_from(str(MessageLength * 2) + 's', data, index)[0].decode('utf-16').strip()
- if Message == "ENABLE" and not cbxEnableAttack_checked:
- global cbxEnableAttack_checked
- cbxEnableAttack_checked = True
- QtBind.setChecked(gui,cbxEnableAttack,True)
- log('xControl: Enabled #ATTACKs mode')
- elif Message == "DISABLE" and cbxEnableAttack_checked:
- global cbxEnableAttack_checked
- cbxEnableAttack_checked = False
- QtBind.setChecked(gui,cbxEnableAttack,False)
- log('xControl: Disabled #ATTACKs mode')
- elif Message == "ATTACK" or Message == "ATTACKS":
- global useSkills
- useSkills = False if Message == "ATTACK" else True
- if not ModeAttack:
- global ModeAttack
- ModeAttack = True
- AutoAttack()
- elif Message == "STOP":
- if ModeAttack:
- global ModeAttack
- ModeAttack = False
- Inject_StopAttack()
- elif Message == "STARTB":
- start_bot()
- elif Message == "STOPB":
- stop_bot()
- elif Message.startswith("TRACE"):
- if Message == "TRACE":
- if start_trace(Character):
- log("xControl: Starting #Trace to ["+Character+"]")
- else:
- Character = Message[5:].split()
- if Character:
- if start_trace(Character[0]):
- log("xControl: Starting #Trace to ["+Character[0]+"]")
- elif Message == "STOPT":
- if stop_trace():
- log("xControl: Stopping #Trace")
- elif Message == "SIT":
- Inject_SitDown()
- elif Message.startswith("CAPE"):
- if Message == "CAPE":
- Inject_UseCape(5)
- log("xControl: Using PVP Cape (Yellow)")
- else:
- type = Message[4:].split()
- if type:
- type = type[0].upper()
- if type == "OFF":
- Inject_UseCape(0)
- log("xControl: Removing PVP Cape")
- elif type == "RED":
- Inject_UseCape(1)
- log("xControl: Using PVP Cape (Red)")
- elif type == "GRAY":
- Inject_UseCape(2)
- log("xControl: Using PVP Cape (Gray)")
- elif type == "BLUE":
- Inject_UseCape(3)
- log("xControl: Using PVP Cape (Blue)")
- elif type == "WHITE":
- Inject_UseCape(4)
- log("xControl: Using PVP Cape (White)")
- elif type == "YELLOW":
- Inject_UseCape(5)
- log("xControl: Using PVP Cape (Yellow)")
- elif Message == "USEZERK":
- Inject_UseZerk()
- elif Message == "USERETURN":
- import random # Try avoid High CPU usage with many chars on same time
- Timer(random.random(), Inject_UseReturnScroll).start()
- elif Message.startswith('INJECT'):
- Inject_Packet(Message.split())
- elif opcode == 0xB070 and cbxEnableAttack_checked: # Object Action & Enable Attack
- if data[0] == 0x01: # Flag (Success)
- if data[1] == 0x02: # Type. 0x00: Buff - 0x02: Attack
- AttackerID = struct.unpack_from("<i",data,7)[0]
- TargetID = struct.unpack_from("<i",data,15)[0]
- if AttackerID != TargetID: # Ensure is not a Buff
- ScannTarget(AttackerID,TargetID)
- elif opcode == 0xB045 and cbxEnableAttack_checked: # Selecting Target & Enable Attack
- if data[0] == 0x01: # Flag (Success)
- TargetID = struct.unpack_from("<i",data,1)[0]
- if TargetID != SelectedTargetID: # Faster
- global SelectedTargetID
- SelectedTargetID = TargetID
- extraInfo = ""
- if len(data) > 5: # Not Pet
- if data[5] == 0x01: # Not NPC
- if data[6] == 0x05:
- extraInfo = " - Nickname:"+getNickname(SelectedTargetID)
- else:
- extraInfo = " - HP:"+str(struct.unpack_from("<i",data,6)[0])
- log('xControl: Target selected [ TargetID:'+str(TargetID)+''+extraInfo+' ]')
- QtBind.setText(gui,lblTarget,"TargetID : "+str(SelectedTargetID))
- return True
- # Return Nick of player from ID only if is near
- def getNickname(PlayerID):
- # Load all near players
- players = get_players()
- # Checking if ID is mine
- if PlayerID == playerData['player_id']:
- return playerData['name']
- # Check the IDs with all players
- for key, player in players.items():
- if key == PlayerID:
- return player['name']
- return ""
- # Select target if some leader is found
- def ScannTarget(AttackerID,TargetID):
- players = get_players()
- if TargetID == playerData['player_id']:
- if cbxDefensive_checked:
- if SelectedTargetID != AttackerID and lstLeaders_exist(playerData['name']):
- Inject_SelectTarget(AttackerID)
- return
- for key, player in players.items():
- if AttackerID == key:
- if SelectedTargetID != TargetID and lstLeaders_exist(player['name']):
- Inject_SelectTarget(TargetID)
- return
- elif TargetID == key:
- if cbxDefensive_checked:
- if SelectedTargetID != AttackerID and lstLeaders_exist(player['name']):
- Inject_SelectTarget(AttackerID)
- return
- # Inject Attacks without stop
- def AutoAttack():
- if ModeAttack:
- # Minim delay to check again
- delayAttack = 0.5
- if SelectedTargetID:
- if useSkills:
- index = lstSkills_useSkill()
- if index >= 0:
- delayAttack = (dataSkills[index]['cast_time']/1000)+0.01
- delaySkill = (dataSkills[index]['cool_down']/1000)
- global dataSkills
- dataSkills[index]['ready'] = False
- Inject_AttackTarget(SelectedTargetID,dataSkills[index]['id'])
- Timer(delaySkill,lstSkills_enableSkill,(index,)).start()
- log('xControl: Attacking target with ['+dataSkills[index]['name']+" Lv"+str(dataSkills[index]['level'])+']')
- else:
- Inject_AttackTarget(SelectedTargetID)
- log('xControl: Attacking target with [Normal Attack]')
- delayAttack = 1.5
- Timer(delayAttack,AutoAttack).start()
- # Inject Packet (Select Target)
- def Inject_SelectTarget(TargetID):
- Packet = bytearray()
- Packet = Packet + struct.pack('<i',TargetID)
- inject_joymax(0x7045,Packet, False)
- # Inject Packet Attack (Skill Attack)
- def Inject_AttackTarget(TargetID,SkillID=None):
- Packet = bytearray()
- Packet.append(0x01) # Flag (Attack)
- if SkillID:
- Packet.append(0x04) # Use Skill
- Packet = Packet + struct.pack('<i',SkillID)
- else:
- Packet.append(0x01) # Use Normal Attack
- Packet.append(0x01) # Flag (Target)
- Packet = Packet + struct.pack('<i',TargetID)
- inject_joymax(0x7074,Packet, False)
- # Inject Packet (Stop Attack)
- def Inject_StopAttack():
- Packet = bytearray()
- Packet.append(0x02) # Flag (Stop)
- inject_joymax(0x7074,Packet, False)
- log("xControl: Stopping attack")
- # Inject Packet (Sit down / Stand up)
- def Inject_SitDown():
- Packet = bytearray()
- Packet.append(0x04) # Flag (Stop)
- inject_joymax(0x704F,Packet, False)
- log("xControl: Sit / Stand")
- # Inject Packet (Cape)
- def Inject_UseCape(option):
- if option >= 0 and option <= 5:
- Packet = bytearray()
- Packet.append(option)
- inject_joymax(0x7516, Packet, False)
- # Inject Packet (Use Zerk)
- def Inject_UseZerk():
- Packet = bytearray()
- Packet.append(0x01)
- inject_joymax(0x70A7, Packet, False)
- log("xControl: Using Berserker mode")
- # Inject Packet (Use Return Scroll)
- def Inject_UseReturnScroll():
- nSlot = 0
- items = get_inventory()['items']
- for item in items:
- if item != None:
- if item['name'] == 'Return Scroll' or item['name'] == 'Special Return Scroll' or item['name'] == 'Token Return Scroll' or item['name'] == 'Beginner instant recall scroll' or item['name'] == 'Instant Return Scroll':
- Packet = bytearray()
- Packet.append(nSlot)
- Packet.append(0x30)
- Packet.append(0x0C)
- Packet.append(0x03)
- Packet.append(0x01)
- inject_joymax(0x704C, Packet, True)
- log('xControl: Using "'+item['name']+'" ')
- return
- nSlot += 1
- log('xControl: Has not been found "Return Scroll" from your inventory.')
- # Inject Packet parsing from Command
- def Inject_Packet(arguments):
- if len(arguments) >= 3:
- opcode = int(arguments[1],16)
- encrypted = False
- iniPos = 2
- if arguments[2].lower() == "true" or arguments[2].lower() == "false":
- encrypted = True if arguments[2].lower() == "true" else False
- iniPos += 1
- Packet = bytearray()
- for i in range(iniPos, len(arguments) ):
- Packet.append(int(arguments[i],16))
- inject_joymax(opcode,Packet,encrypted)
- log("xControl: Injecting #Packet")
- log("[Opcode:"+arguments[1]+"][Data:"+' '.join('{:02X}'.format(int(arguments[x],16)) for x in range(iniPos, len(arguments)))+"][Encrypted:"+("Yes" if encrypted else "No")+"]")
- else:
- log("xControl: Incorrect structure for inject the #Packet")
- return 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement