From 1f4fd186628f9b879d86f9ce50db6ce29d56dbd8 Mon Sep 17 00:00:00 2001 From: wcko87 Date: Mon, 17 Apr 2017 15:39:50 +0800 Subject: [PATCH] Implement a lot of other functionality. Still very experimental at this stage --- rabi_splitter_WPF/MainContext.cs | 120 ++++++++++++++++++++- rabi_splitter_WPF/MainWindow.xaml | 30 ++++-- rabi_splitter_WPF/MainWindow.xaml.cs | 2 + rabi_splitter_WPF/MemorySnapshot.cs | 156 ++++++++++++++++++++++++++- rabi_splitter_WPF/RabiEnums.cs | 66 ++++++++++-- rabi_splitter_WPF/RabiGameState.cs | 18 +++- rabi_splitter_WPF/RabiRibiDisplay.cs | 150 ++++++++++++++++++++------ rabi_splitter_WPF/StaticData.cs | 85 +++++++++++---- 8 files changed, 554 insertions(+), 73 deletions(-) diff --git a/rabi_splitter_WPF/MainContext.cs b/rabi_splitter_WPF/MainContext.cs index 1c2837b..5cd789a 100644 --- a/rabi_splitter_WPF/MainContext.cs +++ b/rabi_splitter_WPF/MainContext.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,14 +130,27 @@ namespace rabi_splitter_WPF class DebugContext : INotifyPropertyChanged { + private int _entityAnalysisIndex; private bool _bossEvent; private string _debugLog; public ObservableCollection BossList = new ObservableCollection(); + public ObservableCollection EntityStatsListData = new ObservableCollection(); + public int targetEntityListSize; + + public ObservableCollection EntityStatsListView + { + get + { + return EntityStatsListData; + } + } public DebugContext() { - BossList=new ObservableCollection(); + this.EntityAnalysisIndex = 0; + + BossList =new ObservableCollection(); for (int i = 0; i < 50; i++) { BossList.Add(new BossData() @@ -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 @@ -138,7 +216,7 @@ namespace rabi_splitter_WPF { public string oldtitle; public int veridx; - + private int _serverPort; private string _gameVer; private string _gameMusic; @@ -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 { @@ -324,7 +405,40 @@ namespace rabi_splitter_WPF OnPropertyChanged(nameof(Text15)); } } - + + 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; } diff --git a/rabi_splitter_WPF/MainWindow.xaml b/rabi_splitter_WPF/MainWindow.xaml index 92fc22a..73d103d 100644 --- a/rabi_splitter_WPF/MainWindow.xaml +++ b/rabi_splitter_WPF/MainWindow.xaml @@ -16,7 +16,7 @@ - + @@ -26,14 +26,14 @@ - + - + @@ -56,12 +56,30 @@ - - - + + + + + + + + + + + + + + + + + + diff --git a/rabi_splitter_WPF/MainWindow.xaml.cs b/rabi_splitter_WPF/MainWindow.xaml.cs index 93a125e..19bf464 100644 --- a/rabi_splitter_WPF/MainWindow.xaml.cs +++ b/rabi_splitter_WPF/MainWindow.xaml.cs @@ -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(() => diff --git a/rabi_splitter_WPF/MemorySnapshot.cs b/rabi_splitter_WPF/MemorySnapshot.cs index ca9dfaa..f56164b 100644 --- a/rabi_splitter_WPF/MemorySnapshot.cs +++ b/rabi_splitter_WPF/MemorySnapshot.cs @@ -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; @@ -26,7 +37,24 @@ 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 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(process, StaticData.IGTAddr[veridx]); @@ -37,11 +65,26 @@ namespace rabi_splitter_WPF musicid = MemoryHelper.GetMemoryValue(process, StaticData.MusicAddr[veridx]); money = MemoryHelper.GetMemoryValue(process, StaticData.MoneyAddress[veridx]); + carrotXp = MemoryHelper.GetMemoryValue(process, 0xD654BC); + hammerXp = MemoryHelper.GetMemoryValue(process, 0xD654B4); + ribbonXp = MemoryHelper.GetMemoryValue(process, 0xD654B8); + itemPercent = MemoryHelper.GetMemoryValue(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(process, StaticData.EnenyPtrAddr[veridx]); hp = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x4D8, false); maxhp = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x4E8, false); + currentSprite = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x654, false); + actionFrame = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x660, false); + animationFrame = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x67c, false); + amulet = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x52C, false); boost = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x5DC, false); mana = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x6B8, false); @@ -49,6 +92,57 @@ namespace rabi_splitter_WPF px = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0xC, false); py = MemoryHelper.GetMemoryValue(process, entityArrayPtr + 0x10, false); + + + // Read Entity Array and Search for boss data + bossList = new List(); + 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(process, + currArrayPtr + StaticData.EnenyEnitiyIDOffset[veridx], false); + int entityMaxHp = MemoryHelper.GetMemoryValue(process, + currArrayPtr + StaticData.EnenyEnitiyMaxHPOffset[veridx], false); + + if (entityId == 0 && entityMaxHp == 0) break; + + int activeFlag = MemoryHelper.GetMemoryValue(process, + currArrayPtr + StaticData.EnenyEnitiyIsActiveOffset[veridx], false); + int animationState = MemoryHelper.GetMemoryValue(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(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(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"; + } + } } } diff --git a/rabi_splitter_WPF/RabiEnums.cs b/rabi_splitter_WPF/RabiEnums.cs index 8d13eed..5ea939d 100644 --- a/rabi_splitter_WPF/RabiEnums.cs +++ b/rabi_splitter_WPF/RabiEnums.cs @@ -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> + { + public void Add(int exp, string shortDescript, string description) + { + Add(new Tuple(exp, shortDescript, description)); + } + } + public static partial class StaticData { - public static readonly Dictionary _getBoss; - public static readonly Dictionary _getBossName; - public static readonly Dictionary _getBossFromType; + private static readonly Dictionary _getBoss; + private static readonly Dictionary _getBossName; + private static readonly Dictionary _getBossFromType; - public static readonly Map[] _getMap; - public static readonly string[] _getMapName; - public static readonly Dictionary _getMapFromType; + private static readonly Map[] _getMap; + private static readonly string[] _getMapName; + private static readonly Dictionary _getMapFromType; - public static readonly Music[] _getMusic; - public static readonly string[] _getMusicName; - public static readonly Dictionary _getMusicFromType; + private static readonly Music[] _getMusic; + private static readonly string[] _getMusicName; + private static readonly Dictionary _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 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 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 GetNextCarrotLevel(int exp) { + int index = 0; + while (index < CarrotLevels.Count && exp >= CarrotLevels[index].Item1) ++index; + return index < CarrotLevels.Count ? CarrotLevels[index] : null; + } } } diff --git a/rabi_splitter_WPF/RabiGameState.cs b/rabi_splitter_WPF/RabiGameState.cs index cb8eba2..7f7f233 100644 --- a/rabi_splitter_WPF/RabiGameState.cs +++ b/rabi_splitter_WPF/RabiGameState.cs @@ -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); } diff --git a/rabi_splitter_WPF/RabiRibiDisplay.cs b/rabi_splitter_WPF/RabiRibiDisplay.cs index b2d0b41..edb79f7 100644 --- a/rabi_splitter_WPF/RabiRibiDisplay.cs +++ b/rabi_splitter_WPF/RabiRibiDisplay.cs @@ -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 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,45 +40,67 @@ 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); - - mainContext.Text4 = "HP: " + snapshot.hp; - mainContext.Text5 = "MaxHP: " + snapshot.maxhp; + #region Game State Machine - mainContext.Text6 = "Amulet: " + snapshot.amulet; - mainContext.Text7 = "Boost: " + snapshot.boost; - mainContext.Text8 = "Mana: " + snapshot.mana; - mainContext.Text9 = "Stamina: " + snapshot.stamina; - - mainContext.Text10 = "x: " + snapshot.px; - mainContext.Text11 = "y: " + snapshot.py; + 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; + } + } + } + #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)!"); } } #endregion #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()) { @@ -90,11 +109,23 @@ namespace rabi_splitter_WPF DebugLog("Death!"); } } - + + if (prevSnapshot != null) + { + if (snapshot.IsDeathSprite() && !prevSnapshot.IsDeathSprite()) + { + if (InGame()) + { + gameState.nDeathsAlt++; + } + DebugLog("Death (Alt)!"); + } + } + #endregion #region Detect Start Game - + if (prevSnapshot != null && (snapshot.CurrentMusicIs(Music.MAIN_MENU) || snapshot.CurrentMusicIs(Music.ARTBOOK_INTRO)) && prevSnapshot.blackness == 0 && snapshot.blackness >= 100000) { @@ -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; } @@ -148,6 +208,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(process, baseArrayPtr + i, false); + float value_float = MemoryHelper.GetMemoryValue(process, baseArrayPtr + i, false); + entityStatsList[index].IntVal = value_int; + entityStatsList[index].FloatVal = value_float; + } + } + } private void UpdateDebugArea(Process process) { @@ -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) diff --git a/rabi_splitter_WPF/StaticData.cs b/rabi_splitter_WPF/StaticData.cs index 9d88a53..7134703 100644 --- a/rabi_splitter_WPF/StaticData.cs +++ b/rabi_splitter_WPF/StaticData.cs @@ -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 MapList = new IndexEnumAssociation @@ -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[] 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"};