From 78572f4f4100bfd7dd6895899de70828e54ba132 Mon Sep 17 00:00:00 2001 From: 1recyclebin1 Date: Sat, 15 Aug 2026 20:48:38 +0200 Subject: [PATCH] Break nearby objects --- TarnishedTool/GameIds/Emevd.cs | 5 ++ TarnishedTool/MainWindow.xaml.cs | 2 +- TarnishedTool/ViewModels/UtilityViewModel.cs | 93 +++++++++++++++++++- TarnishedTool/Views/Tabs/UtilityTab.xaml | 5 ++ 4 files changed, 103 insertions(+), 2 deletions(-) diff --git a/TarnishedTool/GameIds/Emevd.cs b/TarnishedTool/GameIds/Emevd.cs index 824a959..c25158b 100644 --- a/TarnishedTool/GameIds/Emevd.cs +++ b/TarnishedTool/GameIds/Emevd.cs @@ -93,5 +93,10 @@ public static class EmevdCommands public static EmevdCommand ResetCharacterPosition(uint entityId) => new(2004, 81, entityId); public static EmevdCommand AwardItemsIncludingClients(int itemId) => new(2003, 36, itemId); + + public static EmevdCommand ShootBullet(uint bulletTeamEntityId, uint bulletProducerEntityId, int dummypolyId, + int behaviorId, int firingAngleX, int firingAngleY, int firingAngleZ) + => new(2003, 5, bulletTeamEntityId, bulletProducerEntityId, dummypolyId, behaviorId, firingAngleX, + firingAngleY, firingAngleZ); } } diff --git a/TarnishedTool/MainWindow.xaml.cs b/TarnishedTool/MainWindow.xaml.cs index b30cc7d..4854877 100644 --- a/TarnishedTool/MainWindow.xaml.cs +++ b/TarnishedTool/MainWindow.xaml.cs @@ -109,7 +109,7 @@ public MainWindow() UtilityViewModel utilityViewModel = new UtilityViewModel( utilityService, _stateService, ezStateService, playerService, hotkeyManager, playerViewModel, - _dlcService, spEffectService, flaskService, paramService + _dlcService, spEffectService, flaskService, paramService, emevdService ); ItemViewModel itemViewModel = new ItemViewModel( diff --git a/TarnishedTool/ViewModels/UtilityViewModel.cs b/TarnishedTool/ViewModels/UtilityViewModel.cs index 518e982..e733689 100644 --- a/TarnishedTool/ViewModels/UtilityViewModel.cs +++ b/TarnishedTool/ViewModels/UtilityViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Windows.Input; using TarnishedTool.Core; @@ -36,8 +37,10 @@ public class UtilityViewModel : BaseViewModel private readonly ISpEffectService _spEffectService; private readonly IFlaskService _flaskService; private readonly IParamService _paramService; + private readonly IEmevdService _emevdService; public const int MaterialId01Offset = 0x0; + /* saving those just in case I decide to add no crafting cost public const int MaterialId02Offset = 0x4; public const int MaterialId03Offset = 0x8; @@ -45,6 +48,7 @@ public class UtilityViewModel : BaseViewModel public const int MaterialId05Offset = 0x10; public const int MaterialId06Offset = 0x14; */ + public const int ItemNum01Offset = 0x20; private List? _originalMaterialIds; private List? _originalItemNums; @@ -67,6 +71,26 @@ public class UtilityViewModel : BaseViewModel private List? _originalProtectorDiscard; private List? _originalWeaponDiscard; + // Break Objects Stuff + + public const int AtkParamPcAtkObjOffset = 0x62; + public const int AtkParamPcAtkObjVal = 0; + public const int AtkParamPcAtkBehaviourOffset = 0x82; + public const int AtkParamPcAtkBehaviourVal = 7; + + public const int AtkParamPcAppearAiSoundOffset = 0x90; + public const int AtkParamPcAppearAiSoundVal = 2030; + + public const int AtkParamPcHitAiSoundOffset = 0x94; + public const int AtkParamPcHitAiSoundVal = 2130; + + public const int ShackleRowId = 10214000; + + public const int ModifiedBehaviourRowId = 600000800; + public const int OriginalRowId = 200002340; + public const int ReferenceIdOffset = 0xc; + + private static readonly uint[] DisableGraceWarpIds = [4270, 4271, 4272, 4282, 4286, 4288]; private readonly List _equipMtrlUpgrades = DataLoader.GetEquipMtrlUpgrades(); private readonly Dictionary _originalEquipMtrlUpgradeMaterials = new(); @@ -76,7 +100,8 @@ public class UtilityViewModel : BaseViewModel public UtilityViewModel(IUtilityService utilityService, IStateService stateService, IEzStateService ezStateService, IPlayerService playerService, HotkeyManager hotkeyManager, PlayerViewModel playerViewModel, IDlcService dlcService, - ISpEffectService spEffectService, IFlaskService flaskService, IParamService paramService) + ISpEffectService spEffectService, IFlaskService flaskService, IParamService paramService, + IEmevdService emevdService) { _utilityService = utilityService; _ezStateService = ezStateService; @@ -87,6 +112,7 @@ public UtilityViewModel(IUtilityService utilityService, IStateService stateServi _spEffectService = spEffectService; _flaskService = flaskService; _paramService = paramService; + _emevdService = emevdService; stateService.Subscribe(State.AppStart, OnAppStart); stateService.Subscribe(State.Loaded, OnGameLoaded); @@ -116,6 +142,7 @@ public UtilityViewModel(IUtilityService utilityService, IStateService stateServi OpenMirrorCommand = new DelegateCommand(OpenMirror); OpenSpiritTuningCommand = new DelegateCommand(OpenSpiritTuning); QuitoutCommand = new DelegateCommand(() => _utilityService.Quitout()); + BreakNearbyObjectsCommand = new DelegateCommand(BreakNearbyObjects); _allShops = DataLoader.GetShops(); FilteredShops = new ObservableCollection(); @@ -149,6 +176,7 @@ public UtilityViewModel(IUtilityService utilityService, IStateService stateServi public ICommand OpenMirrorCommand { get; } public ICommand QuitoutCommand { get; set; } public ICommand OpenSpiritTuningCommand { get; } + public ICommand BreakNearbyObjectsCommand { get; } #endregion @@ -1162,6 +1190,69 @@ private static List SetBitInAll(List originals, int mask, bool s return result; } + private void PatchShackleAtkParam() + { + var (tableIndex, slotIndex) = ParamIndices.All["AtkParam_Pc"]; + + nint row = _paramService.GetParamRow(tableIndex, slotIndex, ShackleRowId); + if (row == 0) return; + + _paramService.Write(row, AtkParamPcAtkObjOffset, 999); + _paramService.Write(row, AtkParamPcAppearAiSoundOffset, 0); + _paramService.Write(row, AtkParamPcHitAiSoundOffset, 0); + _paramService.Write(row, AtkParamPcAtkBehaviourOffset, 0); + } + + private void RevertShackleAtkParam() + { + var (tableIndex, slotIndex) = ParamIndices.All["AtkParam_Pc"]; + + nint row = _paramService.GetParamRow(tableIndex, slotIndex, ShackleRowId); + if (row == 0) return; + + _paramService.Write(row, AtkParamPcAtkObjOffset, AtkParamPcAtkObjVal); + _paramService.Write(row, AtkParamPcAppearAiSoundOffset, AtkParamPcAppearAiSoundVal); + _paramService.Write(row, AtkParamPcHitAiSoundOffset, AtkParamPcHitAiSoundVal); + _paramService.Write(row, AtkParamPcAtkBehaviourOffset, AtkParamPcAtkBehaviourVal); + } + + private void PatchUnusedBehaviourParam() + { + var (tableIndex, slotIndex) = ParamIndices.All["BehaviorParam_PC"]; + + nint row = _paramService.GetParamRow(tableIndex, slotIndex, ModifiedBehaviourRowId); + if (row == 0) return; + + _paramService.Write(row, ReferenceIdOffset, ShackleRowId); + } + + private void RevertUnusedBehaviourParam() + { + var (tableIndex, slotIndex) = ParamIndices.All["BehaviorParam_PC"]; + + nint row = _paramService.GetParamRow(tableIndex, slotIndex, ModifiedBehaviourRowId); + if (row == 0) return; + + _paramService.Write(row, ReferenceIdOffset, OriginalRowId); + } + + + private void BreakNearbyObjects() + { + var playerIns = _playerService.GetPlayerIns(); + if (playerIns == 0) return; + + PatchShackleAtkParam(); + PatchUnusedBehaviourParam(); + + _emevdService.ExecuteEmevdCommand(Emevd.EmevdCommands.ShootBullet(10000, 10000, 100, + ModifiedBehaviourRowId, 0, 1, 0)); + + Thread.Sleep(20); // sleep until bullet plays out + RevertShackleAtkParam(); + RevertUnusedBehaviourParam(); + } + #endregion } } \ No newline at end of file diff --git a/TarnishedTool/Views/Tabs/UtilityTab.xaml b/TarnishedTool/Views/Tabs/UtilityTab.xaml index fc7d435..b5cb696 100644 --- a/TarnishedTool/Views/Tabs/UtilityTab.xaml +++ b/TarnishedTool/Views/Tabs/UtilityTab.xaml @@ -85,6 +85,11 @@ IsEnabled="{Binding AreOptionsEnabled}" IsChecked="{Binding IsNoUpgradeCostEnabled}" Margin="15,0,0,0" /> +