IllusionMods/KKManager

Tools -> Fix all cards

RizzleRizzz opened this issue · 7 comments

Not a bug but a feature request:

Some cards are missing HS2 or AIChara data. If even one HS2 card in a group is bad out of the other 99 working ones, it causes all scenes to freeze on the white screen afterwards (going to sleep, ending H, etc)
Haven't seen what happens to malformed AI cards.

A tool in the GUI that'd autofill any missing data from detected cards would be much appreciated, as the only current method of fixing cards is to go through them one by one in the Chara maker.

I wouldn't mind taking on the workload myself and submit a PR if someone more familiar with the project could point me in the right direction...

Here's an example of a broken card from output_log.txt:

[Debug  :Sideloader] Sideloader marker found, external info count: 19
KeyNotFoundException: The given key was not present in the dictionary.
  at System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) [0x0001e] in <7ba07f088431485bb722f3b3373e87ee>:0 
  at HS2.GlobalHS2Calc.GetStateIconNum (System.Int32 _nowState, System.Int32 _personality) [0x0000f] in <f4b3ed4e035748eda610b0642947f317>:0 
  at HS2.GroupCharaParameterUI.SetParameter (GameLoadCharaFileSystem.GameCharaFileInfo _info) [0x000c3] in <f4b3ed4e035748eda610b0642947f317>:0 
  at HS2.GroupCharaSelectUI.<Start>b__13_8 (GameLoadCharaFileSystem.GameCharaFileInfo _info) [0x00006] in <f4b3ed4e035748eda610b0642947f317>:0 
  at GameLoadCharaFileSystem.GameCharaFileScrollController.OnValueChange (GameLoadCharaFileSystem.GameCharaFileScrollController+ScrollData _data, System.Boolean _isOn) [0x00056] in <f4b3ed4e035748eda610b0642947f317>:0 
  at GameLoadCharaFileSystem.GameCharaFileScrollController+<>c__DisplayClass31_0.<OnUpdate>b__0 (System.Boolean _isOn) [0x00000] in <f4b3ed4e035748eda610b0642947f317>:0 
  at GameLoadCharaFileSystem.GameCharaFileInfoComponent+<>c__DisplayClass3_0.<SetData>b__0 (System.Boolean _isOn) [0x00000] in <f4b3ed4e035748eda610b0642947f317>:0 
  at UnityEngine.Events.InvokableCall`1[T1].Invoke (T1 args0) [0x00011] in <a43c47796b1b4dc78509dc74aec2356b>:0 
  at UnityEngine.Events.UnityEvent`1[T0].Invoke (T0 arg0) [0x00023] in <a43c47796b1b4dc78509dc74aec2356b>:0 
  at UnityEngine.UI.Toggle.Set (System.Boolean value, System.Boolean sendCallback) [0x00098] in <f0cd79bc997b4fdfbb94781bafee7971>:0 
  at UnityEngine.UI.Toggle.Set (System.Boolean value) [0x00001] in <f0cd79bc997b4fdfbb94781bafee7971>:0 
  at UnityEngine.UI.Toggle.set_isOn (System.Boolean value) [0x00001] in <f0cd79bc997b4fdfbb94781bafee7971>:0 
  at UnityEngine.UI.Toggle.InternalToggle () [0x00023] in <f0cd79bc997b4fdfbb94781bafee7971>:0 
  at UnityEngine.UI.Toggle.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) [0x00011] in <f0cd79bc997b4fdfbb94781bafee7971>:0 
  at UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) [0x00008] in <f0cd79bc997b4fdfbb94781bafee7971>:0 
  at UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) [0x00070] in <f0cd79bc997b4fdfbb94781bafee7971>:0 
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMousePress(MouseButtonEventData)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent(Int32)
UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent()
UnityEngine.EventSystems.StandaloneInputModule:Process()
UnityEngine.EventSystems.EventSystem:Update()
 
(Filename: <7ba07f088431485bb722f3b3373e87ee> Line: 0)

inside KKManager for the card:
image
image

Example of a working card:
image
image

If the data is missing altogether the best you can do is remove the card. If kkmanager does parse the metadata then it might be only partially broken, in that case it might be possible to salvage some of it but you'd need to put in a bunch of sanity checks. The card loading code is all inside the core project under data/cards.

@ManlyMarco Hey thanks for the quick reply!

  • Sometimes they're so broken that the greeting works in the meetup, then there's a white screen freeze before H
  • Most of the time there's a white screen freeze after H or sleep.

So the cards do work, they're just missing a bit of data. I've no idea why this happens but it does, and it's fairly annoying to check every downloaded card for these missing chara attributes.

Basically, if the card is just MISSING data, can we simply add it in?

I'm not sure why this happens, but I have hundreds of cards that do this.
A lot of them are older cards from several years back, some exist on the card sharing sites to this day.

The only way to fix them is to do the following:

  1. Create a new character and define the character information (personality, etc)
  2. Load the broken card on top of the new one WITHOUT loading any character information.
  3. Save.

Just becomes tedious with multiple cards.

If kkmanager does parse the metadata then it might be only partially broken, in that case it might be possible to salvage some of it

I'm not quite sure what KKManager is parsing but I imagine it isn't parsing everything missing.

but you'd need to put in a bunch of sanity checks. The card loading code is all inside the core project under data/cards.

I could do this, if pointed in the right direction. I believe this project would just need the addresses/offsets of the data that's supposed to be there. Has the stenography used by HS2/AI been reverse engineered in full anywhere?

For reference I come from projects where we do the reverse engineering before the modding such as the file:
https://github.com/HaloMods/OpenSauce/blob/40c7715a82a3b438d5e04f4f5e5a9edeb59e2618/OpenSauce/shared/Include/blamlib/Halo1/objects/object_structures.hpp

KKManager currently is only parsing some parts of the cards, and it's doing it in a way that doesn't really let them be re-saved. This could be done by properly implementing the card file format and would allow editing the cards as a bonus, but it's not something I have on my todo list. You can see the entire card load progress in game code at chafile.loadfile, use dnspy to read game assemblies. Ask on the KK discord server in the programming channel for more info.

I honestly tried my best to implement it. I could never get the debugging to work correctly in dnSpy, so my workspace was very limited.
What I managed to do:
write a loadfile function that mirrors hs2/ai/kk exactly
What I couldn't do:
Couldn't find the corrupted data in my cards. I tried catching the KeyNotFound exception, I went through the locals in dnSpy, the logic, the call stack... it seems to be building a new list game.infoPersonalParameterTable, which somehow comes from ChaFileGameInfo2. Then it tries to calcstate the personality parameter 0xA and crashes. I couldn't figure it out.

here's my python script with some nice output.
https://gist.github.com/RizzleRizzz/84577365b96a59b87933529b465719ce
maybe someone else can figure it out.

Since it's very difficult to implement properly I don't think this will be implemented in KKM.