Automatically change weapons when you cast a skill. It is a code that I made for a warrior/cleric friend, therefore it has only been tested in that build on a private server, I share it for anyone who may find it useful but if you have problems you should solve it yourself.
[WeaponSwitch.py]
from phBot import *
import QtBind
import struct
import os
import json
import sqlite3
from types import SimpleNamespace
import time
bot_path = os.getcwd()
gui = QtBind.init(__name__, "WeaponSwitch")
switch = QtBind.createCheckBox(gui, 'cbSwitch_checked', 'Habilitar cambio de arma automático', 10, 10)
switchChecked = False
ESPERAR_PARA_CAMBIAR = 1
# Callback para activar/desactivar el cambio automático
def cbSwitch_checked(checked):
global switchChecked
switchChecked = checked
# Tipos de armas
WEAPON_TYPES = {
"Sword": 2,
"Blade": 3,
"Spear": 4,
"Glaive": 5,
"Bow": 6,
"OneHandSword": 7,
"TwoHandSword": 8,
"DualAxes": 9,
"Warlock": 10,
"TwoHandStaff": 11,
"Crossbow": 12,
"Daggers": 13,
"Harp": 14,
"Cleric": 15
}
# ==== FUNCIONES DE BASE DE DATOS ====
"""Conecta con la base de datos."""
def GetDatabaseConnection(server):
with open(f"{bot_path}/vSRO.json", "r") as f:
data = json.load(f)
for k in data:
if server in data[k]['servers']:
for path in os.scandir(f"{bot_path}/Data"):
if path.is_file() and path.name.endswith(".db3"):
conn = sqlite3.connect(f"{bot_path}/Data/{path.name}")
c = conn.cursor()
c.execute('SELECT * FROM data WHERE k="path" AND v=?', (data[k]['path'],))
if c.fetchone():
return conn
conn.close()
return None
"""Busca información de una habilidad en la base de datos."""
def getSkill(skill_id):
character_data = get_character_data()
conn = GetDatabaseConnection(character_data['server'])
if conn:
c = conn.cursor()
c.execute(f"SELECT id, name, weapon_1, mastery, skillgroup, weapon_2 FROM skills WHERE id={skill_id}")
skill = c.fetchone()
conn.close()
return skill
"""Busca información del grupo de skill de una habilidad."""
def getSkillsGroup(matery, skillgroup):
character_data = get_character_data()
conn = GetDatabaseConnection(character_data['server'])
if conn:
c = conn.cursor()
c.execute(f"SELECT id, name, weapon_1, mastery, skillgroup, weapon_2 FROM skills WHERE mastery={matery} AND skillgroup = {skillgroup}")
skills = c.fetchall()
conn.close()
return skills
"""Busca información de las armas utilizadas por un mastery."""
def getWeaponsFromMastery(matery):
character_data = get_character_data()
conn = GetDatabaseConnection(character_data['server'])
if conn:
c = conn.cursor()
c.execute(f"SELECT weapon FROM mastery WHERE id={matery}")
skills = c.fetchone()
conn.close()
return skills
# ==== FIN DE FUNCIONES DE BASE DE DATOS ====
# ==== FUNCIONES AUXILIARES ====
"""Busca un arma en el inventario según el tipo."""
def buscarArma(tipo_arma):
inventory = get_inventory()
items = inventory['items']
for slot, item in enumerate(items):
if item:
item_data = get_item(item['model'])
if int(item_data['tid1']) == 1 and (item_data['tid2'] in [6, 4]):
if int(item_data['tid3']) == int(tipo_arma):
item_data['slot'] = slot
return item_data
return None
"""Obtiene el arma equipada actualmente."""
def buscarArmaPuesta():
slot = get_inventory()['items'][6]
if slot:
item = get_item(slot['model'])
return item['tid3']
return None
"""Determina la raza del personaje (CH o EU)."""
def raza():
model = get_character_data()['model']
char = get_monster(model)
return "CH" if "CHAR_CH" in char['servername'] else "EU"
# ==== FIN DE FUNCIONES AUXILIARES ====
last_switch_time = 0
def handle_silkroad(opcode, data):
global last_switch_time
current_time = time.time()
if opcode == 0x7074 and switchChecked:
if data[0] == 1 and data[1] == 4:
if current_time - last_switch_time >= ESPERAR_PARA_CAMBIAR:
model = struct.unpack_from("<i", data, 2)[0]
skill = getSkill(model)
if not skill:
return True
skillObj = SimpleNamespace(
id=skill[0],
name=skill[1],
weapon_1=skill[2],
mastery=skill[3],
skillgroup=skill[4],
weapon_2=skill[5]
)
arma_puesta = buscarArmaPuesta()
script = ""
if skillObj.weapon_1 != arma_puesta and skillObj.weapon_2 != arma_puesta: #Si no tiene ninguna de las armas requeridas puesta
arma = buscarArma(skillObj.weapon_1)
if arma:
data_character = get_character_data()
if data_character['hp_max'] > data_character['mp_max'] and raza() == "CH": #Full str Chino busque glavie o blade
arma2 = buscarArma(skillObj.weapon_2)
if arma2:
arma = arma2
script += f"equip,{arma['servername']}\n"
elif skillObj.weapon_1 == 255: #Si no requiere arma o necesita shield
if raza() != "CH":
skillsGroup = getSkillsGroup(skillObj.mastery, skillObj.skillgroup)
if len(skillsGroup) > 0:
for skill in skillsGroup:
if skill[2] != 255:
arma = buscarArma(skill[2])
if arma:
script += f"equip,{arma['servername']}\n"
break
if not arma:
arma = buscarArma(getWeaponsFromMastery(skillObj.mastery)[0][0])
if arma:
script += f"equip,{arma['servername']}\n"
else:
slot7 = get_inventory()['items'][7]
if skillObj.mastery == 275 and skillObj.skillgroup == 1 and slot7 != None: #Linea de Fire Shield
if slot7['durability'] == 0: #Asegurarse que no sean flechas
script += f"equip,{buscarArma(1)['servername']}\n"
if script:
start_script(script)
last_switch_time = current_time
return False
if buscarArmaPuesta() in [WEAPON_TYPES["Sword"],WEAPON_TYPES["Blade"],WEAPON_TYPES["OneHandSword"],WEAPON_TYPES["Warlock"],WEAPON_TYPES["Cleric"]]:
if get_inventory()['items'][7] == None:
shield = buscarArma(1 if raza() == "CH" else 2)
if shield and get_inventory()['items'][7] is None:
start_script(f"equip,{shield['servername']}\n")
return False
return True
log('Plugin: [WeaponSwitch] Cargado correctamente!')