[Plugin] WeaponSwitch

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!')
2 Likes