Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions TarnishedTool/GameIds/Emevd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
2 changes: 1 addition & 1 deletion TarnishedTool/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
93 changes: 92 additions & 1 deletion TarnishedTool/ViewModels/UtilityViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -36,15 +37,18 @@ 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;
public const int MaterialId04Offset = 0xc;
public const int MaterialId05Offset = 0x10;
public const int MaterialId06Offset = 0x14;
*/

public const int ItemNum01Offset = 0x20;
private List<byte[]>? _originalMaterialIds;
private List<byte[]>? _originalItemNums;
Expand All @@ -67,6 +71,26 @@ public class UtilityViewModel : BaseViewModel
private List<byte[]>? _originalProtectorDiscard;
private List<byte[]>? _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> _equipMtrlUpgrades = DataLoader.GetEquipMtrlUpgrades();
private readonly Dictionary<uint, (int Material, int ItemNum)> _originalEquipMtrlUpgradeMaterials = new();
Expand All @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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<ShopCommand>();
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -1162,6 +1190,69 @@ private static List<byte[]> SetBitInAll(List<byte[]> 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
}
}
5 changes: 5 additions & 0 deletions TarnishedTool/Views/Tabs/UtilityTab.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@
IsEnabled="{Binding AreOptionsEnabled}"
IsChecked="{Binding IsNoUpgradeCostEnabled}"
Margin="15,0,0,0" />
<Button Content="Break Nearby Objects"
IsEnabled="{Binding AreOptionsEnabled}"
Padding="5,3"
Command="{Binding BreakNearbyObjectsCommand}"
Margin="15,0,20,0" />

</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,10,0,0">
Expand Down