|
|
|
@ -0,0 +1,457 @@ |
|
|
|
|
using System; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Net.Sockets; |
|
|
|
|
using System.Text; |
|
|
|
|
using System.Text.RegularExpressions; |
|
|
|
|
using System.Threading; |
|
|
|
|
using System.Windows; |
|
|
|
|
using System.Windows.Controls; |
|
|
|
|
using System.Windows.Data; |
|
|
|
|
using System.Windows.Documents; |
|
|
|
|
using System.Windows.Input; |
|
|
|
|
using System.Windows.Media; |
|
|
|
|
using System.Windows.Media.Imaging; |
|
|
|
|
using System.Windows.Navigation; |
|
|
|
|
using System.Windows.Shapes; |
|
|
|
|
using System.Windows.Threading; |
|
|
|
|
|
|
|
|
|
namespace rabi_splitter_WPF |
|
|
|
|
{ |
|
|
|
|
/// <summary> |
|
|
|
|
/// MainWindow.xaml 的交互逻辑 |
|
|
|
|
/// </summary> |
|
|
|
|
public partial class MainWindow : Window |
|
|
|
|
{ |
|
|
|
|
private MainContext mainContext; |
|
|
|
|
private DebugContext debugContext; |
|
|
|
|
private static TcpClient tcpclient; |
|
|
|
|
private static NetworkStream networkStream; |
|
|
|
|
private readonly Regex titleReg = new Regex(@"ver.*?(\d+\.?\d+.*)$"); |
|
|
|
|
private readonly Thread memoryThread; |
|
|
|
|
private void ReadMemory() |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
var processlist = Process.GetProcessesByName("rabiribi"); |
|
|
|
|
if (processlist.Length > 0) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
Process process = processlist[0]; |
|
|
|
|
if (process.MainWindowTitle != mainContext.oldtitle) |
|
|
|
|
{ |
|
|
|
|
var result = titleReg.Match(process.MainWindowTitle); |
|
|
|
|
string rabiver; |
|
|
|
|
if (result.Success) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
rabiver = result.Groups[1].Value; |
|
|
|
|
mainContext.veridx = Array.IndexOf(StaticData.VerNames, rabiver); |
|
|
|
|
if (mainContext.veridx < 0) |
|
|
|
|
{ |
|
|
|
|
mainContext.GameVer = rabiver + " Running (not support)"; |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
mainContext.veridx = -1; |
|
|
|
|
mainContext.GameVer = "Running (Unknown version)"; |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
mainContext.GameVer = rabiver + " Running"; |
|
|
|
|
mainContext.oldtitle = process.MainWindowTitle; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mainContext.veridx < 0) return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region read igt |
|
|
|
|
|
|
|
|
|
int igt = MemoryHelper.GetMemoryValue<int>(process, StaticData.IGTAddr[mainContext.veridx]); |
|
|
|
|
if (igt > 0 && mainContext.Igt) |
|
|
|
|
{ |
|
|
|
|
sendigt((float)igt / 60); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endregion |
|
|
|
|
|
|
|
|
|
#region CheckMoney |
|
|
|
|
|
|
|
|
|
if (mainContext.Computer) |
|
|
|
|
{ |
|
|
|
|
var newmoney = MemoryHelper.GetMemoryValue<int>(process, StaticData.MoneyAddress[mainContext.veridx]); |
|
|
|
|
if (newmoney - mainContext.lastmoney == 17500) |
|
|
|
|
{ |
|
|
|
|
sendsplit(); |
|
|
|
|
DebugLog("get 17500 en, split"); |
|
|
|
|
} |
|
|
|
|
mainContext.lastmoney = newmoney; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endregion |
|
|
|
|
|
|
|
|
|
int mapid = MemoryHelper.GetMemoryValue<int>(process, StaticData.MapAddress[mainContext.veridx]); |
|
|
|
|
if (mainContext.lastmapid != mapid) |
|
|
|
|
{ |
|
|
|
|
DebugLog("newmap: " + mapid + ":" + StaticData.MapNames[mapid]); |
|
|
|
|
mainContext.lastmapid = mapid; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region checkTM |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endregion |
|
|
|
|
|
|
|
|
|
#region Music |
|
|
|
|
|
|
|
|
|
int musicaddr = StaticData.MusicAddr[mainContext.veridx]; |
|
|
|
|
int musicid = MemoryHelper.GetMemoryValue<int>(process, musicaddr); |
|
|
|
|
if (musicid > 0 && musicid < StaticData.MusicNames.Length) |
|
|
|
|
{ |
|
|
|
|
if (mainContext.lastmusicid != musicid) |
|
|
|
|
{ |
|
|
|
|
DebugLog("new music:" + musicid + ":" + StaticData.MusicNames[musicid]); |
|
|
|
|
mainContext.GameMusic = StaticData.MusicNames[musicid]; |
|
|
|
|
|
|
|
|
|
var bossmusicflag = StaticData.BossMusics.Contains(musicid); |
|
|
|
|
if (bossmusicflag) |
|
|
|
|
{ |
|
|
|
|
if (mainContext.bossbattle) |
|
|
|
|
{ |
|
|
|
|
//直接换boss曲 |
|
|
|
|
if (mainContext.MusicStart || mainContext.MusicEnd) |
|
|
|
|
{ |
|
|
|
|
sendsplit(); |
|
|
|
|
DebugLog("new boss music, split"); |
|
|
|
|
} |
|
|
|
|
debugContext.BossEvent = true; |
|
|
|
|
mainContext.lastmusicid = musicid; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!mainContext.bossbattle) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
if (musicid == 54 && mainContext.AliusI) |
|
|
|
|
{ |
|
|
|
|
mainContext.bossbattle = false; |
|
|
|
|
debugContext.BossEvent = false; |
|
|
|
|
mainContext.AliusI = false; |
|
|
|
|
DebugLog("Alius music, ignore once"); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (musicid == 42 && mapid == 1 && mainContext.Irisu1) |
|
|
|
|
{ |
|
|
|
|
mainContext.bossbattle = false; |
|
|
|
|
debugContext.BossEvent = false; |
|
|
|
|
DebugLog("Irisu P1, ignore"); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
if (bossmusicflag) |
|
|
|
|
{ |
|
|
|
|
if (mapid == 5 && musicid == 44 && mainContext.SideCh) |
|
|
|
|
{ |
|
|
|
|
mainContext.bossbattle = false; |
|
|
|
|
debugContext.BossEvent = false; |
|
|
|
|
DebugLog("sidechapter, ignore"); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
mainContext.bossbattle = true; |
|
|
|
|
debugContext.BossEvent = true; |
|
|
|
|
mainContext.lastbosslist = new List<int>(); |
|
|
|
|
mainContext.lastnoah3hp = -1; |
|
|
|
|
if (mainContext.MusicStart) |
|
|
|
|
{ |
|
|
|
|
sendsplit(); |
|
|
|
|
DebugLog("music start, split"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
if (!bossmusicflag) //boss music end! |
|
|
|
|
{ |
|
|
|
|
mainContext.bossbattle = false; |
|
|
|
|
if (mainContext.MusicEnd) |
|
|
|
|
{ |
|
|
|
|
sendsplit(); |
|
|
|
|
DebugLog("music end, split"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
mainContext.lastmusicid = musicid; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
mainContext.GameMusic = "N/A"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endregion Music |
|
|
|
|
|
|
|
|
|
#region SpecialBOSS |
|
|
|
|
|
|
|
|
|
if (mainContext.bossbattle) |
|
|
|
|
{ |
|
|
|
|
if (mainContext.MiruDe || false)//todo noah3 option |
|
|
|
|
{ |
|
|
|
|
int Noah3HP = -1; |
|
|
|
|
|
|
|
|
|
if (mapid >= 0 && mapid < StaticData.MapNames.Length) |
|
|
|
|
{ |
|
|
|
|
int ptr = MemoryHelper.GetMemoryValue<int>(process, StaticData.EnenyPtrAddr[mainContext.veridx]); |
|
|
|
|
List<int> bosses = new List<int>(); |
|
|
|
|
for (var i = 0; i < 50; i++) |
|
|
|
|
{ |
|
|
|
|
ptr = ptr + StaticData.EnenyEntitySize[mainContext.veridx]; |
|
|
|
|
|
|
|
|
|
var emyid = MemoryHelper.GetMemoryValue<int>(process, |
|
|
|
|
ptr + StaticData.EnenyEnitiyIDOffset[mainContext.veridx], false); |
|
|
|
|
if (StaticData.BossNames.ContainsKey(emyid)) |
|
|
|
|
{ |
|
|
|
|
bosses.Add(emyid); |
|
|
|
|
if (emyid == 1053) |
|
|
|
|
{ |
|
|
|
|
Noah3HP = MemoryHelper.GetMemoryValue<int>(process, |
|
|
|
|
ptr + StaticData.EnenyEnitiyHPOffset[mainContext.veridx], false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (mainContext.MiruDe) |
|
|
|
|
{ |
|
|
|
|
foreach (var boss in mainContext.lastbosslist) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
if (boss == 1043) |
|
|
|
|
{ |
|
|
|
|
if (!bosses.Contains(boss)) //despawn |
|
|
|
|
{ |
|
|
|
|
sendsplit(); |
|
|
|
|
DebugLog("miru despawn, split"); |
|
|
|
|
mainContext.bossbattle = false; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// if (cbBoss3.Checked) |
|
|
|
|
// { |
|
|
|
|
// if (bosses.Contains(1053) && Noah3HP < lastnoah3hp && Noah3HP == 1) |
|
|
|
|
// { |
|
|
|
|
// sendsplit(); |
|
|
|
|
// DebugLog("noah3 hp 1, split"); |
|
|
|
|
// bossbattle = false; |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
if (mainContext.Tm2 && musicid == 8) |
|
|
|
|
{ |
|
|
|
|
bool f = true; |
|
|
|
|
foreach (var boss in mainContext.lastbosslist) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
if (boss == 1024) |
|
|
|
|
{ |
|
|
|
|
if (!bosses.Contains(boss)) //despawn |
|
|
|
|
{ |
|
|
|
|
sendsplit(); |
|
|
|
|
DebugLog("nixie despawn, split"); |
|
|
|
|
mainContext.bossbattle = false; |
|
|
|
|
f = false; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int newTM = MemoryHelper.GetMemoryValue<int>(process, StaticData.TownMemberAddr[mainContext.veridx]); |
|
|
|
|
if (newTM - mainContext.lastTM == 1 && f) //for after 1.71 , 1.71 isn't TM+2 at once when skip Nixie, it's TM+1 twice |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
if (DateTime.Now - mainContext.LastTMAddTime < TimeSpan.FromSeconds(1)) |
|
|
|
|
{ |
|
|
|
|
var d = DateTime.Now - mainContext.LastTMAddTime; |
|
|
|
|
mainContext.bossbattle = false; |
|
|
|
|
sendsplit(); |
|
|
|
|
DebugLog("TM+2 in " + d.TotalMilliseconds + " ms, split"); |
|
|
|
|
} |
|
|
|
|
mainContext.LastTMAddTime = DateTime.Now; |
|
|
|
|
} |
|
|
|
|
else if (newTM - mainContext.lastTM == 2 && f)//for 1.65-1.70 |
|
|
|
|
{ |
|
|
|
|
mainContext.bossbattle = false; |
|
|
|
|
sendsplit(); |
|
|
|
|
DebugLog("TM+2, split"); |
|
|
|
|
} |
|
|
|
|
mainContext.lastTM = newTM; |
|
|
|
|
} |
|
|
|
|
mainContext.lastbosslist = bosses; |
|
|
|
|
mainContext.lastnoah3hp = Noah3HP; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endregion SpecialBOSS |
|
|
|
|
|
|
|
|
|
if (mainContext.DebugArea) |
|
|
|
|
{ |
|
|
|
|
int ptr = MemoryHelper.GetMemoryValue<int>(process, StaticData.EnenyPtrAddr[mainContext.veridx]); |
|
|
|
|
// List<int> bosses = new List<int>(); |
|
|
|
|
// List<int> HPS = new List<int>(); |
|
|
|
|
debugContext.BossList.Clear(); |
|
|
|
|
// ptr += StaticData.EnenyEntitySize[mainContext.veridx] * 3; |
|
|
|
|
for (var i = 0; i < 50; i++) |
|
|
|
|
{ |
|
|
|
|
ptr += StaticData.EnenyEntitySize[mainContext.veridx]; |
|
|
|
|
|
|
|
|
|
debugContext.BossList.Add(new BossData() |
|
|
|
|
{ |
|
|
|
|
BossIdx = i, |
|
|
|
|
BossID = MemoryHelper.GetMemoryValue<int>(process, |
|
|
|
|
ptr + StaticData.EnenyEnitiyIDOffset[mainContext.veridx], false), |
|
|
|
|
BossHP = MemoryHelper.GetMemoryValue<int>(process, |
|
|
|
|
ptr + StaticData.EnenyEnitiyHPOffset[mainContext.veridx], false) |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// this.Invoke(new Action(() => |
|
|
|
|
// { |
|
|
|
|
// t1.Text = string.Join("\n", bosses); |
|
|
|
|
// t2.Text = string.Join("\n", HPS); |
|
|
|
|
// })); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
debugContext.BossEvent = mainContext.bossbattle; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
mainContext.oldtitle = ""; |
|
|
|
|
|
|
|
|
|
mainContext.GameVer = "Not Found"; |
|
|
|
|
mainContext.GameMusic = "N/A"; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void DebugLog(string log) |
|
|
|
|
{ |
|
|
|
|
this.debugContext.DebugLog += log + "\n"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void sendsplit() |
|
|
|
|
{ |
|
|
|
|
if (tcpclient != null && tcpclient.Connected) |
|
|
|
|
{ |
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
var b = Encoding.UTF8.GetBytes("split\r\n"); |
|
|
|
|
networkStream.Write(b, 0, b.Length); |
|
|
|
|
} |
|
|
|
|
catch (Exception) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
disconnect(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void sendigt(float time) |
|
|
|
|
{ |
|
|
|
|
if (tcpclient != null && tcpclient.Connected) |
|
|
|
|
{ |
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
var b = Encoding.UTF8.GetBytes($"setgametime {time}\r\n"); |
|
|
|
|
networkStream.Write(b, 0, b.Length); |
|
|
|
|
} |
|
|
|
|
catch (Exception) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
disconnect(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
void disconnect() |
|
|
|
|
{ |
|
|
|
|
tcpclient = null; |
|
|
|
|
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => |
|
|
|
|
{ |
|
|
|
|
BtnConnect.IsEnabled = true; |
|
|
|
|
})); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public MainWindow() |
|
|
|
|
{ |
|
|
|
|
InitializeComponent(); |
|
|
|
|
mainContext=new MainContext(); |
|
|
|
|
debugContext=new DebugContext(); |
|
|
|
|
this.DataContext = mainContext; |
|
|
|
|
DebugPanel.DataContext = debugContext; |
|
|
|
|
memoryThread = new Thread(() => |
|
|
|
|
{ |
|
|
|
|
while (true) |
|
|
|
|
{ |
|
|
|
|
ReadMemory(); |
|
|
|
|
Thread.Sleep(1000 / 60); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}); |
|
|
|
|
memoryThread.IsBackground = true; |
|
|
|
|
memoryThread.Start(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void BtnConnect_Click(object sender, RoutedEventArgs e) |
|
|
|
|
{ |
|
|
|
|
if (tcpclient != null && tcpclient.Connected) return; |
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
tcpclient = new TcpClient("127.0.0.1", Convert.ToInt32(mainContext.ServerPort)); |
|
|
|
|
networkStream = tcpclient.GetStream(); |
|
|
|
|
this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => |
|
|
|
|
{ |
|
|
|
|
BtnConnect.IsEnabled = false; |
|
|
|
|
})); |
|
|
|
|
} |
|
|
|
|
catch (Exception) |
|
|
|
|
{ |
|
|
|
|
tcpclient = null; |
|
|
|
|
networkStream = null; |
|
|
|
|
MessageBox.Show(this, "Connect Failed"); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e) |
|
|
|
|
{ |
|
|
|
|
Process.Start("https://github.com/copyliu/rabiribi_splitter"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |