fix wayland and allow save editing of equipped weapon

This commit is contained in:
CrafterPika 2026-06-27 08:36:30 +02:00
commit 0c56eb8b89
No known key found for this signature in database
GPG key ID: 68B3920DBA3C6C31
9 changed files with 147 additions and 7 deletions

View file

@ -200,5 +200,13 @@ namespace Func {
return "Game not fully loaded yet...";
}
}
public static string EquippedWep() {
try {
var p_SaveDataMgr = Program.readUInt32((uint)(Program.readUInt32(SaveEditor.SAVEDATAMGR_ROOT_PTR) + 0xC));
return $"{Program.readUInt32((uint)(p_SaveDataMgr + 0x18C))}";
} catch {
return "Game not fully loaded yet...";
}
}
}
}

View file

@ -72,9 +72,9 @@ namespace ModMenu {
public static bool IsWayland() {
string runtimeDir = Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR");
if (string.IsNullOrEmpty(runtimeDir)) return false;
if (string.IsNullOrEmpty(runtimeDir) || !Directory.Exists(runtimeDir)) return false;
return File.Exists(Path.Combine(runtimeDir, "wayland-0"));
return Directory.EnumerateFiles(runtimeDir, "wayland-*").Any();
}
[STAThread]
@ -188,7 +188,7 @@ namespace ModMenu {
Console.WriteLine($"Found target process: {targetProcess.ProcessName} (PID: {pid})");
if (cbase != 0) {
Console.WriteLine("SplatTool v3.2.0 by CrafterPika");
Console.WriteLine("SplatTool v3.2.1 by CrafterPika");
Console.WriteLine("Special Thanks: Winterberry, Javi.ig and Tombuntu, KittenTM.");
cbaseCorrected = (Program.cbase + 0xE000000) - 0x10000000;

View file

@ -153,6 +153,11 @@ namespace ModMenu {
Program.writeUInt32((uint)(p_save_start + 0xA5B4), amount);
}
public static void ChangeEquippedWeapon(uint WeaponSetID) {
var p_save_start = Program.readUInt32((uint)(Program.readUInt32(SAVEDATAMGR_ROOT_PTR) + 0xC));
Program.writeUInt32((uint)(p_save_start + 0x18C), WeaponSetID);
}
private static T ByteArrayToStructure<T>(byte[] bytes) where T : struct {
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try {

View file

@ -1 +1 @@
3.2.0
3.2.1

View file

@ -13,7 +13,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>3.2.0</string>
<string>3.2.1</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>

View file

@ -22,6 +22,7 @@ namespace ModMenu {
public static uint Level;
public static uint Cash;
public static uint SeaSnails;
public static uint WeaponSetID;
public static SessionData session = new SessionData();
static WorkThread sessiondIdThread = new WorkThread(() => {
Codes.forceSessiondId(sessionId);
@ -45,12 +46,16 @@ namespace ModMenu {
Thread.Sleep(5000);
SplatTelemetry.SendTelemetry();
});
static WorkThread WeaponChangeThread = new WorkThread(() => {
SaveEditor.ChangeEquippedWeapon(WeaponSetID);
});
public static string RunCode(ModMenuRequest data) {
if (data?.action == null) return "0";
switch (data.action) {
case "cbase":
return $"Cemu Base: 0x{Program.cbase:X} (0x{Program.cbaseCorrected:X})<br><br>Total Wins: {Codes.TotalWins()}<br>Total Losses: {Codes.TotalLoss()}<br><br>Thread Status:<br>- Write Gear: {WriteGear.Status.ToString()}<br>- Telemetry: {TelemetryThread.Status.ToString()}<br>- Change Gender: {ChangeGender.Status.ToString()}<br>- Change Level: {ChangeLevel.Status.ToString()}<br>- Change Cash: {ChangeCash.Status.ToString()}<br>- Change Sea Snails: {ChangeSeaSnails.Status.ToString()}";
return $"Cemu Base: 0x{Program.cbase:X} (0x{Program.cbaseCorrected:X})<br><br>Total Wins: {Codes.TotalWins()}<br>Total Losses: {Codes.TotalLoss()}<br>Equipped Weapon: {Codes.EquippedWep()}<br><br>Thread Status:<br>- Write Gear: {WriteGear.Status.ToString()}<br>- Telemetry: {TelemetryThread.Status.ToString()}<br>- Change Gender: {ChangeGender.Status.ToString()}<br>- Change Level: {ChangeLevel.Status.ToString()}<br>- Change Cash: {ChangeCash.Status.ToString()}<br>- Change Sea Snails: {ChangeSeaSnails.Status.ToString()}<br>- Change Weapon: {WeaponChangeThread.Status.ToString()}";
case "sessiondata":
return Codes.GetSessionData();
@ -130,6 +135,11 @@ namespace ModMenu {
HandleThread(TelemetryThread);
return "1";
case "WepChange":
WeaponSetID = UInt32.Parse(data.settings[0]);
HandleThread(WeaponChangeThread);
return "1";
default:
return "Not Found";
}

View file

@ -355,5 +355,98 @@
"109": "Ink Resistance Up",
"110": "Stealth Jump",
"111": "S_Abillity_Locked"
},
"WeaponSetIds": {
"1000": "Sploosh-o-matic",
"1001": "Neo Sploosh-o-matic",
"1002": "Sploosh-o-matic 7",
"1010": "Splattershot Jr.",
"1011": "Custom Splattershot Jr.",
"1020": "Splash-o-matic",
"1021": "Neo Splash-o-matic",
"1030": "Aerospray MG",
"1031": "Aerospray RG",
"1032": "Aerospray PG",
"1040": "Splattershot",
"1041": "Tentatek Splattershot",
"1042": "Wasabi Splattershot",
"1045": "Hero Shot Replica",
"1046": "Octoshot Replica",
"1050": ".52 Gal",
"1051": ".52 Gal Deco",
"1060": "N-ZAP '85",
"1061": "N-ZAP '89",
"1062": "N-ZAP '83",
"1070": "Splattershot Pro",
"1071": "Forge Splattershot Pro",
"1072": "Berry Splattershot Pro",
"1080": ".96 Gal",
"1081": ".96 Gal Deco",
"1090": "Dual Squelcher",
"1091": "Custom Dual Squelcher",
"1100": "Jet Squelcher",
"1101": "Custom Jet Squelcher",
"1110": "Luna Blaster",
"1111": "Luna Blaster Neo",
"1120": "Blaster",
"1121": "Custom Blaster",
"1130": "Range Blaster",
"1131": "Custom Range Blaster",
"1132": "Grim Range Blaster",
"1140": "Rapid Blaster",
"1141": "Rapid Blaster Deco",
"1150": "Rapid Blaster Pro",
"1151": "Rapid Blaster Pro Deco",
"1160": "L-3 Nozzlenose",
"1161": "L-3 Nozzlenose D",
"1170": "H-3 Nozzlenose",
"1171": "H-3 Nozzlenose D",
"1172": "Cherry H-3 Nozzlenose",
"2000": "Carbon Roller",
"2001": "Carbon Roller Deco",
"2010": "Splat Roller",
"2011": "Krak-On Splat Roller",
"2012": "CoroCoro Splat Roller",
"2015": "Hero Roller Replica",
"2020": "Dynamo Roller",
"2021": "Gold Dynamo Roller",
"2022": "Tempered Dynamo Roller",
"2030": "Inkbrush",
"2031": "Inkbrush Nouveau",
"2032": "Permanent Inkbrush",
"2040": "Octobrush",
"2041": "Octobrush Nouveau",
"3000": "Slosher",
"3001": "Slosher Deco",
"3002": "Soda Slosher",
"3010": "Tri-Slosher",
"3011": "Tri-Slosher Nouveau",
"3020": "Sloshing Machine",
"3021": "Sloshing Machine Neo",
"4000": "Classic Squiffer",
"4001": "New Squiffer",
"4002": "Fresh Squiffer",
"4010": "Splat Charger",
"4011": "Kelp Splat Charger",
"4012": "Bento Splat Charger",
"4015": "Hero Charger Replica",
"4020": "Splatterscope",
"4021": "Kelp Splatterscope",
"4022": "Bento Splatterscope",
"4030": "E-liter 3K",
"4031": "Custom E-liter 3K",
"4040": "E-liter 3K Scope",
"4041": "Custom E-liter 3K Scope",
"4050": "Bamboozler 14 Mk I",
"4051": "Bamboozler 14 Mk II",
"4052": "Bamboozler 14 Mk III",
"5000": "Mini Splatling",
"5001": "Zink Mini Splatling",
"5002": "Refurbished Mini Splatling",
"5010": "Heavy Splatling",
"5011": "Heavy Splatling Deco",
"5012": "Heavy Splatling Remix",
"5020": "Hydra Splatling",
"5021": "Custom Hydra Splatling"
}
}

View file

@ -118,6 +118,16 @@
<button class="action-btn" onclick="SeaSnails()">Toggle Thread</button>
</div>
</div>
<div class="input-row">
<div class="label-stack">
<span class="input-label">Change Weapon:</span>
<span class="input-note">Changes Equipped Weapon.</span>
</div>
<div class="input-group">
<select id="weapon-sets" class="dropdown" style="flex: 1;"></select>
<button class="action-btn" onclick="changeWeapon()">Toggle Thread</button>
</div>
</div>
</div>
</div>
@ -177,7 +187,7 @@
<div id="Tab7" class="tab-content">
<div class="profile-card">
<h3 style="margin-top: 0;">SplatTool v3.2.0</h3>
<h3 style="margin-top: 0;">SplatTool v3.2.1</h3>
<div>Written by CrafterPika</div>
<div>Special Thanks: Winterberry, Javi.ig, Tombuntu, KittenTM, apoplexy</div>
</div>

View file

@ -73,6 +73,17 @@ function populateAbilities() {
});
}
function populateWeaponSets() {
const select = document.getElementById("weapon-sets");
select.innerHTML = '';
for (const [val, name] of Object.entries(gearData.WeaponSetIds)) {
const opt = document.createElement('option');
opt.value = val;
opt.textContent = name;
select.appendChild(opt);
}
}
window.external.receiveMessage(message => {
// console.log(message)
if (message.startsWith("Cemu Base:")) {
@ -212,12 +223,15 @@ function openTab(evt, tabName) {
if (tabName === 'Tab6') {
keepStatsUpdated = true;
updateStatsPage();
} else if (tabName == 'Tab8') {
populateWeaponSets()
} else {
keepStatsUpdated = false;
}
}
function namechange() { sendToCSharp("namechange", [document.getElementById("name-input").value]); }
function changeWeapon() { sendToCSharp("WepChange", [document.getElementById("weapon-sets").value]); }
function sessionid() { sendToCSharp("sessionid", [document.getElementById("session-input").value]); }
function faceimgtga() { sendToCSharp("faceimgtga", [document.getElementById("format-select").value]); }
function GenderChange() { sendToCSharp("ChangeGender", [document.getElementById("gender-select").value]); }