using System.Collections.Generic;
using System.IO;
namespace OpenVIII
{
namespace Kernel
{
///
/// Magic Data
///
///
public class Magic_Data
{
public const int id = 1;
public const int count = 57;
public FF8String Name { get; private set; }
public FF8String Description { get; private set; }
public byte ID { get; private set; }
public bool PositiveMagic
{
get
{
switch (Attack_type)
{
case AttackType.CurativeItem:
case AttackType.CurativeMagic:
case AttackType.GivePercentageHP:
case AttackType.Revive:
case AttackType.ReviveAtFullHP:
case AttackType.WhiteWindQuistis:
case AttackType.Scan: //scan is kinda both.
return true;
}
return false;
}
}
public override string ToString() => Name;
//0x0000 2 bytes Offset to spell name
//0x0002 2 bytes Offset to spell description
public Magic_ID MagicID { get; private set; } //0x0004 2 bytes Magic ID
public byte Unknown { get; private set; } //0x0006 1 byte Unknown
public AttackType Attack_type { get; private set; } //0x0007 1 byte Attack type
public byte Spellpower { get; private set; } //0x0008 1 byte Spell power(used in damage formula)
public byte Unknown2 { get; private set; } //0x0009 1 byte Unknown
public Target Target { get; private set; }//0x000A 1 byte Default_target
public AttackFlags Attack_flags { get; private set; } //0x000B 1 byte Attack Flags
public byte Draw_resist { get; private set; } //0x000C 1 byte Draw resist(how hard is the magic to draw)
public byte Hit_count { get; private set; } //0x000D 1 byte Hit Count(works with meteor animation, not sure about others)
public Element Element { get; private set; } //0x000E 1 byte Element
public byte Unknown3 { get; private set; } //0x000F 1 byte Unknown
public Persistent_Statuses Statuses0 { get; private set; } //0x0014 2 bytes Statuses 0
public Battle_Only_Statuses Statuses1 { get; private set; } //0x0010 4 bytes Statuses 1
public byte Status_attack { get; private set; } //0x0016 1 byte Status attack enabler\
public IReadOnlyDictionary J_Val { get => _j_Val; }
//public byte HP_J; //0x0017 1 byte Characters HP junction value
//public byte STR_J; //0x0018 1 byte Characters STR junction value
//public byte VIT_J; //0x0019 1 byte Characters VIT junction value
//public byte MAG_J; //0x001A 1 byte Characters MAG junction value
//public byte SPR_J; //0x001B 1 byte Characters SPR junction value
//public byte SPD_J; //0x001C 1 byte Characters SPD junction value
//public byte EVA_J; //0x001D 1 byte Characters EVA junction value
//public byte HIT_J; //0x001E 1 byte Characters HIT junction value
//public byte LUCK_J; //0x001F 1 byte Characters LUCK junction value
public Element EL_Atk { get; private set; } //0x0020 1 byte Characters J - Elem attack
//public byte J_Val[Kernel_bin.Stat.EL_Atk];//0x0021 1 byte Characters J - Elem attack value
public Element EL_Def { get; private set; } //0x0022 1 byte Characters J - Elem defense
//public byte J_Val[Kernel_bin.Stat.EL_Def_1];//0x0023 1 byte Characters J - Elem defense value
//public byte J_Val[Kernel_bin.Stat.ST_Atk];//0x0024 1 byte Characters J - Status attack value
//public byte J_Val[Kernel_bin.Stat.ST_Def_1];//0x0025 1 byte Characters J - Status defense value
public J_Statuses ST_Atk { get; private set; } //0x0026 2 bytes Characters J - Statuses Attack
public J_Statuses ST_Def { get; private set; } //0x0028 2 bytes Characters J - Statuses Defend
public byte[] GF_Compatibility { get; private set; }
//0x002A 1 byte Quezacolt compatibility
//0x002B 1 byte Shiva compatibility
//0x002C 1 byte Ifrit compatibility
//0x002D 1 byte Siren compatibility
//0x002E 1 byte Brothers compatibility
//0x002F 1 byte Diablos compatibility
//0x0030 1 byte Carbuncle compatibility
//0x0031 1 byte Leviathan compatibility
//0x0032 1 byte Pandemona compatibility
//0x0033 1 byte Cerberus compatibility
//0x0034 1 byte Alexander compatibility
//0x0035 1 byte Doomtrain compatibility
//0x0036 1 byte Bahamut compatibility
//0x0037 1 byte Cactuar compatibility
//0x0038 1 byte Tonberry compatibility
//0x0039 1 byte Eden compatibility
public byte[] Unknown4 { get; private set; } //0x003A 2 bytes Unknown
private Dictionary _j_Val;
public void Read(BinaryReader br, int i)
{
Name = Memory.Strings.Read(Strings.FileID.KERNEL, id, i * 2);
Description = Memory.Strings.Read(Strings.FileID.KERNEL, id, i * 2 + 1);
ID = (byte)i;
br.BaseStream.Seek(4, SeekOrigin.Current);
MagicID = (Magic_ID)br.ReadUInt16();
Unknown = br.ReadByte();
Attack_type = (AttackType)br.ReadByte();
Spellpower = br.ReadByte();
Unknown2 = br.ReadByte();
Target = (Target)br.ReadByte();
Attack_flags = (AttackFlags)br.ReadByte();
Draw_resist = br.ReadByte();
Hit_count = br.ReadByte();
Element = (Element)br.ReadByte();
Unknown3 = br.ReadByte();
Statuses1 = (Battle_Only_Statuses)br.ReadUInt32();
Statuses0 = (Persistent_Statuses)br.ReadUInt16();
Status_attack = br.ReadByte();
_j_Val = new Dictionary(6)
{
{ Stat.HP, br.ReadByte() },
{ Stat.STR, br.ReadByte() },
{ Stat.VIT, br.ReadByte() },
{ Stat.MAG, br.ReadByte() },
{ Stat.SPR, br.ReadByte() },
{ Stat.SPD, br.ReadByte() },
{ Stat.EVA, br.ReadByte() },
{ Stat.HIT, br.ReadByte() },
{ Stat.LUCK, br.ReadByte() }
};
EL_Atk = (Element)br.ReadByte();
_j_Val.Add(Stat.EL_Atk, br.ReadByte());
EL_Def = (Element)br.ReadByte();
_j_Val.Add(Stat.EL_Def_1, br.ReadByte());
_j_Val.Add(Stat.EL_Def_2, _j_Val[Stat.EL_Def_1]);
_j_Val.Add(Stat.EL_Def_3, _j_Val[Stat.EL_Def_1]);
_j_Val.Add(Stat.EL_Def_4, _j_Val[Stat.EL_Def_1]);
_j_Val.Add(Stat.ST_Atk, br.ReadByte());
_j_Val.Add(Stat.ST_Def_1, br.ReadByte());
_j_Val.Add(Stat.ST_Def_2, _j_Val[Stat.ST_Def_1]);
_j_Val.Add(Stat.ST_Def_3, _j_Val[Stat.ST_Def_1]);
_j_Val.Add(Stat.ST_Def_4, _j_Val[Stat.ST_Def_1]);
ST_Atk = (J_Statuses)br.ReadUInt16();
ST_Def = (J_Statuses)br.ReadUInt16();
GF_Compatibility = br.ReadBytes(16);
Unknown4 = br.ReadBytes(2);
}
public uint totalStatVal(Stat stat)
{
if (stat < Stat.EL_Atk)
return J_Val[stat];
else if (stat == Stat.EL_Atk)
return J_Val[stat] * EL_Atk.Count();
else if (stat == Stat.ST_Atk)
return J_Val[stat] * ST_Atk.Count();
else if (stat >= Stat.EL_Def_1 && stat <= Stat.EL_Def_4)
return J_Val[stat] * EL_Def.Count();
else if (stat >= Stat.ST_Def_1 && stat <= Stat.ST_Def_4)
return J_Val[stat] * ST_Def.Count();
return 0;
}
public static List Read(BinaryReader br)
{
var ret = new List(count);
for (int i = 0; i < count; i++)
{
var tmp = new Magic_Data();
tmp.Read(br, i);
ret.Add(tmp);
}
return ret;
}
}
}
}