示例#1
0
 def __init__(self):
     super().__init__()
     self.handler = MemHandler()
     self._global = models.Global(0, self.handler)
     self.ingame_item = models.IngameItem(0, self.handler)
     self.saved_item = models.SavedItem(0, self.handler)
     # self.inventory_treasure_item = models.InventoryTreasureItem(0, self.handler)
     self.char_index = self._global.char_index = 0
示例#2
0
 def __init__(self):
     super().__init__()
     self.handler = MemHandler()
     self._global = models.Global(0, self.handler)
     self.ingame_item = models.IngameItem(0, self.handler)
     self.char_index = self._global.char_index = 0
示例#3
0
class Main(NativeHacktool):
    CLASS_NAME = WINDOW_NAME = 'RESIDENT EVIL 6'

    def __init__(self):
        super().__init__()
        self.handler = MemHandler()
        self._global = models.Global(0, self.handler)
        self.ingame_item = models.IngameItem(0, self.handler)
        self.char_index = self._global.char_index = 0

    def render_main(self):
        person = (self._person, models.Character)

        with Group("player", "全局", self._global):
            ModelInput("skill_points", instance=(self._skill_points, models.SkillPoints))

        with Group("player", "角色", person):
            self.char_choice = Choice("角色", datasets.PERSONS, self.weak.on_person_change)
            ModelInput("health")
            ModelInput("health_max")
            ModelInput("stamina")
            ModelInput("stamina_max")
            ModelInput("moving_speed")
            ModelInput("rapid_fire")
            ModelInput("is_wet")
            ModelCoordWidget("coord", labels=('X坐标', 'Z坐标', 'Y坐标'), savable=True)
            ModelCheckBox("invincible")

        self.lazy_group(Group("person_items", "角色物品", person, serializable=False, cols=4), self.render_person_items)
        self.lazy_group(Group("person_skills", "角色技能", self._global, cols=4), self.render_person_skills)
        self.lazy_group(StaticGroup("代码插入"), self.render_assembly_functions)
        self.lazy_group(StaticGroup("功能"), self.render_functions)

    def render_person_items(self):
        """游戏中物品"""
        for label, index_range in (('水平武器', (0, 7)), ('药丸', (7, 8)), ('垂直武器', (8, 13)), ('其他物品', (15, 24))):
            r = 1
            for i in range(*index_range):
                prop = "items.%d" % i
                select = ModelChoiceDisplay(prop + ".type", "%s%d" % (label, r),
                    choices=datasets.INVENTORY_ITEMS.choices, values=datasets.INVENTORY_ITEMS.values)
                with select.container:
                    ui.Button("详情", className="btn_sm", onclick=partial(__class__.show_ingame_item, self.weak,
                        instance=self._person, prop=prop))
                r += 1

    def render_person_skills(self):
        with ModelSelect.choices_cache:
            for i in range(3):
                ModelSelect("char_skills.$char_index.%d" % i, "技能%d" % (i + 1), choices=datasets.SKILLS)

    def render_assembly_functions(self):
        # NOP_7 = b'\x90' * 7
        NOP_8 = b'\x90' * 8
        # NOP_9 = b'\x90' * 9
        super().render_assembly_functions((
            AssemblyItem('ammo_keep', '子弹不减', b'\x66\x29\x54\x41\x0A\x79\x07', 0x900000, 0xA00000,
                b'\x66\x4A\x90\x90\x90'),
            AssemblyItem('no_recoil', '无后坐力', b'\xF3\x0F\x10\x8E\xFC\x4A\x00\x00', 0x680000, 0x700000, NOP_8),
            AssemblyItem('rapid_fire', '快速射击', b'\xF3\x0F\x5C\xC2\xF3\x0F\x11\x86\x4C\x4F\x00\x00', 0x680000, 0x700000,
                b'', b'\xF3\x0F\x58\xD2\xF3\x0F\x58\xD2\xF3\x0F\x5C\xC2\xF3\x0F\x11\x86\x4C\x4F\x00\x00',
                inserted=True),
            AssemblyItem('merce_timer_keep', '佣兵模式时间不减',
                b'\xF3\x0F\x11\x86\x6C\x48\x00\x00\xF3\x0F\x11\x8E\x74\x48\x00\x00', 0x100000, 0x200000, NOP_8),
            AssemblyItem('god_on_hit_kill', '血不减+一击必杀', b'\x66\x8b\x44\x24\x04\x66\x29\x81\x10\x0f\x00\x00',
                0x600000, 0x700000, b'',
                b'\x83\x79\x38\x01\x75\x0A\xC7\x81\x10\x0F\x00\x00\x00\x00\x00\x00', inserted=True),
            AssemblyItem('skill_points', '技能点数', b'\x8B\xBE\x88\x05\x00\x00\x8B\x8E\x8C\x05\x00\x00',
                0x580000, 0x640000, b'', b'\x8B\xBE\x88\x05\x00\x00\x8B\x8E\x8C\x05\x00\x00\x89\x35%s',
                inserted=True, args=('skill_points_base',)),
        ))

    def render_functions(self):
        super().render_functions(('unlock_guns', 'give_rocket_launcher'))

    def get_ingame_item_dialog(self):
        """物品信息对话框"""
        name = 'ingame_item_dialog'
        dialog = getattr(self, name, None)
        if dialog is None:
            with DialogGroup(name, "物品详情", self.ingame_item, cols=1, dialog_style={'width': 800, 'height': 1400},
                    closable=False, horizontal=False, button=False) as dialog:
                ModelCheckBox("enabled")
                ModelInput("slot")
                ModelSelect("type", choices=datasets.INVENTORY_ITEMS.choices, values=datasets.INVENTORY_ITEMS.values,
                    instance=self.ingame_item)
                ModelInput("quantity")
                ModelInput("max_quantity")
                ModelInput("model", hex=True)
            with dialog.footer:
                ui.Button("复制", className='btn_sm', onclick=self.weak.ingame_item_copy)
                ui.Button("粘贴", className='btn_sm', onclick=self.weak.ingame_item_paste)

            setattr(self, name, dialog)
        return dialog

    def get_hotkeys(self):
        this = self.weak
        return (
            (VK.MOD_ALT, VK.H, this.pull_through),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.H, this.pull_through_all),
            (VK.MOD_ALT, VK.E, this.set_ammo_one),
            (VK.MOD_ALT, VK.R, this.set_ammo_full),
            (VK.MOD_ALT, VK.getCode(','), this.save_coord),
            (VK.MOD_ALT, VK.getCode('.'), this.load_coord),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.getCode(','), this.undo_coord),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.getCode('.'), this.reload_coord),
            (VK.MOD_ALT, VK.O, this.p1_go_p2),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.O, this.p2_go_p1),
        )

    def onattach(self):
        super().onattach()
        self._global.addr = self.handler.base_addr

    def _person(self):
        if self.handler.active:
            chars = self._global.character_struct.chars
            person = chars[self.char_index]
            if person.addr is 0:
                for i in range(len(datasets.PERSONS)):
                    if chars[i].addr:
                        self.char_choice.index = self.char_index = i
                        person = chars[i]
                        break
            return person

    def _person_config(self):
        if self.handler.active:
            return self._global.character_config.chars[self.char_index]

    def _skill_points(self):
        skill_points_base = self.get_variable('skill_points_base')
        if skill_points_base:
            return models.SkillPoints(self.handler.read32(skill_points_base.addr), self.handler)
        print('未初始化')

    @property
    def saved_items(self):
        return self._global.character_config.saved_items[self.char_index].items

    person = property(_person)
    person_config = property(_person_config)

    def on_person_change(self, lb):
        self.char_index = self._global.char_index = lb.index

    def show_ingame_item(self, view, instance, prop):
        """显示物品详情对话框"""
        if callable(instance):
            instance = instance()
        item = getattr(instance, prop)
        if item and item.addr:
            self.ingame_item.addr = item.addr
            dialog = self.get_ingame_item_dialog()
            dialog.read()
            dialog.show()
        else:
            print("没有数据")

    @property
    def saved_item_manager(self):
        addr = self.handler.remote_call(0x4F7230, 0)
        addr = self.handler.read32(addr + 0x658)
        return models.SavedItemManager(addr, self.handler)

    def set_ingame_item(self, slot, type, ammo, character=0):
        """设置物品 TODO: 加载物品模型"""
        func_addr = self.get_cached_address('_set_ingame_item', b'\x51\x53\x55\x8B\x6C\x24\x14\xC1', 0x600000, 0x700000)
        self.native_call_auto(func_addr, '5L', slot, type, ammo, 0, 0, this=character or self.person.addr)

    def set_ingame_saved_item(self, slot, type, quantity=0):
        """检查点间有效"""
        targets = []
        temp = self.saved_item_manager
        targets.append(temp.saved_items[self.char_index].items[slot])
        targets.append(temp.saved_items2[self.char_index].items[slot])
        targets.append(self._global.character_config.saved_item_manager.saved_items2[self.char_index].items[slot])
        for item in targets:
            item.type = type
            if quantity:
                item.quantity = quantity

    def ingame_item_copy(self, _):
        fefactory_api.set_clipboard(self.ingame_item.hex())

    def ingame_item_paste(self, _):
        self.ingame_item.fromhex(fefactory_api.get_clipboard())

    def pull_through(self):
        self.person.set_with('health', 'health_max').set_with('stamina', 'stamina_max')

    def pull_through_all(self):
        character_struct = self._global.character_struct
        for i in range(character_struct.chars_count):
            character_struct.chars[i].set_with('health', 'health_max')

    def set_ammo_full(self):
        person = self.person
        person.items[person.cur_item].set_with('quantity', 'max_quantity')

    def set_ammo_one(self):
        person = self.person
        person.items[person.cur_item].quantity = 1

    def save_coord(self):
        self.last_coord = self.person.coord.values()

    def load_coord(self):
        if hasattr(self, 'last_coord'):
            person = self.person
            self.prev_coord = person.coord.values()
            person.coord = self.last_coord

    def undo_coord(self):
        if hasattr(self, 'prev_coord'):
            self.person.coord = self.prev_coord

    def reload_coord(self):
        if hasattr(self, 'last_coord'):
            self.person.coord = self.last_coord

    def p1_go_p2(self):
        self._person()  # 确保当前角色正确
        chars = self._global.character_struct.chars
        chars[self.char_index].coord = chars[self.char_index + 1].coord.values()

    def p2_go_p1(self):
        self._person()  # 确保当前角色正确
        chars = self._global.character_struct.chars
        chars[self.char_index + 1].coord = chars[self.char_index].coord.values()

    def unlock_guns(self, _):
        """解锁横向武器"""
        items = self._global.character_config.saved_item_manager.saved_items2[self.char_index].items
        person = self.person
        for i in range(7):
            if items[i].type:
                person.items[i].enabled = True

    def give_rocket_launcher(self, _):
        """火箭发射器(检查点)"""
        self.set_ingame_saved_item(12, 0x11b, 1)
示例#4
0
 def __init__(self):
     super().__init__()
     self.handler = MemHandler()
     self._global = models.Global(0, self.handler)
     self._weapon = models.Weapon(0, self.handler)
示例#5
0
class Main(AssemblyHacktool):
    CLASS_NAME = 'LaunchUnrealUWindowsClient'
    WINDOW_NAME = 'Borderlands'

    def __init__(self):
        super().__init__()
        self.handler = MemHandler()
        self._global = models.Global(0, self.handler)
        self._weapon = models.Weapon(0, self.handler)

    def render_main(self):
        character = (self._character, models.Character)
        weapon = (self._current_weapon, models.Weapon)

        with Group("global", "全局", self._global):
            self.render_global()
        self.lazy_group(Group("character", "角色", character, cols=4),
                        self.render_character)
        self.lazy_group(Group("character_ext", "角色额外", character),
                        self.render_character_ext)
        self.lazy_group(Group("vehicle", "载具", self._global),
                        self.render_vehicle)
        self.lazy_group(Group("ammo", "弹药", character, cols=4),
                        self.render_ammo)
        self.lazy_group(Group("weapon_prof", "武器熟练度", self._global, cols=4),
                        self.render_weapon_prof)
        self.lazy_group(Group("weapon", "武器", weapon, cols=4),
                        self.render_weapon)
        self.lazy_group(Group("drop_rates", "掉落率", None),
                        self.render_drop_rates)
        self.lazy_group(StaticGroup("代码插入"), self.render_assembly_functions)
        self.lazy_group(StaticGroup("快捷键"), self.render_hotkeys)

    def render_global(self):
        movement_mgr = (self._movement_mgr, models.MovementManager)

        ModelInput('base_move_speed', instance=movement_mgr)
        ModelInput('current_move_speed', instance=movement_mgr)
        ModelInput('current_jump_height', instance=movement_mgr)

    def render_character(self):
        health = (self._character_health, models.ShieldHealth)
        shield = (self._character_shield, models.ShieldHealth)
        experience = (self._experience, models.Value)
        ability_cooldown = (self._ability_cooldown, models.Value)
        character_config = (lambda: self._global.mgr.play_mgr.character_config,
                            models.CharacterConfig)

        Title('生命')
        ModelInput('value', instance=health)
        ModelInput('scaled_maximum', instance=health)
        ModelInput('base_maximum', instance=health)
        ModelInput('regen_rate', instance=health)
        ModelSelect('status',
                    instance=health,
                    choices=datasets.SHIELD_HEALTH_STATUS_CHOICES,
                    values=datasets.SHIELD_HEALTH_STATUS_VALUES)

        Title('护甲')
        ModelInput('value', instance=shield)
        ModelInput('scaled_maximum', instance=shield)
        ModelInput('base_maximum', instance=shield)
        ModelInput('regen_rate', instance=shield)
        ModelSelect('status',
                    instance=shield,
                    choices=datasets.SHIELD_HEALTH_STATUS_CHOICES,
                    values=datasets.SHIELD_HEALTH_STATUS_VALUES)

        Title('经验值')
        ModelInput('value', instance=experience)
        ModelInput('scaled_maximum', instance=experience)
        ModelInput('base_maximum', instance=experience)
        # ModelInput('multiplier', instance=experience)

        Title('技能冷却')
        ModelInput('value', instance=ability_cooldown)
        ModelInput('scaled_maximum', instance=ability_cooldown)
        ModelInput('base_maximum', instance=ability_cooldown)

        ModelInput('level', instance=character_config)
        ModelInput('money', instance=character_config)
        ModelInput('skill_points', instance=character_config)

    def render_character_ext(self):
        movement_mgr = (self._movement_mgr, models.MovementManager)

        ModelCoordWidget('coord', instance=movement_mgr, savable=True)

    def render_vehicle(self):
        ModelInput('vehicle_mgr.health.value', '载具血量')
        ModelInput('vehicle_mgr.boost.value', '载具推进')
        ModelInput('vehicle_mgr.boost.scaled_maximum', '载具推进最大值')
        # ModelInput('vehicle_mgr.vehicle_2.health.value', '载具2血量')
        # ModelInput('vehicle_mgr.vehicle_2.boost.value', '载具2推进')
        # ModelInput('vehicle_mgr.vehicle_2.boost.scaled_maximum', '载具2推进最大值')

    def render_ammo(self):
        for i, label in enumerate(
            ('狙击枪', '手枪', '手雷', '左轮手枪', '冲锋枪', '霰弹枪', '战斗步枪', '火箭筒')):
            with ModelInput('weapon_ammos.%d.value' % i, label).container:
                ui.Button(label="最大",
                          className='btn_sm',
                          onclick=partial(self.weapon_ammo_max, i=i))
            ModelInput('weapon_ammos.%d.regen_rate' % i, '恢复速度')

    def render_weapon_prof(self):
        for i, label in enumerate(
            ('手枪', '冲锋枪', '霰弹枪', '战斗步枪', '狙击枪', '火箭筒', '外星枪')):
            ModelInput('another_mgr.weapon_profs.%d.level' % i, '%s等级' % label)
            ModelInput('another_mgr.weapon_profs.%d.exp' % i, '经验')

    def render_weapon(self):
        ModelInput('addr_hex', '地址', readonly=True)
        ModelInput('level')
        ModelInput('item_price')
        # ModelInput('display_level')
        # ModelInput('actual_level')
        # ModelInput('item_actual_level')
        # ModelInput('specification_level')
        ModelInput('base_damage')
        ModelInput('base_accuracy')
        ModelInput('base_fire_rate')
        ModelInput('calculated_bullets_used')

    def render_drop_rates(self):
        self._drop_rates_scan_data = (
            b'\xFF\xFF\xFF\xFF', b'\x00\x00\x00????????????????????'
            b'\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
        )

        self._drop_rates_table = (
            (b'\x4C', 'chest_awesome_ini', 'ChestAwesomeIni'),
            (b'\x53', 'verycommon', '遍地'),
            (b'\x54', 'verycommon_lower', '遍地 lower'),
            (b'\x55', 'common', '普通'),
            (b'\x57', 'uncommon', '罕见'),
            (b'\x58', 'uncommoner', '更罕见'),
            (b'\x59', 'rare', '稀有'),
            (b'\x5A', 'veryrare', '非常稀有'),
            (b'\x5B', 'awesome_verycommon', '特殊遍地'),
            (b'\x5C', 'awesome_common', '特殊普通'),
            (b'\x5D', 'awesome_uncommon', '特殊罕见'),
            (b'\x5E', 'awesome_uncommoner', '特殊更罕见'),
            (b'\x5F', 'awesome_rare', '特殊稀有'),
            (b'\x60', 'awesome_veryrare', '特殊非常稀有'),
            (b'\x61', 'awesome_legendary', '特殊传说'),
        )

        self._drop_rates_preset = (
            ('原始', (1, 200, 100, 10, 5, 1, 0.1, 0.05, 1, 1, 1, 1, 1, 0.1,
                    0.01)),
            ('更好', (10, 40, 20, 5, 2.5, 1, 1, 0.5, 1, 1, 1, 1, 1, 1, 0.5)),
            ('最好', (1, 0.01, 0.01, 0.01, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 1,
                    25, 50, 100)),
            ('5x橙', (1, 200, 100, 10, 5, 1, 0.1, 0.05, 1, 1, 1, 1, 1, 0.1,
                     0.05)),
            ('10x橙', (1, 200, 100, 10, 5, 1, 0.2, 0.1, 1, 1, 1, 1, 1, 0.2,
                      0.1)),
            ('50x橙', (1, 200, 100, 10, 5, 1, 1, 0.5, 1, 1, 1, 1, 1, 1, 0.5)),
        )

        self._drop_rates = types.SimpleNamespace()

        ui.Hr()
        with ui.Horizontal(className='expand'):
            ui.Button('读取地址', onclick=self.read_drop_rates)
            for i, item in enumerate(self._drop_rates_preset):
                ui.Button(item[0],
                          className='btn_md',
                          onclick=partial(self.set_drop_rates_preset, index=i))
        self._drop_rates_views = [
            Input(key,
                  label,
                  addr=partial(__class__.get_drop_rates_item,
                               self.weak,
                               key=key),
                  type=float) for _id, key, label in self._drop_rates_table
        ]

    def render_assembly_functions(self):
        super().render_assembly_functions((
            # AssemblyItem('accuracy_keep', '精准度不减', b'\xF3\x0F\x10\x40\x68\xF3\x0F\x11\x44\x24\x08',
            #     0x008D0000, 0x008F0000, b'\x0F\x57\xC0\x90\x90'),
            AssemblyItem('rapid_fire', '快速射击',
                         b'\xF3\x0F\x10\x81\x94\x02\x00\x00\x0F\x2F',
                         0x00330000, 0x00340000,
                         b'\x0F\x57\xC0\x90\x90\x90\x90\x90'),
            AssemblyItem(
                'no_recoil', '无后坐力',
                b'\xF3\x0F\x10\x8B\xD8\x0B\x00\x00\xF3\x0F\x10\x83\xD4\x0B\x00\x00',
                0x010C0000, 0x010D0000,
                b'\x0F\x57\xC0\x0F\x57\xC9' + b'\x90' * 10),
            AssemblyItem('no_reload',
                         '无需换弹',
                         b'\x2B\x86\xCC\x03\x00\x00\x39\x86\x90\x03\x00\x00',
                         0x01130000,
                         0x01140000,
                         b'',
                         b'\xC7\x86\xCC\x03\x00\x00\x63\x00\x00\x00',
                         inserted=True,
                         replace_len=6),
            AssemblyItem('cur_weapon',
                         '当前武器',
                         b'\x8B\x86\xCC\x03\x00\x00\x33\xC9',
                         0x01070000,
                         0x01080000,
                         b'',
                         AssemblyGroup(
                             b'\x89\x35',
                             assembly_code.Variable('selected_item_addr'),
                             b'\x8B\x86\xCC\x03\x00\x00'),
                         inserted=True,
                         replace_len=6,
                         args=('selected_item_addr', )),
        ))

    def render_hotkeys(self):
        ui.Text("H: 回复护甲+血量\n"
                "P: 回复载具推进+血量\n"
                "B: 前进\n"
                "N: 向上\n"
                "Shift+N: 向下\n"
                "Alt+F: 技能冷却\n"
                ";: 弹药全满\n"
                ".: 升级\n")

    def onattach(self):
        super().onattach()
        self._global.addr = self.handler.base_addr

    def get_hotkeys(self):
        this = self.weak
        return (
            (0, VK.H, this.pull_through),
            (0, VK.U, this.vehicle_full),
            (0, VK.B, this.go_forward),
            (0, VK.N, this.go_up),
            (VK.MOD_SHIFT, VK.N, this.go_down),
            (VK.MOD_ALT, VK.F, this.ability_cooldown),
            (0, VK.getCode(';'), this.all_ammo_full),
            (0, VK.getCode('.'), this.level_up),
        )

    def _character(self):
        return self._global.mgr.play_mgr.character

    def _character_health(self):
        character = self._character()
        return character and character.health

    def _character_shield(self):
        character = self._character()
        return character and character.shield

    def _experience(self):
        character = self._character()
        return character and character.experience

    def _ability_cooldown(self):
        character = self._character()
        return character and character.ability_cooldown

    def _weapon_ammos(self):
        character = self._character()
        return character and character.weapon_ammos

    def _current_weapon(self):
        # player_config = self._player_config()
        # weapon = player_config and player_config.current_weapon
        # if weapon:
        #     if not weapon.addr:
        #         weapon.addr = self.get_variable_value('selected_item_addr', 0)
        self._weapon.addr = self.get_variable_value('selected_item_addr', 0)
        return self._weapon

    def _movement_mgr(self):
        return self._global.physics_mgr.movement_mgr

    def weapon_ammo_max(self, _=None, i=0):
        ammos = self._weapon_ammos()
        if ammos:
            ammos[i].value_max()

    def pull_through(self):
        health = self._character_health()
        if health:
            health.value_max()
        shield = self._character_shield()
        if shield:
            shield.value_max()

    def vehicle_full(self):
        vehicle_mgr = self._global.vehicle_mgr
        if vehicle_mgr.addr > 0x100000:
            vehicle_mgr.boost.value_max()
            vehicle_mgr.health.value_max()
            # if vehicle_mgr.vehicle_1.addr > 0x100000:
            #     vehicle_mgr.vehicle_1.boost.value_max()
            #     vehicle_mgr.vehicle_1.health.value_max()
            # if vehicle_mgr.vehicle_2.addr > 0x100000:
            #     vehicle_mgr.vehicle_2.boost.value_max()
            #     vehicle_mgr.vehicle_2.health.value_max()

    def go_forward(self):
        movement_mgr = self._movement_mgr()
        if movement_mgr:
            vector = movement_mgr.move_vector.values()
            coord = movement_mgr.coord
            delta_z = max(abs(vector[2] * 3), 500) if coord.z < 1500 else 0
            coord += (vector[0] * 5, vector[1] * 5, delta_z)

    def go_up(self):
        movement_mgr = self._movement_mgr()
        if movement_mgr:
            movement_mgr.coord.z += 500

    def go_down(self):
        movement_mgr = self._movement_mgr()
        if movement_mgr:
            movement_mgr.coord.z -= 500

    def all_ammo_full(self):
        ammos = self._weapon_ammos()
        if ammos:
            for ammo in ammos:
                ammo.value_max()

    def level_up(self):
        """升级"""
        character = self._character()
        if character:
            character.experience.value = self._global.mgr.play_mgr.character_config.exp_next_level

    def ability_cooldown(self):
        """技能冷却"""
        character = self._character()
        if character:
            character.ability_cooldown.value = 0

    def read_drop_rates(self, _):
        start = 0x1E000000
        end = 0x1F000000
        for _id, key, label in self._drop_rates_table:
            find_data = _id.join(self._drop_rates_scan_data)
            addr = self.handler.find_bytes(find_data, start, end, fuzzy=True)
            if addr is -1:
                addr = self.handler.find_bytes(find_data,
                                               start - 0x10000,
                                               end - 0x10000,
                                               fuzzy=True)
                if addr is -1:
                    raise ValueError('找不到地址, ' + label)
            if start == 0x1E000000:
                start = addr & 0xFFFF0000
                end = start + 0x10000
            setattr(self._drop_rates, key, addr + 0x30)

    def get_drop_rates_item(self, key):
        addr = getattr(self._drop_rates, key, 0)
        if addr is 0:
            print('未读取地址')
        return addr

    def set_drop_rates_preset(self, _, index):
        for view, value in zip(self._drop_rates_views,
                               self._drop_rates_preset[index][1]):
            view.input_value = value
示例#6
0
 def __init__(self):
     super().__init__()
     self.handler = MemHandler()
     self._global_ins = models.Global(0, self.handler)
     self._movement_ins = models.Movement(0, self.handler)
示例#7
0
class Main(AssemblyHacktool):
    CLASS_NAME = 'LaunchUnrealUWindowsClient'
    WINDOW_NAME = 'Borderlands: The Pre-Sequel (32-bit, DX9)'

    def __init__(self):
        super().__init__()
        self.handler = MemHandler()
        self._global = models.Global(0, self.handler)

    def render_main(self):
        character = (self._character, models.Character)
        team_config = (self._team_config, models.TeamConfig)
        weapon = (self._current_weapon, models.Weapon)

        with Group("global", "全局", self._global):
            self.render_global()
        self.lazy_group(Group("character", "角色", character, cols=4), self.render_character)
        self.lazy_group(Group("character_ext", "角色额外", character), self.render_character_ext)
        self.lazy_group(Group("vehicle", "载具", self._global), self.render_vehicle)
        self.lazy_group(Group("ammo", "弹药", self._global, cols=4), self.render_ammo)
        self.lazy_group(Group("weapon", "武器", weapon, cols=4), self.render_weapon)
        self.lazy_group(Group("team", "团队", team_config, cols=4), self.render_team)
        self.lazy_group(Groups("技能", self.weak.onNotePageChange, addr=team_config), self.render_skill)
        self.lazy_group(Group("drop_rates", "掉落率", None), self.render_drop_rates)
        self.lazy_group(StaticGroup("代码插入"), self.render_assembly_functions)
        self.lazy_group(Group("assembly_variable", "代码变量", self.variable_model), self.render_assembly_variable)
        self.lazy_group(StaticGroup("快捷键"), self.render_hotkeys)

    def render_global(self):
        player_config = (self._player_config, models.PlayerConfig)
        physics_config = (lambda: self._global.mgr.player_mgr.physics_config, models.PhysicsConfig)

        ModelInput('time_scale_multiplier', instance=player_config)
        ModelInput('gravity', instance=player_config)

        ModelInput('move_speed', instance=physics_config)
        ModelInput('jump_height', instance=physics_config)
        ModelInput('friction', instance=physics_config)
        ModelInput('viewing_height', instance=physics_config)

    def render_character(self):
        health = (self._character_health, models.ShieldHealth)
        shield = (self._character_shield, models.ShieldHealth)
        oxygen = (self._character_oxygen, models.ShieldHealth)
        experience = (self._experience, models.Experience)
        player_mgr = (self._player_mgr, models.PlayerManager)

        for label, instance in (('生命', health), ('护甲', shield), ('氧气', oxygen)):
            Title(label)
            ModelInput('value', instance=instance)
            ModelInput('scaled_maximum', instance=instance)
            ModelInput('base_maximum', instance=instance)
            ModelInput('regen_rate', instance=instance)
            ModelSelect('status', instance=instance,
                choices=datasets.STATUS_CHOICES, values=datasets.STATUS_VALUES)

        Title('经验值')
        ModelInput('value', instance=experience)
        ModelInput('scaled_maximum', instance=experience)
        ModelInput('base_maximum', instance=experience)
        ModelInput('multiplier', instance=experience)

        ModelInput('exp_next_level')
        ModelInput('level')
        ModelInput('money')
        ModelInput('moon_shards')
        ModelInput('shift_coins')
        ModelInput('skill_points')

        ModelInput('bank_size', instance=player_mgr)
        ModelInput('weapon_deck_size', instance=player_mgr)
        ModelInput('backpack_size', instance=player_mgr)
        ModelInput('backpack_used_space', instance=player_mgr)

    def render_character_ext(self):
        player_config = (self._player_config, models.PlayerConfig)

        ModelCoordWidget('coord', instance=player_config, savable=True)
        ModelInput('player_visibility', instance=player_config).set_help('216: 对敌人不可见')
        ModelInput('move_speed_mult', instance=player_config)
        ModelInput('ffyl_time_mult', '原地复活生命倍数', instance=player_config)
        ModelInput('ffyl_Health_mult', '原地复活时间倍数', instance=player_config)

    def render_vehicle(self):
        ModelInput('mgr.vehicle_mgrs.0.health.value', '载具1血量')
        ModelInput('mgr.vehicle_mgrs.0.boost.value', '载具1推进')
        ModelInput('mgr.vehicle_mgrs.0.boost.scaled_maximum', '载具1推进最大值')
        ModelCoordWidget('mgr.vehicle_mgrs.0.coord', '载具1坐标', savable=True)
        ModelInput('mgr.vehicle_mgrs.1.health.value', '载具2血量')
        ModelInput('mgr.vehicle_mgrs.1.boost.value', '载具2推进')
        ModelInput('mgr.vehicle_mgrs.1.boost.scaled_maximum', '载具2推进最大值')
        ModelCoordWidget('mgr.vehicle_mgrs.1.coord', '载具1坐标', savable=True)

    def render_ammo(self):
        for i, label in enumerate(('突击步枪子弹', '霰弹枪子弹', '手雷', '冲锋枪子弹', '手枪子弹', '火箭炮弹药', '狙击步枪子弹', '激光子弹')):
            with ModelInput('mgr.weapon_ammos.%d.value' % i, label).container:
                ui.Button(label="最大", className='btn_sm', onclick=partial(self.weapon_ammo_max, i=i))
            with ModelInput('mgr.weapon_ammos.%d.regen_rate' % i, '恢复速度').container:
                ModelCheckBox('mgr.weapon_ammos.%d.infinite' % i, '不减', alone=True)

    def render_weapon(self):
        ModelInput('addr_hex', '地址', readonly=True)
        ModelInput('display_level')
        ModelInput('actual_level')
        ModelInput('item_actual_level')
        ModelInput('specification_level')
        ModelInput('base_damage')
        ModelInput('base_accuracy')
        ModelInput('base_fire_rate')
        ModelInput('base_projectile_speed')
        ModelInput('calculated_projectile_speed')
        ModelInput('base_reload_speed')
        ModelInput('base_burst_length')
        ModelInput('base_projectiles_per_shot')
        ModelInput('calculated_projectiles_per_shot')
        ModelInput('calculated_bullets_used')
        ModelInput('base_extra_shot_chance')
        ModelInput('magazine_size')
        ModelInput('current_bullets')
        ModelInput('clip_ammo')
        ModelInput('item_price')
        ModelInput('item_quantity')
        ModelInput('item_state')

    def render_team(self):
        ModelInput('team_ammo_regen')
        ModelInput('badass_tokens')
        ModelInput('ability_cooldown.value', '能力冷却时间')
        ModelInput('ability_cooldown.mult', '能力冷却倍数')

        for i, label in enumerate(datasets.BADASS_BONUSES):
            ModelInput('badass_bonuses.%d' % i, label).set_help('100% = 464, 200% = 1169, Max = 8388607')

    def render_skill(self):
        with Group('ability', "主技能"):
            ModelInput('skill_mgr.ability_status', '主技能状态')
            ModelInput('skill_mgr.ability_duration', '主技能持续时间')

        def render_sub_skill(data):
            i = 0
            for page in data:
                with Group(None, page[0], cols=4):
                    for item in page[1]:
                        ModelInput('skill_mgr.skills.%d.status' % i, item)
                        i += 1

        for i, item in enumerate(datasets.SKILL_NAMES):
            self.lazy_group(Groups(item[0]), partial(render_sub_skill, item[2]))

    def render_drop_rates(self):
        self._drop_rates_scan_data = (b'\x00\x00\x00????????????????????\x00\x00\x00\x00\x01\x00\x00\x00????'
            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F\x00\x00\x80\x3F')

        self._drop_rates_table = (
            (b'\x2D', 'very_common', '药'),
            (b'\x2F', 'common', '白'),
            (b'\x32', 'uncommon', '绿'),
            (b'\x33', 'very_uncommon', '月'),
            (b'\x34', 'rare', '蓝'),
            (b'\x35', 'very_rare', '紫'),
            (b'\x36', 'legendary', '橙/珠光')
        )

        self._drop_rates_preset = (
            ('原始', (200, 100, 10, 5, 1, 0.1, 0.01)),
            ('仅橙', (0.001, 0.001, 0.001, 0.001, 0.001, 100, 10000)),
            ('仅紫', (0.001, 0.001, 0.001, 0.001, 0.001, 1000, 0.001)),
            ('仅蓝', (0.001, 0.001, 0.001, 0.001, 1000, 0.001, 0.001)),
            ('10x橙', (200, 100, 10, 5, 1, 0.1, 0.1)),
            ('100x橙', (200, 100, 10, 5, 1, 0.1, 1)),
            ('1000x橙', (200, 100, 10, 5, 1, 0.1, 10)),
        )

        self._drop_rates = types.SimpleNamespace()

        ui.Hr()
        with ui.Horizontal(className='expand'):
            ui.Button('读取地址', onclick=self.read_drop_rates)
            for i, item in enumerate(self._drop_rates_preset):
                ui.Button(item[0], className='btn_md', onclick=partial(self.set_drop_rates_preset, index=i))
        self._drop_rates_views = [Input(key, label, addr=partial(__class__.get_drop_rates_item, self.weak, key=key),
            type=float) for _id, key, label in self._drop_rates_table]

    def render_assembly_functions(self):
        super().render_assembly_functions((
            AssemblyItem('ammo_inf', '子弹不减+精准不减', b'\xF3\x0F\x58\x45\x08\x51',
                0x005C0000, 0x008D0000, b'',
                AssemblyGroup(
                    b'\x83\x79\x48\x00\x75\x24\x83\x79\x4C\x00\x75\x1E\x0F\xAE\x05',
                    assembly_code.Variable('fxbuff'),
                    b'\xF3\x0F\x10\x4D\x08\x0F\x57\xDB\x0F\x2F\xCB\x7E\x31\xF3\x0F\x11\x5D\x08\xE9\x27\x00\x00\x00'
                    b'\x0F\xAE\x05', assembly_code.Variable('fxbuff'),
                    b'\xF3\x0F\x10\x4D\x08\x0F\x57\xDB\x0F\x2F\xCB\x7A\x13\x72\x11\xF3\x0F\x10\x25',
                    assembly_code.Variable('minus_one'), b'\xF3\x0F\x59\xCC\xF3\x0F\x11\x4D\x08\x0F\xAE\x0D',
                    assembly_code.Variable('fxbuff'), b'\xF3\x0F\x58\x45\x08'
                ),
                inserted=True, replace_len=5,
                args=(VariableType('fxbuff', size=512, align=16), VariableType('minus_one', value=0xBF800000))),
            AssemblyItem('ammo_inf2', '无需换弹', b'\x3B\xC1\x7C\x0B\x8B\x55\x0C\x89\x02\x8B\xE5\x5D\xC2\x08\x00',
                # old: 0x00460000, 0x00470000,
                # steam
                0x00050000, 0x00060000,
                b'', b'\x8B\x02\x89\x02\x8B\xE5\x5D',
                inserted=True, replace_len=5, replace_offset=7),
            AssemblyItem('no_recoil', '无后坐力', b'\xF3\x0F\x2C\x8F\x98\x0F\x00\x00\x01\x0E',
                0x009D0000, 0x00CE0000, b'',
                b'\x31\xC9\x89\x8F\x94\x0F\x00\x00\x89\x8F\x98\x0F\x00\x00\x89\x8F\x9C\x0F\x00\x00'
                    b'\x89\x8F\xA0\x0F\x00\x00\x89\x8F\xA4\x0F\x00\x00\x89\x8F\xA8\x0F\x00\x00',
                inserted=True, replace_len=8),
            AssemblyItem('without_golden_keys', '无需金钥匙', b'\x74\x1D\x8A\x54',
                # old: 0x00440000, 0x00450000,
                # steam
                0x00B40000, 0x00B50000,
                b'\xEB\x1D\x8A\x54'),
            AssemblyItem('ammo_upgrade_mod', '弹药上限升级', b'\xFF\x04\xB0\x8B\x8F\xE0\x00\x00\x00',
                0x009FF000, 0x00C10000, b'',
                AssemblyGroup(b'\x83\xFE\x07\x0F\x84\x14\x00\x00\x00\x83\xFE\x08\x0F\x84\x0B\x00\x00\x00\x8B\x0D',
                    assembly_code.Variable('ammo_upgrade_level'),
                    b'\x01\x0C\xB0\xEB\x03\xFF\x04\xB0\x8B\x8F\xE0\x00\x00\x00'),
                inserted=True, args=(VariableType('ammo_upgrade_level', value=100),)),
            AssemblyItem('mission_timer_freeze', '任务时间锁定', b'\xF3\x0F\x2C\x54\x03\x04\x89\x11',
                0x00A50000, 0x00DF0000, b'',
                AssemblyGroup(b'\xF3\x0F\x2C\x54\x18\x04\x80\x7C\x18\x08\x00\x74\x2E\x83\x3D',
                    assembly_code.Variable('mission_timer_loaded'),
                    b'\x01\x74\x10\x89\x15', assembly_code.Variable('mission_timer_temp'),
                    b'\xC7\x05', assembly_code.Variable('mission_timer_loaded'),
                    b'\x01\x00\x00\x00\xDB\x05', assembly_code.Variable('mission_timer_temp'),
                    b'\xD9\x5C\x18\x04\x8B\x15', assembly_code.Variable('mission_timer_temp'),
                    b'\xE9\x0A\x00\x00\x00\xC7\x05', assembly_code.Variable('mission_timer_loaded'),
                    b'\x00\x00\x00\x00',),
                inserted=True, replace_len=6, args=('mission_timer_loaded', 'mission_timer_temp')),
            AssemblyItems('选中的物品',
                AssemblyItem('selected_gun', None, b'\x8B\x8F\x78\x0E\x00\x00\x33',
                    0x00B8F000, 0x00E00000, b'',
                    AssemblyGroup(b'\x8B\x8F\x78\x0E\x00\x00\x89\x3D', assembly_code.Variable('selected_item_addr')),
                    inserted=True, replace_len=6, args=('selected_item_addr',)),
                AssemblyItem('selected_item', None, b'\x8B\x81\xA4\x08\x00\x00\x85\xC0\x74\x14',
                    0x00A40000, 0x00C50000, b'',
                    AssemblyGroup(b'\x8B\x81\xA4\x08\x00\x00\x89\x0D', assembly_code.Variable('selected_item_addr')),
                    inserted=True, replace_len=6, args=('selected_item_addr',))),
            # AssemblyItem('no_equip_level_limit', '解除装备等级限制', b'\x8B\x80\x58\x02\x00\x00\x5F\x5E\xC3',
            #     0x00830000, 0x00840000, b'\x90\x90\x90\x90\x90\x90', replace_len=6),
            AssemblyItem('no_unique_weapon_spreadfire_patterns', '无扩散', b'\x99\xF7\xFE\x8B\xC1\x89\x17',
                0x00C00000, 0x00D10000, b'', b'\x99\xF7\xFE\x8B\xC1\xC7\x07\x00\x00\x00\x00',
                inserted=True, replace_len=8),
            AssemblyItem('free_world_usage', '免费世界使用', b'\x8B\x44\x81\x60\x8B\x4D\x14',
                0x00440000, 0x00B50000, b'', b'\xB8\x00\x00\x00\x00\x8B\x4D\x14', inserted=True),
            AssemblyItem('free_moxi_drinks', '免费喝酒', b'\x8B\x81\xDC\x00\x00\x00\x8B\x4D\x10',
                0x00680000, 0x00C00000, b'\xB8\x00\x00\x00\x00\x90', replace_len=6),
            AssemblyItem('unlimited_moxi_drink_duration', '无限喝酒时长', b'\xF3\x0F\x11\x8E\xBC\x10\x00\x00',
                # old: 0x00090000, 0x000A0000,
                # steam
                0x00C00000, 0x00D00000,
                b'\x90\x90\x90\x90\x90\x90\x90\x90'),
            AssemblyItem('infinite_double_jump', '无限二段跳', b'\x8B\x8B\x98\x0B\x00\x00\xC1\xE9\x09',
                0x00B00000, 0x00ED0000, b'', b'\x8B\x8B\x98\x0B\x00\x00\xC6\x83\x99\x0B\x00\x00\x10',
                inserted=True, replace_len=6),
            AssemblyItem('no_backpack_pickup_limit', '解除背包限制', b'\x8B\x81\x00\x02\x00\x00\xC3\xCC\xCC',
                0x00790000, 0x00C00000, b'\xB8\x00\x00\x00\x00\x90', replace_len=6),
        ))

    def render_assembly_variable(self):
        ModelInput('ammo_upgrade_level', '弹药上限等级')
        ModelInput('super_speed_mult', '超级速度倍数')
        ModelInput('super_jump_mult', '超级跳跃倍数')

    def render_hotkeys(self):
        ui.Text("H: 回复护甲+血量\n"
            "P: 回复载具推进+血量\n"
            "B: 前进\n"
            "N: 向上\n"
            "Shift+N: 向下\n"
            "F3: 切换2倍移动速度\n"
            ";: 弹药全满\n"
            ".: 升级\n"
            "': 当前武器高精准,高射速\n"
            "/: 武器等级与人物等级同步(装备中的武器需切到背包再装备)")

    def onattach(self):
        super().onattach()
        self._global.addr = self.handler.base_addr

    def get_hotkeys(self):
        this = self.weak
        return (
            (0, VK.H, this.pull_through),
            (0, VK.P, this.vehicle_full),
            (0, VK.B, this.go_forward),
            (0, VK.N, this.go_up),
            (0, VK.X, this.current_ammo_full),
            (VK.MOD_SHIFT, VK.N, this.go_down),
            (VK.MOD_ALT, VK.F, this.ability_cooldown),
            (0, VK.F3, this.move_quickly),
            (0, VK.getCode(';'), this.all_ammo_full),
            (0, VK.getCode('.'), this.level_up),
            (0, VK.getCode("'"), this.make_weapon_useful),
            (0, VK.getCode('/'), this.sync_weapon_level),
        )

    def _character(self):
        return self._global.mgr.character

    def _character_health(self):
        character = self._character()
        return character and character.health

    def _character_shield(self):
        character = self._character()
        return character and character.shield

    def _character_oxygen(self):
        character = self._character()
        return character and character.oxygen

    def _experience(self):
        character = self._character()
        return character and character.experience

    def _player_mgr(self):
        return self._global.mgr.player_mgr

    def _player_config(self):
        player_mgr = self._player_mgr()
        return player_mgr and player_mgr.player_config

    def _current_weapon(self):
        player_config = self._player_config()
        weapon = player_config and player_config.current_weapon
        if weapon:
            if not weapon.addr:
                weapon.addr = self.get_variable_value('selected_item_addr', 0)
        return weapon

    def _team_config(self):
        return self._global.mgr.team_config

    def weapon_ammo_max(self, _=None, i=0):
        weapon = self._current_weapon()
        if weapon:
            self._global.mgr.weapon_ammos[i].value_max()

    def pull_through(self):
        health = self._character_health()
        if health:
            health.value_max()
        shield = self._character_shield()
        if shield:
            shield.value_max()
        oxygen = self._character_oxygen()
        if oxygen:
            oxygen.value_max()

    def vehicle_full(self):
        vehicle_mgrs = self._global.mgr.vehicle_mgrs
        if vehicle_mgrs.addr:
            if vehicle_mgrs[0].addr:
                vehicle_mgrs[0].boost.value_max()
                vehicle_mgrs[0].health.value_max()
            if vehicle_mgrs[1].addr:
                vehicle_mgrs[1].boost.value_max()
                vehicle_mgrs[1].health.value_max()

    def go_forward(self):
        player_config = self._player_config()
        if player_config:
            vector = player_config.move_vector.values()
            coord = player_config.coord
            coord += (vector[0] * 5, vector[1] * 5, max(abs(vector[2] * 3), 500))

    def go_up(self):
        player_config = self._player_config()
        if player_config:
            player_config.coord.z += 500

    def go_down(self):
        player_config = self._player_config()
        if player_config:
            player_config.coord.z -= 500

    def current_ammo_full(self):
        weapon = self._current_weapon()
        if weapon.addr:
            weapon.ammo.value_max()

    def all_ammo_full(self):
        for ammo in self._global.mgr.weapon_ammos:
            ammo.value_max()

    def level_up(self):
        """升级"""
        character = self._character()
        if character:
            character.experience.value = character.exp_next_level

    def sync_weapon_level(self):
        """同步武器等级"""
        character = self._character()
        level = character and character.level
        if level:
            weapon = self._current_weapon()
            if weapon and weapon.addr:
                weapon.set_level(level)

    def make_weapon_useful(self):
        weapon = self._current_weapon()
        if weapon and weapon.addr:
            weapon.base_accuracy = 0.1
            weapon.base_fire_rate = 0.1 if weapon.base_fire_rate < 0.2 else 0.2

    def move_quickly(self):
        config = self._player_config()
        if config and config.addr:
            config.move_speed_mult = 2 if config.move_speed_mult == 1 else 1

    def ability_cooldown(self):
        """技能冷却"""
        team_config = self._team_config()
        if team_config:
            team_config.ability_cooldown.value = 0

    def read_drop_rates(self, _):
        for _id, key, label in self._drop_rates_table:
            addr = self.handler.find_bytes(_id + self._drop_rates_scan_data, 0x1B000000, 0x1E000000, fuzzy=True)
            if addr is -1:
                raise ValueError('找不到地址, ' + label)
            setattr(self._drop_rates, key, addr + 0x20)

    def get_drop_rates_item(self, key):
        addr = getattr(self._drop_rates, key, 0)
        if addr is 0:
            print('未读取地址')
        return addr

    def set_drop_rates_preset(self, _, index):
        for view, value in zip(self._drop_rates_views, self._drop_rates_preset[index][1]):
            view.input_value = value
示例#8
0
 def __init__(self):
     super().__init__()
     self.handler = MemHandler()
示例#9
0
class Main(AssemblyHacktool):
    CLASS_NAME = 'Valve001'
    WINDOW_NAME = 'HALF-LIFE 2'

    def __init__(self):
        super().__init__()
        self.handler = MemHandler()
        # self._global = models.Global(0, self.handler)

    def render_main(self):
        # with Group("global", "全局", self._global):
        #     pass
        self.lazy_group(StaticGroup("代码插入"), self.render_assembly_functions)

    def onattach(self):
        super().onattach()
        self._server_base = self.handler.get_module('server.dll')

    def server_base(self):
        return self._server_base

    def render_assembly_functions(self):
        server_base = self.server_base
        NOP_6 = b'\x90' * 6
        super().render_assembly_functions((
            AssemblyItem('invincible',
                         '血量不减',
                         b'\x89\xBE\x9C\x00\x00\x00\x5F\x5E\x5D\xB8',
                         0x218000,
                         0x228000,
                         NOP_6,
                         find_base=server_base),
            AssemblyItem('suit_keep',
                         '护甲不减',
                         b'\x2B\xE8\x39\xAE\xB4\x0B\x00\x00',
                         0x33A000,
                         0x33B000,
                         b'\x90\x90',
                         replace_len=2,
                         find_base=server_base),
            AssemblyItem('ammo_999',
                         '装填弹药999',
                         b'\x89\x9C\xBE\x30\x06\x00\x00\x5F\x5E\x5B',
                         0x21A000,
                         0x220000,
                         b'',
                         b'\xC7\x84\xBE\x30\x06\x00\x00\xE7\x03\x00\x00',
                         inserted=True,
                         replace_len=7,
                         find_base=server_base),
            SimpleButton('no_reload_all', '不用换弹', onclick=self.no_reload_all),
            AssemblyItem('no_reload_grenade',
                         '炮弹不用换弹',
                         b'\x89\x9C\xBE\x30\x06\x00\x00\x5F\x5E\x5B',
                         0x21A000,
                         0x220000,
                         b'\x90' * 7,
                         find_base=server_base),
            AssemblyItem('no_reload_pistol',
                         '手枪不用换弹',
                         b'\x89\x9E\xC4\x04\x00\x00\xEB\x39',
                         0x218000,
                         0x228000,
                         NOP_6,
                         find_base=server_base),
            AssemblyItem('no_reload_revolver',
                         '左轮不用换弹',
                         b'\x83\x09\x01\x8B\x12\x89\x10',
                         0x158000,
                         0x160000,
                         b'\x83\x09\x01\x8B\x10',
                         find_base=server_base),
            AssemblyItem('no_reload_slot3',
                         '冲锋/步枪不用换弹',
                         b'\x89\xAE\xC4\x04\x00\x00\x33\xED',
                         0x37000,
                         0x38000,
                         NOP_6,
                         find_base=server_base),
            AssemblyItem('no_reload_shotgun',
                         '单管霰弹枪不用换弹',
                         b'\x89\x9F\xC4\x04\x00\x00\x8B\x06',
                         0x173000,
                         0x173200,
                         NOP_6,
                         find_base=server_base),
            AssemblyItem('no_reload_shotgun2',
                         '双管霰弹枪不用换弹',
                         b'\x89\x9F\xC4\x04\x00\x00\x8B\x06',
                         0x173200,
                         0x173300,
                         NOP_6,
                         find_base=server_base),
            AssemblyItem('no_reload_crossbow',
                         '十字弩不用换弹',
                         b'\x89\x9E\xC4\x04\x00\x00\x8D\x54\x24\x24',
                         0x15E000,
                         0x160000,
                         NOP_6,
                         find_base=server_base),
        ))

    # def get_hotkeys(self):
    #     this = self.weak
    #     return (
    #         (0, VK.H, this.pull_through),
    #     )

    # def pull_through(self):
    #     self.toggle_assembly_button('health_inf')

    def no_reload_all(self, checked):
        keys = ('no_reload_grenade', 'no_reload_pistol', 'no_reload_revolver',
                'no_reload_slot3', 'no_reload_shotgun', 'no_reload_shotgun2',
                'no_reload_crossbow')
        for key in keys:
            self.toggle_assembly_button(key)
示例#10
0
class BaseGTATool(NativeHacktool):
    RAISE_UP_SPEED = 1.0
    GO_DOWN_SPEED = 0.5
    TO_UP_DELTA = 10
    TO_DOWN_DELTA = 6
    key_hook = False

    def __init__(self):
        super().__init__()
        self.handler = MemHandler()

    def get_hotkeys(self):
        """重写这个函数,返回要注册的热键列表"""
        return self.get_common_hotkeys()

    def inputCheat(self, text):
        auto.sendKey(TextVK(text), 10)

    def _player(self):
        player_addr = self.handler.read32(self.address.PLAYER_PTR)
        if player_addr is 0:
            return None
        player = getattr(self, '_player_ins', None)
        if not player:
            player = self._player_ins = self.Player(player_addr, self)
        elif player.addr != player_addr:
            player.addr = player_addr
        return player

    def _vehicle(self):
        addr = self.handler.read32(self.address.VEHICLE_PTR)
        if addr >= self.vehicle_pool.start:
            return self.Vehicle(self.handler.read32(self.address.VEHICLE_PTR), self) or None

    player = property(_player)
    vehicle = property(_vehicle)

    @property
    def last_vehicle(self):
        return self.player.vehicle or self.vehicle

    @property
    def isInVehicle(self):
        """当前是否在乘车"""
        return self.player.isInVehicle

    @property
    def entity(self):
        """在车中则返回载具对象,否则返回角色对象"""
        return self.vehicle if self.isInVehicle else self.player

    @property
    def ped_pool(self):
        """角色池"""
        return self.models.Pool(self.address.PED_POOL, self, self.Player)

    @property
    def vehicle_pool(self):
        """载具池"""
        return self.models.Pool(self.address.VEHICLE_POOL, self, self.Vehicle)

    @property
    def object_pool(self):
        """物体池"""
        return self.models.Pool(self.address.OBJECT_POOL, self, self.models.Object)

    def get_yaw(self):
        """获取偏航角"""
        PI = math.pi
        HALF_PI = PI / 2
        yaw = self.player.rotation
        yaw += HALF_PI
        if yaw > PI:
            yaw += PI * 2
        return yaw

    def get_camera_rot(self):
        """获取摄像机朝向参数 (pitch, yaw, roll)"""
        yaw = self.get_yaw()
        return (math.cos(yaw), math.sin(yaw), 0.1)

    def get_front_coord(self, delta=5):
        """获取前面一点的坐标"""
        yaw = self.get_yaw()

        x = math.cos(yaw)
        y = math.sin(yaw)
        coord = self.player.coord.values()
        coord[0] += x * delta
        coord[1] += y * delta
        return coord

    def get_cam_front_coord(self, delta=5):
        """根据摄像机朝向获取前面一点的坐标"""
        rot = self.get_camera_rot()
        coord = self.player.coord.values()
        coord[0] += rot[0] * delta
        coord[1] += rot[1] * delta
        return coord

    def go_forward(self, _=None, rate=0):
        """前进"""
        rate = rate or self.GO_FORWARD_COORD_RATE

        yaw = self.get_yaw()
        x = math.cos(yaw)
        y = math.sin(yaw)

        entity = self.entity
        coord = entity.coord.values()
        coord[0] += x * rate
        coord[1] += y * rate

        entity.coord = coord

    def speed_up(self, _=None, rate=0):
        """弹射起步"""
        speed_rate = rate or getattr(self, 'SAFE_SPEED_RATE', 0.5)

        yaw = self.get_yaw()
        x = math.cos(yaw)
        y = math.sin(yaw)

        entity = self.entity
        speed = entity.speed.values()
        speed[0] += x * speed_rate
        speed[1] += y * speed_rate

        if not self.isInVehicle:
            safe_speed_up = getattr(self, 'SAFE_SPEED_UP', 0.2)
            speed[2] = safe_speed_up
            self.raise_up(speed=safe_speed_up)
            time.sleep(0.1)
        entity.speed = speed

    def raise_up(self, _=None, speed=0):
        """上天(有速度)"""
        self.entity.speed[2] = speed or self.RAISE_UP_SPEED

    def go_down(self, _=None, speed=0):
        """向下(有速度)"""
        self.entity.speed[2] = -(speed or self.GO_DOWN_SPEED)

    def to_up(self, _=None, delta=0):
        """往上(无速度)"""
        self.entity.coord[2] += delta or self.TO_UP_DELTA

    def to_down(self, _=None, delta=0):
        """向下(无速度)"""
        self.entity.coord[2] -= delta or self.TO_DOWN_DELTA

    def stop(self, _=None):
        """停止移动"""
        self.entity.stop()

    def restore_hp(self, _=None):
        """恢复HP"""
        if self.isInVehicle:
            self.vehicle.hp = 1000
            self.vehicle_fix(self.vehicle)
        else:
            self.player.hp = 200
            self.player.ap = 200

    def restore_hp_large(self, _=None):
        """恢复大量HP"""
        if self.isInVehicle:
            self.vehicle.hp = 2000
            self.vehicle_fix(self.vehicle)
        else:
            self.player.hp = 999
            self.player.ap = 999

    def vehicle_fix(self, vehicle):
        """修车"""
        pass

    def from_player_coord(self, btn):
        """车坐标从人坐标取值"""
        self.vehicle_coord_view.input_value = self.coord_view.input_value

    def from_vehicle_coord(self, btn):
        """人坐标从车坐标取值"""
        self.coord_view.input_value = self.vehicle_coord_view.input_value

    def go_prev_pos(self, _=None):
        """瞬移到上一处地点"""
        view = self.vehicle_coord_view if self.isInVehicle else self.coord_view
        view.listbox.prev()
        view.write()

    def go_next_pos(self, _=None):
        """瞬移到下一处地点"""
        view = self.vehicle_coord_view if self.isInVehicle else self.coord_view
        view.listbox.next()
        view.write()

    def iter_cam_dir_coords(self, count, space, first_double=False):
        """往视角方向迭代坐标
        :param first_double: 第一个坐标是否是双倍距离
        """
        cam_x, cam_y, cam_z = self.get_camera_rot()
        offset = (cam_x * space, cam_y * space, cam_z * space)
        coord = self.player.get_offset_coord_m(offset)
        if first_double:
            coord += offset

        for i in range(count):
            yield coord
            coord += offset

    def get_peds(self):
        """获取角色池中的角色列表"""
        return iter(self.ped_pool)

    def get_near_peds(self, distance=100):
        """获取附近的人"""
        coord = self.player.coord.values()
        myaddr = self.player.addr
        for p in self.get_peds():
            if p.hp > 0 and p.coord[2] > 0 and p.distance(coord) <= distance and p.addr != myaddr:
                yield p

    def get_vehicles(self):
        """载具池中的载具列表"""
        return iter(self.vehicle_pool)

    def get_near_vehicles(self, distance=100):
        """获取附近的载具"""
        coord = self.player.coord.values()
        mycar = self.vehicle
        myaddr = mycar.addr if mycar else 0
        for v in self.get_vehicles():
            if v.coord[2] > 0 and v.distance(coord) <= distance and v.addr != myaddr:
                yield v

    def collect_vehicles(self):
        """暂存附近的载具"""
        self._vehicles = self.get_near_vehicles()

    def next_collected_vehicle(self, is_retry=False, recollect=False):
        """获取下一辆暂存的载具"""
        vehicles = None if recollect else getattr(self, '_vehicles', None)
        flag = False
        if vehicles:
            try:
                if getattr(self, 'iter_vehicle_locked', False):
                    vehicle = getattr(self, 'last_iter_vehicle', None)
                    if vehicle:
                        flag = True

                if not flag:
                    vehicle = next(vehicles)
                    self.last_iter_vehicle = vehicle
                    flag = True
            except StopIteration:
                if is_retry:
                    # 大概是附近没有车了
                    return

        if not flag:
            self.collect_vehicles()
            return self.next_collected_vehicle(is_retry=True)

        return vehicle

    def iter_vehicle_lock(self, _=None):
        """锁住载具迭代(接下来只操作上一个返回的已收集载具)"""
        self.iter_vehicle_locked = not getattr(self, 'iter_vehicle_locked', False)

    def kill_near_peds(self, _=None):
        """杀死附近的人"""
        for p in self.get_near_peds():
            p.hp = 0

    def near_vehicles_boom(self, _=None):
        """摧毁附近的载具"""
        for v in self.get_near_vehicles():
            v.hp = 0

    def near_vehicles_down(self, _=None):
        """获取附近的载具下陷"""
        for v in self.get_near_vehicles():
            v.coord[2] -= 0.7

    def near_vehicles_to_front(self, _=None, zinc=0):
        """ 获取附近的载具移到眼前
        :param zinc: 下一个目标的z坐标增加
        """
        coord = self.get_front_coord()
        for p in self.get_near_vehicles():
            p.coord = coord
            if zinc:
                coord[2] += zinc

    def near_peds_to_front(self, _=None, zinc=0):
        """附近的人移到眼前"""
        coord = self.get_front_coord()
        for p in self.get_near_peds():
            p.coord = coord
            if zinc:
                coord[2] += zinc

    def jump_on_vehicle(self, _=None):
        """跳上附近的一辆行驶中的车"""
        for v in self.get_near_vehicles():
            if v.driver:
                v.stop()
                coord = v.coord.values()
                coord[2] += 1
                self.entity.coord = coord
                break

    def near_vehicles_flip(self, _=None):
        """附近的载具上下翻转"""
        for v in self.get_near_vehicles():
            v.flip()

    def near_vehicle_unlock(self, _=None):
        """附近的载具解锁"""
        for v in self.get_near_vehicles():
            v.unlock_door()

    def near_peds_fly(self, _=None):
        """附近的人上天"""
        fly_speed = getattr(self, 'FLY_SPEED', 1)
        for p in self.get_near_peds():
            p.speed[2] = fly_speed

    def near_vehicles_fly(self, _=None):
        """获取附近的载具上天"""
        fly_speed = getattr(self, 'FLY_SPEED', 1)
        for v in self.get_near_vehicles():
            v.coord[2] += fly_speed
            v.speed[2] = fly_speed

    def near_fly(self, _=None):
        """获取附近的人/载具上天"""
        self.near_peds_fly()
        self.near_vehicles_fly()

    def vehicle_flip(self, _=None):
        """当前的载具翻转"""
        self.last_vehicle.flip()

    def call_vehicle(self, _=None):
        """召唤上一辆车回来"""
        car = self.last_vehicle
        if car:
            car.coord = self.get_front_coord()

    def go_vehicle(self, _=None):
        """回到上一辆车旁边"""
        car = self.last_vehicle
        if car:
            coord = car.coord.values()
            coord[2] += 5
            self.player.coord = coord

    def bring_one_vehicle(self, _=None):
        """ 把一辆车移到眼前 """
        vehicle = self.next_collected_vehicle()

        if not vehicle:
            return

        cam_x, cam_y, cam_z = self.get_camera_rot()
        coord = self.player.coord.values()
        coord[0] += cam_x * 5
        coord[1] += cam_y * 5
        coord[2] += cam_z * 5
        vehicle.stop()
        vehicle.coord = coord

    def vehicle_lock_door(self, _=None, lock=True):
        """锁车门"""
        vehicle = self.last_vehicle
        if vehicle:
            if lock:
                vehicle.lock_door()
            else:
                vehicle.unlock_door()

    def vehicle_toggle_door(self, tb):
        """切换锁车状态"""
        self.vehicle_lock_door(lock=tb.checked)

    # ----------------------------------------------------------------------
    # MARKER
    # ----------------------------------------------------------------------
    def get_blips(self, color=None, types=None, sprite=None):
        """获取所有标记"""
        Marker = self.models.Marker
        addr = self.address.BLIP_LIST
        it = Marker(addr, self)

        for i in range(self.MARKER_RANGE):
            blipType = it.blipType
            if (it.blipType and (types is None or blipType in types) and (color is None or it.color is color)
                    and (sprite is None or it.sprite is sprite)):
                yield Marker(it.addr, self)
            it.next()

    def get_first_blip(self, *args, **kwargs):
        try:
            return next(self.get_blips(*args, **kwargs))
        except StopIteration:
            pass

    def get_target_blips(self, color=None, types=None, sprite=0):
        """获取目标的所有标记"""
        return self.get_blips(color, types or self.models.Marker.AVAILABLE_TYPE)

    def recal_markers(self, _=None):
        """重新获取人/车标记点"""
        self._markers = tuple(self.get_target_blips())
        self._marker_index = 0

    def go_next_marker(self, _=None):
        """到下一处 人/车标记点"""
        if not hasattr(self, '_markers'):
            self.recal_markers()

        while True:
            try:
                entity = self._markers[self._marker_index].entity
            except IndexError:
                self.recal_markers()
                return
            if entity:
                self.entity.coord = entity.coord
                break
            self._marker_index += 1

    def move_marker_to_front(self, _=None, zinc=0):
        """人/车标记点目标移到眼前"""
        if not hasattr(self, '_markers'):
            self.recal_markers()

        moved_car_addr = []
        coord = self.get_front_coord()

        for marker in self._markers:
            entity = marker.entity
            if isinstance(entity, self.Player):
                car = entity.vehicle
                if car and car.hp > 1:
                    if car.addr not in moved_car_addr:
                        moved_car_addr.append(car.addr)
                        car.coord = coord
                else:
                    entity.coord = coord
            elif isinstance(entity, self.Vehicle):
                entity.coord = coord
            if zinc:
                coord[2] += zinc

    def teleport_to_blip(self, blip):
        """瞬移到指定标记"""
        if blip:
            blipType = blip.blipType
            if blipType is self.models.Marker.MARKER_TYPE_COORDS:
                coord = blip.coord
            else:
                entity = blip.entity
                self.en = entity
                if entity:
                    coord = entity.coord
                else:
                    return False
            self.entity.coord = coord
            return True
        return False

    def teleport_to_destination(self, _=None, color=None, types=None):
        """瞬移到目的地"""
        Marker = self.models.Marker

        if color is None:
            color = getattr(self, '_last_dest_color', self.DEST_DEFAULT_COLOR)
        else:
            self._last_dest_color = color

        if types is None:
            types = (Marker.MARKER_TYPE_CAR, Marker.MARKER_TYPE_PED, Marker.MARKER_TYPE_COORDS)

        for blip in self.get_blips(color, types):
            if blip.sprite is 0:
                if self.teleport_to_blip(blip):
                    break

    def get_selected_vehicle_model(self):
        """获取刷车器选中的载具模型"""
        return getattr(self, 'spwan_vehicle_id', None)

    def spawn_choosed_vehicle(self, _=None, coord=None):
        """生成选中的载具"""
        model = self.get_selected_vehicle_model()
        if model:
            return self.spawn_vehicle(model, coord)

    def on_spawn_vehicle_id_change(self, lb):
        """刷车器listbox回调"""
        self.spwan_vehicle_id = self.VEHICLE_LIST[lb.index][1]

    def spawn_vehicle_id_prev(self, _=None):
        """选中上一个载具"""
        pos = self.spawn_vehicle_id_view.index
        if pos == 0:
            pos = len(self.VEHICLE_LIST)
        self.spawn_vehicle_id_view.setSelection(pos - 1, True)

    def spawn_vehicle_id_next(self, _=None):
        """选中下一个载具"""
        pos = self.spawn_vehicle_id_view.index
        if pos == len(self.VEHICLE_LIST) - 1:
            pos = -1
        self.spawn_vehicle_id_view.setSelection(pos + 1, True)

    def lock_door(self, _=None):
        """锁最近使用的载具的车门"""
        vehicle = self.last_vehicle
        if vehicle:
            vehicle.lock_door()

    def unlock_door(self, _=None):
        """解锁最近使用的载具的车门"""
        vehicle = self.last_vehicle
        if vehicle:
            vehicle.unlock_door()

    def launch_entity(self, entitys, need_set_coord=True):
        """朝前方发射载具"""
        if not hasattr(entitys, '__iter__'):
            entitys = (entitys,)

        for entity in entitys:
            cam_x, cam_y, cam_z = self.get_camera_rot()
            speed_rate = getattr(self, 'SLING_SPEED_RATE', 3)
            speed = (cam_x * speed_rate, cam_y * speed_rate, cam_z * speed_rate)
            if need_set_coord:
                coord_up = getattr(self, 'SLING_COORD_UP', 1)
                coord_delta = getattr(self, 'SLING_COORD_DELTA', 5)
                if self.isInVehicle:
                    coord_delta *= 1.5
                coord = self.player.coord.values()
                coord[0] += cam_x * coord_delta
                coord[1] += cam_y * coord_delta
                coord[2] += cam_z * coord_delta + coord_up
                entity.stop()
                entity.coord = coord
            entity.speed = speed

    def sling(self, _=None, recollect=False):
        """载具发射台"""
        vehicle = self.next_collected_vehicle(recollect=recollect)
        if vehicle:
            self.launch_entity(vehicle)
            self._last_launch_vehicle = vehicle

    def spawn_and_launch(self, _=None, recreate=False):
        """生产载具并发射"""
        vehicle = None
        if not recreate:
            vehicle = getattr(self, '_last_spawn_and_launch_vehicle', None)
        if not vehicle or vehicle.model_id != self.get_selected_vehicle_model():
            coord_delta = getattr(self, 'SLING_COORD_DELTA', 5)
            if self.isInVehicle:
                coord_delta *= 1.5
            vehicle = self.spawn_choosed_vehicle(coord=self.get_cam_front_coord(coord_delta))
            self._last_spawn_and_launch_vehicle = vehicle
        if vehicle:
            self.launch_entity(vehicle)
            self._last_launch_vehicle = vehicle

    def explode_last_launch_vehicle(self, _=None):
        """爆破上次发射的载具"""
        vehicle = getattr(self, '_last_launch_vehicle', None)
        if vehicle:
            vehicle.explode()

    def clear_wanted_level(self, _=None):
        """清除通缉等级"""
        self.set_wanted_level(0)

    def set_wanted_level(self, value):
        self.player.wanted_level = value

    def explode_art(self, _=None, count=10):
        """焰之炼金术 (向前生成数个爆炸)"""
        distance = (getattr(self, 'EXPLODE_DISTANCE_VEHICLE', 8) if self.isInVehicle
            else getattr(self, 'EXPLODE_DISTANCE', 6))
        for coord in self.iter_cam_dir_coords(count, distance, True):
            self.create_explosion(coord)

    def g3l2json(self, _=None):
        """g3l坐标转json"""
        path = fefactory_api.choose_file("选择要读取的文件", wildcard='*.g3l')
        if path:
            with open(path) as file:
                if not file.readline().strip() == '[Locks]':
                    fefactory_api.alert('不支持的格式')
                    return

                coord = [0, 0, 0]
                datas = []
                while True:
                    line = file.readline()
                    if not line:
                        break
                    line = line.strip()
                    if line.startswith('x='):
                        coord[0] = float(line[2:])
                    elif line.startswith('y='):
                        coord[1] = float(line[2:])
                    elif line.startswith('z='):
                        coord[2] = float(line[2:])
                    elif line.startswith('desc='):
                        datas.append({'name': line[5:], 'value': tuple(coord)})

            jsonpath = path[:path.rfind('.') + 1] + 'json'
            with open(jsonpath, 'w', encoding="utf-8") as file:
                json.dump(datas, file, ensure_ascii=False)

            fefactory_api.alert('转换成功: ' + jsonpath)

    def render_common_button(self):
        ui.Button("杀掉附近的人", onclick=self.kill_near_peds)
        ui.Button("附近的车摧毁", onclick=self.near_vehicles_boom)
        ui.Button("附近的车下陷", onclick=self.near_vehicles_down)
        ui.Button("附近的车移到眼前", onclick=self.near_vehicles_to_front)
        ui.Button("附近的人移到眼前", onclick=self.near_peds_to_front)
        ui.Button("附近的车上天", onclick=self.near_vehicles_fly)
        ui.Button("附近的人上天", onclick=self.near_peds_fly)
        ui.Button("附近的车翻转", onclick=self.near_vehicles_flip)
        ui.Button("跳上一辆车", onclick=self.jump_on_vehicle)
        ui.Button("召唤上一辆车回来", onclick=self.call_vehicle)
        ui.Button("回到上一辆车旁边", onclick=self.go_vehicle)
        ui.Button("附近的载具解锁", onclick=self.near_vehicle_unlock)
        ui.Button("锁定载具迭代", onclick=self.iter_vehicle_lock)

    def render_common_text(self):
        ui.Text("生产选中的载具: alt+v\n"
            "选中上一个载具: alt+[\n"
            "选中下一个载具: alt+]\n"
            "向前穿墙: alt+w\n"
            "向前穿墙大: alt+shift+w\n"
            "弹射起步: alt+m\n"
            "上天(有速度): alt+空格\n"
            "往上(无速度): alt+.\n"
            "下坠: alt+shift+空格\n"
            "停止移动: alt+x\n"
            "恢复HP: alt+h\n"
            "恢复大量HP: alt+shift+h\n"
            "跳上一辆车: alt+j\n"
            "附近的人上天: alt+f\n"
            "附近的人和载具上天: alt+shift+f\n"
            "自己的载具翻转: alt+k\n"
            "附近的载具翻转: alt+shift+k\n"
            "附近的人移到眼前: alt+shift+p\n"
            "附近的载具移到眼前: alt+p\n"
            "瞬移到上一个地点: alt+shift+,\n"
            "瞬移到下一个地点: alt+shift+.\n"
            "重新获取雷达上标记的目标: alt+'\n"
            "瞬移到下一个标记目标处: alt+/\n"
            "把获取到的标记目标移到眼前: alt+shift+/\n"
            "上一辆车锁门: alt+l\n"
            "上一辆车解锁: alt+shift+l\n"
            "载具发射台(扫描附件的车,依次把一辆车发射出去): alt+d\n"
            "载具发射台(重新扫描): alt+shift+d\n"
            "生产载具并发射: alt+a\n"
            "爆破上次发射的载具: alt+shift+a\n"
            "把一辆车移到眼前: alt+b\n"
            "清除通缉等级: alt+0\n"
            "红莲之炼金术 (向前生成数个爆炸): alt+`\n"
            "红莲之炼金术 (长): alt+shift+`\n"
            "瞬移到目的地: alt+1\n"
            "自定义临时热键(执行tool.cfn): alt+c")

    def get_common_hotkeys(self):
        return (
            (VK.MOD_ALT, VK.W, self.go_forward),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.W, partial(self.go_forward, rate=10), 'go_forward_large'),
            (VK.MOD_ALT, VK.M, self.speed_up),
            (VK.MOD_ALT, VK.SPACE, self.raise_up),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.SPACE, self.go_down),
            (VK.MOD_ALT, VK.getCode(','), self.to_up),
            (VK.MOD_ALT, VK.getCode('.'), self.to_down),
            (VK.MOD_ALT, VK.X, self.stop),
            (VK.MOD_ALT, VK.H, self.restore_hp),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.H, self.restore_hp_large),
            (VK.MOD_ALT, VK.J, self.jump_on_vehicle),
            (VK.MOD_ALT, VK.F, self.near_peds_fly),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.F, self.near_fly),
            (VK.MOD_ALT, VK.K, self.vehicle_flip),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.K, self.near_vehicles_flip),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.P, self.near_peds_to_front),
            (VK.MOD_ALT, VK.P, self.near_vehicles_to_front),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.getCode(','), self.go_prev_pos),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.getCode('.'), self.go_next_pos),
            (VK.MOD_ALT, VK.getCode("'"), self.recal_markers),
            (VK.MOD_ALT, VK.getCode('/'), self.go_next_marker),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.getCode('/'), self.move_marker_to_front),
            (VK.MOD_ALT, VK.L, self.lock_door),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.L, self.unlock_door),
            (VK.MOD_ALT, VK.D, self.sling),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.D, partial(self.sling, recollect=True), 'resling'),
            (VK.MOD_ALT, VK.A, self.spawn_and_launch),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.A, partial(self.spawn_and_launch, recreate=True), 'respawn_and_launch'),
            (VK.MOD_ALT, VK.Z, self.explode_last_launch_vehicle),
            (VK.MOD_ALT, VK.B, self.bring_one_vehicle),
            (VK.MOD_ALT, VK._0, self.clear_wanted_level),
            (VK.MOD_ALT, VK.getCode('`'), self.explode_art),
            (VK.MOD_ALT | VK.MOD_SHIFT, VK.getCode('`'), partial(self.explode_art, count=24), 'explode_art_long'),
            (VK.MOD_ALT, VK.Q, partial(self.explode_art, count=1), 'explode_art_one'),
            (VK.MOD_ALT, VK._1, self.teleport_to_destination),
            (VK.MOD_ALT, VK.getCode('['), self.spawn_vehicle_id_prev),
            (VK.MOD_ALT, VK.getCode(']'), self.spawn_vehicle_id_next),
            (VK.MOD_ALT, VK.V, self.spawn_choosed_vehicle),
            (VK.MOD_ALT, VK.C, self.custom_hotkey),
        )