Implement a lot of other functionality. Still very experimental at this stage

rabi_display
wcko87 8 years ago
parent d4fa840616
commit 1f4fd18662
  1. 114
      rabi_splitter_WPF/MainContext.cs
  2. 30
      rabi_splitter_WPF/MainWindow.xaml
  3. 2
      rabi_splitter_WPF/MainWindow.xaml.cs
  4. 154
      rabi_splitter_WPF/MemorySnapshot.cs
  5. 66
      rabi_splitter_WPF/RabiEnums.cs
  6. 18
      rabi_splitter_WPF/RabiGameState.cs
  7. 140
      rabi_splitter_WPF/RabiRibiDisplay.cs
  8. 83
      rabi_splitter_WPF/StaticData.cs

@ -31,6 +31,55 @@ namespace rabi_splitter_WPF
#endregion
}
public class EntityStatsData : INotifyPropertyChanged
{
private int _addr;
private int _intval;
private float _floatval;
public int Addr
{
get { return _addr; }
set
{
if (value == _addr) return;
_addr = value;
OnPropertyChanged(nameof(Addr));
}
}
public int IntVal
{
get { return _intval; }
set
{
if (value == _intval) return;
_intval = value;
OnPropertyChanged(nameof(IntVal));
}
}
public float FloatVal
{
get { return _floatval; }
set
{
if (value == _floatval) return;
_floatval = value;
OnPropertyChanged(nameof(FloatVal));
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class BossData:INotifyPropertyChanged
{
private int _bossIdx;
@ -81,13 +130,26 @@ namespace rabi_splitter_WPF
class DebugContext : INotifyPropertyChanged
{
private int _entityAnalysisIndex;
private bool _bossEvent;
private string _debugLog;
public ObservableCollection<BossData> BossList = new ObservableCollection<BossData>();
public ObservableCollection<EntityStatsData> EntityStatsListData = new ObservableCollection<EntityStatsData>();
public int targetEntityListSize;
public ObservableCollection<EntityStatsData> EntityStatsListView
{
get
{
return EntityStatsListData;
}
}
public DebugContext()
{
this.EntityAnalysisIndex = 0;
BossList =new ObservableCollection<BossData>();
for (int i = 0; i < 50; i++)
{
@ -96,6 +158,22 @@ namespace rabi_splitter_WPF
BossIdx = i
});
}
while (EntityStatsListData.Count < 449)
{
EntityStatsListData.Add(new EntityStatsData() { Addr = EntityStatsListData.Count * 4 });
}
}
public int EntityAnalysisIndex
{
get { return _entityAnalysisIndex; }
set
{
if (value == _entityAnalysisIndex) return;
_entityAnalysisIndex = value;
OnPropertyChanged(nameof(EntityAnalysisIndex));
}
}
public bool BossEvent
@ -159,6 +237,9 @@ namespace rabi_splitter_WPF
private string _text13;
private string _text14;
private string _text15;
private string _text16;
private string _text17;
private string _text18;
public string Text1
{
@ -325,6 +406,39 @@ namespace rabi_splitter_WPF
}
}
public string Text16
{
get { return _text16; }
set
{
if (value == _text16) return;
_text16 = value;
OnPropertyChanged(nameof(Text16));
}
}
public string Text17
{
get { return _text17; }
set
{
if (value == _text17) return;
_text17 = value;
OnPropertyChanged(nameof(Text17));
}
}
public string Text18
{
get { return _text18; }
set
{
if (value == _text18) return;
_text18 = value;
OnPropertyChanged(nameof(Text18));
}
}
public int ServerPort
{
get { return _serverPort; }

@ -16,7 +16,7 @@
<TextBlock Text="GitHub" MouseUp="TextBlock_MouseUp" Cursor="Hand" Foreground="Blue" TextDecorations="Underline" VerticalAlignment="Top" />
</StackPanel>
<DockPanel Margin="5" DockPanel.Dock="Top">
<StackPanel Margin="0,0,100,0" Width="356">
<StackPanel Margin="0,0,0,0" Width="500">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,0,3">
<TextBlock TextWrapping="Wrap" Text="LiveSplit Server Port" VerticalAlignment="Center" FontSize="16" Margin="0,0,10,0"/>
<TextBox TextWrapping="Wrap" Text="{Binding ServerPort}" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalContentAlignment="Center" FontSize="16" Padding="6,0"/>
@ -26,14 +26,14 @@
<TextBlock TextWrapping="Wrap" Text="Rabi-Ribi Status:" FontSize="16"/>
<TextBlock TextWrapping="Wrap" Text="{Binding GameVer}" FontSize="16"/>
</StackPanel>
<Grid Height="280">
<Grid Height="500">
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="3*"/>
<RowDefinition Height="3*"/>
<RowDefinition Height="3*"/>
<RowDefinition Height="3*"/>
<RowDefinition Height="3*"/>
<RowDefinition Height="15*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
@ -56,12 +56,30 @@
<TextBlock Grid.Row="3" Grid.Column="1" TextWrapping="Wrap" Text="{Binding Text11}" FontSize="16"/>
<TextBlock Grid.Row="3" Grid.Column="2" TextWrapping="Wrap" Text="{Binding Text12}" FontSize="16"/>
<TextBlock Grid.Row="4" Grid.Column="0" TextWrapping="Wrap" Text="{Binding Text13}" FontSize="16"/>
<TextBlock Grid.Row="4" Grid.Column="1" TextWrapping="Wrap" Text="{Binding Text14}" FontSize="16"/>
<TextBlock Grid.Row="4" Grid.Column="2" TextWrapping="Wrap" Text="{Binding Text15}" FontSize="16"/>
<TextBlock Grid.Row="4" Grid.ColumnSpan="2" Grid.Column="0" TextWrapping="Wrap" Text="{Binding Text13}" FontSize="16"/>
<TextBlock Grid.Row="4" Grid.Column="2" TextWrapping="Wrap" Text="{Binding Text14}" FontSize="16"/>
<ScrollViewer Grid.Row="5" Grid.ColumnSpan="2" Grid.Column="0" >
<TextBlock TextWrapping="Wrap" Text="{Binding Text16}" FontSize="16"/>
</ScrollViewer>
<TextBlock Grid.Row="5" Grid.Column="2" TextWrapping="Wrap" Text="{Binding Text17}" FontSize="16"/>
</Grid>
</StackPanel>
<DockPanel x:Name="EntityDataPanel" d:DataContext="{d:DesignData local:DebugContext}">
<TextBox Width="100" DockPanel.Dock="Top" TextWrapping="Wrap" Text="{Binding EntityAnalysisIndex}" VerticalAlignment="Center" HorizontalAlignment="Center" VerticalContentAlignment="Center" FontSize="16" Padding="0,0"/>
<DataGrid Width="250" x:Name="EntityStats" ItemsSource="{Binding EntityStatsListView}" CanUserAddRows="False" IsReadOnly="True" AutoGenerateColumns="False" SelectionUnit="FullRow"
d:DataContext="{d:DesignData local:EntityStatsData}">
<DataGrid.Columns>
<DataGridTextColumn Width="2*" Binding="{Binding Addr}" ClipboardContentBinding="{Binding Addr}" Header="Addr"/>
<DataGridTextColumn Width="3*" Binding="{Binding IntVal}" ClipboardContentBinding="{Binding IntVal}" Header="int"/>
<DataGridTextColumn Width="3*" Binding="{Binding FloatVal}" ClipboardContentBinding="{Binding FloatVal}" Header="float"/>
</DataGrid.Columns>
</DataGrid>
<!--<ScrollViewer Width="250">
<TextBlock TextWrapping="Wrap" Text="{Binding Text18}" FontSize="16"/>
</ScrollViewer>-->
</DockPanel>
<DockPanel>
<TextBlock TextWrapping="Wrap" Text="debug area" Height="15.24" Width="352.251" DockPanel.Dock="Top"/>
<CheckBox x:Name="BossEventDebug" IsEnabled="False" Content="(DEBUG)BOSS event tracked" FontSize="15" VerticalAlignment="Top" HorizontalAlignment="Left" IsChecked="{Binding BossEvent, Mode=TwoWay}" DockPanel.Dock="Top"/>

@ -113,6 +113,8 @@ namespace rabi_splitter_WPF
this.DataContext = mainContext;
DebugPanel.DataContext = debugContext;
this.Grid.ItemsSource = debugContext.BossList;
EntityDataPanel.DataContext = debugContext;
this.EntityStats.ItemsSource = debugContext.EntityStatsListView;
BossEventDebug.DataContext = debugContext;
rabiRibiDisplay = new RabiRibiDisplay(mainContext, debugContext, this);
memoryThread = new Thread(() =>

@ -6,6 +6,15 @@ using System.Text;
namespace rabi_splitter_WPF
{
struct BossStats
{
public int entityArrayIndex;
public int id;
public Boss type;
public int hp;
public int maxHp;
}
class MemorySnapshot
{
public readonly int t_playtime;
@ -17,7 +26,9 @@ namespace rabi_splitter_WPF
public readonly int hp;
public readonly int maxhp;
public readonly int entityArrayPtr;
public readonly int currentSprite;
public readonly int actionFrame;
public readonly int animationFrame;
public readonly float amulet;
public readonly int boost;
@ -27,6 +38,23 @@ namespace rabi_splitter_WPF
public readonly float px;
public readonly float py;
public readonly int entityArrayPtr;
public readonly int entityArraySize;
public readonly int nActiveEntities;
public readonly List<BossStats> bossList;
public readonly int carrotXp;
public readonly int hammerXp;
public readonly int ribbonXp;
public readonly float itemPercent;
public readonly int nAttackUps;
public readonly int nHpUps;
public readonly int nManaUps;
public readonly int nPackUps;
public readonly int nRegenUps;
public MemorySnapshot(Process process, int veridx)
{
t_playtime = MemoryHelper.GetMemoryValue<int>(process, StaticData.IGTAddr[veridx]);
@ -37,11 +65,26 @@ namespace rabi_splitter_WPF
musicid = MemoryHelper.GetMemoryValue<int>(process, StaticData.MusicAddr[veridx]);
money = MemoryHelper.GetMemoryValue<int>(process, StaticData.MoneyAddress[veridx]);
carrotXp = MemoryHelper.GetMemoryValue<int>(process, 0xD654BC);
hammerXp = MemoryHelper.GetMemoryValue<int>(process, 0xD654B4);
ribbonXp = MemoryHelper.GetMemoryValue<int>(process, 0xD654B8);
itemPercent = MemoryHelper.GetMemoryValue<int>(process, 0xA730E8);
nAttackUps = countItems(process, 0xD6352C, 0xD63628);
nHpUps = countItems(process, 0xD6342C, 0xD63528);
nManaUps = countItems(process, 0xD6362C, 0xD63728);
nPackUps = countItems(process, 0xD6382C, 0xD63928);
nRegenUps = countItems(process, 0xD6372C, 0xD63828);
entityArrayPtr = MemoryHelper.GetMemoryValue<int>(process, StaticData.EnenyPtrAddr[veridx]);
hp = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x4D8, false);
maxhp = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x4E8, false);
currentSprite = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x654, false);
actionFrame = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x660, false);
animationFrame = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x67c, false);
amulet = MemoryHelper.GetMemoryValue<float>(process, entityArrayPtr + 0x52C, false);
boost = MemoryHelper.GetMemoryValue<int>(process, entityArrayPtr + 0x5DC, false);
mana = MemoryHelper.GetMemoryValue<float>(process, entityArrayPtr + 0x6B8, false);
@ -49,6 +92,57 @@ namespace rabi_splitter_WPF
px = MemoryHelper.GetMemoryValue<float>(process, entityArrayPtr + 0xC, false);
py = MemoryHelper.GetMemoryValue<float>(process, entityArrayPtr + 0x10, false);
// Read Entity Array and Search for boss data
bossList = new List<BossStats>();
nActiveEntities = 0;
entityArraySize = 4;
int entitySize = StaticData.EnenyEntitySize[veridx];
int currArrayPtr = entityArrayPtr + entitySize * 4;
for (int i=0; i<500; ++i) {
// (Hard limit of reading 500 entries)
int entityId = MemoryHelper.GetMemoryValue<int>(process,
currArrayPtr + StaticData.EnenyEnitiyIDOffset[veridx], false);
int entityMaxHp = MemoryHelper.GetMemoryValue<int>(process,
currArrayPtr + StaticData.EnenyEnitiyMaxHPOffset[veridx], false);
if (entityId == 0 && entityMaxHp == 0) break;
int activeFlag = MemoryHelper.GetMemoryValue<int>(process,
currArrayPtr + StaticData.EnenyEnitiyIsActiveOffset[veridx], false);
int animationState = MemoryHelper.GetMemoryValue<int>(process,
currArrayPtr + StaticData.EnenyEnitiyAnimationOffset[veridx], false);
bool isAlive = activeFlag == 1 && animationState >= 0;
if (isAlive && StaticData.IsBoss(entityId))
{
BossStats boss;
boss.entityArrayIndex = entityArraySize;
boss.id = entityId;
boss.hp = MemoryHelper.GetMemoryValue<int>(process, currArrayPtr + StaticData.EnenyEnitiyHPOffset[veridx], false);
boss.type = StaticData.GetBoss(entityId).Value;
boss.maxHp = entityMaxHp;
bossList.Add(boss);
}
currArrayPtr += entitySize;
if (isAlive) ++nActiveEntities;
++entityArraySize;
}
}
private int countItems(Process process, int addrFirst, int addrLast)
{
int count = 0;
for (int addr = addrFirst; addr <= addrLast; ++addr)
{
count += MemoryHelper.GetMemoryValue<int>(process, addr) == 1 ? 1 : 0;
}
return count;
}
public bool CurrentMapIs(Map? map)
@ -60,5 +154,63 @@ namespace rabi_splitter_WPF
{
return StaticData.GetMusic(musicid) == music;
}
public string GetCurrentAction()
{
if (actionFrame == 0) return "None";
int actionType = actionFrame / 100;
switch (actionType)
{
case 1: return "Carrot Bomb";
case 2: return "Bunny Whirl";
case 4: return "Hammer Roll";
case 7: return "Hammer Combo 1";
case 8: return "Hammer Combo 2";
case 0: return "Hammer Combo 3";
case 9: return "Hammer Combo 4";
case 10: return "Hammer Drill";
case 13: return "Air Dash";
case 14: return "Down Drill";
case 100: return "Up Drill";
case 110: return "Walking Hammer";
case 120: return "Bunny Strike";
case 150: return "Amulet";
default: return "Unknown";
}
}
public bool IsDeathSprite()
{
return currentSprite == 31;
}
public string GetCurrentSprite()
{
switch (currentSprite)
{
case 0: return "Idle";
case 1: return "Walking";
case 2: return "Jump";
case 3: return "Air Jump";
case 4: return "Falling";
case 5: return "Slide";
case 6: return "Carrot Bomb";
case 7: return "Hurt";
case 9: return "Bunny Whirl";
case 15: return "Hammer Roll";
case 20: return "Hammer Combo 1/4";
case 21: return "Hammer Combo 2";
case 10: return "Hammer Combo 3";
case 22: return "Hammer Drill";
case 23: return "Air Dash";
case 24: return "Down Drill";
case 25: return "Up Drill";
case 26: return "Walking Hammer";
case 27: return "Amulet";
case 31: return "Death";
case 32: return "Bunny Strike";
default: return "Unknown";
}
}
}
}

@ -14,6 +14,7 @@ namespace rabi_splitter_WPF
Ribbon,
Cocoa2,
Cicini,
Cicini2,
Saya,
Syaro,
Pandora,
@ -25,13 +26,17 @@ namespace rabi_splitter_WPF
Vanilla,
Chocolate,
IllusionAlius,
PinkKotri,
Kotri,
Noah1,
Irisu,
Miriam,
Miru,
Noah3,
KekeBunny,
Cats,
BigBox,
RainbowMaid,
TreasureCrystal,
}
public enum Map
@ -130,19 +135,30 @@ namespace rabi_splitter_WPF
}
}
// A set of (exp, string)
public class ExpDescriptions : List<Tuple<int, string, string>>
{
public void Add(int exp, string shortDescript, string description)
{
Add(new Tuple<int, string, string>(exp, shortDescript, description));
}
}
public static partial class StaticData {
public static readonly Dictionary<int, Boss> _getBoss;
public static readonly Dictionary<int, string> _getBossName;
public static readonly Dictionary<Boss, string> _getBossFromType;
private static readonly Dictionary<int, Boss> _getBoss;
private static readonly Dictionary<int, string> _getBossName;
private static readonly Dictionary<Boss, string> _getBossFromType;
public static readonly Map[] _getMap;
public static readonly string[] _getMapName;
public static readonly Dictionary<Map, string> _getMapFromType;
private static readonly Map[] _getMap;
private static readonly string[] _getMapName;
private static readonly Dictionary<Map, string> _getMapFromType;
public static readonly Music[] _getMusic;
public static readonly string[] _getMusicName;
public static readonly Dictionary<Music, string> _getMusicFromType;
private static readonly Music[] _getMusic;
private static readonly string[] _getMusicName;
private static readonly Dictionary<Music, string> _getMusicFromType;
private static readonly bool[] _isBossMusic;
static StaticData()
{
@ -157,6 +173,8 @@ namespace rabi_splitter_WPF
_getMusic = MusicList.Select(t => t.Item1).ToArray();
_getMusicName = MusicList.Select(t => t.Item2).ToArray();
_getMusicFromType = MusicList.ToDictionary(t => t.Item1, t => t.Item2);
_isBossMusic = Enumerable.Range(0, _getMusic.Length).Select(i => BossMusics.Contains(_getMusic[i])).ToArray();
}
public static Boss? GetBoss(int id) {
@ -177,6 +195,11 @@ namespace rabi_splitter_WPF
return "";
}
public static bool IsBoss(int id)
{
return GetBoss(id).HasValue;
}
public static Map? GetMap(int id) {
if (0 <= id && id < _getMap.Length) return _getMap[id];
return null;
@ -208,5 +231,28 @@ namespace rabi_splitter_WPF
if (music.HasValue && _getMusicFromType.TryGetValue(music.Value, out value)) return value;
return "";
}
public static bool IsBossMusic(int musicId)
{
return musicId < _isBossMusic.Length && _isBossMusic[musicId];
}
public static Tuple<int, string, string> GetNextHammerLevel(int exp) {
int index = 0;
while (index < HammerLevels.Count && exp >= HammerLevels[index].Item1) ++index;
return index < HammerLevels.Count ? HammerLevels[index] : null;
}
public static Tuple<int, string, string> GetNextRibbonLevel(int exp) {
int index = 0;
while (index < RibbonLevels.Count && exp >= RibbonLevels[index].Item1) ++index;
return index < RibbonLevels.Count ? RibbonLevels[index] : null;
}
public static Tuple<int, string, string> GetNextCarrotLevel(int exp) {
int index = 0;
while (index < CarrotLevels.Count && exp >= CarrotLevels[index].Item1) ++index;
return index < CarrotLevels.Count ? CarrotLevels[index] : null;
}
}
}

@ -7,6 +7,7 @@ namespace rabi_splitter_WPF
{
enum GameActivity
{
STARTING,
WALKING,
BOSS_BATTLE,
}
@ -16,12 +17,27 @@ namespace rabi_splitter_WPF
public int nRestarts;
public int nDeaths;
public int nRestartsAlt;
public int nDeathsAlt;
public GameActivity currentActivity;
public int currentBoss;
public int lastNonZeroPlayTime = -1;
public RabiGameState()
{
currentActivity = GameActivity.WALKING;
currentActivity = GameActivity.STARTING;
}
public bool CurrentActivityIs(GameActivity gameActivity)
{
return currentActivity == gameActivity;
}
public bool IsGameStarted()
{
return !CurrentActivityIs(GameActivity.STARTING);
}

@ -23,15 +23,12 @@ namespace rabi_splitter_WPF
private MemorySnapshot prevSnapshot;
private MemorySnapshot snapshot;
public int previousBlackness = -1;
public int lastplaytime = 0;
public bool bossbattle;
public List<int> lastbosslist;
public DateTime LastTMAddTime;
private string[] datastrings;
public RabiRibiDisplay(MainContext mainContext, DebugContext debugContext, MainWindow mainWindow)
{
this.datastrings = new string[StaticData.EnenyEntitySize[mainContext.veridx]];
this.mainContext = mainContext;
this.debugContext = debugContext;
this.mainWindow = mainWindow;
@ -43,33 +40,57 @@ namespace rabi_splitter_WPF
// Snapshot Game Memory
snapshot = new MemorySnapshot(process, mainContext.veridx);
mainContext.Text1 = "Music: " + StaticData.GetMusicName(snapshot.musicid);
mainContext.Text2 = "Map: " + StaticData.GetMapName(snapshot.mapid);
mainContext.Text3 = gameState == null ? "" : ("Deaths: " + gameState.nDeaths + "\n" + "Resets: " + gameState.nRestarts);
#region Game State Machine
mainContext.Text4 = "HP: " + snapshot.hp;
mainContext.Text5 = "MaxHP: " + snapshot.maxhp;
mainContext.Text6 = "Amulet: " + snapshot.amulet;
mainContext.Text7 = "Boost: " + snapshot.boost;
mainContext.Text8 = "Mana: " + snapshot.mana;
mainContext.Text9 = "Stamina: " + snapshot.stamina;
if (gameState.CurrentActivityIs(GameActivity.STARTING)) {
// Detect start game
if (snapshot.playtime < 200)
{
gameState.currentActivity = GameActivity.WALKING;
DebugLog("IGT start?");
}
} else {
if (MusicChanged())
{
if (StaticData.IsBossMusic(snapshot.musicid))
{
gameState.currentActivity = GameActivity.BOSS_BATTLE;
}
else
{
gameState.currentActivity = GameActivity.WALKING;
}
}
}
mainContext.Text10 = "x: " + snapshot.px;
mainContext.Text11 = "y: " + snapshot.py;
#endregion
#region Detect Reload
bool reloaded = false;
if (prevSnapshot != null) {
reloaded = snapshot.playtime != 0 && snapshot.playtime < prevSnapshot.playtime;
if (reloaded)
bool reloaded = (prevSnapshot != null) && (snapshot.playtime < prevSnapshot.playtime);
if (gameState.IsGameStarted() && snapshot.playtime > 0)
{
if (snapshot.playtime < gameState.lastNonZeroPlayTime)
{
if (InGame())
{
gameState.nRestarts++;
}
DebugLog("Reload Game!");
DebugLog("Reload Game! " + snapshot.playtime + " <- " + gameState.lastNonZeroPlayTime);
}
gameState.lastNonZeroPlayTime = snapshot.playtime;
}
if (gameState.IsGameStarted() && prevSnapshot != null)
{
// Issue: This sometimes detects warps as resets too.
if (snapshot.animationFrame < prevSnapshot.animationFrame)
{
if (InGame())
{
gameState.nRestartsAlt++;
}
DebugLog("Reload Game (Alt)!");
}
}
@ -77,11 +98,9 @@ namespace rabi_splitter_WPF
#region Detect Death
bool died = false;
if (prevSnapshot != null)
{
died = snapshot.hp == 0 && prevSnapshot.hp > 0;
if (died)
if (snapshot.hp == 0 && prevSnapshot.hp > 0)
{
if (InGame())
{
@ -91,6 +110,18 @@ namespace rabi_splitter_WPF
}
}
if (prevSnapshot != null)
{
if (snapshot.IsDeathSprite() && !prevSnapshot.IsDeathSprite())
{
if (InGame())
{
gameState.nDeathsAlt++;
}
DebugLog("Death (Alt)!");
}
}
#endregion
#region Detect Start Game
@ -110,14 +141,43 @@ namespace rabi_splitter_WPF
DebugLog("newmap: " + snapshot.mapid + ":" + StaticData.GetMapName(snapshot.mapid));
}
mainContext.Text1 = "Music: " + StaticData.GetMusicName(snapshot.musicid);
mainContext.Text2 = "Map: " + StaticData.GetMapName(snapshot.mapid);
mainContext.Text3 = gameState == null ? "" : ("Deaths: " + gameState.nDeaths// + " [" + gameState.nDeathsAlt + "]"
+ "\n" + "Resets: " + gameState.nRestarts);// + " [" + gameState.nRestartsAlt + "]");
#region checkTM
mainContext.Text4 = "HP: " + snapshot.hp + " / " + snapshot.maxhp;
mainContext.Text5 = "Amulet: " + snapshot.amulet + "\n" + "Boost: " + snapshot.boost;
mainContext.Text6 = "MP: " + snapshot.mana + "\n" + "SP: " + snapshot.stamina;
var nextHammer = StaticData.GetNextHammerLevel(snapshot.hammerXp);
var nextRibbon = StaticData.GetNextRibbonLevel(snapshot.ribbonXp);
var nextCarrot = StaticData.GetNextCarrotLevel(snapshot.carrotXp);
mainContext.Text7 = "Hammer: " + snapshot.hammerXp + (nextHammer == null ? "" : ("/" + nextHammer.Item1 + "\n" + "NEXT: " + nextHammer.Item2));
mainContext.Text8 = "Ribbon: " + snapshot.ribbonXp + (nextRibbon == null ? "" : ("/" + nextRibbon.Item1 + "\n" + "NEXT: " + nextRibbon.Item2));
mainContext.Text9 = "Carrot: " + snapshot.carrotXp + (nextCarrot == null ? "" : ("/" + nextCarrot.Item1 + "\n" + "NEXT: " + nextCarrot.Item2));
mainContext.Text10 = "x: " + snapshot.px + "\n" + "y: " + snapshot.py;
mainContext.Text11 = "[A/H/M/P/R] ups:\n" + snapshot.nAttackUps + "/" + snapshot.nHpUps + "/" + snapshot.nManaUps + "/" + snapshot.nPackUps + "/" + snapshot.nRegenUps;
#endregion
mainContext.Text12 = "Entities: " + snapshot.entityArraySize + "\n" + "Active: " + snapshot.nActiveEntities;
mainContext.Text13 = "Sprite: " + snapshot.GetCurrentSprite() + "\n" + "Action: " + snapshot.GetCurrentAction();
mainContext.Text14 = "AnimFrame: " + snapshot.animationFrame;
{
string bosstext = "Boss Fight: " + (gameState.currentActivity == GameActivity.BOSS_BATTLE) + "\n";
bosstext += "Bosses: " + snapshot.bossList.Count + "\n";
foreach (var boss in snapshot.bossList)
{
bosstext += "[" + boss.entityArrayIndex + "] " + StaticData.GetBossName(boss.id) + ": " + boss.hp + "/" + boss.maxHp + "\n";
}
mainContext.Text16 = bosstext;
}
UpdateDebugArea(process);
UpdateEntityData(process);
prevSnapshot = snapshot;
}
@ -149,6 +209,30 @@ namespace rabi_splitter_WPF
return MusicChanged() && snapshot.CurrentMusicIs(music);
}
private void UpdateEntityData(Process process)
{
// Read entire entity data for specific entity
{
var entityStatsList = debugContext.EntityStatsListData;
int entitySize = StaticData.EnenyEntitySize[mainContext.veridx];
int baseArrayPtr = snapshot.entityArrayPtr + entitySize * debugContext.EntityAnalysisIndex;
int[] entitydataint = new int[entitySize / 4];
float[] entitydatafloat = new float[entitySize / 4];
debugContext.targetEntityListSize = entitySize / 4;
int length = Math.Min(entitySize, entityStatsList.Count * 4);
for (int i = 0; i < length; i += 4)
{
int index = i / 4;
int value_int = MemoryHelper.GetMemoryValue<int>(process, baseArrayPtr + i, false);
float value_float = MemoryHelper.GetMemoryValue<float>(process, baseArrayPtr + i, false);
entityStatsList[index].IntVal = value_int;
entityStatsList[index].FloatVal = value_float;
}
}
}
private void UpdateDebugArea(Process process)
{
int ptr = snapshot.entityArrayPtr;
@ -165,7 +249,7 @@ namespace rabi_splitter_WPF
ptr += StaticData.EnenyEntitySize[mainContext.veridx];
}
debugContext.BossEvent = bossbattle;
debugContext.BossEvent = gameState.currentActivity == GameActivity.BOSS_BATTLE;
}
private void DebugLog(string log)

@ -11,8 +11,9 @@ namespace rabi_splitter_WPF
{1012, Boss.Ashuri, "Ashuri"},
{1013, Boss.Rita, "Rita"},
{1014, Boss.Ribbon, "Ribbon"},
{1015, Boss.Cocoa2, "Cocoa"},
{1018, Boss.Cicini, "Cicini"},
{1015, Boss.Cocoa2, "Cocoa2"},
{1016, Boss.Cicini, "Cicini"},
{1018, Boss.Cicini2, "Cicini2"},
{1020, Boss.Saya, "Saya"},
{1021, Boss.Syaro, "Syaro"},
{1022, Boss.Pandora, "Pandora"},
@ -24,13 +25,18 @@ namespace rabi_splitter_WPF
{1032, Boss.Vanilla, "Vanilla"},
{1033, Boss.Chocolate, "Chocolate"},
{1035, Boss.IllusionAlius, "Illusion Alius"},
{1036, Boss.PinkKotri, "Pink Kotri"},
{1036, Boss.Kotri, "Kotri"},
{1037, Boss.Noah1, "Noah 1"},
{1038, Boss.Irisu, "Irisu"},
{1039, Boss.Miriam, "Miriam"},
{1043, Boss.Miru, "Miru"},
{1053, Boss.Noah3, "Noah 3"},
{1054, Boss.KekeBunny, "Keke Bunny"},
{1056, Boss.Cats, "Plurkwood Cats"},
{1133, Boss.BigBox, "Big Box"},
{1136, Boss.RainbowMaid, "Robot Maid"},
{1143, Boss.TreasureCrystal, "Treasure Crystal"},
};
public static IndexEnumAssociation<Map> MapList = new IndexEnumAssociation<Map>
@ -126,29 +132,72 @@ namespace rabi_splitter_WPF
{Music.MISCHIEVOUS_MASQUERADE, "MISCHIEVOUS MASQUERADE"},
};
public static int[] BossMusics = new[]
public static Music[] BossMusics = new[]
{
44,
38,
47,
34,
51,
43,
52,
37,
39,
42,
48,
8,
54
Music.BOUNCE_BOUNCE,
Music.MIDSTREAM_JAM,
Music.THE_TRUTH_NEVER_SPOKEN,
Music.BRAWL_BREAKS_VER_2,
Music.BRAWL_BREAKS,
Music.RFN_III,
Music.NO_REMORSE,
Music.GET_ON_WITH_IT,
Music.FULL_ON_COMBAT,
Music.HI_TECH_DUEL,
Music.KITTY_ATTACK,
Music.M_R_,
Music.SUDDEN_DEATH,
Music.MISCHIEVOUS_MASQUERADE,
};
public static ExpDescriptions HammerLevels = new ExpDescriptions
{
{600, "+Rang", "Attack Range Increase"},
{1000, "UpDr", "Up-drill"},
{1650, "Quad", "Quad-combo"},
{2050, "Spd1", "Combo Speed Increase (Lv.1)"},
{2500, "DwnDr", "Down-drill"},
{2750, "Dmg1", "Hammer Drill Damage Increase (Lv.1)"},// / Up-drill Exp Increase"},
{3100, "Penta", "Penta-combo (Ground-drill)"},
{3750, "Spd2", "Combo Speed Increase (Lv.2)"},
{5500, "-SP", "SP Usage Reduced"},
{6450, "Spd3", "Combo Speed Increase (Lv.3)"},
{7500, "Dmg2", "Hammer Drill Damage Increase (Lv.2)"},// / Up-drill/Down-drill Exp Increase"},
};
public static ExpDescriptions RibbonLevels = new ExpDescriptions
{
{100, "CSpd1", "Charge Speed Increase (Lv.1)"},
{600, "CSpd2", "Charge Speed Increase (Lv.2)"},
{1100, "BSpd1", "Boost Attack Speed Increase (Lv.1)"},
{1650, "CSpd3", "Charge Speed Increase (Lv.3)"},
{2800, "BSpd2", "Boost Attack Speed Increase (Lv.2)"},
{3300, "CSpd4", "Charge Speed Increase (Lv.4)"},
{3800, "BGag1", "Boost Gauge Charges Faster (Lv.1)"},
{4500, "BSpd3", "Boost Attack Speed Increase (Lv.3)"},
{5800, "BGag2", "Boost Gauge Charges Faster (Lv.2)"},
{7000, "BGag3", "Boost Gauge Charges Faster (Lv.3)"},
};
public static ExpDescriptions CarrotLevels = new ExpDescriptions
{
{7, "Del1", "Shorter Delay (Lv.1)"},
{25, "Dmg1", "Damage Increase (Lv.1)"},
{50, "Del2", "Shorter Delay (Lv.2)"},
{100, "Rad", "Effect Radius Increase"},
{175, "Dmg2", "Damage Increase (Lv.2)"},// / Exp Increase"},
{275, "Del3", "Shorter Delay (Lv.3)"},
{500, "Dmg3", "Damage Increase (Lv.3)"},// / Exp Increase"},
};
public static int[] MapAddress = { 0xA3353C, 0xA57020, 0xA5E0AC, 0xA600AC };
public static int[] EnenyPtrAddr = { 0x00940EE0, 0x00964A1C, 0x0096BA3C, 0x0096DA3C };
public static int[] EnenyEnitiyHPOffset = { 0x4c8, 0x4d0, 0x4d8, 0x4d8 };
public static int[] EnenyEnitiyMaxHPOffset = { 0, 0, 0, 0x4e8 };
public static int[] EnenyEnitiyIDOffset = { 0x4e4,0x4ec, 0x4F4, 0x4F4 };
public static int[] EnenyEntitySize = {0x6F4, 0x6FC, 0x704, 0x704 };
public static int[] EnenyEnitiyIsActiveOffset = { 0, 0, 0, 0x674 };
public static int[] EnenyEnitiyAnimationOffset = { 0, 0, 0, 0x678 };
public static int[] MaxEntityEntry = { 50,50,50 ,50};
public static int[] MoneyAddress = { 0xD3823C, 0xD5B9FC, 0xD63D2C, 0xD654CC };
public static string[] VerNames = {"1.65", "1.70","1.71","1.75"};

Loading…
Cancel
Save