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
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
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)
def __init__(self): super().__init__() self.handler = MemHandler() self._global = models.Global(0, self.handler) self._weapon = models.Weapon(0, self.handler)
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
def __init__(self): super().__init__() self.handler = MemHandler() self._global_ins = models.Global(0, self.handler) self._movement_ins = models.Movement(0, self.handler)
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
def __init__(self): super().__init__() self.handler = MemHandler()
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)
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), )