This version only works for vSro 1.188 Servers
So here is my work from yesterday. Maybe my rookie python skills can help someone. Iām sure someone with better python skills could do it better than I have done. Feel free to improve it
What it does is:
- If a character is lvl 40 or above the plugin will delete this chars
- If a char lower than 40 is available the plugin will login this char
- If not it will create a new char and login this char then.
Two files are needed:
academy.py
from phBot import *
from packet import *
import struct
from struct import pack
from threading import Thread
from time import sleep
import string
import random
successfullCharCreated = False
loginChar = False
loginCharname = ""
charsDeleted = False
CHARACTER_TYPE = 'CH'
generalCharCount = 0
def create_character(name):
global CHARACTER_TYPE
if CHARACTER_TYPE == 'CH':
c_model = get_monster_string('CHAR_CH_MAN_ADVENTURER')['model']
chest = get_item_string('ITEM_CH_M_HEAVY_01_BA_A_DEF')['model']
legs = get_item_string('ITEM_CH_M_HEAVY_01_LA_A_DEF')['model']
shoes = get_item_string('ITEM_CH_M_HEAVY_01_FA_A_DEF')['model']
weapon = get_item_string('ITEM_CH_SWORD_01_A_DEF')['model']
elif CHARACTER_TYPE == 'EU':
c_model = get_monster_string('CHAR_EU_MAN_NOBLE')['model']
chest = get_item_string('ITEM_EU_M_HEAVY_01_BA_A_DEF')['model']
legs = get_item_string('ITEM_EU_M_HEAVY_01_LA_A_DEF')['model']
shoes = get_item_string('ITEM_EU_M_HEAVY_01_FA_A_DEF')['model']
weapon = get_item_string('ITEM_EU_DAGGER_01_A_DEF')['model']
else:
log('Invalid character type (CH or EU)')
return
if c_model == 0 or chest == 0 or legs == 0 or shoes == 0 or weapon == 0:
log('Could not retrieve item models')
return
log('Creating character with name %s and type %s' % (name, CHARACTER_TYPE))
p = b'\x01'
p += pack('H', len(name))
p += name.encode('ascii')
p += pack('I', c_model)
p += pack('B', 0)
p += pack('I', chest)
p += pack('I', legs)
p += pack('I', shoes)
p += pack('I', weapon)
inject_joymax(0x7007, p, False)
sleep(1)
inject_joymax(0x7007, b'\x02', False)
def deleteChar(chars):
sleep(2)
for x in chars:
packet = stream_writer()
packet.write_int8(3)
packet.write_uint16(len(x))
packet.write_ascii(x)
inject_joymax(0x7007, packet.data, False)
log('Delete: ' + x)
sleep(0.2)
sleep(2)
inject_joymax(0x7007, b'\x02', False)
def loginChars(chars):
global successfullCharCreated
global generalCharCount
global loginChar
global loginCharname
sleep(2)
if len(chars) > 0:
for x in chars:
log('SelectCharacter: ' + x)
loginChar = True
loginCharname = x
break
else:
log('Can not find any characters for login...Try to create new character')
if successfullCharCreated == False and int(generalCharCount) < 4:
name = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10))
create_character(name)
else:
log('Can not create a new character. Not enough character space')
def event_loop():
global loginChar, loginCharname
if loginChar:
loginChar = False
select_character(loginCharname)
def handle_joymax(opcode, data):
if opcode == 0xB007:
packet = stream_reader(data)
type = packet.read_uint8()
if type == 2:
if packet.read_uint8() == 1:
charsToDelete = list()
charsToLogin = list()
global charsDeleted
global generalCharCount
count = packet.read_uint8()
generalCharCount = count
x = 0
while x < count:
packet.read_int32() #Model
lng = packet.read_int16()
charname = packet.read_ascii(int(lng)) #Charname
packet.read_uint8() #Volume
level = packet.read_uint8() #Level
packet.read_uint64() #EXP
packet.read_uint16() #STR
packet.read_uint16() #INT
packet.read_uint16() #Stats
packet.read_uint32() #HP
packet.read_uint32() #MP
restoreFlag = packet.read_uint8()
if restoreFlag == 1:
packet.read_uint32() #Delete Time
packet.read_uint8()
packet.read_uint8()
packet.read_uint8()
itemCount = packet.read_uint8()
y = 0
while y < itemCount:
packet.read_uint32()
packet.read_uint8()
y += 1
avatarCount = packet.read_uint8()
z = 0
while z < avatarCount:
packet.read_uint32()
packet.read_uint8()
z += 1
if level >= 40 and restoreFlag != 1:
charsToDelete.append(charname)
elif restoreFlag != 1:
charsToLogin.append(charname)
x += 1
if charsDeleted == False and len(charsToDelete) > 0:
delete = Thread(target = deleteChar, args = (charsToDelete, ))
delete.daemon = True
delete.start()
else:
log('Can not find chars LvL 40 or above...Try to login a character')
loginThread = Thread(target = loginChars, args = (charsToLogin, ))
loginThread.daemon = True
loginThread.start()
charsDeleted = True
elif type == 1:
global successfullCharCreated
successfullCharCreated = True
return False
log('[AcademyLoginHelper]v1.0 Loaded - Credits: CharCreation by Ryan')
packet.py
import struct
import array
class stream_reader(object):
index = 0
data = None
size = 0
def __init__(self, data, index=0):
self.reset(data, index)
def reset(self, data, index=0):
self.data = data
self.size = self.data.__len__()
self.seek_set(index)
def bytes_left(self):
return self.size - self.index
def seek_forward(self, count):
if self.index + count > self.size:
raise Exception('index would be past end of stream')
self.index += count
def seek_backward(self, count):
if self.index - count < 0:
raise Exception('index would be < 0 if seeked further back')
self.index -= count
def seek_set(self, index):
if index > self.size or index < 0:
raise Exception('invalid index')
self.index = index
def read_int8(self):
if self.index + 1 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('b', self.data, self.index)[0]
self.index += 1
return unpacked
def read_uint8(self):
if self.index + 1 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('B', self.data, self.index)[0]
self.index += 1
return unpacked
def read_int16(self):
if self.index + 2 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('h', self.data, self.index)[0]
self.index += 2
return unpacked
def read_uint16(self):
if self.index + 2 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('H', self.data, self.index)[0]
self.index += 2
return unpacked
def read_int32(self):
if self.index + 4 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('i', self.data, self.index)[0]
self.index += 4
return unpacked
def read_uint32(self):
if self.index + 4 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('I', self.data, self.index)[0]
self.index += 4
return unpacked
def read_int64(self):
if self.index + 8 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('q', self.data, self.index)[0]
self.index += 8
return unpacked
def read_uint64(self):
if self.index + 8 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('Q', self.data, self.index)[0]
self.index += 8
return unpacked
def read_float(self):
if self.index + 4 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('f', self.data, self.index)[0]
self.index += 4
return unpacked
def read_double(self):
if self.index + 8 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('d', self.data, self.index)[0]
self.index += 8
return unpacked
def read_char(self):
if self.index + 1 > self.size:
raise Exception('past end of stream')
unpacked = struct.unpack_from('c', self.data, self.index)[0]
self.index += 1
return unpacked
def read_ascii(self, length):
if self.index + length > self.size:
raise Exception('past end of stream')
string = struct.unpack_from(str(length) + 's', self.data, self.index)[0]
self.index += length
return string.decode('ascii', 'replace')
'''
def read_utf8(self, length):
if self.index + length > self.size:
raise Exception('past end of stream')
string = struct.unpack_from(str(length) + 's', self.data, self.index)[0]
self.index += length
return string.decode('utf-8')
'''
def read_utf16(self, length):
length *= 2
if self.index + length > self.size:
raise Exception('past end of stream')
string = struct.unpack_from(str(length) + 's', self.data, self.index)[0]
self.index += length
return string.decode('utf-16le')
def read_utf32(self, length):
length *= 4
if self.index + length > self.size:
raise Exception('past end of stream')
string = struct.unpack_from(str(length) + 's', self.data, self.index)[0]
self.index += length
return string.decode('utf-32le')
class stream_writer(object):
data = array.array('B')
index = 0
size = 0
def __init__(self, data=None):
self.reset(data)
def reset(self, data=None):
if type(data) == array.array:
self.data = data
elif type(data) == list:
self.data = array.array('B', data)
elif data == None:
self.data = array.array('B')
else:
raise Exception('incorrect data type was used to reset the class')
self.size = self.data.__len__()
self.seek_end()
def tostring(self):
return self.data.tostring()
def tolist(self):
return self.data.tolist()
def tofile(self, f):
return self.data.tofile(f)
def toarray(self):
return self.data
def seek_forward(self, count):
if self.index + count > self.size:
raise Exception('index would be past end of stream')
self.index += count
def seek_backward(self, count):
if self.index - count < 0:
raise Exception('index would be < 0 if seeked further back')
self.index -= count
def seek_set(self, index):
if index > self.size or index < 0:
raise Exception('invalid index')
self.index = index
def seek_end(self):
self.index = self.size
def write_int8(self, val):
self.__append(struct.pack('b', val))
def write_uint8(self, val):
self.__append(struct.pack('B', val))
def write_int16(self, val):
self.__append(struct.pack('h', val))
def write_uint16(self, val):
self.__append(struct.pack('H', val))
def write_int32(self, val):
self.__append(struct.pack('i', val))
def write_uint32(self, val):
self.__append(struct.pack('I', val))
def write_int64(self, val):
self.__append(struct.pack('q', val))
def write_uint64(self, val):
self.__append(struct.pack('Q', val))
def write_float(self, val):
self.__append(struct.pack('f', val))
def write_double(self, val):
self.__append(struct.pack('d', val))
def write_char(self, val):
self.__append(struct.pack('c', val))
def write_ascii(self, val):
self.__append(bytes(val, 'ascii', 'replace'))
'''
def write_utf8(self, val):
self.__append(bytes(val, 'utf-8'))
'''
def write_utf16(self, val):
self.__append(val.encode('utf-16le'))
def write_utf32(self, val):
self.__append(val.encode('utf-32le'))
def write(self, val):
self.__append(val)
def __append(self, packed):
for x in packed:
self.data.insert(self.index, x)
self.index += 1
self.size += 1
Have fun