Experimental stuff for now. Don't think too much about it. Branched off Rabi-Ribi Autosplitter.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rabiribi-display/rabi_splitter_WPF/MainWindow.xaml.cs

515 lines
19 KiB

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];
if ((musicid == 45 || musicid == 46 || musicid == 53) && mainContext.AutoReset)
{
DebugLog("Title music, reset");
//reset
sendreset();
mainContext.AliusI = true;
mainContext.Noah1Reload = false;
mainContext.bossbattle = false;
}
else
{
var bossmusicflag = StaticData.BossMusics.Contains(musicid);
if (bossmusicflag)
{
if (mainContext.bossbattle)
{
if (mainContext.Noah1Reload && (mainContext.lastmusicid == 52 || musicid == 52))
{
DebugLog("noah 1 reload? ignore");
}
else
{
if (mainContext.MusicStart || mainContext.MusicEnd)
{
sendsplit();
DebugLog("new boss music, split");
}
if (musicid == 37)
{
mainContext.Noah1Reload = true;
DebugLog("noah1 music start, ignore MR forever");
}
}
mainContext.lastmusicid = musicid;
return;
}
}
if (!mainContext.bossbattle)
{
if (musicid == 54 && mainContext.AliusI)
{
mainContext.bossbattle = false;
mainContext.AliusI = false;
DebugLog("Alius music, ignore once");
}
else if (musicid == 42 && mapid == 1 && mainContext.Irisu1)
{
mainContext.bossbattle = false;
DebugLog("Irisu P1, ignore");
}
else
{
if (bossmusicflag)
{
if (mapid == 5 && musicid == 44 && mainContext.SideCh)
{
mainContext.bossbattle = false;
DebugLog("sidechapter, ignore");
}
else
{
mainContext.bossbattle = true;
mainContext.lastbosslist = new List<int>();
mainContext.lastnoah3hp = -1;
if (musicid == 37)
{
mainContext.Noah1Reload = true;
DebugLog("noah1 music start, ignore MR forever");
}
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 && mapid==8)
{
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>();
// this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => debugContext.BossList.Clear()));
// ptr += StaticData.EnenyEntitySize[mainContext.veridx] * 3;
for (var i = 0; i < 50; i++)
{
ptr += StaticData.EnenyEntitySize[mainContext.veridx];
debugContext.BossList[i].BossID = MemoryHelper.GetMemoryValue<int>(process,
ptr + StaticData.EnenyEnitiyIDOffset[mainContext.veridx], false);
debugContext.BossList[i].BossHP = MemoryHelper.GetMemoryValue<int>(process,
ptr + StaticData.EnenyEnitiyHPOffset[mainContext.veridx], false);
}
}
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 sendreset()
{
if (tcpclient != null && tcpclient.Connected)
{
try
{
var b = Encoding.UTF8.GetBytes("reset\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;
this.Grid.ItemsSource = debugContext.BossList;
BossEventDebug.DataContext = debugContext;
memoryThread = new Thread(() =>
{
while (true)
{
try
{
ReadMemory();
}
catch (Exception e)
{
DebugLog(e.ToString());
}
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");
}
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var s = sender as TextBox;
if (s != null)
{
s.ScrollToEnd();
}
}
}
}