using System; using System.Collections.Generic; using System.IO; namespace OpenVIII.Kernel { public class KernelBin { #region Fields public const ushort MaxHPValue = 9999; public const byte MaxStatValue = 255; #endregion Fields #region Constructors /// /// Read binary data from into structures and arrays /// /// /// /// private KernelBin() { Memory.Log.WriteLine($"{nameof(KernelBin)} :: new "); var aw = ArchiveWorker.Load(ArchiveString); var buffer = aw.GetBinaryFile(Memory.Strings[Strings.FileID.Kernel].GetFileNames()[0]); var subPositions = Memory.Strings[Strings.FileID.Kernel].GetFiles().SubPositions; MemoryStream ms; if (buffer == null) return; using (var br = new BinaryReader(ms = new MemoryStream(buffer))) { ms.Seek(subPositions[BattleCommand.ID], SeekOrigin.Begin); BattleCommands = BattleCommand.Read(br); ms.Seek(subPositions[Kernel.MagicData.ID], SeekOrigin.Begin); MagicData = Kernel.MagicData.Read(br); ms.Seek(subPositions[Kernel.JunctionableGFsData.ID], SeekOrigin.Begin); JunctionableGFsData = Kernel.JunctionableGFsData.Read(br); ms.Seek(subPositions[Kernel.EnemyAttacksData.ID], SeekOrigin.Begin); EnemyAttacksData = Kernel.EnemyAttacksData.Read(br, BattleCommands); ms.Seek(subPositions[Kernel.WeaponsData.ID], SeekOrigin.Begin); WeaponsData = Kernel.WeaponsData.Read(br); ms.Seek(subPositions[Kernel.RenzokukenFinishersData.ID], SeekOrigin.Begin); RenzokukenFinishersData = Kernel.RenzokukenFinishersData.Read(br); ms.Seek(subPositions[Kernel.CharacterStats.ID], SeekOrigin.Begin); CharacterStats = Kernel.CharacterStats.Read(br); ms.Seek(subPositions[BattleItemData.ID], SeekOrigin.Begin); BattleItemsData = BattleItemData.Read(br); NonBattleItemsData = Kernel.NonBattleItemsData.Read(); ms.Seek(subPositions[Kernel.NonJunctionableGFsAttacksData.ID], SeekOrigin.Begin); NonJunctionableGFsAttacksData = Kernel.NonJunctionableGFsAttacksData.Read(br); ms.Seek(subPositions[Kernel.CommandAbilityData.ID], SeekOrigin.Begin); CommandAbilityData = Kernel.CommandAbilityData.Read(br); ms.Seek(subPositions[Kernel.JunctionAbilities.ID], SeekOrigin.Begin); JunctionAbilities = Kernel.JunctionAbilities.Read(br); ms.Seek(subPositions[Kernel.CommandAbility.ID], SeekOrigin.Begin); CommandAbilities = Kernel.CommandAbility.Read(br, BattleCommands); ms.Seek(subPositions[StatPercentageAbilities.ID], SeekOrigin.Begin); StatPercentAbilities = StatPercentageAbilities.Read(br); ms.Seek(subPositions[Kernel.CharacterAbilities.ID], SeekOrigin.Begin); CharacterAbilities = Kernel.CharacterAbilities.Read(br); ms.Seek(subPositions[Kernel.PartyAbilities.ID], SeekOrigin.Begin); PartyAbilities = Kernel.PartyAbilities.Read(br); ms.Seek(subPositions[Kernel.GFAbilities.ID], SeekOrigin.Begin); GFAbilities = Kernel.GFAbilities.Read(br); ms.Seek(subPositions[Kernel.MenuAbilities.ID], SeekOrigin.Begin); MenuAbilities = Kernel.MenuAbilities.Read(br); ms.Seek(subPositions[Kernel.TemporaryCharacterLimitBreaks.ID], SeekOrigin.Begin); TemporaryCharacterLimitBreaks = Kernel.TemporaryCharacterLimitBreaks.Read(br); ms.Seek(subPositions[Kernel.BlueMagicQuistisLimitBreak.ID], SeekOrigin.Begin); BlueMagicQuistisLimitBreak = Kernel.BlueMagicQuistisLimitBreak.Read(br); //ms.Seek(subPositions[Quistis_limit_break_parameters.ID], SeekOrigin.Begin); //QuistisLimitBreakParameters = Quistis_limit_break_parameters.Read(br); ms.Seek(subPositions[Kernel.ShotIrvineLimitBreak.ID], SeekOrigin.Begin); ShotIrvineLimitBreak = Kernel.ShotIrvineLimitBreak.Read(br); ms.Seek(subPositions[Kernel.DuelZellLimitBreak.ID], SeekOrigin.Begin); DuelZellLimitBreak = Kernel.DuelZellLimitBreak.Read(br); ms.Seek(subPositions[Kernel.ZellLimitBreakParameters.ID], SeekOrigin.Begin); ZellLimitBreakParameters = Kernel.ZellLimitBreakParameters.Read(br); ms.Seek(subPositions[Kernel.RinoaLimitBreaksPart1.ID], SeekOrigin.Begin); RinoaLimitBreaksPart1 = Kernel.RinoaLimitBreaksPart1.Read(br); ms.Seek(subPositions[Kernel.RinoaLimitBreaksPart2.ID], SeekOrigin.Begin); RinoaLimitBreaksPart2 = Kernel.RinoaLimitBreaksPart2.Read(br); ms.Seek(subPositions[Kernel.SlotArray.ID], SeekOrigin.Begin); SlotArray = Kernel.SlotArray.Read(br); ms.Seek(subPositions[Kernel.SelphieLimitBreakSets.ID], SeekOrigin.Begin); SelphieLimitBreakSets = Kernel.SelphieLimitBreakSets.Read(br); ms.Seek(subPositions[Kernel.Devour.ID], SeekOrigin.Begin); //List tmp = Kernel.Devour.Read(br); //tmp.Add(new Devour { Description = Memory.Strings.Read(Strings.FileID.KERNEL, 30, 112) }); Devour = Kernel.Devour.Read(br); ms.Seek(subPositions[Kernel.MiscSection.ID], SeekOrigin.Begin); MiscSection = Kernel.MiscSection.Read(br); MiscTextPointers = Kernel.MiscTextPointers.Read(); var allAbilities = new Dictionary( Kernel.MenuAbilities.Count + Kernel.JunctionAbilities.Count + Kernel.CommandAbility.Count + StatPercentageAbilities.Count + Kernel.CharacterAbilities.Count + Kernel.PartyAbilities.Count + Kernel.GFAbilities.Count); var equippableAbilities = new Dictionary( StatPercentageAbilities.Count + Kernel.CharacterAbilities.Count + Kernel.PartyAbilities.Count + Kernel.GFAbilities.Count); foreach (var ability in (Abilities[])(Enum.GetValues(typeof(Abilities)))) { combine(MenuAbilities); combine(StatPercentAbilities); combine(JunctionAbilities); combine(CommandAbilities); combine(CharacterAbilities); combine(PartyAbilities); combine(GFAbilities); combine2(StatPercentAbilities); combine2(CharacterAbilities); combine2(PartyAbilities); combine2(CharacterAbilities); void combine(IReadOnlyDictionary dict) where T : IAbility { if (!dict.TryGetValue(ability, out var a) || allAbilities.ContainsKey(ability)) return; allAbilities.Add(ability, a); } void combine2(IReadOnlyDictionary dict) where T : IEquippableAbility { if (!dict.TryGetValue(ability, out var a) || equippableAbilities.ContainsKey(ability)) return; equippableAbilities.Add(ability, a); } } AllAbilities = allAbilities; EquippableAbilities = equippableAbilities; } } #endregion Constructors #region Properties public static IReadOnlyList AutoAtk { get; } = new List { Stat.STR, Stat.HIT, Stat.ElAtk, Stat.StAtk, Stat.MAG, Stat.SPD, Stat.Luck, Stat.HP, Stat.VIT, Stat.SPR, Stat.EVA, Stat.ElDef1, Stat.StDef1, Stat.ElDef2, Stat.StDef2, Stat.ElDef3, Stat.StDef3, Stat.ElDef4, Stat.StDef4 }; public static IReadOnlyList AutoDef { get; } = new List { Stat.HP, Stat.VIT, Stat.SPR, Stat.EVA, Stat.ElDef1, Stat.StDef1, Stat.ElDef2, Stat.StDef2, Stat.ElDef3, Stat.StDef3, Stat.ElDef4, Stat.StDef4, Stat.SPD, Stat.Luck, Stat.MAG, Stat.STR, Stat.HIT, Stat.ElAtk, Stat.StAtk }; public static IReadOnlyList AutoMAG { get; } = new List { Stat.MAG, Stat.SPR, Stat.SPD, Stat.Luck, Stat.HP, Stat.VIT, Stat.EVA, Stat.ElDef1, Stat.StDef1, Stat.ElDef2, Stat.StDef2, Stat.ElDef3, Stat.StDef3, Stat.ElDef4, Stat.StDef4, Stat.STR, Stat.HIT, Stat.ElAtk, Stat.StAtk }; /// /// Convert stat to stat junction /// public static IReadOnlyDictionary Stat2Ability { get; } = new Dictionary { { Stat.HP, Abilities.HPJ }, { Stat.STR, Abilities.StrJ }, { Stat.VIT, Abilities.VitJ}, { Stat.MAG, Abilities.MagJ}, { Stat.SPR, Abilities.SprJ }, { Stat.SPD, Abilities.SpdJ }, { Stat.EVA, Abilities.EvaJ }, { Stat.Luck, Abilities.LuckJ }, { Stat.HIT, Abilities.HitJ }, { Stat.ElAtk, Abilities.ElAtkJ }, { Stat.StAtk, Abilities.StAtkJ }, { Stat.ElDef1, Abilities.ElDefJ },//or Elem_Def_Jx2 or Elem_Def_Jx4 { Stat.ElDef2, Abilities.ElDefJ2 },//or Elem_Def_Jx4 { Stat.ElDef3, Abilities.ElDefJ4 }, { Stat.ElDef4, Abilities.ElDefJ4 }, { Stat.StDef1, Abilities.StDefJ },//or ST_Def_Jx2 or ST_Def_Jx4 { Stat.StDef2, Abilities.StDefJ2 },//or ST_Def_Jx4 { Stat.StDef3, Abilities.StDefJ4 }, { Stat.StDef4, Abilities.StDefJ4 } }; public IReadOnlyDictionary AllAbilities { get; } public IReadOnlyList BattleCommands { get; } public IReadOnlyList BattleItemsData { get; } public IReadOnlyDictionary BlueMagicQuistisLimitBreak { get; } public IReadOnlyDictionary CharacterAbilities { get; } public IReadOnlyDictionary CharacterStats { get; } public IReadOnlyDictionary CommandAbilities { get; } public IReadOnlyDictionary CommandAbilityData { get; } public IReadOnlyList Devour { get; } public IReadOnlyList DuelZellLimitBreak { get; } public IReadOnlyList EnemyAttacksData { get; } public IReadOnlyDictionary EquippableAbilities { get; } public IReadOnlyDictionary GFAbilities { get; } public IReadOnlyDictionary JunctionAbilities { get; } public IReadOnlyDictionary JunctionableGFsData { get; } public IReadOnlyList MagicData { get; } public IReadOnlyDictionary MenuAbilities { get; } public IReadOnlyList MiscSection { get; } public IReadOnlyList MiscTextPointers { get; } public IReadOnlyList NonBattleItemsData { get; } public IReadOnlyList NonJunctionableGFsAttacksData { get; } public IReadOnlyDictionary PartyAbilities { get; } public IReadOnlyDictionary RenzokukenFinishersData { get; } public IReadOnlyList RinoaLimitBreaksPart1 { get; } public IReadOnlyList RinoaLimitBreaksPart2 { get; } public IReadOnlyList SelphieLimitBreakSets { get; } public IReadOnlyList ShotIrvineLimitBreak { get; } public IReadOnlyList SlotArray { get; } public IReadOnlyDictionary StatPercentAbilities { get; } public IReadOnlyList TemporaryCharacterLimitBreaks { get; } public IReadOnlyList WeaponsData { get; } public IReadOnlyList ZellLimitBreakParameters { get; } private Memory.Archive ArchiveString { get; } = Memory.Archives.A_MAIN; #endregion Properties #region Methods public static KernelBin CreateInstance() => new KernelBin(); #endregion Methods } }