diff --git a/README.md b/README.md index ccd8378b..36b1a3ee 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,11 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | GGUF | | [`patterns/gguf.hexpat`](patterns/gguf.hexpat) | GGML Inference Models | | GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files | | GLTF | `model/gltf-binary` | [`patterns/gltf.hexpat`](patterns/gltf.hexpat) | GL Transmission Format binary 3D model file | +| Gold Box Games: Character | | [`patterns/GoldBox/GB_CHR.hexpat`](patterns/GoldBox/GB_CHR.hexpat) | Gold Box Game Character/Monster files | +| Gold Box Games: Executable | | [`patterns/GoldBox/GB_EXE.hexpat`](patterns/GoldBox/GB_EXE.hexpat) | Gold Box Game Executables | +| Gold Box Games: Item Base | | [`patterns/GoldBox/GB_ITM-Base.hexpat`](patterns/GoldBox/GB_ITM-Base.hexpat) | Gold Box Game Item Base files | +| Gold Box Games: Item Record | | [`patterns/GoldBox/GB_ITM-Record.hexpat`](patterns/GoldBox/GB_ITM-Record.hexpat) | Gold Box Game Item Record files | +| Gold Box Games: Vault | | [`patterns/GoldBox/GB_VLT.hexpat`](patterns/GoldBox/GB_VLT.hexpat) | Gold Box Game Vault files | | GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format | | Halo Tag || [`patterns/hinf_tag.hexpat`](patterns/hinf_tag.hexpat) | Halo Infinite Tag Files | | Halo Module || [`patterns/hinf_module.hexpat`](patterns/hinf_module.hexpat) | Halo Infinite Module Archive Files | diff --git a/patterns/GoldBox/GB_CHR.hexpat b/patterns/GoldBox/GB_CHR.hexpat new file mode 100644 index 00000000..f96f714a --- /dev/null +++ b/patterns/GoldBox/GB_CHR.hexpat @@ -0,0 +1,987 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Character +#include +#include +#include +#include +#include +import std.core; +import std.string; + +/********** + This is intended to allow looking up and/or modifying the character/monster + record files for all Gold Box games (D&D, no one cares about Buck Rogers) + + Supported Games: + 01 - Pool of Radiance (CHRDAT[A-J]#.SAV / .CHA / MON[1-8]CHA.DAX) + 02 - Curse of the Azure Bonds (CHRDAT[A-J]#.SAV / .GUY / MON[1-6]CHA.DAX) + 03 - Secret of the Silver Blades (CHRDAT[A-J]#.SAV / .WHO / MON1CHA.DAX) + 04 - Pools of Darkness (CHRDAT[A-J]#.SAV / .PC / MON1CHA.DAX) + 05 - Champions of Krynn (CHRDAT[A-J]#.SAV / .WHO / MON[1-3]CHA.DAX) + 06 - Death Knights of Krynn (CHRDAT[A-J]#.GAM / .PC / MON1CHA.DAX) + 07 - The Dark Queen of Krynn (SAVGAM[A-J].QSV / .QCH / DISK1\MONCHA.GLB) + 08 - Gateway to the Savage Frontier (CHRDAT[A-J]#.SAV / .GUY / MON[2-6]CHA.DAX) + 09 - Treasures of the Savage Frontier (CHRDAT[A-J]#.SAV / .PC / MON1CHA.DAX) + 10 - Unlimited Adventures (SAVGAM[A-J].CSV / .CCH / DISK1\MONST.GLB / MONST###.DAT) + + Monster files (i.e. MON1CHA.DAX) must be decompressed first in order to view the records + This means that in order to edit those you must recompress/recreate the DAX file afterwards + + Note: + An attempt is made to identify/validate the source game; however, some games have identical + file sizes and the 7/10 files are variable length with multiple possible overlaps so make + sure the GameID is set correctly below if it returns an error or the data looks wrong + + The GameID variable below must be set for to the number in the list above for the source game +*********/ +u8 GameID = 0; + +u32 FileSize = std::mem::size(); +u8 CHARCount = 1; +u32 Offset = 0x00; + +// Attempt to auto identify file +if (GameID == 0) { +// 01 + if (FileSize == 285) { + GameID = 1; + std::print("Pool of Radiance file detected. GameID set to 1."); + } + else if (FileSize == 439) { + GameID = 3; + std::print("Secret of the Silver Blades file detected. GameID set to 3."); + } + else if (FileSize == 409) { + GameID = 5; + std::print("Champions of Krynn file detected. GameID set to 5."); + } + else if (FileSize == 216) { + GameID = 6; + std::print("Death Knights of Krynn file detected. GameID set to 6."); + } + else if (FileSize == 7965) { + GameID = 7; + std::print("The Dark Queen of Krynn file detected. GameID set to 7."); + } + else if (FileSize == 10285) { + GameID = 10; + std::print("Unlimited Adventures file detected. GameID set to 10."); + } +// 2/8 & 4/9 have same file sizes and 7/10 are variable length so cannot be auto set - Note: 10 MON files are fixed at 450 but can conflict with 7 CHR records (414 + 4xSFX + 0xITM) + else if (FileSize == 422 || (FileSize >= 398 && FileSize <= 886)) { + std::warning("Please set the GameID variable to the source game's number."); + return; + } + else { + std::warning("File is not a Gold Box character record file. Aborting."); + return; + } + +} + +// Ensure GameID is in range +if (GameID > 10) { + std::warning("Invalid GameID. Aborting."); + return; +} + +/*********************** + 7/10 variables +***********************/ +// 7/10 - Item variables +u8 RecordSize = GameID == 7 ? 17 : 18; +u8 ItemCount = 16; // Hardcoding ItemCount to keep numbering same across characters (and it's easier :P) +bool HasBundle = true; + +// 7/10 - FileType +bool IsSAV = false; +bool IsMON = false; + +// Validate file +if ((GameID == 1 && FileSize != 285) || ((GameID == 2 || GameID == 8) && FileSize != 422) || (GameID == 3 && FileSize != 439) || ((GameID == 4 || GameID == 9) && FileSize != 510) || (GameID == 5 && FileSize != 409) || (GameID == 6 && FileSize != 216)) { + std::warning("Invalid file for specified game. Aborting."); + return; +} +else if (GameID == 7) { +// Abort if out of range (not going to bother with full validation as it's a combo of sizes with 414 + 20x9 SFX records + 16x17 ITM records) + if (FileSize != 7965 && !(FileSize >= 414 && FileSize <= 866)) { + std::warning("Invalid file for specified game. Aborting."); + return; + } +// Probe file to determine if save or standalone character/monster record + u8 MoraleCheck @ 0x009B; // This value is always 0 on player records and populated on all monster records (NPC party members have a value but those are in saves and file size check takes care of that) + IsSAV = std::mem::size() == 7965 ? true : false; + IsMON = (!IsSAV && MoraleCheck > 0) ? true : false; +} +else if (GameID == 10) { +// Abort if out of range (not going to bother with full validation as it's a combo of sizes with 398 + 20x10 SFX records + 16x18 ITM records) + if (FileSize != 10285 && !(FileSize >= 398 && FileSize <= 886)) { + std::warning("Invalid file for specified game. Aborting."); + return; + } + IsSAV = std::mem::size() == 10285 ? true : false; + IsMON = FileSize == 450 ? true : false; // No possible combo of SFX/ITM records equals 450 for standalone player character records (CCH) +} + +// Set number of characters in file and offset for saves +if (IsSAV) { + u8 SaveCharCount @ 0x040D; + CHARCount = SaveCharCount; + Offset = 0x040F; +} + +/******************************* + Structs + Additional included from: + GoldBox/GB_STRUCT.cs + GoldBox/GB_STRUCT_ITM.cs +*******************************/ +// 10 - Monster Item record - CHAR_MON.Item (CHR specific so not part of Item patterns) +struct ITM_MON10 { + u8 ItemID [[comment("Item ID in ITEM.DAT (0 = No item)")]]; + u8 Quantity @ $ + 15 [[comment("How many of that item the monster is carrying")]]; +} [[name(std::format("{:02d}: Item", std::core::array_index()))]]; + +/*********************** + SFX 7/10 only +***********************/ +// 7 - Base Effect record - SFX_CHR/CHAR_MON.SFX_Effect - temp - move to common struct once SFX pattern complete +struct SFX_BASE { + u8 EffectID [[comment("ID of the effect")]]; + u16 TimeRemaining [[comment("Number of rounds remaining on the effect (0 for permanent)")]]; + u8 Modifier [[comment("Variable usage, depending on effect")]]; + u8 IsItemEffect [[comment("Indicates if effect is due to an equipped item")]];; +} [[name(std::format("{:02d}: SFX_Effect", std::core::array_index()))]]; + +// 7 - Character Effect record - CHAR_CHR.SFX_Effect - has pointer to the next effect record - always 0 on last record - temp +struct SFX_CHR07 : SFX_BASE{ + u32 ADDR_NextEffect [[comment("Pointer to next effect record")]]; +}; + +// 10 - Monster Effect record +struct SFX_MON10 { + u8 EffectID [[name(std::format("{:02d}: EffectID", std::core::array_index()))]]; +} [[inline]]; + +// 10 - Character Effect record - CHAR_CHR.SFX_Effect - 10 - temp - move to common struct once SFX pattern complete +struct SFX_CHR10 { + u8 EffectID [[comment("ID of the effect")]]; + u8 Unknown_01 [[comment("Unknown")]]; + u16 TimeRemaining [[comment("Number of rounds remaining on the effect (0 for permanent)")]]; + u8 Modifier [[comment("Variable usage, depending on effect")]]; + bool IsItemEffect [[comment("Indicates if effect is due to an equipped item")]]; + u32 ADDR_NextEffect [[comment("Pointer to next effect record")]]; +} [[name(std::format("{:02d}: SFX_Effect", std::core::array_index()))]]; + +/*********************** + Character flags +***********************/ +// 1 - Character flags - N/A + +// 2 - Character flags +bitfield FLAGARRAY02 { + Vulnerable_Dispel : 1 [[comment("Vulnerable to Dispel Evil (Extraplanar)")]]; + Penalty_ToHit_Dwarf : 1 [[comment("-4 Penalty To Hit vs Dwarves")]]; + Penalty_ToHit_Gnome : 1 [[comment("-4 Penalty To Hit vs Gnomes")]]; + Bonus_Damage_Ranger : 1 [[comment("Takes +1 Additional Damage Per Level from Rangers)")]]; +}; + +// 3 - Character flags +bitfield FLAGARRAY03 { + Vulnerable_Dispel : 1 [[comment("Vulnerable to Dispel Evil (Extraplanar type)")]]; + Type_Mammal : 1 [[comment("Mammal type")]]; + Penalty_ToHit_Dwarf : 1 [[comment("-4 Penalty To Hit vs Dwarves")]]; + Bonus_Damage_Ranger : 1 [[comment("Takes +1 Additional Damage Per Level from Rangers)")]]; + Type_Snake : 1 [[comment("Snake type")]]; + Penalty_ToHit_Gnome : 1 [[comment("-4 Penalty To Hit vs Gnomes")]]; + Type_Animal : 1 [[comment("Animal type")]]; + Bonus_ToHit_Dwarf : 1 [[comment("Dwarves Have +1 Bonus To Hit")]]; + Type_Giant : 1 [[comment("Giant type")]]; + Unknown_09 : 1 [[comment("Unknown Flag")]]; + Unknown_10 : 1 [[comment("Unknown Flag")]]; + Immune_DeathMagic : 1 [[comment("Immune to Death Magic")]]; +}; + +// 4 - Character flags +bitfield FLAGARRAY04 { + Vulnerable_Dispel : 1 [[ncomment("Vulnerable to Dispel Evil (Extraplanar)")]]; + Unknown_01 : 1 [[comment("Unknown Flag")]]; + Penalty_ToHit_Dwarf : 1 [[comment("-4 Penalty To Hit vs Dwarves")]]; + Bonus_Damage_Ranger : 1 [[comment("Takes +1 Additional Damage Per Level from Rangers")]]; + Type_Snake : 1 [[comment("Snake type")]]; + Penalty_ToHit_Gnome : 1 [[comment("-4 Penalty To Hit vs Gnomes")]]; + Type_Animal : 1 [[comment("Animal type")]]; + Bonus_ToHit_Dwarf : 1 [[comment("Dwarves Have +1 Bonus To Hit")]]; + Type_Giant : 1 [[comment("Giant type")]]; + Vulnerable_CharmHold : 1 [[comment("Vulnerable to Charm/Hold")]]; + Type_Reptile : 1 [[comment("Reptile type")]]; + Immune_DeathMagic : 1 [[comment("Immune to Death Magic")]]; + Immune_Poison : 1 [[comment("Immune to Poison")]]; + Immune_Decapitation : 1 [[comment("Immune to Decapitation\n(Vorpal Sword)")]]; + Immune_Confusion : 1 [[comment("Immune to Confusion")]]; +}; + +// 5 - Character flags +bitfield FLAGARRAY05 { + Vulnerable_Dispel : 1 [[comment("Vulnerable to Dispel Evil (Extraplanar)")]]; + Type_Undead : 1 [[comment("Undead type")]]; + Penalty_ToHit_Dwarf : 1 [[comment("-4 Penalty To Hit vs Dwarves")]]; + Bonus_Damage_Ranger : 1 [[comment("Takes +1 Additional Damage Per Level from Rangers)")]]; + Type_Snake : 1 [[comment("Snake type")]]; + Type_Reptile : 1 [[comment("Reptile type")]]; + Type_Animal : 1 [[comment("Animal type")]]; + Bonus_ToHit_Dwarf : 1 [[comment("Dwarves Have +1 Bonus To Hit")]]; + Type_Dragon : 1 [[comment("Dragon type")]]; + Bonus_ToHit_Gnome : 1 [[comment("Gnomes Have +1 Bonus To Hit")]]; +}; + +// 6 - Character flags +bitfield FLAGARRAY06 { + Vulnerable_Dispel : 1 [[comment("Vulnerable to Dispel Evil (Extraplanar)")]]; + Unknown_01 : 1 [[comment("Unknown Flag")]]; + Unknown_02 : 1 [[comment("Unknown Flag")]]; + Unknown_03 : 1 [[comment("Unknown Flag")]]; + Unknown_04 : 1 [[comment("Unknown Flag")]]; + Type_Reptile : 1 [[comment("Reptile type")]]; + Unknown_06 : 1 [[comment("Unknown Flag")]]; + Unknown_07 : 1 [[comment("Unknown Flag")]]; + Type_Dragon : 1 [[comment("Dragon type")]]; + Unknown_09 : 1 [[comment("Unknown Flag")]]; + Unknown_10 : 1 [[comment("Unknown Flag")]]; + Immune_DeathMagic : 1 [[comment("Immune to Death Magic")]]; +}; + +// 7 - Character flags +bitfield FLAGARRAY07 { + Vulnerable_Dispel : 1 [[comment("Vulnerable to Dispel Evil (Extraplanar)")]]; + Type_Mammal : 1 [[comment("Mammal type")]]; + Penalty_ToHit_Dwarf : 1 [[comment("-4 Penalty To Hit vs Dwarves")]]; + Bonus_Damage_Ranger : 1 [[comment("Takes +1 Additional Damage Per Level from Rangers)")]]; + Type_Snake : 1 [[comment("Snake type")]]; + Type_Undead : 1 [[comment("Undead type")]]; + Type_Animal : 1 [[comment("Animal type")]]; + Bonus_ToHit_Dwarf : 1 [[comment("Dwarves Have +1 Bonus To Hit")]]; + Type_Giant : 1 [[comment("Giant type")]]; + Vulnerable_CharmHold : 1 [[comment("Vulnerable to Charm/Hold")]]; + Type_Reptile : 1 [[comment("Reptile type")]]; + Immune_DeathMagic : 1 [[comment("Immune to Death Magic")]]; + Immune_Poison : 1 [[comment("Immune to Poison")]]; + Immune_Decapitation : 1 [[comment("Immune to Decapitation")]]; + Immune_Confusion : 1 [[comment("Immune to Confusion")]]; + Type_Dragon : 1 [[comment("Dragon type")]]; +}; + +// 8 - Character flags +bitfield FLAGARRAY08 { + Vulnerable_Dispel : 1 [[comment("Vulnerable to Dispel Evil (Extraplanar)")]]; + Type_Mammal : 1 [[comment("Mammal type")]]; + Penalty_ToHit_Dwarf : 1 [[comment("-4 Penalty To Hit vs Dwarves")]]; + Bonus_Damage_Ranger : 1 [[comment("Takes +1 Additional Damage Per Level from Rangers)")]]; + Type_Snake : 1 [[comment("Snake type")]]; + Penalty_ToHit_Gnome : 1 [[comment("-4 Penalty To Hit vs Gnomes")]]; + Type_Animal : 1 [[comment("Animal type")]]; + Bonus_ToHit_Dwarf : 1 [[comment("Dwarves Have +1 Bonus To Hit")]]; +}; + +// 9 - Character flags +bitfield FLAGARRAY09 { + Vulnerable_Dispel : 1 [[comment("Vulnerable to Dispel Evil (Extraplanar)")]]; + Type_Mammal : 1 [[comment("Mammal type")]]; + Penalty_ToHit_Dwarf : 1 [[comment("-4 Penalty To Hit vs Dwarves")]]; + Bonus_Damage_Ranger : 1 [[comment("Takes +1 Additional Damage Per Level from Rangers)")]]; + Type_Snake : 1 [[comment("Snake type")]]; + Penalty_ToHit_Gnome : 1 [[comment("-4 Penalty To Hit vs Gnomes")]]; + Type_Animal : 1 [[comment("Animal type")]]; + Bonus_ToHit_Dwarf : 1 [[comment("Dwarves Have +1 Bonus To Hit")]]; + Type_Giant : 1 [[comment("Giant type")]]; + Vulnerable_CharmHold : 1 [[comment("Vulnerable to Charm/Hold")]]; + Unknown_10 : 1 [[comment("Unknown Flag")]]; + Immune_DeathMagic : 1 [[comment("Immune to Death Magic")]]; + Immune_Poison : 1 [[comment("Immune to Poison")]]; + Immune_Decapitation : 1 [[comment("Immune to Decapitation")]]; + Immune_Confusion : 1 [[comment("Immune to Confusion")]]; +}; + +// 10 - Character flags +bitfield FLAGARRAY10 { + Vulnerable_Dispel : 1 [[comment("Vulnerable to Dispel Evil (Extraplanar)")]]; + Type_Mammal : 1 [[comment("Mammal type")]]; + Penalty_ToHit_Dwarf : 1 [[comment("-4 Penalty To Hit vs Dwarves")]]; + Bonus_Damage_Ranger : 1 [[comment("Takes +1 Additional Damage Per Level from Rangers)")]]; + Type_Snake : 1 [[comment("Snake type")]]; + Penalty_ToHit_Gnome : 1 [[comment("-4 Penalty To Hit vs Gnomes")]]; + Type_Animal : 1 [[comment("Animal type")]]; + Bonus_ToHit_Dwarf : 1 [[comment("Dwarves Have +1 Bonus To Hit")]]; + Type_Giant : 1 [[comment("Giant type")]]; + Vulnerable_CharmHold : 1 [[comment("Vulnerable to Charm/Hold")]]; + Bonus_ToHit_Gnome : 1 [[comment("Gnomes Have +1 Bonus To Hit")]]; + Immune_DeathMagic : 1 [[comment("Immune to Death Magic")]]; + Immune_Poison : 1 [[comment("Immune to Poison")]]; + Immune_Decapitation : 1 [[comment("Immune to Decapitation")]]; + Immune_Confusion : 1 [[comment("Immune to Confusion")]]; +}; + +/*********************** + Character record +***********************/ +// 1 - Player/Monster character record +struct CHAR01 { + u8 Name_Length [[comment("Contains the number of characters to read from the following Name field")]]; + char Name[15] [[format("std::string::to_string"),comment("The character's name")]]; + ABILITY Ability [[comment("Character ability values")]]; + SPL_NAME01 MemorizedSpell[21] [[comment("Spells currently memorized (available to cast) by the character")]]; + u8 Unknown_02C [[comment("Always 00")]]; + u8 THAC0_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Base THAC0 value, unaltered by equipment/effects")]]; + RACE_A Race [[comment("Index of the character's race")]]; + CLASS_A Class [[comment("Index of the character's current class")]]; + u16 Age [[comment("Character's age")]]; + u8 HP_Max [[comment("Character's max HP")]]; + SPL_KNOWN01 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + u8 LVL_Sweep [[comment("The level to use for the fighter sweep ability calculations")]]; + ICO_DIMENSION ICO_Dimension [[comment("Combo value that sets the number of tiles the character uses and a flag that indicates if the character is considered 'large' for combat calculations")]]; + SAVETHROW SAV_Base [[comment("Base saving throws")]]; + u8 MOV_Base [[comment("Base movement, excluding any modifiers")]]; + u8 LVL_Current_PreDrain [[comment("Highest unmodified level of currently active class")]]; + s8 LVL_Drained [[comment("Number of levels drained from character")]]; + s8 HP_Drained [[comment("Amount to subtract from HP_Max on drained characters")]]; + u8 MON_UndeadLevel [[comment("Undead level used in turn undead calculations")]]; + THIEFSKILL ThiefSkill [[comment("Thief skills")]]; + u32 ADDR_Effect [[comment("Pointer to effects linked to this character")]]; + u8 Unknown_083 [[comment("Unknown")]]; + u8 Morale [[comment("Value used for calculating when the character should bravely run away")]]; + u8 TreasureShare [[comment("Combo value for the amount of treasure the NPC will take")]]; + u8 Unknown_086 [[comment("Always 00")]]; + u8 Unknown_087 [[comment("Always 00")]]; + MONEY Money [[comment("The amount of money the character has")]]; + CLASSLEVEL LVL_Current [[comment("Current level with adjustments (draining) applied")]]; + GENDER_A Gender [[comment("Character's gender")]]; + MON_TYPE MON_Type [[comment("Character/creature type")]]; + ALIGNMENT_A Alignment [[comment("Index of the character's alignment")]]; + ATTACK ATK_Base [[comment("Base (unarmed) attack ability")]]; + u8 AC_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC unadjusted by equipment")]]; + bool STR_Bonus [[comment("Indicates if character's strength bonus (if any) should be added to attacks")]]; + u8 MON_Index [[comment("Index to the original record in a MON#CHA file for NPCs")]]; + u32 XP_Current [[comment("Character's current experience points")]]; + CLASSRESTRICTION ITM_Allowed [[comment("Bit array flagging the character's active classes")]]; + u8 HP_Base [[comment("Character's unadjusted HP")]]; + SPL_COUNT<3> SPL_Count_CL [[comment("Total number of Cleric spells the character can memorize")]]; + SPL_COUNT<3> SPL_Count_MU [[comment("Total number of Magic-User spells the character can memorize")]]; + u16 XP_Award_Base [[comment("Base XP awarded for killing the character")]]; + u8 XP_Award_Bonus [[comment("Additional XP awarded per HP of the character")]]; + u8 POR_Head [[comment("The character's head portrait image in HEAD3.DAX - Index to table in EXE for player characters")]]; + u8 POR_Body [[comment("The character's body portrait image in BODY3.DAX - Index to table in EXE for player characters")]]; + u8 ICO_Head [[format("FormatICOHead"),comment("ID number of the character's combat 'READY' head image for party members (+128 for 'ACTION' image ID)")]]; + u8 ICO_Body [[format("FormatICOBody"),comment("ID number of the character's combat 'READY' body image for party members - this follows the same logic as ICO_Head")]]; + u8 Party_Position [[comment("Character's position in the party list")]]; + ICO_SIZE ICO_Size [[comment("Indicates if the character's icon is shorter or tall (i.e. Dwarf vs Human)")]]; + ICO_COLOR ICO_Color [[comment("Combat icon colors")]]; + u8 ITM_Count [[comment("Number of items in the character's ITM file")]]; + INVENTORY Inventory [[comment("Pointers to the character's inventory items")]]; + u8 ITM_Hands [[comment("Number of equipped hands")]]; + u8 SAV_Bonus [[comment("Saving throw bonus")]]; + u16 ITM_Weight [[comment("Total weight the character is carrying from items/money")]]; + u32 ADDR_NextCharacter [[comment("Pointer to the next character record")]]; + u32 ADDR_Combat [[comment("Pointer to combat data")]]; + STATUS_A Status [[comment("Index to the character's status")]]; + bool IsActive [[comment("Indicates if the character can still move in combat")]]; + bool IsHostile [[comment("Indicates if the character wants to kill you")]]; + bool IsQuickFight [[comment("Indicates if quick fight is enabled for that character")]]; + u8 THAC0_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Current THAC0 value with equipment/dexterity/effects applied")]]; + u8 AC_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment")]]; + u8 AC_Back [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment when attacked from behind")]]; + ATTACK ATK_Current [[comment("Current attack ability")]]; + u8 HP_Current [[comment("The character's current HP")]]; + u8 MOV_Current [[comment("The character's current movement with equipment/effects applied")]]; +} [[name(std::format("{}", Name))]]; + +// 2/8 - Player/Monster character record +struct CHAR0208 { + u8 Name_Length [[comment("Contains the number of characters to read from the following Name field")]]; + char Name[15] [[format("std::string::to_string"),comment("The character's name")]]; + ABILITY Ability [[comment("Character ability values")]]; + SPL_MEMORIZED SPL_Memorized[84] [[comment("Spells currently memorized by the character")]]; + u8 Unknown_072 [[comment("Always 00")]]; + u8 THAC0_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Base THAC0 value, unaltered by equipment/effects")]]; + RACE_A Race [[comment("Index of the character's race")]]; + CLASS_A Class [[comment("Index of the character's current class")]]; + u16 Age [[comment("Character's age")]]; + u8 HP_Max [[comment("Character's max HP")]]; + if (GameID == 2) { + SPL_KNOWN02 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + } + else { + SPL_KNOWN08 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + } + u8 LVL_Sweep [[comment("The level to use for the fighter sweep ability calculations")]]; + ICO_DIMENSION ICO_Dimension [[comment("Combo value that sets the number of tiles the character uses and a flag that indicates if the character is considered 'large' for combat calculations")]]; + SAVETHROW SAV_Base [[comment("Base saving throws")]]; + u8 MOV_Base [[comment("Base movement, excluding any modifiers")]]; + u8 LVL_Current_PreDrain [[comment("Highest unmodified level of currently active class")]]; + u8 LVL_Previous_PreDrain [[comment("Highest unmodified level of previous class for dual class characters")]]; + s8 LVL_Drained [[comment("Number of levels drained from character")]]; + s8 HP_Drained [[comment("Amount to subtract from HP_Max on drained characters")]]; + u8 MON_UndeadLevel [[comment("Undead level used in turn undead calculations")]]; + THIEFSKILL ThiefSkill [[comment("Thief skills")]]; + u32 ADDR_Effect [[comment("Pointer to effects linked to this character")]]; + u8 Unknown_0F6 [[comment("Unknown")]]; + u8 Morale [[comment("Value used for calculating when the character should bravely run away")]]; + u8 TreasureShare [[comment("Combo value for the amount of treasure the NPC will take")]]; + u8 Unknown_0F9 [[comment("Always 00")]]; + u8 Unknown_0FA [[comment("Always 00")]]; + MONEY Money [[comment("The amount of money the character has")]]; + CLASSLEVEL LVL_Current [[comment("Current level with adjustments (draining) applied")]]; + CLASSLEVEL LVL_Previous [[comment("Previous level for dual class characters")]]; + GENDER_A Gender [[comment("Character's gender")]]; + MON_TYPE MON_Type [[comment("Character/creature type")]]; + ALIGNMENT_A Alignment [[comment("Index of the character's alignment")]]; + ATTACK ATK_Base [[comment("Base (unarmed) attack ability")]]; + u8 AC_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC unadjusted by equipment")]]; + bool STR_Bonus [[comment("Indicates if character's strength bonus (if any) should be added to attacks")]]; + u8 MON_Index [[comment("Index to the original record in a MON#CHA file for NPCs")]]; + u32 XP_Current [[comment("Character's current experience points")]]; + CLASSRESTRICTION ITM_Allowed [[comment("Bit array flagging the character's active classes")]]; + u8 HP_Base [[comment("Character's unadjusted HP")]]; + SPL_COUNT<5> SPL_Count_CL [[comment("Total number of Cleric spells the character can memorize")]]; + SPL_COUNT<5> SPL_Count_DR [[comment("Total number of Druid spells the character can memorize")]]; + SPL_COUNT<5> SPL_Count_MU [[comment("Total number of Magic-User spells the character can memorize")]]; + u16 XP_Award_Base [[comment("Base XP awarded for killing the character")]]; + u8 XP_Award_Bonus [[comment("Additional XP awarded per HP of the character")]]; + u8 POR_Head [[comment("Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 POR_Body [[comment("Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 ICO_Head [[format("FormatICOHead"),comment("ID number of the character's combat 'READY' head image for party members (+128 for 'ACTION' image ID)")]]; + u8 ICO_Body [[format("FormatICOBody"),comment("ID number of the character's combat 'READY' body image for party members - this follows the same logic as ICO_Head")]]; + u8 Party_Position [[comment("Character's position in the party list")]]; + ICO_SIZE ICO_Size [[comment("Indicates if the character's icon is shorter or tall (i.e. Dwarf vs Human)")]]; + ICO_COLOR ICO_Color [[comment("Combat icon colors")]]; + if (GameID == 2) { + FLAGARRAY02 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + } + else { + FLAGARRAY08 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + } + u8 ITM_Count [[comment("Number of items in the character's ITM file")]]; + INVENTORY Inventory [[comment("Pointers to the character's inventory items")]]; + u8 ITM_Hands [[comment("Number of equipped hands")]]; + u8 SAV_Bonus [[comment("Saving throw bonus")]]; + u16 ITM_Weight [[comment("Total weight the character is carrying from items/money")]]; + u32 ADDR_NextCharacter [[comment("Pointer to the next character record")]]; + u32 ADDR_Combat [[comment("Pointer to combat data")]]; + bool CanCureDisease [[comment("Indicates if character is able to use Paladin's cure disease ability")]]; + u8 Unknown_192 [[comment(std::format("{}", GameID == 2 ? "Always 00" : "Unknown"))]]; + u8 Unknown_193 [[comment("Always 00")]]; + u8 Unknown_194 [[comment("Always 00")]]; + STATUS_A Status [[comment("Index to the character's status")]]; + bool IsActive [[comment("Indicates if the character can still move in combat")]]; + bool IsHostile [[comment("Indicates if the character wants to kill you")]]; + bool IsQuickFight [[comment("Indicates if quick fight is enabled for that character")]]; + u8 THAC0_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Current THAC0 value with equipment/dexterity/effects applied")]]; + u8 AC_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment")]]; + u8 AC_Back [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment when attacked from behind")]]; + ATTACK ATK_Current [[comment("Current attack ability")]]; + u8 HP_Current [[comment("The character's current HP")]]; + u8 MOV_Current [[comment("The character's current movement with equipment/effects applied")]]; +} [[name(std::format("{}", Name))]]; + +// 3 - Player/Monster character record +struct CHAR03 { + u8 Name_Length [[comment("Contains the number of characters to read from the following Name field")]]; + char Name[15] [[format("std::string::to_string"),comment("The character's name")]]; + ABILITY Ability [[comment("Character ability values")]]; + SPL_MEMORIZED SPL_Memorized[75] [[comment("Spells currently memorized by the character")]]; + u8 Unknown_069 [[comment("Always 00")]]; + u8 THAC0_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Base THAC0 value, unaltered by equipment/effects")]]; + RACE_B Race [[comment("Index of the character's race")]]; + CLASS_A Class [[comment("Index of the character's current class")]]; + u8 CanCureDisease [[comment("Indicates if character is able to use Paladin's cure disease ability")]]; + u16 Age [[comment("Character's age")]]; + u8 HP_Max [[comment("Character's max HP")]]; + SPL_KNOWN03 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + u8 LVL_Sweep [[comment("The level to use for the fighter sweep ability calculations")]]; + ICO_DIMENSION ICO_Dimension [[comment("Combo value that sets the number of tiles the character uses and a flag that indicates if the character is considered 'large' for combat calculations")]]; + SAVETHROW SAV_Base [[comment("Base saving throws")]]; + u8 MOV_Base [[comment("Base movement, excluding any modifiers")]]; + u8 LVL_Current_PreDrain [[comment("Highest unmodified level of currently active class")]]; + u8 LVL_Previous_PreDrain [[comment("Highest unmodified level of previous class for dual class characters")]]; + s8 LVL_Drained [[comment("Number of levels drained from character")]]; + s8 HP_Drained [[comment("Amount to subtract from HP_Max on drained characters")]]; + u8 MON_UndeadLevel [[comment("Undead level used in turn undead calculations")]]; + THIEFSKILL ThiefSkill [[comment("Thief skills")]]; + u32 ADDR_Effect [[comment("Pointer to effects linked to this character")]]; + u8 Morale [[comment("Value used for calculating when the character should bravely run away")]]; + bool IsModified [[comment("Indicates if the character was 'modified' after creation")]]; + u8 Unknown_101 [[comment("Always 00")]]; + u8 Unknown_102 [[comment("Always 00")]]; + MONEY Money [[comment("The amount of money the character has")]]; + CLASSLEVEL LVL_Current [[comment("Current level with adjustments (draining) applied")]]; + CLASSLEVEL LVL_Previous [[comment("Previous level for dual class characters")]]; + GENDER_A Gender [[comment("Character's gender")]]; + ALIGNMENT_A Alignment [[comment("Index of the character's alignment")]]; + ATTACK ATK_Base [[comment("Base (unarmed) attack ability")]]; + u8 AC_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC unadjusted by equipment")]]; + bool STR_Bonus [[comment("Indicates if character's strength bonus (if any) should be added to attacks")]]; + u8 MON_Index [[comment("Index to the original record in a MON#CHA file for NPCs")]]; + u32 XP_Current [[comment("Character's current experience points")]]; + CLASSRESTRICTION ITM_Allowed [[comment("Bit array flagging the character's active classes")]]; + u8 HP_Base [[comment("Character's unadjusted HP")]]; + SPL_COUNT<7> SPL_Count_CL [[comment("Total number of Cleric spells the character can memorize")]]; + SPL_COUNT<7> SPL_Count_DR [[comment("Total number of Druid spells the character can memorize")]]; + SPL_COUNT<7> SPL_Count_SP [[comment("Total number of Special spells the character can memorize (Unused)")]]; + SPL_COUNT<7> SPL_Count_MU [[comment("Total number of Magic-User spells the character can memorize")]]; + u16 XP_Award_Base [[comment("Base XP awarded for killing the character")]]; + u8 XP_Award_Bonus [[comment("Additional XP awarded per HP of the character")]]; + u8 POR_Head [[comment("Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 POR_Body [[comment("Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 ICO_Head [[format("FormatICOHead"),comment("ID number of the character's combat 'READY' head image for party members (+128 for 'ACTION' image ID)")]]; + u8 ICO_Body [[format("FormatICOBody"),comment("ID number of the character's combat 'READY' body image for party members - this follows the same logic as ICO_Head")]]; + u8 Party_Position [[comment("Character's position in the party list")]]; + ICO_SIZE ICO_Size [[comment("Indicates if the character's icon is shorter or tall (i.e. Dwarf vs Human)")]]; + ICO_COLOR ICO_Color [[comment("Combat icon colors")]]; + FLAGARRAY03 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + u8 Unknown_15F [[comment("Always 00")]]; + u8 ITM_Count [[comment("Number of items in the character's ITM file")]]; + INVENTORY Inventory [[comment("Pointers to the character's inventory items")]]; + u8 ITM_Hands [[comment("Number of equipped hands")]]; + u8 SAV_Bonus [[comment("Saving throw bonus")]]; + u16 ITM_Weight [[comment("Total weight the character is carrying from items/money")]]; + u32 ADDR_NextCharacter [[comment("Pointer to the next character record")]]; + u32 ADDR_Combat [[comment("Pointer to combat data")]]; + u8 SPL_Resistance [[comment("Character's magic resistance percentage")]]; + STATUS_B Status [[comment("Index to the character's status")]]; + bool IsActive [[comment("Indicates if the character can still move in combat")]]; + bool IsHostile [[comment("Indicates if the character wants to kill you")]]; + bool IsQuickFight [[comment("Indicates if quick fight is enabled for that character")]]; + u8 THAC0_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Current THAC0 value with equipment/dexterity/effects applied")]]; + u8 AC_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment")]]; + u8 AC_Back [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment when attacked from behind")]]; + ATTACK ATK_Current [[comment("Current attack ability")]]; + u8 HP_Current [[comment("The character's current HP")]]; + u8 MOV_Current [[comment("The character's current movement with equipment/effects applied")]]; +} [[name(std::format("{}", Name))]]; + +// 4/9 - Player/Monster character record +struct CHAR0409 { + u8 Name_Length [[comment("Contains the number of characters to read from the following Name field")]]; + char Name[15] [[format("std::string::to_string"),comment("The character's name")]]; + ABILITY Ability [[comment("Character ability values")]]; + SPL_MEMORIZED SPL_Memorized[141] [[comment("Spells currently memorized by the character")]]; + u8 Unknown_0AB [[comment("Always 00")]]; + u8 THAC0_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Base THAC0 value, unaltered by equipment/effects")]]; + RACE_C Race [[comment("Index of the character's race")]]; + CLASS_A Class [[comment("Index of the character's current class")]]; + u8 CanCureDisease [[comment("Indicates if character is able to use Paladin's cure disease ability")]]; + u16 Age [[comment("Character's age")]]; + u8 HP_Max [[comment("Character's max HP")]]; + if (GameID == 4) { + SPL_KNOWN04 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + } + else { + SPL_KNOWN09 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + } + ICO_DIMENSION ICO_Dimension [[comment("Combo value that sets the number of tiles the character uses and a flag that indicates if the character is considered 'large' for combat calculations")]]; + SAVETHROW SAV_Base [[comment("Base saving throws")]]; + u8 MOV_Base [[comment("Base movement, excluding any modifiers")]]; + u8 LVL_Current_PreDrain [[comment("Highest unmodified level of currently active class")]]; + u8 LVL_Previous_PreDrain [[comment("Highest unmodified level of previous class for dual class characters")]]; + u8 MON_UndeadLevel [[comment("Undead level used in turn undead calculations")]]; + THIEFSKILL ThiefSkill [[comment("Thief skills")]]; + u32 ADDR_Effect [[comment("Pointer to effects linked to this character")]]; + u8 Morale [[comment("Value used for calculating when the character should bravely run away")]]; + bool IsModified [[comment("Indicates if the character was 'modified' after creation")]]; + u8 Unknown_149 [[comment(std::format("{}", GameID == 4 ? "Unknown" : "Always 00"))]]; + u8 Unknown_14A [[comment("Always 00")]]; + MONEY Money [[comment("The amount of money the character has")]]; + CLASSLEVEL LVL_Current [[comment("Current level with adjustments (draining) applied")]]; + CLASSLEVEL LVL_Previous [[comment("Previous level for dual class characters")]]; + CLASSLEVEL LVL_PreDrain [[comment("Level without adjustments (draining) applied")]]; + GENDER_A Gender [[comment("Character's gender")]]; + ALIGNMENT_A Alignment [[comment("Index of the character's alignment")]]; + ATTACK ATK_Base [[comment("Base (unarmed) attack ability")]]; + u8 AC_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC unadjusted by equipment")]]; + u8 MON_Index [[comment("Index to the original record in a MON1CHA file for NPCs")]]; + u32 XP_Current [[comment("Character's current experience points with draining (if any) applied")]]; + u32 XP_PreDrain [[comment("Character's experience points without adjustments (draining) applied")]]; + u8 HP_PreDrain [[comment("Character's HP_Max before draining was applied")]]; + CLASSRESTRICTION ITM_Allowed [[comment("Bit array flagging the character's active classes")]]; + u8 HP_Base [[comment("Character's unadjusted HP")]]; + SPL_COUNT<9> SPL_Count_CL [[comment("Total number of Cleric spells the character can memorize")]]; + SPL_COUNT<9> SPL_Count_DR [[comment("Total number of Druid spells the character can memorize")]]; + SPL_COUNT<9> SPL_Count_MU [[comment("Total number of Magic-User spells the character can memorize")]]; + u16 XP_Award_Base [[comment("Base XP awarded for killing the character")]]; + u8 ICO_Head [[format("FormatICOHead"),comment("ID number of the character's combat 'READY' head image for party members (+128 for 'ACTION' image ID)")]]; + u8 ICO_Body [[format("FormatICOBody"),comment("ID number of the character's combat 'READY' body image for party members - this follows the same logic as ICO_Head")]]; + u8 Party_Position [[comment("Character's position in the party list")]]; + ICO_SIZE ICO_Size [[comment("Indicates if the character's icon is shorter or tall (i.e. Dwarf vs Human)")]]; + ICO_COLOR ICO_Color [[comment("Combat icon colors")]]; + if (GameID == 4) { + FLAGARRAY04 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + } + else { + FLAGARRAY09 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + } + u8 ITM_Count [[comment("Number of items in the character's ITM file")]]; + INVENTORY Inventory [[comment("Pointers to the character's inventory items")]]; + u8 ITM_Hands [[comment("Number of equipped hands")]]; + u8 SAV_Bonus [[comment("Saving throw bonus")]]; + u16 ITM_Weight [[comment("Total weight the character is carrying from items/money")]]; + u32 ADDR_NextCharacter [[comment("Pointer to the next character record")]]; + u32 ADDR_Combat [[comment("Pointer to combat data")]]; + u8 SPL_Resistance [[comment("Character's magic resistance percentage")]]; + bool CanTrain [[comment("Indicates if the character has enough XP to train")]]; + STATUS_B Status [[comment("Index to the character's status")]]; + bool IsActive [[comment("Indicates if the character can still move in combat")]]; + bool IsHostile [[comment("Indicates if the character wants to kill you")]]; + bool IsQuickFight [[comment("Indicates if quick fight is enabled for that character")]]; + u8 THAC0_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Current THAC0 value with equipment/dexterity/effects applied")]]; + u8 AC_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment")]]; + u8 AC_Back [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment when attacked from behind")]]; + ATTACK ATK_Current [[comment("Current attack ability")]]; + u8 HP_Current [[comment("The character's current HP")]]; + u8 MOV_Current [[comment("The character's current movement with equipment/effects applied")]]; +} [[name(std::format("{}", Name))]]; + +// 5 - Player/Monster character record +struct CHAR05 { + u8 Name_Length [[comment("Contains the number of characters to read from the following Name field")]]; + char Name[15] [[format("std::string::to_string"),comment("The character's name")]]; + ABILITY Ability [[comment("Character ability values")]]; + SPL_MEMORIZED SPL_Memorized[58] [[comment("Spells currently memorized by the character")]]; + u8 Unknown_058 [[comment("Always 00")]]; + u8 THAC0_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Base THAC0 value, unaltered by equipment/effects")]]; + RACE_D Race [[comment("Index of the character's race")]]; + CLASS_B Class [[comment("Index of the character's current class")]]; + KNIGHTORDER KN_Order [[comment("Index of the character's knight order")]]; + DIETY CL_Diety [[comment("Index of the character's diety")]]; + ROBE MU_Robe [[comment("Index of the character's magic order/robe")]]; + u8 CanCureDisease [[comment("Indicates if character is able to use Paladin's cure disease ability")]]; + u16 Age [[comment("Character's age")]]; + u8 HP_Max [[comment("Character's max HP")]]; + SPL_KNOWN05 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + u8 LVL_Sweep [[comment("The level to use for the fighter sweep ability calculations")]]; + ICO_DIMENSION ICO_Dimension [[comment("Combo value that sets the number of tiles the character uses and a flag that indicates if the character is considered 'large' for combat calculations")]]; + SAVETHROW SAV_Base [[comment("Base saving throws")]]; + u8 MOV_Base [[comment("Base movement, excluding any modifiers")]]; + u8 LVL_Current_PreDrain [[comment("Highest unmodified level of currently active class")]]; + u8 LVL_Previous_PreDrain [[comment("*Highest unmodified level of previous class for dual class characters (Unused)")]]; + s8 LVL_Drained [[comment("Number of levels drained from character")]]; + s8 HP_Drained [[comment("Amount to subtract from HP_Max on drained characters")]]; + u8 MON_UndeadLevel [[comment("Undead level used in turn undead calculations")]]; + THIEFSKILL ThiefSkill [[comment("Thief skills")]]; + u32 ADDR_Effect [[comment("Pointer to effects linked to this character")]]; + u8 Morale [[comment("Value used for calculating when the character should bravely run away")]]; + bool IsModified [[comment("Indicates if the character was 'modified' after creation")]]; + u8 Unknown_0E9 [[comment("Always 00")]]; + u8 Unknown_0EA [[comment("Always 00")]]; + MONEY Money [[comment("The amount of money the character has")]]; + CLASSLEVEL LVL_Current [[comment("Current level with adjustments (draining) applied")]]; + CLASSLEVEL LVL_Previous [[comment("Previous level for dual class characters")]]; + GENDER_A Gender [[comment("Character's gender")]]; + ALIGNMENT_A Alignment [[comment("Index of the character's alignment")]]; + ATTACK ATK_Base [[comment("Base (unarmed) attack ability")]]; + u8 AC_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC unadjusted by equipment")]]; + bool STR_Bonus [[comment("Indicates if character's strength bonus (if any) should be added to attacks")]]; + u8 MON_Index [[comment("Index to the original record in a MON#CHA file for NPCs")]]; + u32 XP_Current [[comment("Character's current experience points")]]; + CLASSRESTRICTION ITM_Allowed [[comment("Bit array flagging the character's active classes")]]; + u8 HP_Base [[comment("Character's unadjusted HP")]]; + SPL_COUNT<5> SPL_Count_CL [[comment("Total number of Cleric spells the character can memorize")]]; + SPL_COUNT<5> SPL_Count_DR [[comment("Total number of Druid spells the character can memorize (Unused)")]]; + SPL_COUNT<5> SPL_Count_SP [[comment("Total number of Special spells the character can memorize")]]; + SPL_COUNT<5> SPL_Count_MU [[comment("Total number of Magic-User spells the character can memorize")]]; + u16 XP_Award_Base [[comment("Base XP awarded for killing the character")]]; + u8 XP_Award_Bonus [[comment("Additional XP awarded per HP of the character")]]; + u8 POR_Head [[comment("*Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 POR_Body [[comment("*Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 ICO_Head [[format("FormatICOHead"),comment("ID number of the character's combat 'READY' head image for party members (+128 for 'ACTION' image ID)")]]; + u8 ICO_Body [[format("FormatICOBody"),comment("ID number of the character's combat 'READY' body image for party members - this follows the same logic as ICO_Head")]]; + u8 Party_Position [[comment("Character's position in the party list")]]; + ICO_SIZE ICO_Size [[comment("Indicates if the character's icon is shorter or tall (i.e. Dwarf vs Human)")]]; + ICO_COLOR ICO_Color [[comment("Combat icon colors")]]; + FLAGARRAY05 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + u8 Unknown_141 [[comment("Always 00")]]; + u8 ITM_Count [[comment("Number of items in the character's ITM file")]]; + INVENTORY Inventory [[comment("Pointers to the character's inventory items")]]; + u8 ITM_Hands [[comment("Number of equipped hands")]]; + u8 SAV_Bonus [[comment("Saving throw bonus")]]; + u16 ITM_Weight [[comment("Total weight the character is carrying from items/money")]]; + u32 ADDR_NextCharacter [[comment("Pointer to the next character record")]]; + u32 ADDR_Combat [[comment("Pointer to combat data")]]; + u8 SPL_Resistance [[comment("Character's magic resistance percentage")]]; + STATUS_A Status [[comment("Index to the character's status")]]; + bool IsActive [[comment("Indicates if the character can still move in combat")]]; + bool IsHostile [[comment("Indicates if the character wants to kill you")]]; + bool IsQuickFight [[comment("Indicates if quick fight is enabled for that character")]]; + u8 THAC0_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Current THAC0 value with equipment/dexterity/effects applied")]]; + u8 AC_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment")]]; + u8 AC_Back [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment when attacked from behind")]]; + ATTACK ATK_Current [[comment("Current attack ability")]]; + u8 HP_Current [[comment("The character's current HP")]]; + u8 MOV_Current [[comment("The character's current movement with equipment/effects applied")]]; +} [[name(std::format("{}", Name))]]; + +// 6 - Player/Monster character record +struct CHAR06 { + u8 Name_Length [[comment("Contains the number of characters to read from the following Name field")]]; + char Name[15] [[format("std::string::to_string"),comment("The character's name")]]; + ABILITY Ability [[comment("Character ability values")]]; + u8 Unknown_01E [[comment("Always 00")]]; + u8 THAC0_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Base THAC0 value, unaltered by equipment/effects")]]; + RACE_D Race [[comment("Index of the character's race")]]; + CLASS_B Class [[comment("Index of the character's current class")]]; + KNIGHTORDER KN_Order [[comment("Index of the character's knight order")]]; + DIETY CL_Diety [[comment("Index of the character's diety")]]; + ROBE MU_Robe [[comment("Index of the character's magic order/robe")]]; + u8 CanCureDisease [[comment("Indicates if character is able to use Paladin's cure disease ability")]]; + u16 Age [[comment("Character's age")]]; + u8 HP_Max [[comment("Character's max HP")]]; + ICO_DIMENSION ICO_Dimension [[comment("Combo value that sets the number of tiles the character uses and a flag that indicates if the character is considered 'large' for combat calculations")]]; + SAVETHROW SAV_Base [[comment("Base saving throws")]]; + u8 MOV_Base [[comment("Base movement, excluding any modifiers")]]; + u8 LVL_Current_PreDrain [[comment("Highest unmodified level of currently active class")]]; + u8 MON_UndeadLevel [[comment("Undead level used in turn undead calculations")]]; + THIEFSKILL ThiefSkill [[comment("Thief skills")]]; + u32 ADDR_Effect [[comment("Pointer to effects linked to this character")]]; + u8 Morale [[comment("Value used for calculating when the character should bravely run away")]]; + MONEY Money [[comment("The amount of money the character has")]]; + CLASSLEVEL LVL_Current [[comment("Current level with adjustments (draining) applied")]]; + CLASSLEVEL LVL_Previous [[comment("Previous level for dual class characters")]]; + GENDER_A Gender [[comment("Character's gender")]]; + ALIGNMENT_A Alignment [[comment("Index of the character's alignment")]]; + ATTACK ATK_Base [[comment("Base (unarmed) attack ability")]]; + u8 AC_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC unadjusted by equipment")]]; + bool STR_Bonus [[comment("Indicates if character's strength bonus (if any) should be added to attacks")]]; + u8 MON_Index [[comment("Index to the original record in MON1CHA.DAX for NPCs")]]; + u32 XP_Current [[comment("Character's current experience points with draining (if any) applied")]]; + u32 XP_PreDrain [[comment("Character's experience points without adjustments (draining) applied")]]; + u8 HP_PreDrain [[comment("Character's HP_Max before draining was applied")]]; + CLASSRESTRICTION ITM_Allowed [[comment("Bit array flagging the character's active classes")]]; + u8 HP_Base [[comment("Character's unadjusted HP")]]; + u16 XP_Award_Base [[comment("Base XP awarded for killing the character")]]; + u8 XP_Award_Bonus [[comment("Additional XP awarded per HP of the character")]]; + u8 ICO_Head [[format("FormatICOHead"),comment("ID number of the character's combat 'READY' head image for party members (+128 for 'ACTION' image ID)")]]; + u8 ICO_Body [[format("FormatICOBody"),comment("ID number of the character's combat 'READY' body image for party members - this follows the same logic as ICO_Head")]]; + u8 Party_Position [[comment("Character's position in the party list")]]; + ICO_SIZE ICO_Size [[comment("Indicates if the character's icon is shorter or tall (i.e. Dwarf vs Human)")]]; + ICO_COLOR ICO_Color [[comment("Combat icon colors")]]; + FLAGARRAY06 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + u8 ITM_Count [[comment("Number of items in the character's ITM file")]]; + INVENTORY Inventory [[comment("Pointers to the character's inventory items")]]; + u8 ITM_Hands [[comment("Number of equipped hands")]]; + u8 SAV_Bonus [[comment("Saving throw bonus")]]; + u16 ITM_Weight [[comment("Total weight the character is carrying from items/money")]]; + u32 ADDR_NextCharacter [[comment("Pointer to the next character record")]]; + u32 ADDR_Combat [[comment("Pointer to combat data")]]; + u8 SPL_Resistance [[comment("Character's magic resistance percentage")]]; + u32 ADDR_Spell [[comment("Pointer to the character's spell data")]]; + bool CanTrain [[comment("Indicates if the character has enough XP to train")]]; + STATUS_A Status [[comment("Index to the character's status")]]; + bool IsActive [[comment("Indicates if the character can still move in combat")]]; + bool IsHostile [[comment("Indicates if the character wants to kill you")]]; + bool IsQuickFight [[comment("Indicates if quick fight is enabled for that character")]]; + u8 THAC0_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Current THAC0 value with equipment/dexterity/effects applied")]]; + u8 AC_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment")]]; + u8 AC_Back [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment when attacked from behind")]]; + ATTACK ATK_Current [[comment("Current attack ability")]]; + u8 HP_Current [[comment("The character's current HP")]]; + u8 MOV_Current [[comment("The character's current movement with equipment/effects applied")]]; +} [[name(std::format("{}", Name))]]; + +// 7 - Shared Player/Monster struct +struct CHAR_BASE07 { + u32 ADDR_NextCharacter [[comment("Pointer to the next character record")]]; + u32 ADDR_Effect [[comment("Pointer to effects linked to this character")]]; + INVENTORY Inventory [[comment("Pointers to the character's inventory items")]]; + u32 ADDR_Combat [[comment("Pointer to combat data")]]; + u32 XP_Current [[comment("Character's current experience points with draining (if any) applied")]]; + u32 XP_PreDrain [[comment("Character's experience points without adjustments (draining) applied")]]; + MONEY Money [[comment("The amount of money the character has")]]; + u16 Age [[comment("Character's age")]]; + u16 XP_Award_Base [[comment("Base XP awarded for killing the character")]]; + u16 ITM_Weight [[comment("Total weight the character is carrying from items/money")]]; + RACE_E Race [[comment("Index of the character's race")]]; + CLASS_C Class [[comment("Index of the character's current class")]]; + u16 MON_UndeadLevel [[comment("Undead level used in turn undead calculations")]]; + u16 Unknown_05E [[comment("Unknown")]]; + GENDER_B Gender [[comment("Character's gender")]]; + ALIGNMENT_B Alignment [[comment("Index of the character's alignment")]]; + STATUS_C Status [[comment("Index to the character's status")]]; + u16 IsHostile [[comment("Indicates if the character wants to kill you")]]; + char Name[16] [[format("std::string::to_string"),comment("The character's name")]]; + ABILITY Ability [[comment("Character ability values")]]; + u8 Unknown_086 [[comment("Always 00")]]; + u8 THAC0_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Base THAC0 value, unaltered by equipment/effects")]]; + u8 CanCureDisease [[comment("Indicates if character is able to use Paladin's cure disease ability")]]; + u8 HP_Max [[comment("Character's max HP")]]; + ICO_DIMENSION ICO_Dimension [[comment("Combo value that sets the number of tiles the character uses and a flag that indicates if the character is considered 'large' for combat calculations")]]; + SAVETHROW SAV_Base [[comment("Base saving throws")]]; + u8 MOV_Base [[comment("Base movement, excluding any modifiers")]]; + u8 LVL_Current_PreDrain [[comment("Highest unmodified level of currently active class")]]; + u8 LVL_Previous_PreDrain [[comment("*Highest unmodified level of previous class for dual class characters (Unused)")]]; + THIEFSKILL ThiefSkill [[comment("Thief skills")]]; + u8 Morale [[comment("Value used for calculating when the character should bravely run away")]]; + u8 LVL_Sweep [[comment("The level to use for the fighter sweep ability calculations")]]; + u8 Unknown_09D [[comment("Always 00")]]; + CLASSLEVEL LVL_PreDrain [[comment("Level without adjustments (draining) applied")]]; + CLASSLEVEL LVL_Current [[comment("Current level with adjustments (draining) applied")]]; + CLASSLEVEL LVL_Previous [[comment("Previous level for dual class characters")]]; + ATTACK ATK_Base [[comment("Base (unarmed) attack ability")]]; + u8 AC_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC unadjusted by equipment")]]; + bool STR_Bonus [[comment("Indicates if character's strength bonus (if any) should be added to attacks")]]; + u8 MON_Index [[comment("Index to the original record in MONCHA.GLB for NPCs")]]; + u8 HP_PreDrain [[comment("Character's HP_Max before draining was applied")]]; + CLASSRESTRICTION ITM_Allowed [[comment("Bit array flagging the character's active classes")]]; + u8 HP_Base [[comment("Character's unadjusted HP")]]; + u8 POR_Head [[comment("*Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 POR_Body [[comment("*Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 ICO_Head [[comment("*Carried over from previous games but not used as characters are predefined in 7/10")]]; + u8 ICO_ID [[comment("Index to the image in CBODY.TLB for the character's combat icon")]]; + u8 Party_Position [[comment("Character's position in the party list")]]; + ICO_SIZE ICO_Size [[comment("*Carried over from previous games but not used as characters are predefined in 7/10")]]; + FLAGARRAY07 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + u8 ITM_Count [[comment("Number of items in the character's inventory - Not set on MON records")]]; + u8 ITM_Hands [[comment("Number of equipped hands")]]; + u8 SAV_Bonus [[comment("Saving throw bonus")]]; + u8 SPL_Resistance [[comment("Character's magic resistance percentage")]]; + bool CanTrain [[comment("Indicates if the character has enough XP to train")]]; + SPL_MEMORIZED SPL_Memorized[137] [[comment("Spells currently memorized by the character")]]; + SPL_KNOWN07 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + SPL_COUNT<9> SPL_Count_CL [[comment("Total number of Cleric spells the character can memorize")]]; + SPL_COUNT<9> SPL_Count_DR [[comment("Total number of Druid spells the character can memorize")]]; + SPL_COUNT<9> SPL_Count_MU [[comment("Total number of Magic-User spells the character can memorize")]]; + SPL_COUNT<9> SPL_Count_SP [[comment("Total number of Special spells the character can memorize")]]; + bool IsActive [[comment("Indicates if the character can still move in combat")]]; + bool IsQuickFight [[comment("Indicates if quick fight is enabled for that character")]]; + u8 THAC0_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Current THAC0 value with equipment/dexterity/effects applied")]]; + u8 AC_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment")]]; + u8 AC_Back [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment when attacked from behind")]]; + ATTACK ATK_Current [[comment("Current attack ability")]]; + u8 HP_Current [[comment("The character's current HP")]]; + u8 MOV_Current [[comment("The character's current movement with equipment/effects applied")]]; + KNIGHTORDER KN_Order [[comment("Index of the character's knight order")]]; + DIETY CL_Diety [[comment("Index of the character's diety")]]; + u8 MON_Slot [[comment("Monster slot ID - 10 only (Unused)")]]; + ROBE MU_Robe [[comment("Index of the character's magic order/robe")]]; +} [[name(std::format("{}", Name))]]; + +// 7 - Player character struct +struct CHAR_CHR07 : CHAR_BASE07 { + ITEM Item[ITM_Count] [[comment("Items in the character's inventory")]]; + if (ADDR_Effect != 0) { + SFX_CHR07 SFX_Effect[GetSFXCount(9)] [[comment("Active effect or ability")]]; + } +}; + +// 7 - Monster struct +struct CHAR_MON07 : CHAR_BASE07 { + u8 SFX_Count [[comment("Number of active effects on the character")]]; + u8 ITM_Count_MON [[comment("Number of items in the character's inventory")]]; + SFX_BASE SFX_Effect[SFX_Count] [[comment("Active effect or ability")]]; + ITEM Item[ITM_Count_MON] [[comment("Items in the character's inventory")]]; + u8 Unknown_LastByte; +}; + +// 10 - Shared Player/Monster struct +struct CHAR_BASE10 { + u32 ADDR_NextCharacter [[comment("Pointer to the next character record")]]; + u32 ADDR_Effect [[comment("Pointer to effects linked to this character")]]; + INVENTORY Inventory [[comment("Pointers to the character's inventory items")]]; + u32 ADDR_Combat [[comment("Pointer to combat data")]]; + u32 XP_Current [[comment("Character's current experience points with draining (if any) applied")]]; + u32 XP_PreDrain [[comment("Character's experience points without adjustments (draining) applied")]]; + MONEY Money [[comment("The amount of money the character has")]]; + u16 Age [[comment("Character's age")]]; + u16 XP_Award_Base [[comment("Base XP awarded for killing the character")]]; + u16 ITM_Weight [[comment("Total weight the character is carrying from items/money")]]; + RACE_C Race [[comment("Index of the character's race")]]; + CLASS_D Class [[comment("Index of the character's current class")]]; + UNDEADTYPE MON_UndeadLevel [[comment("Undead level used in turn undead calculations")]]; + u8 Unknown_05B [[comment("Always 00")]]; + GENDER_A Gender [[comment("Character's gender")]]; + ALIGNMENT_A Alignment [[comment("Index of the character's alignment")]]; + STATUS_B Status [[comment("Index to the character's status")]]; + bool IsHostile [[comment("Indicates if the character wants to kill you")]]; + char Name[16] [[format("std::string::to_string"),comment("The character's name")]]; + ABILITY Ability [[comment("Character ability values")]]; + u8 Unknown_07E [[comment("Always 00")]]; + u8 THAC0_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Base THAC0 value, unaltered by equipment/effects")]]; + u8 CanCureDisease [[comment("Indicates if character is able to use Paladin's cure disease ability")]]; + u8 HP_Max [[comment("Character's max HP")]]; + ICO_DIMENSION ICO_Dimension [[comment("Combo value that sets the number of tiles the character uses and a flag that indicates if the character is considered 'large' for combat calculations")]]; + SAVETHROW SAV_Base [[comment("Base saving throws")]]; + u8 MOV_Base [[comment("Base movement, excluding any modifiers")]]; + u8 LVL_Current_PreDrain [[comment("Highest unmodified level of currently active class")]]; + u8 LVL_Previous_PreDrain [[comment("Highest unmodified level of previous class for dual class characters")]]; + THIEFSKILL ThiefSkill [[comment("Thief skills")]]; + u8 Morale [[comment("Value used for calculating when the character should bravely run away")]]; + u8 LVL_Sweep [[comment("The level to use for the fighter sweep ability calculations")]]; + u8 Unknown_095 [[comment("Always 00")]]; + CLASSLEVEL LVL_PreDrain [[comment("Level without adjustments (draining) applied")]]; + CLASSLEVEL LVL_Current [[comment("Current level with adjustments (draining) applied")]]; + CLASSLEVEL LVL_Previous [[comment("Previous level for dual class characters")]]; + ATTACK ATK_Base [[comment("Base (unarmed) attack ability")]]; + u8 AC_Base [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC unadjusted by equipment")]]; + bool STR_Bonus [[comment("Indicates if character's strength bonus (if any) should be added to attacks")]]; + u8 MON_Index [[comment("Index to the original record in MONCHA.GLB for NPCs")]]; + u8 HP_PreDrain [[comment("Character's HP_Max before draining was applied")]]; + CLASSRESTRICTION ITM_Allowed [[comment("Bit array flagging the character's active classes")]]; + u8 HP_Base [[comment("Character's unadjusted HP")]]; + u8 POR_Head [[comment("*Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 POR_Body [[comment("*Carried over from 1 but no longer used as portraits were removed in later games")]]; + u8 ICO_Head [[comment("*Carried over from previous games but not used as characters are predefined in 7/10")]]; + u8 ICO_ID [[comment("Index to the image in CBODY.TLB for the character's combat icon")]]; + u8 Party_Position [[comment("Character's position in the party list")]]; + ICO_SIZE ICO_Size [[comment("*Carried over from previous games but not used as characters are predefined in 7/10")]]; + FLAGARRAY10 CharacterFlag [[comment("Bit array flagging various character attributes")]]; + u8 ITM_Count [[comment("Number of items in the character's inventory")]]; + u8 ITM_Hands [[comment("Number of equipped hands")]]; + u8 SAV_Bonus [[comment("Saving throw bonus")]]; + u8 SPL_Resistance [[comment("Character's magic resistance percentage")]]; + bool CanTrain [[comment("Indicates if the character has enough XP to train")]]; + SPL_MEMORIZED SPL_Memorized[141] [[comment("Spells currently memorized by the character")]]; + SPL_KNOWN10 SPL_Known [[comment("Spells known (can memorize) by the character")]]; + SPL_COUNT<9> SPL_Count_CL [[comment("Total number of Cleric spells the character can memorize")]]; + SPL_COUNT<9> SPL_Count_DR [[comment("Total number of Druid spells the character can memorize")]]; + SPL_COUNT<9> SPL_Count_MU [[comment("Total number of Magic-User spells the character can memorize")]]; + bool IsActive [[comment("Indicates if the character can still move in combat")]]; + bool IsQuickFight [[comment("Indicates if quick fight is enabled for that character")]]; + u8 THAC0_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Current THAC0 value with equipment/dexterity/effects applied")]]; + u8 AC_Current [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment")]]; + u8 AC_Back [[format_read("FormatACTHAC0"),format_write("FormatACTHAC0"),comment("Character's AC adjusted by equipment when attacked from behind")]]; + ATTACK ATK_Current [[comment("Current attack ability")]]; + u8 HP_Current [[comment("The character's current HP")]]; + u8 MOV_Current [[comment("The character's current movement with equipment/effects applied")]]; + u8 MON_Slot [[comment("Monster slot ID")]]; +} [[name(std::format("{}", Name))]]; + +// 10 - Player character struct +struct CHAR_CHR10 : CHAR_BASE10 { + ITEM Item[ITM_Count] [[comment("Items in the character's inventory")]]; + SFX_CHR10 SFX_Effect[GetSFXCount(10)] [[comment("Active effect or ability")]]; +}; + +// 10 - Monster struct +struct CHAR_MON10 : CHAR_BASE10 { + ITM_MON10 Item[16] [[comment("Items in the character's inventory")]]; +// Since we're offsetting to get the ItemID/Quantity paired, it doesn't actually move the read position forward, so need to skip the Quantity values + padding[16]; + SFX_MON10 SFX_EffectID[20] [[comment("Active effect or ability ID (0 = None)")]]; +}; + +// Generic struct - ImHex doesn't export to PatternData on conditionals (or I'm doing it wrong) so using this as a workaround +struct CHAR { + match (GameID,IsMON,IsSAV) { + (1,_,_): CHAR01 Character; + (2|8,_,_): CHAR0208 Character; + (3,_,_): CHAR03 Character; + (4|9,_,_): CHAR0409 Character; + (5,_,_): CHAR05 Character; + (6,_,_): CHAR06 Character; + (7,true,false): CHAR_MON07 Monster; + (7,false,true): CHAR_CHR07 Character[CHARCount] [[inline]]; + (7,false,false): CHAR_CHR07 Character; + (10,true,false): CHAR_MON10 Monster; + (10,false,true): CHAR_CHR10 Character[CHARCount] [[inline]]; + (10,false,false): CHAR_CHR10 Character; + } +}; + +CHAR Character @ Offset; \ No newline at end of file diff --git a/patterns/GoldBox/GB_ENUM.cs b/patterns/GoldBox/GB_ENUM.cs new file mode 100644 index 00000000..39012c18 --- /dev/null +++ b/patterns/GoldBox/GB_ENUM.cs @@ -0,0 +1,1568 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Common Enumerations +#pragma once + +// Alignment - 1-6/8-10 +enum ALIGNMENT_A:u8 { + LawfulGood = 0, + LawfulNeutral = 1, + LawfulEvil = 2, + NeutralGood = 3, + TrueNeutral = 4, + NeutralEvil = 5, + ChaoticGood = 6, + ChaoticNeutral = 7, + ChaoticEvil = 8 +}; + +// Alignment - 7 - Identical to ALIGNMENT_A but is u16 (2 bytes) +enum ALIGNMENT_B:u16 { + LawfulGood = 0, + LawfulNeutral = 1, + LawfulEvil = 2, + NeutralGood = 3, + TrueNeutral = 4, + NeutralEvil = 5, + ChaoticGood = 6, + ChaoticNeutral = 7, + ChaoticEvil = 8 +}; + +/*** + Boolean + Some games have boolean values where non-zero = true + Generally just a thing in MON records and typically in SPL_Known + Handling as an ENUM so can have drop down list in PatternData +***/ +enum BOOL:u8 { + False = 0, + True = 1 ... 255 +}; + +// Class - 1-4/8-9 +enum CLASS_A:u8 { + Cleric = 0, + Druid = 1, + Fighter = 2, + Paladin = 3, + Ranger = 4, + MagicUser = 5, + Thief = 6, + Monk = 7, + Cleric_Fighter = 8, + Cleric_Fighter_MagicUser = 9, + Cleric_Ranger = 10, + Cleric_MagicUser = 11, + Cleric_Thief = 12, + Fighter_MagicUser = 13, + Fighter_Thief = 14, + Fighter_MagicUser_Thief = 15, + MagicUser_Thief = 16, + Monster = 17 +}; + +// Class - 5-6 +enum CLASS_B:u8 { + Cleric = 0, + Druid = 1, + Fighter = 2, + Paladin = 3, + Ranger = 4, + MagicUser = 5, + Thief = 6, + Knight = 7, + Cleric_Fighter = 8, + Cleric_Fighter_MagicUser = 9, + Cleric_Ranger = 10, + Cleric_MagicUser = 11, + Cleric_Thief = 12, + Fighter_MagicUser = 13, + Fighter_Thief = 14, + Fighter_MagicUser_Thief = 15, + MagicUser_Thief = 16, + Monster = 17 +}; + +// Class - 7 +enum CLASS_C:u16 { + Cleric = 0, + Knight = 1, + Fighter = 2, + Paladin = 3, + Ranger = 4, + MagicUser = 5, + Thief = 6, + Monk = 7, + Cleric_Fighter = 8, + Cleric_Fighter_MagicUser = 9, + Cleric_Ranger = 10, + Cleric_MagicUser = 11, + Cleric_Thief = 12, + Fighter_MagicUser = 13, + Fighter_Thief = 14, + Fighter_MagicUser_Thief = 15, + MagicUser_Thief = 16, + Monster = 17 +}; + +// Class - 10 +enum CLASS_D:u8 { + Cleric = 0, + Knight = 1, + Fighter = 2, + Paladin = 3, + Ranger = 4, + MagicUser = 5, + Thief = 6, + Monk = 7, + Cleric_Fighter = 8, + Cleric_Fighter_MagicUser = 9, + Cleric_Ranger = 10, + Cleric_MagicUser = 11, + Cleric_Thief = 12, + Fighter_MagicUser = 13, + Fighter_Thief = 14, + Fighter_MagicUser_Thief = 15, + MagicUser_Thief = 16, + Monster = 17 +}; + +// Item Class Restrictions +bitfield CLASSRESTRICTION { + MagicUser : 1 [[name("Magic-User")]]; + Cleric : 1; + Thief : 1; + Fighter : 1; + match (GameID) { + (1|2|8): { + Druid : 1 [[name("Druid*"),comment("Unused")]]; + Monk : 1 [[name("Monk*"),comment("Unused")]]; + } + (5|6|7): { + Knight : 1 [[name("Knight")]]; + Druid : 1 [[name("Druid*"),comment("Unused")]]; + } + (_): { + Knight : 1 [[name("Knight*"),comment("Unused")]]; + Druid : 1 [[name("Druid*"),comment("Unused")]]; + } + } + match (GameID) { + (1): { + PaladinRanger : 1 [[name("Paladin/Ranger*"),comment("Unused")]]; + padding : 1; + } + (5|6|7): { + Paladin : 1; + Ranger : 1; + } + (_): { + Paladin : 1 [[comment("Ranger class characters refer to this value")]]; + Ranger : 1 [[name("Ranger**"),comment("Ranger class characters have Paladin flag set\nUnused")]]; + } + } +}; + +// Icon Color +enum COLORNAME:u8 { + DarkGray = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + Black = 8, + BrightBlue = 9, + BrightGreen = 10, + BrightCyan = 11, + BrightRed = 12, + BrightMagenta = 13, + BrightYellow = 14, + BrightWhite = 15 +}; + +// Diety - 5-7 +enum DIETY:u8 { + None = 0, + Paladine = 1, + Majere = 2, + KiriJolith = 3, + Mishakal = 4, + Sirrion = 5, + Reorx = 6, + Shinare = 7 +}; + +// Icon Dimension - The underscore looks dumb but it won't work with a leading number +enum DIMENSION:u8 { + _1x1 = 1, + _1x2 = 2, + _2x1 = 3, + _2x2 = 4, + _3x2 = 5 +}; + +// Gender - 1-6/8-10 +enum GENDER_A:u8 { + Male = 0, + Female = 1 +}; + +// Gender - 7 - Identical to GENDER_A but is u16 (2 bytes) +enum GENDER_B:u16 { + Male = 0, + Female = 1 +}; + +// Icon Size +enum ICO_SIZE:u8 { + NotApplicable = 0, + Small = 1, + Large = 2 +}; + +// Knight Order - 5-7 +enum KNIGHTORDER:u8 { + None = 0, + Crown = 1, + Sword = 2, + Rose = 3 +}; + +// Monster Type - 1-2/8 +enum MON_TYPE:u8 { + Humanoid = 0, + MonstrousHumanoid = 1, + Giant = 2, + Dragon = 3, + Undead = 4, + Unknown05 = 5, + Unknown06 = 6, + Extraplanar = 7, + FireBased = 8, + ColdBased = 9, + Regenerating = 10, + Reptile = 11, + Avian = 12, + Aquatic = 13, + Snake = 14, + Mammal = 15, + Insect = 16, + Monster = 17, + Plant = 18, + Beast = 19 +}; + +// Undead Type - 10 +enum UNDEADTYPE:u8 { + NotUndead = 0, + Skeleton = 1, + Zombie = 2, + Ghoul = 3, + Shadow = 4, + Wight = 5, + Ghast = 6, + Wraith = 7, + Mummy = 8, + Spectre = 9, + Vampire = 10, + Ghost = 11, + Lich = 12, + Special = 13 +}; + +// Race - 1-2 & 8 +enum RACE_A:u8 { + Monster = 0, + Dwarf = 1, + Elf = 2, + Gnome = 3, + HalfElf = 4, + Halfling = 5, + HalfOrc = 6, + Human = 7 +}; + +// Race - 3 +enum RACE_B:u8 { + Tribble = 0, + Elf = 1, + HalfElf = 2, + Dwarf = 3, + Gnome = 4, + Halfling = 5, + Human = 6, + Monster = 7 +}; + +// Race - 4 & 9-10 +enum RACE_C:u8 { + Elf = 0, + HalfElf = 1, + Dwarf = 2, + Gnome = 3, + Halfling = 4, + Human = 5, + Monster = 6 +}; + +// Race - 5-6 +enum RACE_D:u8 { + SilvanestiElf = 0, + QualinestiElf = 1, + HalfElf = 2, + MountainDwarf = 3, + HillDwarf = 4, + Kender = 5, + Human = 6, + Monster = 7 +}; + +// Race - 7 - Identical to RACE_D but is u16 (2 bytes) +enum RACE_E:u16 { + SilvanestiElf = 0, + QualinestiElf = 1, + HalfElf = 2, + MountainDwarf = 3, + HillDwarf = 4, + Kender = 5, + Human = 6, + Monster = 7 +}; + +// Robe - 5-7 +enum ROBE:u8 { + None = 0, + White = 1, + Red = 2, + Black = 3 +}; + +// Status - 1-2/5-6/8 +enum STATUS_A:u8 { + Okay = 0, + Animated = 1, + tempgone = 2, + Running = 3, + Unconscious = 4, + Dying = 5, + Dead = 6, + Stoned = 7, + Gone = 8 +}; + +// Status - 3-4/9-10 +enum STATUS_B:u8 { + Okay = 0, + Animated = 1, + tempgone = 2, + Running = 3, + Unconscious = 4, + Dying = 5, + Dead = 6, + Petrified = 7, + Gone = 8 +}; + +// Status - 7 - Identical to STATUS_B but is u16 (2 bytes) +enum STATUS_C:u16 { + Okay = 0, + Animated = 1, + tempgone = 2, + Running = 3, + Unconscious = 4, + Dying = 5, + Dead = 6, + Petrified = 7, + Gone = 8 +}; + +/******************************* + Spell names +*******************************/ +// Spell names - 1 +enum SPL_NAME01:u8 { + None = 0, + CL1_Bless = 1, + CL1_Curse = 2, + CL1_CureLightWounds = 3, + CL1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + CL3_AnimateDead = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + CL7_Restoration = 56, + IT6_PotionOfSpeed = 57, + IT6_Unknown_58 = 58, + IT6_PotionOfGiantStrength = 59, + IT6_JavelinOfLightning = 60, + IT6_WandOfParalyzation = 61, + IT6_PotionOfHealing = 62, + IT6_DustOfDisappearance = 63, + IT6_NecklaceOfMissiles = 64, + IT6_WandOfMagicMissiles = 65, + IT6_Unknown_66 = 66, + IT6_ManualOfBodilyHealth = 67 +}; + +// Spell names - 2 +enum SPL_NAME02:u8 { + None = 0, + CL1_Bless = 1, + CL1_Curse = 2, + CL1_CureLightWounds = 3, + CL1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + IT7_AnimateDead = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + CL7_Restoration = 56, + IT6_PotionOfSpeed = 57, + CL4_CureSeriousWounds = 58, + IT6_PotionOfGiantStrength = 59, + IT6_JavelinOfLightning = 60, + IT6_WandOfParalyzation = 61, + IT6_PotionOfHealing = 62, + IT6_DustOfDisappearance = 63, + IT6_NecklaceOfMissiles = 64, + IT6_WandOfMagicMissiles = 65, + CL4_CauseSeriousWounds = 66, + CL4_NeutralizePoison = 67, + CL4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + CL5_CauseCriticalWounds = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + CL5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + IT5_AnimateDead = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtDragonBreath = 95, + IT6_ScrollOfProtParalyzation = 96, + IT6_PotionOfInvisibility = 97, + IT6_WandOfDefoliation = 98, + IT6_PotionExtraHealing = 99, + MU4_BestowCurse = 100 +}; + +// Spell names - 3 +enum SPL_NAME03:u8 { + None = 0, + CL1_Bless = 1, + CL1_Curse = 2, + CL1_CureLightWounds = 3, + CL1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + CL6_Heal = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + CL6_Harm = 56, + IT6_PotionOfSpeed = 57, + CL4_CureSeriousWounds = 58, + IT6_PotionOfGiantStrength = 59, + IT6_JavelinOfLightning = 60, + IT6_WandOfParalyzation = 61, + IT6_PotionOfHealing = 62, + IT6_ElixirOfYouth = 63, + IT6_NecklaceOfMissiles = 64, + IT6_WandOfMagicMissiles = 65, + CL4_CauseSeriousWounds = 66, + CL4_NeutralizePoison = 67, + CL4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + CL5_CauseCriticalWounds = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + CL5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + DR2_Barkskin = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtDragonBreath = 95, + DR2_CharmPersonOrMammal = 96, + IT6_PotionOfInvisibility = 97, + DR2_CureLightWounds = 98, + IT6_PotionExtraHealing = 99, + MU4_BestowCurse = 100, + IT0_ProtectionFromEvil10Radius = 101, + IT0_Silence15Radius = 102, + IT0_DetectMagic = 103, + IT0_RemoveCurse = 104, + IT0_Bless = 105, + IT0_CharmPerson = 106, + IT0_BurningHands = 107, + DR9_Spell108 = 108, + MU0_Spell109 = 109, + MU6_DeathSpell = 110, + MU6_Disintegrate = 111, + MU6_GlobeOfInvulnerability = 112, + MU6_StoneToFlesh = 113, + MU6_FleshToStone = 114, + MU7_DelayedBlastFireball = 115, + MU7_MassInvisibility = 116, + MU7_PowerWordStun = 117 +}; + +// Spell names - 4 +enum SPL_NAME04:u8 { + None = 0, + CL1_Bless = 1, + CL1_Curse = 2, + CL1_CureLightWounds = 3, + CL1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + CL6_Heal = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + CL6_Harm = 56, + IT6_PotionOfSpeed = 57, + CL4_CureSeriousWounds = 58, + IT6_PotionOfGiantStrength = 59, + IT6_JavelinOfLightning = 60, + IT6_WandOfParalyzation = 61, + IT6_PotionOfHealing = 62, + IT6_ElixirOfYouth = 63, + IT6_NecklaceOfMissiles = 64, + IT6_WandOfMagicMissiles = 65, + CL4_CauseSeriousWounds = 66, + CL4_NeutralizePoison = 67, + CL4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + CL5_CauseCriticalWounds = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + CL5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + DR2_Barkskin = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtDragonBreath = 95, + DR2_CharmPersonOrMammal = 96, + IT6_PotionOfInvisibility = 97, + DR2_CureLightWounds = 98, + IT6_PotionOfExtraHealing = 99, + MU4_BestowCurse = 100, + CL6_BladeBarrier = 101, + CL7_Restoration = 102, + CL7_EnergyDrain = 103, + CL7_Destruction = 104, + CL7_Resurrection = 105, + DR3_CureDisease = 106, + DR3_NeutralizePoison = 107, + DR3_HoldAnimal = 108, + DR3_ProtFromFire = 109, + MU6_DeathSpell = 110, + MU6_Disintegrate = 111, + MU6_GlobeOfInvulnerability = 112, + MU6_StoneToFlesh = 113, + MU6_FleshToStone = 114, + MU7_DelayedBlastFireball = 115, + MU7_MassInvisibility = 116, + MU7_PowerWordStun = 117, + MU5_FireTouch = 118, + MU5_IronSkin = 119, + MU8_MassCharm = 120, + MU8_OttosIrrDance = 121, + MU8_MindBlank = 122, + MU8_PowerWordBlind = 123, + MU9_MeteorSwarm = 124, + MU9_PowerWordKill = 125, + MU9_MonsterSummoning = 126 +}; + +// Spell names - 5 +enum SPL_NAME05:u8 { + None = 0, + CL1_Bless = 1, + CL1_Curse = 2, + CL1_CureLightWounds = 3, + CL1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + IT7_AnimateDead = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + CL7_Restoration = 56, + IT6_PotionOfSpeed = 57, + CL4_CureSeriousWounds = 58, + IT6_PotionOfGiantStrength = 59, + IT6_JavelinOfLightning = 60, + IT6_WandOfParalyzation = 61, + IT6_PotionOfHealing = 62, + IT6_DustOfDisappearance = 63, + IT6_NecklaceOfMissiles = 64, + IT6_WandOfMagicMissiles = 65, + CL4_CauseSeriousWounds = 66, + CL4_NeutralizePoison = 67, + CL4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + CL5_CauseCriticalWounds = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + CL5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + IT5_AnimateDead = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtDragonBreath = 95, + IT6_ScrollOfProtParalyzation = 96, + IT6_PotionOfInvisibility = 97, + IT6_WandOfDefoliation = 98, + IT6_PotionExtraHealing = 99, + MU4_BestowCurse = 100, + SP0_ProtectionFromEvil10Radius = 101, + SP0_Silence15Radius = 102, + SP0_DetectMagic = 103, + SP0_RemoveCurse = 104, + SP0_Bless = 105, + SP0_CharmPerson = 106, + SP0_BurningHands = 107 +}; + +// Spell names - 6 +enum SPL_NAME06:u8 { + None = 0, + CL1_Bless = 1, + DR2_Barkskin = 2, + CL1_CureLightWounds = 3, + DR2_CharmPersonMammal = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL7_Resurrection = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + CL7_Restoration = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + IT7_AnimateDead = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL6_Harm = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + CL6_Heal = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + MU6_DeathSpell = 56, + IT6_PotionOfSpeed = 57, + CL4_CureSeriousWounds = 58, + IT6_PotionOfGiantStrength = 59, + MU6_Disentegrate = 60, + IT6_WandOfParalyzation = 61, + IT6_PotionOfHealing = 62, + MU6_GlobeOfInvulnerability = 63, + IT6_NecklaceOfMissiles = 64, + IT6_WandOfMagicMissiles = 65, + MU6_StoneToFlesh = 66, + CL4_NeutralizePoison = 67, + CL4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + MU6_FleshToStone = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + CL5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + MU5_IronSkin = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtDragonBreath = 95, + IT6_ElixirOfYouth = 96, + IT6_PotionOfInvisibility = 97, + MU5_FireTouch = 98, + IT6_PotionExtraHealing = 99, + MU4_BestowCurse = 100, + SP0_ProtectionFromEvil10Radius = 101, + SP0_Silence15Radius = 102, + SP0_DetectMagic = 103, + SP0_RemoveCurse = 104, + SP0_Bless = 105, + SP0_CharmPerson = 106, + SP0_BurningHands = 107, + MU7_DelayBlastFireball = 108, + MU7_MassInvisibility = 109, + MU7_PowerWordStun = 110, + MU8_MassCharm = 111, + MU8_MindBlank = 112, + MU8_OttosIrresitableDance = 113, + MU8_PowerWordBlind = 114, +}; + +// Spell names - 7 +enum SPL_NAME07:u8 { + None = 0, + CL1_Bless = 1, + EV1_Curse = 2, + CL1_CureLightWounds = 3, + EV1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + EV1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + CL6_Heal = 36, + CL3_CureBlindness = 37, + EV3_CauseBlindness = 38, + CL3_CureDisease = 39, + EV3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + EV3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + EV6_Harm = 56, + SP0_ProtectionFromEvil10Radius = 57, + CL4_CureSeriousWounds = 58, + SP0_Silence15Radius = 59, + SP0_DetectMagic = 60, + SP0_RemoveCurse = 61, + SP0_Bless = 62, + SP0_CharmPerson = 63, + SP0_BurningHands = 64, + IT6_WandOfMagicMissiles = 65, + EV4_CauseSeriousWounds = 66, + CL4_NeutralizePoison = 67, + EV4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + EV5_CauseCriticalWounds = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + EV5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + DR2_Barkskin = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtection = 95, + DR2_CharmPersonOrMammal = 96, + IT6_PotionOfInvisibility = 97, + DR2_CureLightWounds = 98, + IT6_PotionOfExtraHealing = 99, + MU4_BestowCurse = 100, + CL6_BladeBarrier = 101, + CL7_Restoration = 102, + EV7_EnergyDrain = 103, + EV7_Destruction = 104, + CL7_Resurrection = 105, + DR3_CureDisease = 106, + DR3_NeutralizePoison = 107, + DR3_HoldAnimal = 108, + DR3_ProtFromFire = 109, + MU6_DeathSpell = 110, + MU6_Disintegrate = 111, + MU6_GlobeOfInvulnerability = 112, + MU6_StoneToFlesh = 113, + MU6_FleshToStone = 114, + MU7_DelayedBlastFireball = 115, + MU7_MassInvisibility = 116, + MU7_PowerWordStun = 117, + MU5_FireTouch = 118, + MU5_IronSkin = 119, + MU8_MassCharm = 120, + MU8_OttosIrrDance = 121, + MU8_MindBlank = 122, + MU8_PowerWordBlind = 123, + MU9_MeteorSwarm = 124, + MU9_PowerWordKill = 125, + MU9_MonsterSummoning = 126, + IT6_PotionOfSpeed = 127, + IT6_PotionOfGiantStrength = 128, + IT6_JavelinOfLightning = 129, + IT6_WandOfParalyzation = 130, + IT6_PotionOfHealing = 131, + IT6_ElixirOfYouth = 132, + IT6_NecklaceOfMissiles = 133, + IT6_WandOfMagicMissiles = 134, + IT6_ScrollOfProtDragonBreath = 135, + IT6_PotionOfInvisibility = 136, + IT6_PotionOfExtraHealing = 137, + IT8_StaffOfStriking = 138, + IT8_EyesOfPetrification = 139, + IT8_Unknown_140 = 140 +}; + +// Spell names - 8 +enum SPL_NAME08:u8 { + None = 0, + CL1_Bless = 1, + CL1_Curse = 2, + CL1_CureLightWounds = 3, + CL1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + IT7_AnimateDead = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + CL7_Restoration = 56, + IT6_PotionOfSpeed = 57, + CL4_CureSeriousWounds = 58, + IT6_PotionOfGiantStrength = 59, + IT6_JavelinOfLightning = 60, + IT6_WandOfParalyzation = 61, + IT6_PotionOfHealing = 62, + IT6_DustOfDisappearance = 63, + IT6_NecklaceOfMissiles = 64, + IT6_WandOfMagicMissiles = 65, + CL4_CauseSeriousWounds = 66, + CL4_NeutralizePoison = 67, + CL4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + CL5_CauseCriticalWounds = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + CL5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + IT5_AnimateDead = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtDragonBreath = 95, + IT6_ScrollOfProtParalyzation = 96, + IT6_PotionOfInvisibility = 97, + IT6_WandOfDefoliation = 98, + IT6_PotionExtraHealing = 99, + MU4_BestowCurse = 100 +}; + +// Spell names - 9 +enum SPL_NAME09:u8 { + None = 0, + CL1_Bless = 1, + CL1_Curse = 2, + CL1_CureLightWounds = 3, + CL1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + CL6_Heal = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + CL6_Harm = 56, + IT6_PotionOfSpeed = 57, + CL4_CureSeriousWounds = 58, + IT6_PotionOfGiantStrength = 59, + IT6_JavelinOfLightning = 60, + IT6_WandOfParalyzation = 61, + IT6_PotionOfHealing = 62, + IT6_ElixirOfYouth = 63, + IT6_NecklaceOfMissiles = 64, + IT6_WandOfMagicMissiles = 65, + CL4_CauseSeriousWounds = 66, + CL4_NeutralizePoison = 67, + CL4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + CL5_CauseCriticalWounds = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + CL5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + DR2_Barkskin = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtDragonBreath = 95, + DR2_CharmPersonOrMammal = 96, + IT6_PotionOfInvisibility = 97, + DR2_CureLightWounds = 98, + IT6_PotionOfExtraHealing = 99, + MU4_BestowCurse = 100, + CL6_BladeBarrier = 101, + CL7_Restoration = 102, + CL7_EnergyDrain = 103, + CL7_Destruction = 104, + CL7_Resurrection = 105, + DR3_CureDisease = 106, + DR3_NeutralizePoison = 107, + DR3_HoldAnimal = 108, + DR3_ProtFromFire = 109, + MU6_DeathSpell = 110, + MU6_Disintegrate = 111, + MU6_GlobeOfInvulnerability = 112, + MU6_StoneToFlesh = 113, + MU6_FleshToStone = 114, + MU7_DelayedBlastFireball = 115, + MU7_MassInvisibility = 116, + MU7_PowerWordStun = 117, + MU5_FireTouch = 118, + MU5_IronSkin = 119, + MU8_MassCharm = 120, + MU8_OttosIrrDance = 121, + MU8_MindBlank = 122, + MU8_PowerWordBlind = 123, + MU9_MeteorSwarm = 124, + MU9_PowerWordKill = 125, + MU9_MonsterSummoning = 126, + MU4_Unknown_127 = 127 +}; + +// Spell names - 10 +enum SPL_NAME10:u8 { + None = 0, + CL1_Bless = 1, + CL1_Curse = 2, + CL1_CureLightWounds = 3, + CL1_CauseLightWounds = 4, + CL1_DetectMagic = 5, + CL1_ProtectionFromEvil = 6, + CL1_ProtectionFromGood = 7, + CL1_ResistCold = 8, + MU1_BurningHands = 9, + MU1_CharmPerson = 10, + MU1_DetectMagic = 11, + MU1_Enlarge = 12, + MU1_Reduce = 13, + MU1_Friends = 14, + MU1_MagicMissile = 15, + MU1_ProtectionFromEvil = 16, + MU1_ProtectionFromGood = 17, + MU1_ReadMagic = 18, + MU1_Shield = 19, + MU1_ShockingGrasp = 20, + MU1_Sleep = 21, + CL2_FindTraps = 22, + CL2_HoldPerson = 23, + CL2_ResistFire = 24, + CL2_Silence15Radius = 25, + CL2_SlowPoison = 26, + CL2_SnakeCharm = 27, + CL2_SpiritualHammer = 28, + MU2_DetectInvisibility = 29, + MU2_Invisibility = 30, + MU2_Knock = 31, + MU2_MirrorImage = 32, + MU2_RayOfEnfeeblement = 33, + MU2_StinkingCloud = 34, + MU2_Strength = 35, + CL6_Heal = 36, + CL3_CureBlindness = 37, + CL3_CauseBlindness = 38, + CL3_CureDisease = 39, + CL3_CauseDisease = 40, + CL3_DispelMagic = 41, + CL3_Prayer = 42, + CL3_RemoveCurse = 43, + CL3_BestowCurse = 44, + MU3_Blink = 45, + MU3_DispelMagic = 46, + MU3_Fireball = 47, + MU3_Haste = 48, + MU3_HoldPerson = 49, + MU3_Invisibility10Radius = 50, + MU3_LightningBolt = 51, + MU3_ProtectionFromEvil10Radius = 52, + MU3_ProtectionFromGood10Radius = 53, + MU3_ProtectionFromNormalMissiles = 54, + MU3_Slow = 55, + CL6_Harm = 56, + SP0_ProtectionFromEvil10Radius = 57, + CL4_CureSeriousWounds = 58, + SP0_Silence15Radius = 59, + SP0_DetectMagic = 60, + SP0_RemoveCurse = 61, + SP0_Bless = 62, + SP0_CharmPerson = 63, + SP0_BurningHands = 64, + IT6_WandOfMagicMissiles = 65, + CL4_CauseSeriousWounds = 66, + CL4_NeutralizePoison = 67, + CL4_Poison = 68, + CL4_ProtectionEvil10Radius = 69, + CL4_SticksToSnakes = 70, + CL5_CureCriticalWounds = 71, + CL5_CauseCriticalWounds = 72, + CL5_DispelEvil = 73, + CL5_FlameStrike = 74, + CL5_RaiseDead = 75, + CL5_SlayLiving = 76, + DR1_DetectMagic = 77, + DR1_Entangle = 78, + DR1_FaerieFire = 79, + DR1_InvisibilityToAnimals = 80, + MU4_CharmMonsters = 81, + MU4_Confusion = 82, + MU4_DimensionDoor = 83, + MU4_Fear = 84, + MU4_FireShield = 85, + MU4_Fumble = 86, + MU4_IceStorm = 87, + MU4_MinorGlobeOfInvulnerability = 88, + MU4_RemoveCurse = 89, + DR2_Barkskin = 90, + MU5_CloudKill = 91, + MU5_ConeOfCold = 92, + MU5_Feeblemind = 93, + MU5_HoldMonsters = 94, + IT6_ScrollOfProtDragonBreath = 95, + DR2_CharmPersonOrMammal = 96, + IT6_PotionOfInvisibility = 97, + DR2_CureLightWounds = 98, + IT6_PotionOfExtraHealing = 99, + MU4_BestowCurse = 100, + CL6_BladeBarrier = 101, + CL7_Restoration = 102, + CL7_EnergyDrain = 103, + CL7_Destruction = 104, + CL7_Resurrection = 105, + DR3_CureDisease = 106, + DR3_NeutralizePoison = 107, + DR3_HoldAnimal = 108, + DR3_ProtFromFire = 109, + MU6_DeathSpell = 110, + MU6_Disintegrate = 111, + MU6_GlobeOfInvulnerability = 112, + MU6_StoneToFlesh = 113, + MU6_FleshToStone = 114, + MU7_DelayedBlastFireball = 115, + MU7_MassInvisibility = 116, + MU7_PowerWordStun = 117, + MU5_FireTouch = 118, + MU5_IronSkin = 119, + MU8_MassCharm = 120, + MU8_OttosIrrDance = 121, + MU8_MindBlank = 122, + MU8_PowerWordBlind = 123, + MU9_MeteorSwarm = 124, + MU9_PowerWordKill = 125, + MU9_MonsterSummoning = 126, + IT6_PotionOfSpeed = 127, + IT6_PotionOfGiantStrength = 128, + IT6_JavelinOfLightning = 129, + IT6_WandOfParalyzation = 130, + IT6_PotionOfHealing = 131, + IT6_ElixirOfYouth = 132, + IT6_NecklaceOfMissiles = 133, + IT6_WandOfMagicMissiles = 134, + IT6_ScrollOfProtDragonBreath = 135, + IT6_PotionOfInvisibility = 136, + IT6_PotionOfExtraHealing = 137 +}; \ No newline at end of file diff --git a/patterns/GoldBox/GB_EXE.hexpat b/patterns/GoldBox/GB_EXE.hexpat new file mode 100644 index 00000000..4a75b26f --- /dev/null +++ b/patterns/GoldBox/GB_EXE.hexpat @@ -0,0 +1,1302 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Executable +// Using the first record in the class table (Cleric in all) to auto identify target files +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x00DDD9 +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x00C039 +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x00F2FC +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x00B468 +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x00D58B +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x00CF8E +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x067CC4 +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x0067F5 +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x00DDBF +#pragma magic [ 43 6C 65 72 69 63 ] @ 0x08903E +// Update this value if adding additional tables +#define DataTypeCount 49 +import std.core; +import std.io; +import std.string; + +/********** + This is intended to allow looking up and/or modifying the standard data tables embedded + in the executable for all Gold Box games (D&D, no one cares about Buck Rogers) + + Supported Games: + 01 - Pool of Radiance v1.3 (START.EXE) + 02 - Curse of the Azure Bonds v1.3 (START.EXE) + 03 - Secret of the Silver Blades v1.3 (START.EXE) + 04 - Pools of Darkness v1.1 (GAME.EXE) + 05 - Champions of Krynn v1.2 (START.EXE) + 06 - Death Knights of Krynn v1.1 (START.EXE) + 07 - The Dark Queen of Krynn v1.1. (DQK.EXE) + 08 - Gateway to the Savage Frontier v1.2 (GAME.EXE) + 09 - Treasures of the Savage Frontier v1.0 (GAME.EXE) + 10 - Unlimited Adventures v1.2 (CKIT.EXE) + + To avoid making 10 separate patterns that would clutter the repo and also because + I wanted to see if I could, they are all merged into this single pattern + + While most tables are found in each, not all are, and there is variability in record + counts along with, obviously, none of the tables being located at the same offset + + To avoid making this a several thousands of lines long file by setting the values for each table's record + count and offset for each game individually, two arrays are used with the RecordCount/Offset indexes paired + + This is then populated once the game executable is detected and used when setting the data placement + Where a table does not exist, the record count is set to 0, this skips adding it when the pattern runs + + To add a new table, increase the DataTypeCount define at the top (currently 49) and add the count/offset + to each game's array list in the same positions - probably easiest to just put them on the end + If a game doesn't have that table, set the count to 0 and offset to whereever (I just used 0x00 for those) + + Note: + This only supports the latest version of these games (GOG, WizWorks, and Steam (I assume but haven't checked that)) + as different versions will have different offsets for everything and I'm not about to track down every variant to get those + + Additionally, the executables for all but Dark Queen of Krynn and Unlimited Adventures must be decompressed first + This can be done using the UNP utility which can be found at https://gbc.zorbus.net/unp411.zip (at least as of Jan 2026) + That is a very old program so you must run it in DOSBOX, which you have to run the games in so I assume that's not a problem + You can (and should if you want to modify things) replace the original executable with the decompressed version, it runs fine +**********/ +u8 RecordCount[DataTypeCount]; +u32 Offset[DataTypeCount]; + +// Set default DataType parameters +u8 GameID = 0; +u8 ClassAlignmentAllowed_Param = 8; +u8 ClassBaseSavePerLevel_Param = 12; +u8 ClassSpellAllowed_Param = 8; +u8 ClassTHAC0PerLevel_Param = 22; +u8 ClassXPPerLevel_Param = 12; +u8 RaceClassAge_Param = 7; +u8 RaceNameOffset = 0; +bool SPLCountIsTotal = false; +u8 TurnUndeadTypeLevel_Param = 0; +u8 String_Alignment_Param = 16; +u8 String_Class_Param = 26; +u8 String_CompassDirection_Param = 2; +u8 String_Diety_Param = 11; +u8 String_DiskMessage_Param = 29; +u8 String_Effect_Param = 37; +u8 String_Gender_Param = 6; +u8 String_IconModify_Param = 40; +u8 String_ItemNamePart_Param = 20; +u8 String_MenuCommand_Param = 40; +u8 String_Money_Param = 10; +u8 String_Race_Param = 9; +u8 String_Robe_Param = 6; +u8 String_SpellLevel_Param = 40; +u8 String_SpellName_Param = 40; +u8 String_Status_Param = 12; +u8 String_TempleSpell_Param = 40; + +// Determine executable version and set overrides +u128 FileSize = std::mem::size(); + +// 01-Pool of Radiance (START.EXE) +if (FileSize == 70864) { + GameID = 1; + ClassBaseSavePerLevel_Param = 9; + ClassTHAC0PerLevel_Param = 11; + RaceNameOffset = 1; + SPLCountIsTotal = true; + TurnUndeadTypeLevel_Param = 1; + u8 RecordCount_01[DataTypeCount] = {0x09, 0x11, 0x08, 0x00, 0x08, 0x00, 0x02, 0x05, 0xFF, 0x0B, 0x05, 0x07, 0x08, 0x00, 0x09, 0x38, 0x09, 0x0B, 0x11, 0x11, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x07, 0x07, 0x07, 0x07, 0x0B, 0x07, 0x09, 0x12, 0x13, 0x05, 0x0C, 0x0E, 0x43, 0x01, 0x0A, 0x00}; + u32 Offset_01[DataTypeCount] = {0x00DFF3, 0x00DDD8, 0x00F648, 0x000000, 0x00F6D2, 0x000000, 0x00E08C, 0x00D888, 0x00E15C, 0x00D6B9, 0x00D556, 0x00E09A, 0x00DFA3, 0x000000, 0x00DB42, 0x00F9B2, 0x00E0E7, 0x00D1BA, 0x011021, 0x011087, 0x000000, 0x011313, 0x010D8E, 0x00D956, 0x00D95E, 0x010D74, 0x011303, 0x000000, 0x000000, 0x010D1C, 0x010D7D, 0x000000, 0x011143, 0x010E53, 0x010FDB, 0x010F17, 0x010EC3, 0x010E1C, 0x010DE4, 0x010D9C, 0x011131, 0xDA12, 0x00DDC4, 0x00F91E, 0x00F910, 0x0102AA, 0x0106DA, 0x00D4F2, 0x000000}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_01[i]; + Offset[i] = Offset_01[i]; + } +} +// 02-Curse of the Azure Bonds (START.EXE) +else if (FileSize == 64384) { + GameID = 2; + ClassTHAC0PerLevel_Param = 13; + RaceNameOffset = 1; + TurnUndeadTypeLevel_Param = 1; + + u8 RecordCount_02[DataTypeCount] = {0x09, 0x12, 0x08, 0x00, 0x06, 0x00, 0x02, 0x05, 0xFF, 0x0C, 0x05, 0x07, 0x08, 0x00, 0x09, 0x64, 0x09, 0x0B, 0x11, 0x11, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x07, 0x07, 0x07, 0x07, 0x0B, 0x07, 0x0C, 0x17, 0x07, 0x05, 0x00, 0x00, 0x64, 0x01, 0x0A, 0x00}; + u32 Offset_02[DataTypeCount] = {0x00C26E, 0x00C038, 0x00D8C2, 0x000000, 0x00D94E, 0x000000, 0x00C307, 0x00BACC, 0x00C3D7, 0x00B8D3, 0x00B758, 0x00C315, 0x00C21E, 0x000000, 0x00BC20, 0x00DB68, 0x00C362, 0x00B466, 0x00F4F4, 0x00F55A, 0x000000, 0x00F943, 0x00F23B, 0x00BB9A, 0x00BBA2, 0x00F222, 0x00F933, 0x000000, 0x000000, 0x00F1BA, 0x00F22A, 0x000000, 0x00F61B, 0x00F318, 0x00F4AE, 0x00F3EA, 0x00F388, 0x00F2E1, 0x00F2A9, 0x00F249, 0x00F604, 0x00BBB0, 0x00C024, 0x000000, 0x000000, 0x00EB6C, 0x00F1AC, 0x00B6F4, 0x000000}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_02[i]; + Offset[i] = Offset_02[i]; + } +} +// 03-Secret of the Silver Blades (START.EXE) +else if (FileSize == 82208) { + GameID = 3; + ClassBaseSavePerLevel_Param = 18; + ClassTHAC0PerLevel_Param = 19; + RaceNameOffset = 1; + String_Race_Param = 8; + String_SpellLevel_Param = 3; + String_SpellName_Param = 34; + + u8 RecordCount_03[DataTypeCount] = {0x09, 0x12, 0x08, 0x00, 0x05, 0x78, 0x02, 0x05, 0x7B, 0x0D, 0x04, 0x07, 0x08, 0x00, 0x09, 0x75, 0x09, 0x0B, 0x11, 0x11, 0x00, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x0B, 0x06, 0x12, 0x17, 0x07, 0x05, 0x00, 0x00, 0x75, 0x01, 0x00, 0x00}; + u32 Offset_03[DataTypeCount] = {0x00F529, 0x00F2FB, 0x0100AA, 0x000000, 0x010156, 0x0109BD, 0x00F5C2, 0x00F052, 0x00F692, 0x00EE30, 0x00EB47, 0x00F5D0, 0x00F4E1, 0x000000, 0x00F155, 0x011C1E, 0x00F61D, 0x00E8BC, 0x0136B5, 0x01371B, 0x000000, 0x013D07, 0x013419, 0x00F120, 0x00F127, 0x013402, 0x013CF9, 0x000000, 0x000000, 0x01337C, 0x013409, 0x000000, 0x0137DC, 0x01351D, 0x013679, 0x0135D1, 0x01357D, 0x0134E6, 0x0134B6, 0x013426, 0x0137C5, 0xF19A, 0x00F2B0, 0x000000, 0x000000, 0x012C1D, 0x01336E, 0x000000, 0x000000}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_03[i]; + Offset[i] = Offset_03[i]; + } +} +// 04-Pools of Darkness (GAME.EXE) +else if (FileSize == 74736) { + GameID = 4; + ClassBaseSavePerLevel_Param = 21; + SPLCountIsTotal = true; + String_IconModify_Param = 45; + String_Race_Param = 8; + String_SpellName_Param = 34; + + u8 RecordCount_04[DataTypeCount] = {0x09, 0x12, 0x08, 0x00, 0x05, 0x7F, 0x02, 0x05, 0x7D, 0x0D, 0x02, 0x03, 0x08, 0x00, 0x0A, 0x7E, 0x09, 0x00, 0x11, 0x11, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x0B, 0x06, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x01, 0x0D, 0x07}; + u32 Offset_04[DataTypeCount] = {0x00B68C, 0x00B467, 0x00E3A6, 0x000000, 0x00E41A, 0x00E697, 0x00B725, 0x00D7CF, 0x00D964, 0x00B7C9, 0x00D54A, 0x00B733, 0x00B64D, 0x000000, 0x00B0BC, 0x00FA00, 0x00B754, 0x000000, 0x01169F, 0x011705, 0x000000, 0x01200F, 0x0113D9, 0x0113E0, 0x0113E7, 0x0113C2, 0x012001, 0x000000, 0x000000, 0x011328, 0x0113C9, 0x000000, 0x0117C6, 0x011507, 0x011663, 0x0115BB, 0x011567, 0x0114B4, 0x011484, 0x0113F4, 0x0117AF, 0x000000, 0x000000, 0x000000, 0x000000, 0x010B3A, 0x01131A, 0x00B016, 0x0114EB}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_04[i]; + Offset[i] = Offset_04[i]; + } +} +// 05-Champions of Krynn (START.EXE) +else if (FileSize == 68080) { + GameID = 5; + ClassAlignmentAllowed_Param = 1; + ClassSpellAllowed_Param = 4; + ClassTHAC0PerLevel_Param = 13; + TurnUndeadTypeLevel_Param = 5; + RaceClassAge_Param = 8; + String_Race_Param = 15; + + u8 RecordCount_05[DataTypeCount] = {0x09, 0x12, 0x08, 0x08, 0x03, 0x00, 0x02, 0x05, 0x7B, 0x0D, 0x04, 0x07, 0x08, 0x04, 0x0A, 0x6B, 0x09, 0x0B, 0x11, 0x11, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0x00, 0x08, 0x08, 0x00, 0x0A, 0x07, 0x07, 0x07, 0x07, 0x0B, 0x07, 0x0C, 0x17, 0x07, 0x05, 0x00, 0x00, 0x6B, 0x01, 0x0C, 0x00}; + u32 Offset_05[DataTypeCount] = {0x00D7F0, 0x00D58A, 0x00E3EC, 0x00D889, 0x00E498, 0x000000, 0x00D905, 0x00D0D0, 0x00D9D5, 0x00CEA8, 0x00CB1E, 0x00D913, 0x00D770, 0x00D8E9, 0x00D22A, 0x00E6D0, 0x00D960, 0x00C7FC, 0x01020F, 0x010275, 0x000000, 0x01068B, 0x00FF33, 0x00D19E, 0x00D1A6, 0x00FF1A, 0x01067B, 0x01086B, 0x000000, 0x00FEB2, 0x00FF22, 0x000000, 0x01029D, 0x010010, 0x0101C9, 0x0100E9, 0x010080, 0x00FFD9, 0x00FFA1, 0x00FF41, 0x010286, 0x00D1BA, 0x00D576, 0x000000, 0x000000, 0x00F7F3, 0x00FEA4, 0x00CA82, 0x000000}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_05[i]; + Offset[i] = Offset_05[i]; + } +} +// 06-Death Knights of Krynn (START.EXE) +else if (FileSize == 84896) { + GameID = 6; + ClassAlignmentAllowed_Param = 1; + ClassBaseSavePerLevel_Param = 18; + ClassTHAC0PerLevel_Param = 19; + RaceClassAge_Param = 8; + String_Race_Param = 15; + String_SpellLevel_Param = 10; + + u8 RecordCount_06[DataTypeCount] = {0x09, 0x12, 0x08, 0x08, 0x05, 0x79, 0x02, 0x05, 0x7D, 0x0D, 0x01, 0x07, 0x08, 0x04, 0x0D, 0x72, 0x09, 0x00, 0x11, 0x11, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0x00, 0x08, 0x08, 0x00, 0x0B, 0x07, 0x07, 0x07, 0x07, 0x0B, 0x07, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x72, 0x01, 0x0D, 0x00}; + u32 Offset_06[DataTypeCount] = {0x00D1F3, 0x00CF8D, 0x010948, 0x00D28C, 0x010A32, 0x010C95, 0x00D308, 0x00FCC6, 0x00FEDF, 0x00D3D8, 0x00FAFF, 0x00D316, 0x00D173, 0x00D2EC, 0x00FE50, 0x011F2E, 0x00D363, 0x000000, 0x013C92, 0x013CF8, 0x000000, 0x0145F4, 0x013984, 0x00CD36, 0x00CD3E, 0x01396A, 0x0145E4, 0x0148C4, 0x000000, 0x0138D2, 0x013973, 0x000000, 0x013D20, 0x013A93, 0x013C4C, 0x013B6C, 0x013B03, 0x013A5C, 0x013A24, 0x013994, 0x013D09, 0x000000, 0x000000, 0x000000, 0x000000, 0x013170, 0x013890, 0x00CC90, 0x000000}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_06[i]; + Offset[i] = Offset_06[i]; + } +} +// 07-The Dark Queen of Krynn (DQK.EXE) - Does not need decompressed +else if (FileSize == 449664) { + GameID = 7; + ClassAlignmentAllowed_Param = 16; + ClassBaseSavePerLevel_Param = 22; + ClassSpellAllowed_Param = 9; + ClassXPPerLevel_Param = 19; + SPLCountIsTotal = true; + String_Alignment_Param = 0; + String_Class_Param = 0; + String_CompassDirection_Param = 3; + String_Diety_Param = 0; + String_Effect_Param = 0; + String_Gender_Param = 0; + String_ItemNamePart_Param = 0; + String_Money_Param = 0; + String_Race_Param = 0; + String_Robe_Param = 0; + String_SpellName_Param = 0; + String_Status_Param = 0; + + u8 RecordCount_07[DataTypeCount] = {0x09, 0x14, 0x08, 0x08, 0x00, 0x45, 0x02, 0x00, 0x8E, 0x00, 0x00, 0x03, 0x08, 0x03, 0x0A, 0x73, 0x0A, 0x00, 0x11, 0x11, 0x11, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x01, 0x08, 0x07, 0x07, 0x0B, 0x00, 0x07, 0x07, 0x07, 0x07, 0x0B, 0x07, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x01, 0x0D, 0x0B}; + u32 Offset_07[DataTypeCount] = {0x067E17, 0x067CC4, 0x069B78, 0x067EFB, 0x000000, 0x06A35F, 0x067E8F, 0x000000, 0x068C8D, 0x000000, 0x000000, 0x067E9B, 0x067DC1, 0x067F3B, 0x06C54D, 0x066E3D, 0x067EAE, 0x000000, 0x063F1D, 0x063F83, 0x0640E8, 0x064DEC, 0x069E2A, 0x069E31, 0x069E38, 0x069E13, 0x064DDE, 0x0650EE, 0x0645B6, 0x069D79, 0x069E1A, 0x064272, 0x000000, 0x063CD8, 0x063ED7, 0x063E13, 0x063D48, 0x069F0D, 0x069ED5, 0x069E45, 0x064250, 0x000000, 0x000000, 0x000000, 0x000000, 0x06621F, 0x069D6B, 0x06948A, 0x063CAC}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_07[i]; + Offset[i] = Offset_07[i]; + } +} +// 08-Gateway to the Savage Frontier (GAME.EXE) +else if (FileSize == 42128) { + GameID = 8; + ClassTHAC0PerLevel_Param = 13; + RaceNameOffset = 1; + TurnUndeadTypeLevel_Param = 1; + + u8 RecordCount_08[DataTypeCount] = {0x09, 0x12, 0x08, 0x00, 0x07, 0x00, 0x02, 0x05, 0xFF, 0x0E, 0x05, 0x07, 0x08, 0x00, 0x09, 0x64, 0x09, 0x0B, 0x11, 0x11, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x07, 0x07, 0x07, 0x07, 0x0B, 0x07, 0x0C, 0x17, 0x08, 0x05, 0x00, 0x00, 0x64, 0x01, 0x0A, 0x07}; + u32 Offset_08[DataTypeCount] = {0x006A2A, 0x0067F4, 0x008084, 0x000000, 0x0080E6, 0x000000, 0x006AC4, 0x005F94, 0x006B96, 0x005D48, 0x0054E0, 0x006AD2, 0x0069DA, 0x000000, 0x0060F8, 0x00839A, 0x006B20, 0x0051E6, 0x009D44, 0x009DAA, 0x000000, 0x00A194, 0x009A6E, 0x006062, 0x00606A, 0x009A54, 0x00A184, 0x000000, 0x000000, 0x0099EC, 0x009A5C, 0x000000, 0x009E6C, 0x009B68, 0x009CFE, 0x009C3A, 0x009BD8, 0x009B14, 0x009ADC, 0x009A7C, 0x009E54, 0x006078, 0x0067E0, 0x000000, 0x000000, 0x00939E, 0x0099DE, 0x00547C, 0x009B4C}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_08[i]; + Offset[i] = Offset_08[i]; + } +} +// 09-Treasures of the Savage Frontier (GAME.EXE) +else if (FileSize == 81872) { + GameID = 9; + ClassBaseSavePerLevel_Param = 21; + SPLCountIsTotal = true; + String_IconModify_Param = 45; + String_Race_Param = 8; + String_SpellName_Param = 34; + + u8 RecordCount_09[DataTypeCount] = {0x09, 0x12, 0x08, 0x00, 0x00, 0x00, 0x02, 0x05, 0xB5, 0x0D, 0x01, 0x03, 0x08, 0x00, 0x0A, 0x7E, 0x09, 0x00, 0x11, 0x11, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x0B, 0x06, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x01, 0x0D, 0x07}; + u32 Offset_09[DataTypeCount] = {0x00DFE4, 0x00DDBE, 0x01127A, 0x000000, 0x000000, 0x000000, 0x00E07E, 0x0101E0, 0x0103A0, 0x00E124, 0x00FF4C, 0x00E08C, 0x00DFA4, 0x000000, 0x00DB14, 0x011590, 0x00E0AE, 0x000000, 0x013246, 0x0132AC, 0x000000, 0x013BB8, 0x012F7C, 0x012F84, 0x012F8C, 0x012F62, 0x013BAA, 0x000000, 0x000000, 0x012EC8, 0x012F6A, 0x000000, 0x01336E, 0x0130AE, 0x01320A, 0x013162, 0x01310E, 0x01305A, 0x01302A, 0x012F9A, 0x013356, 0x000000, 0x000000, 0x000000, 0x000000, 0x0126CA, 0x012EBA, 0x00DA6E, 0x013092}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_09[i]; + Offset[i] = Offset_09[i]; + } +} +// 10-Unlimited Adventures (CKIT.EXE) - Does not need decompressed +else if (FileSize == 587843) { + GameID = 10; + ClassAlignmentAllowed_Param = 16; + ClassBaseSavePerLevel_Param = 22; + SPLCountIsTotal = true; + String_Alignment_Param = 0; + String_Class_Param = 0; + String_CompassDirection_Param = 3; + String_Effect_Param = 0; + String_Gender_Param = 0; + String_ItemNamePart_Param = 0; + String_Money_Param = 0; + String_Race_Param = 0; + String_SpellName_Param = 0; + String_Status_Param = 0; + + u8 RecordCount_10[DataTypeCount] = {0x09, 0x11, 0x08, 0x00, 0x00, 0x46, 0x02, 0x00, 0x75, 0x00, 0x00, 0x03, 0x07, 0x00, 0x0A, 0x73, 0x09, 0x00, 0x11, 0x11, 0x00, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x01, 0x04, 0x07, 0x07, 0x07, 0x00, 0x06, 0x06, 0x06, 0x06, 0x0B, 0x06, 0x12, 0x17, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x01, 0x0D, 0x07}; + u32 Offset_10[DataTypeCount] = {0x089133, 0x08C216, 0x08B012, 0x000000, 0x000000, 0x08B789, 0x0891AB, 0x000000, 0x089FF8, 0x000000, 0x000000, 0x0891B7, 0x089103, 0x000000, 0x08D6B5, 0x08829C, 0x0891CD, 0x000000, 0x086218, 0x08627E, 0x000000, 0x086976, 0x08B2C2, 0x08B2C9, 0x08B2D0, 0x08B2AB, 0x086968, 0x085F42, 0x086554, 0x08B211, 0x08B2B2, 0x086404, 0x000000, 0x086032, 0x0861DC, 0x086134, 0x086092, 0x08B39D, 0x08B36D, 0x08B2DD, 0x0863E6, 0x000000, 0x000000, 0x000000, 0x000000, 0x0876C0, 0x08B203, 0x08A6C8, 0x085F26}; + + for (u8 i = 0, i < DataTypeCount, i = i + 1) { + RecordCount[i] = RecordCount_10[i]; + Offset[i] = Offset_10[i]; + } +} +// Compressed Executable +else if (FileSize == 65231 || FileSize == 57789 || FileSize == 72097 || FileSize == 64203 || FileSize == 61607 || FileSize == 74299 || FileSize == 36603 || FileSize == 71971) { + std::warning("Compressed executable found. Decompress using the UNP utility first."); + std::warning("The UNP utility can be found at: https://gbc.zorbus.net/unp411.zip (as of 2026-01)"); + return; +} +// Unknown file +else { + std::warning("This pattern is only intended to work with decompressed versions of the Gold Box D&D game executables."); + return; +} + +/******************************* + Enumerations +*******************************/ +// Alignment - 1-6/8-9 +enum ALIGNMENT_A:u8 { + LawfulGood = 0, + LawfulNeutral = 1, + LawfulEvil = 2, + NeutralGood = 3, + TrueNeutral = 4, + NeutralEvil = 5, + ChaoticGood = 6, + ChaoticNeutral = 7, + ChaoticEvil = 8 +}; + +// Alignment - 7/10 +enum ALIGNMENT_B:u16 { + LawfulGood = 0, + LawfulNeutral = 1, + LawfulEvil = 2, + NeutralGood = 3, + TrueNeutral = 4, + NeutralEvil = 5, + ChaoticGood = 6, + ChaoticNeutral = 7, + ChaoticEvil = 8 +}; + +// Class - 1-4/8-9 +enum CLASS_A:u8 { + Cleric = 0, + Druid = 1, + Fighter = 2, + Paladin = 3, + Ranger = 4, + MagicUser = 5, + Thief = 6, + Monk = 7, + Cleric_Fighter = 8, + Cleric_Fighter_MagicUser = 9, + Cleric_Ranger = 10, + Cleric_MagicUser = 11, + Cleric_Thief = 12, + Fighter_MagicUser = 13, + Fighter_Thief = 14, + Fighter_MagicUser_Thief = 15, + MagicUser_Thief = 16, + Monster = 17 +}; + +// Class - 5-6 +enum CLASS_B:u8 { + Cleric = 0, + Druid = 1, + Fighter = 2, + Paladin = 3, + Ranger = 4, + MagicUser = 5, + Thief = 6, + Knight = 7, + Cleric_Fighter = 8, + Cleric_Fighter_MagicUser = 9, + Cleric_Ranger = 10, + Cleric_MagicUser = 11, + Cleric_Thief = 12, + Fighter_MagicUser = 13, + Fighter_Thief = 14, + Fighter_MagicUser_Thief = 15, + MagicUser_Thief = 16, + Monster = 17 +}; + +// Class - 7/10 +enum CLASS_C:u16 { + Cleric = 0, + Knight = 1, + Fighter = 2, + Paladin = 3, + Ranger = 4, + MagicUser = 5, + Thief = 6, + Monk = 7, + Cleric_Fighter = 8, + Cleric_Fighter_MagicUser = 9, + Cleric_Ranger = 10, + Cleric_MagicUser = 11, + Cleric_Thief = 12, + Fighter_MagicUser = 13, + Fighter_Thief = 14, + Fighter_MagicUser_Thief = 15, + MagicUser_Thief = 16, + Monster = 17 +}; + +// Class Alignment Allowed - 5/6 +bitfield CLASSALIGNARRAY{ + LawfulGood : 1; + LawfulNeutral : 1; + NeutralGood : 1; + TrueNeutral : 1; + ChaoticGood : 1; + ChaoticEvil : 1; + padding : 2; +}; + +// Item Class Restrictions - 1 +bitfield CLASSRESTRICTION_A { + MagicUser : 1; + Cleric : 1; + Thief : 1; + Fighter : 1; + Monk : 1; + Druid : 1; + Paladin : 1; + Ranger : 1; +}; + +// Item Class Restrictions - 2/8 +bitfield CLASSRESTRICTION_B { + MagicUser : 1; + Cleric : 1; + Thief : 1; + Fighter : 1; + Druid : 1; + Monk : 1; + PaladinRanger : 1; + padding : 1; +}; + +// Item Class Restrictions - 3-4/9-10 +bitfield CLASSRESTRICTION_C { + MagicUser : 1; + Cleric : 1; + Thief : 1; + Fighter : 1; + Knight : 1; + Druid : 1; + PaladinRanger : 1; + padding : 1; +}; + +// Item Class Restrictions - 5-7 +bitfield CLASSRESTRICTION_D { + MagicUser : 1; + Cleric : 1; + Thief : 1; + Fighter : 1; + Knight : 1; + Druid : 1; + Paladin : 1; + Ranger : 1; +}; + +// Spell - Class - 1 +enum SPELLCLASS_A:u8 { + Cleric = 0, + MagicUser = 1, + Item = 2 +}; + +// Spell - Class - 2/4/8/9 +enum SPELLCLASS_B:u8 { + Cleric = 0, + Druid = 1, + MagicUser = 2, + Item = 3 +}; + +// Spell - Class - 3/5/6 +enum SPELLCLASS_C:u8 { + Cleric = 0, + Druid = 1, + Special = 2, + MagicUser = 3, + Item = 4 +}; + +// Spell - Class - 7/10 - 255 is 7 only +enum SPELLCLASS_D:u16 { + Cleric = 0, + Druid = 1, + MagicUser = 2, + Special = 3, + Item = 4, + ClericEvil = 255 +}; + +// Spell - Area_Camp - 1/2/5/8 +enum AREACAMP_A:u8 { + None = 0, + Caster = 1, + Target_1 = 2, + Invalid = 3, + All = 4 +}; + +// Spell - Area_Camp - 3-4/6/9 +enum AREACAMP_B:u8 { + None = 0, + Caster = 1, + Target_1 = 2, + All = 3 +}; + +// Spell - Area_Camp - 7/10 +enum AREACAMP_C:u16 { + None = 0, + Caster = 1, + Target_1 = 2, + All = 3 +}; + +// Spell - Area_Combat +enum AREACOMBAT:u8 { + Caster = 0, + All = 3, + Target_1 = 4, + Target_Var = 5, + Target_1_3 = 6, + Target_1_4 = 7, + LineCone = 8, + Other = 9, + Area_5x5 = 10, + Area_7x7 = 11, + TargetArea_3x3 = 14, + TargetArea_3x3 = 31, + Target_LVL = 240 +}; + +// Spell - Type - 1-6/8-9 +enum SPELLTYPE_A:u8 { + Camp = 0, + Combat = 1, + Both = 2 +}; + +// Spell - Type - 7/10 +enum SPELLTYPE_B:u16 { + Camp = 0, + Combat = 1, + Both = 2 +}; + +// Spell - SAV_Action - 1-6/8-9 +enum SAV_ACTION_A:u8 { + None = 0, + Negate = 1, + Half = 2, + Special = 3 +}; + +// Spell - SAV_Action - 7/10 +enum SAV_ACTION_B:u16 { + None = 0, + Negate = 1, + Half = 2, + Special = 3 +}; + +// Spell - SAV_Type - 1-6/8-9 +enum SAV_TYPE_A:u8 { + SAV_1_PPD = 0, + SAV_2_PP = 1, + SAV_3_RSW = 2, + SAV_4_BW = 3, + SAV_5_S = 4 +}; + +// Spell - SAV_Type - 7/10 +enum SAV_TYPE_B:u16 { + SAV_1_PPD = 0, + SAV_2_PP = 1, + SAV_3_RSW = 2, + SAV_4_BW = 3, + SAV_5_S = 4 +}; + +/******************************* + Functions +*******************************/ +// Formatting function for AC/THAC0 (RW) +fn FormatACTHAC0 (u8 Input) { + s8 Val = 60 - Input; + return Val; +}; + +// Formatting function for SPLBASE.CastTime +fn FormatCastTime (u8 Input) { + u8 TempVal = (Input / 3); + str ReturnVal = TempVal == 0 ? "-" : std::format("{:.1f}", TempVal * 0.1); + return ReturnVal; +}; + +// Formatting function for Turn Undead values - Write function didn't work right (at all), so need to directly edit the hex +fn FormatTurnUndead(u8 Input) { + str TurnVal; + if (Input == 0x63) { + TurnVal = "-"; // Cannot turn + } + else if (Input == 0) { + TurnVal = "D"; // Auto Destroy 1-12 + } + else if (Input == 1) { + TurnVal = "T"; // Auto Turn 1-12 + } + else if (Input == 255) { + TurnVal = "D*"; // Auto Destroy 7-12 + } + else { + TurnVal = std::string::to_string(Input); + } + + return TurnVal; +}; + +// Formatting function for Class names in ClassXPPerLevel/ClassXPSpellPerLevel (5-7) +fn KrynnClassName(u8 Input) { + if (Input == 0) { + return "Cleric of Good"; + } + else if (Input == 1) { + return "Cleric of Neutrality"; + } + else if (Input == 2) { + return "Fighter"; + } + else if (Input == 3) { + return "Knight of the Crown"; + } + else if (Input == 4) { + return "Knight of the Sword"; + } + else if (Input == 5) { + return "Knight of the Rose"; + } + else if (Input == 6) { + return "Ranger"; + } + else if (Input == 7) { + return "White Robe Mage"; + } + else if (Input == 8) { + return "Red Robe Mage"; + } + else if (Input == 9) { + return "Thief"; + } + else if (Input == 10) { + return "Paladin"; + } + else { + return "Unknown"; + } +}; + +// Formatting function for Class names in CLASSSPELLPERLVL (7/10) +fn CasterClassName(u8 Input) { + if (GameID == 7) { + if (Input == 0) { + return "Cleric of Good"; + } + else if (Input == 1) { + return "Cleric of Neutrality"; + } + else if (Input == 2) { + return "Knight of the Sword"; + } + else if (Input == 3) { + return "Knight of the Rose"; + } + else if (Input == 4) { + return "Ranger"; + } + else if (Input == 5) { + return "White Robe Mage"; + } + else if (Input == 6) { + return "Red Robe Mage"; + } + else if (Input == 7) { + return "Paladin"; + } + } + else if (GameID == 10) { + if (Input == 0) { + return "Cleric"; + } + else if (Input == 1) { + return "Paladin"; + } + else if (Input == 2) { + return "Ranger"; + } + else if (Input == 3) { + return "Magic-User"; + } + } + return "Unknown"; +}; + +// Formatting function for Undead level/names in TurnUndeadTypeLevel +fn UndeadLevelName(u8 Input) { + if (Input == 0) { + return "01: Skeleton"; + } + else if (Input == 1) { + return "02: Zombie"; + } + else if (Input == 2) { + return "03: Ghoul"; + } + else if (Input == 3) { + return "04: Shadow"; + } + else if (Input == 4) { + return "05: Wight"; + } + else if (Input == 5) { + return "06: Ghast"; + } + else if (Input == 6) { + return "07: Wraith"; + } + else if (Input == 7) { + return "08: Mummy"; + } + else if (Input == 8) { + return "09: Spectre"; + } + else if (Input == 9) { + return "10: Vampire"; + } + else if (Input == 10) { + return "11: Ghost"; + } + else if (Input == 11) { + return "12: Lich"; + } + else if (Input == 12) { + return "13: Special"; + } + else { + return "Unknown"; + } +}; + +// Formatting function for ItemRandom.NamePart[1-3] - Used to blank 0s and avoid creating enumerations for each game (1-3/5/8) +fn GetItemName(u8 Input) { + if (Input == 0) { + return ""; + } + return std::format("{}", Input < std::core::member_count(String_ItemNamePart) ? String_ItemNamePart[Input -1].String : "Undefined"); +}; + +// Formatiting function to display the spell name for the records in SpellBase +fn GetSpellName(u8 Input) { + if (Input == 0) { + return "-"; + } + return std::format("{:03d}: {}", Input, Input < std::core::member_count(String_SpellName) ? String_SpellName[Input -1].String : "Undefined"); +}; + +/******************************* + String Structs +*******************************/ +// Generic String struct +struct STRING { +// NULL terminated strings in 7/10 + if (Size == 0) { + char String[] [[format("std::string::to_string")]]; + } +// Workaround for fixed length without Length value for compass strings in 7/10 + else if (Size == 3 && $ > 0x069B77) { + char String[Size] [[format("std::string::to_string")]]; + } +// Standard PASCAL style strings in 1-6/8-9 + else { + u8 Length [[hidden]]; + char String[Size] [[format("std::string::to_string")]]; + } +} [[inline]]; + +// String_MenuCommand +/*** + Main Menu (create char/load game/etc) has a trailing boolean value + Need to double check, but guessing this is what controls hiding + some options after you load a saved game - need to doublecheck +***/ +struct MAINMENU { + STRING<40> String; + bool Unknown_29; +}; + +/******************************* + Class Structs +*******************************/ +// ClassAbilityMin - Generic name in case I find another dataset using this +struct BASEABILITY { + u8 STR [[comment("Strength value")]]; + u8 INT [[comment("Intelligence value")]]; + u8 WIS [[comment("Wisdom value")]]; + u8 DEX [[comment("Dexterity value")]]; + u8 CON [[comment("Constitution value")]]; + u8 CHA [[comment("Charisma value")]]; +} [[name(std::format("{}", String_Class[std::core::array_index()].String)),comment("Minimum class ability values")]]; + +// ClassAlignmentAllowed/ClassAlignmentAllowedDwarf (Dwarf is 7 only - used to force neutral for clerics) +struct CLASSALIGN { +// 5-6 uses bit array - this works here as you cannot pick evil alignments in the Krynn games + if (Size == 1) { + CLASSALIGNARRAY Alignment [[inline]]; + } + else { + u8 AlignmentCount [[comment("Number of alignments allowed\nModify this value to match if adding/removing alignments")]]; + // 1-4/8-9 + if (Size == 8) { + ALIGNMENT_A Alignment[AlignmentCount] [[inline]]; + padding[9 - AlignmentCount]; + } + // 7/10 - u16 values - 7 has junk data in the padding area for some + else { + ALIGNMENT_B Alignment[AlignmentCount] [[inline]]; + padding[20 - (AlignmentCount * 2)]; + } + } +} [[name(std::format("{}", String_Class[std::core::array_index()].String)),comment("Available alignments for this class")]]; + +// Generic Class array +/*** + Generic single value per class array used for: + ClassHDLevelMax + ClassHDStartCount + ClassHDType + ClassTrainCode +***/ +struct CLASSARRAY { + Type Value [[name(std::format("{}", String_Class[std::core::array_index()].String))]]; +} [[inline]]; + +// ClassMoneyBase +struct CLASSMONEYBASE { + u8 DiceCount [[comment("Number of rolls to make")]]; + u8 DiceType [[comment("Dice type (d4/d6/d8/etc) rolled")]]; +} [[name(std::format("{}", String_Class[std::core::array_index()].String)),comment("New character starting money per class")]]; + +// ClassItemAllowed +/*** + Bitmask value compared against ItemBase.ItemRestriction to control equippable/usable items by class + Note: The Ranger class is only set correctly in 5-7, it has the Paladin flag set instead in 1-4/8-10 + This ultimately doesn't matter as all items with the Paladin flag set also has the Ranger flag set + I don't believe there's a difference in allowed weapons between those two classes (or with fighters) + in 1e so, despite being set wrong, it still ends up working correctly +***/ +struct CLASSRESTRICTION { +// Minor variations in bit values/classes + match (GameID) { + (1): CLASSRESTRICTION_A ClassItemAllowed [[inline,comment("Item restriction class")]]; + (2|8): CLASSRESTRICTION_B ClassItemAllowed [[inline,comment("Item restriction class")]]; + (3|4|9|10): CLASSRESTRICTION_C ClassItemAllowed [[inline,comment("Item restriction class")]]; + (5|6|7): CLASSRESTRICTION_D ClassItemAllowed [[inline,comment("Item restriction class")]]; + } +} [[name(std::format("{}", String_Class[std::core::array_index()].String)),comment("Item restriction flags for this class")]]; + +/*********************** + ClassTHAC0PerLevel +***********************/ +// Child struct of CLASSTHAC0PERLVL - Used to get format/name/comment attributes to work correctly +struct THAC0BASE { + u8 THAC0Base [[format("FormatACTHAC0"),format_write("FormatACTHAC0"),name(std::format("LVL_{:02d}", std::core::array_index() +1)),comment(std::format("Base THAC0 at level {:d}", std::core::array_index() +1))]]; +} [[inline]]; + +// ClassTHAC0PerLevel +struct CLASSTHAC0PERLVL { + THAC0BASE THAC0[Size] [[inline]]; +} [[name(std::format("{}", String_Class[std::core::array_index()].String)),comment("Base THAC0 value per level")]]; + +/*********************** + ClassSpellAllowed +***********************/ +// Child struct of SPELLALLOWED - Used to get format attribute to work correctly +struct SPELLNAME { + u8 Spell [[format("GetSpellName")]]; +} [[inline]]; + +// Child struct of CLASSSPELLALLOWED - Used to get the level groupings/names to work correctly +struct SPELLALLOWED { + SPELLNAME SpellID[10] [[inline]]; +} [[name(std::format("LVL_{:02d}", std::core::array_index() +1)),comment(std::format("Level {:d} spells allowed", std::core::array_index() +1))]]; + +// ClassSpellAllowed - 5-7/10 - Note: While data is there, this is unused in 10 +struct CLASSSPELLALLOWED { + SPELLALLOWED Cleric[Size] [[comment("Cleric class spells available to player Clerics")]]; + SPELLALLOWED White[Size] [[comment("Magic-User class spells available to player White Robe mages")]]; + SPELLALLOWED Red[Size] [[comment("Magic-User class spells available to player Red Robe mages")]]; +} [[inline]]; + +/*********************** + ClassBaseSavePerLevel +***********************/ +// Child struct of CLASSBASESAVE - Used to get level groupings/names to work correctly +struct SAVEPERLVL { + u8 SAV1_PPD [[name("Paralyzation, Poison, or Death Magic")]]; + u8 SAV2_PP [[name("Petrification or Polymorph")]]; + u8 SAV3_RSW [[name("Rod, Staff, or Wand")]]; + u8 SAV4_BW [[name("Breath Weapon")]]; + u8 SAV5_SPL [[name("Spell")]]; +} [[name(std::format("LVL_{:02d}", std::core::array_index() +1)),comment(std::format("Class base saving throw values at level {:d}", std::core::array_index() +1))]]; + +// ClassBaseSavePerLevel +struct CLASSBASESAVE { + SAVEPERLVL SavePerLevel[Size] [[inline]]; +} [[name(std::format("{}", String_Class[std::core::array_index()].String)),comment("Class base saving throw per level")]]; + +/*********************** + ClassSpellPerLevel 7/10 + ClassXPPerLevel 7/10 + ClassXPSpellPerLevel 1-6/8-9 + + Variation between 7/10 and other games as to how this is handled + 1-6/8-9 has merges XP/SpellCounts into a single class record + 7/10 has this split into 2 separate tables, with SpellCount only + containing classes that has spells + + Both variants use the SPL_COUNT & CLASSSPELLPERLVLRANGER child structs + so bundling this under the same heading +***********************/ +// Child struct for most of these - Should probably rewrite this as a template array but this works +struct SPL_COUNT { + u8 SPL_1 [[comment(std::format("{} number of level 1 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + if (Size > 1) { + u8 SPL_2 [[comment(std::format("{} number of level 2 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + } + if (Size > 2) { + u8 SPL_3 [[comment(std::format("{} number of level 3 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + } + if (Size > 3) { + u8 SPL_4 [[comment(std::format("{} number of level 4 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + } + if (Size > 4) { + u8 SPL_5 [[comment(std::format("{} number of level 5 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + } + if (Size > 5) { + u8 SPL_6 [[comment(std::format("{} number of level 6 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + u8 SPL_7 [[comment(std::format("{} number of level 7 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + } + if (Size > 7) { + u8 SPL_8 [[comment(std::format("{} number of level 8 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + } + if (Size > 8) { + u8 SPL_9 [[comment(std::format("{} number of level 9 spells the character can memorize", SPLCountIsTotal ? "Total" : "Additional"))]]; + } +} [[name(std::format("LVL_{:02d}", std::core::array_index() +1)),comment(std::format("Number of spells this class can memorize at level {:d}", std::core::array_index() +1))]]; + +// Child struct of CLASSXPPERLVL/CLASSXPSPELLPERLVL - Used to get name/comment attributes to work +struct XPPERLVL { + s32 XP [[name(std::format("LVL_{:02d}", (GameID == 4 || GameID == 9) ? 1 + std::core::array_index() : std::core::array_index())),comment(std::format("Total XP required for level {:d}", (GameID == 4 || GameID == 9) ? 1 + std::core::array_index() : std::core::array_index()))]]; +} [[inline]]; + +// Child struct of CLASS*SPELL* structs - Used to handle Ranger's Druid/MagicUser split +struct CLASSSPELLPERLVLRANGER { + SPL_COUNT Druid [[name("Druid"),comment(std::format("Number of Druid spells this class can memorize at level {:d}", std::core::array_index() +1))]]; + SPL_COUNT MagicUser [[name("Magic-User"),comment(std::format("Number of Magic-User spells this class can memorize at level {:d}", std::core::array_index() +1))]]; +} [[name(std::format("LVL_{:02d}", std::core::array_index() +1)),comment(std::format("Number of spells this class can memorize at level {:d}", std::core::array_index() +1))]]; + +// ClassSpellPerLevel - 7/10 +struct CLASSSPELLPERLVL { + if ((GameID == 7 && std::core::array_index() == 4) || (GameID == 10 && std::core::array_index() == 2)) { + CLASSSPELLPERLVLRANGER<4,5> SpellPerLVL[29] [[inline]]; + } + else { + SPL_COUNT<9> SpellPerLVL[29] [[inline]]; + } +} [[name(CasterClassName(std::core::array_index())),comment("Total number of spells this class can memorize per level")]]; + +// ClassXPPerLevel - 7/10 +struct CLASSXPPERLVL { + XPPERLVL XP[Size] [[inline]]; +} [[name(std::format("{}", GameID == 7 ? KrynnClassName(std::core::array_index()) : String_Class[std::core::array_index()].String)),comment("Fixed XP required per level")]]; + +// Child struct of CLASSXPSPELLPERLVL - 1-3/5-6/8 - Used to handle offset from XP and inline the spell levels +struct CLASSXPSPELLLVL { + s32 XP [[comment(std::format("XP required to advance to level {:d}", std::core::array_index() +2))]]; + match (GameID,ClassID) { + (1,4): CLASSSPELLPERLVLRANGER<2,1> SpellPerLVL @ $ + (4 * (8 -1)) - std::core::array_index() [[inline]]; + (2|8,4): CLASSSPELLPERLVLRANGER<3,2> SpellPerLVL @ $ + (4 * (11 -1)) + std::core::array_index() [[inline]]; + (3,4): CLASSSPELLPERLVLRANGER<3,4> SpellPerLVL @ $ + (4 * (17 - 1)) + (std::core::array_index() * 3) [[inline]]; + (5,6): CLASSSPELLPERLVLRANGER<3,2> SpellPerLVL @ $ + (4 * (11 -1)) + std::core::array_index() [[inline]]; + (6,6): CLASSSPELLPERLVLRANGER<4,4> SpellPerLVL @ $ + (4 * (17 - 1)) + (std::core::array_index() * 4) [[inline]]; + (1,0 ... 3|5 ... 10): SPL_COUNT<3> SpellPerLVL @ $ + (4 * (8 -1)) - std::core::array_index() [[inline]]; + (2|8,0 ... 3|5 ... 10): SPL_COUNT<5> SpellPerLVL @ $ + (4 * (11 -1)) + std::core::array_index() [[inline]]; + (3,0 ... 3|5 ... 10): SPL_COUNT<7> SpellPerLVL @ $ + (4 * (17 - 1)) + (std::core::array_index() * 3) [[inline]]; + (5,0 ... 5|7 ... 10): SPL_COUNT<5> SpellPerLVL @ $ + (4 * (11 -1)) + std::core::array_index() [[inline]]; + (6,0 ... 5|7 ... 10): SPL_COUNT<8> SpellPerLVL @ $ + (4 * (17 - 1)) + (std::core::array_index() * 4) [[inline]]; + } +} [[name(std::format("LVL_{:02d}", std::core::array_index() +1))]]; + +// ClassXPSpellPerLevel +struct CLASSXPSPELLPERLVL { + u8 ClassID = std::core::array_index(); + match (GameID) { + (1): { + CLASSXPSPELLLVL ClassXPSpellCount[8] [[inline]]; + padding[3 * 8]; + } + (2|5|8): { + CLASSXPSPELLLVL ClassXPSpellCount[11] [[inline]]; + padding[5 * 11]; + } + (3): { + CLASSXPSPELLLVL ClassXPSpellCount[17] [[inline]]; + padding[7 * 17]; + } + (6): { + CLASSXPSPELLLVL ClassXPSpellCount[17] [[inline]]; + padding[8 * 17]; + } + // Can't link up XP/SpellCount due to XP only recording to 10 :( + (4|9): { + XPPERLVL XP[10]; + if (ClassID == 4) { + CLASSSPELLPERLVLRANGER<4,5> SpellPerLVL[29]; + } + else { + SPL_COUNT<9> SpellPerLVL[29]; + } + } + } +} [[name(std::format("{}", (GameID == 5 || GameID == 6 || GameID == 7) ? KrynnClassName(std::core::array_index()) : String_Class[std::core::array_index()].String))]]; + +// ClassXPPerLevelFixed - This is the XP value used once the amount required to level up becomes fixed at level 10 - Note: Not a part of the section above +struct CLASSXPPERLVLFIXED { + u32 XP [[name(std::format("{}", GameID == 7 ? KrynnClassName(std::core::array_index()) : String_Class[std::core::array_index()].String)),comment("Fixed XP required per level")]]; +} [[inline]]; + +/******************************* + Race Structs +*******************************/ +// RaceAbilityLimit +struct RACEABILITYLIMIT { + u8 STR_MIN_M [[comment("Minimum Strength for males")]]; + u8 STR_MIN_F [[comment("Minimum Strength for females")]]; + u8 STR_MAX_M [[comment("Maximum Strength for males")]]; + u8 STR_MAX_F [[comment("Maximum Strength for females")]]; + u8 STX_MAX_M [[comment("Maximum Extraordinary Strength for males")]]; + u8 STX_MAX_F [[comment("Maximum Extraordinary Strength for females")]]; + u8 INT_MIN [[comment("Minimum Intelligence")]]; + u8 INT_MAX [[comment("Maximum Intelligence")]]; + u8 WIS_MIN [[comment("Minimum Wisdom")]]; + u8 WIS_MAX [[comment("Maximum Wisdom")]]; + u8 DEX_MIN [[comment("Minimum Dexterity")]]; + u8 DEX_MAX [[comment("Maximum Wisdom")]]; + u8 CON_MIN [[comment("Minimum Constitution")]]; + u8 CON_MAX [[comment("Maximum Constitution")]]; + u8 CHA_MIN [[comment("Minimum Charisma")]]; + u8 CHA_MAX [[comment("Maximum Charisma")]]; +} [[name(std::format("{}", String_Race[std::core::array_index() + RaceNameOffset].String))]]; + +// Child struct of RACECLASSAGE - Used to control class grouping names +struct RACECLASSAGEBASE { + u8 AgeBase [[comment("Base age value")]]; + u8 Age256Mult [[comment("Value multiplied by 256 added to age")]]; + u8 DiceCount [[comment("Number of rolls to make for additional random age")]]; + u8 DiceType [[comment("Dice type (d4/d6/d8/etc) rolled for additional random age")]]; +} [[name(std::format("{}", String_Class[std::core::array_index()].String))]]; + +// RaceClassAge +struct RACECLASSAGE { + RACECLASSAGEBASE RaceClassAge[Size] [[inline,comment("Formula for calculating the age of a new character of this race")]]; +} [[name(std::format("{}", String_Race[std::core::array_index() + RaceNameOffset].String))]]; + +// RaceAgeRange +struct RACEAGERANGE { + u16 Young [[comment("Maximum age the character is considered 'young'")]]; + u16 Mature [[comment("Maximum age the character is considered 'mature'")]]; + u16 MiddleAge [[comment("Maximum age the character is considered 'middle aged'")]]; + u16 Old [[comment("Maximum age the character is considered 'old'")]]; + u16 Venerable [[comment("Maximum age the character is considered 'venerable' (expiration date)")]]; +} [[name(std::format("{}", String_Race[std::core::array_index() + RaceNameOffset].String))]]; + +// RaceClassAllowed +struct RACECLASSALLOWED { + u8 ClassCount [[comment("Number of classes allowed\nModify this value to match if adding/removing classes")]]; +// Variable number of allocated bytes per Race between games, could potentially simplify this with passed parameter but 7/10 would make messy so this works + match (GameID) { + (1): { + CLASS_A Class[ClassCount] [[comment("Available classes for this race")]]; + padding[11 - ClassCount]; + } + (2|3|4|8|9): { + CLASS_A Class[ClassCount] [[comment("Available classes for this race")]]; + padding[13 - ClassCount]; + } + (5|6): { + CLASS_B Class[ClassCount] [[comment("Available classes for this race")]]; + padding[14 - ClassCount]; + } + // 7/10 are u16 values + (7): { + CLASS_C Class[ClassCount] [[comment("Available classes for this race")]]; + padding[28 - (ClassCount * 2)]; + } + (10): { + CLASS_C Class[ClassCount] [[comment("Available classes for this race")]]; + padding[26 - (ClassCount * 2)]; + } + } +} [[name(std::format("{}", String_Race[std::core::array_index() + RaceNameOffset].String))]]; + +/******************************* + Thief Skill Structs +*******************************/ +// ThiefSkillPerLevel +struct THIEFSKLPERLVL { + u8 TH_1_PickPocket [[comment("Pick Pockets ability")]]; + u8 TH_2_OpenLock [[comment("Open Locks ability")]]; + u8 TH_3_FindRemoveTrap [[comment("Find/Remove Traps ability")]]; + u8 TH_4_MoveSilent [[comment("Move Silently ability")]]; + u8 TH_5_HideInShadow [[comment("Hide in Shadows ability")]]; + u8 TH_6_HearNoise [[comment("Hear Noise ability")]]; + u8 TH_7_ClimbWall [[comment("Climb Walls ability")]]; + u8 TH_8_ReadLanguage [[comment("Read Languages ability")]]; +} [[name(std::format("LVL_{:02d}", std::core::array_index() +1)),comment("Base Thief skill ability per level")]];; + +// ThiefSkillModifierDEX +struct THIEFSKLMODDEX { + s8 TS1_PickPocket [[comment("Dexterity modifier for Pick Pockets ability")]];; + s8 TS2_OpenLock [[comment("Dexterity modifier for Open Locks ability")]]; + s8 TS3_FindRemoveTrap [[comment("Dexterity modifier for Find/Remove Traps ability")]]; + s8 TS4_MoveSilent [[comment("Dexterity modifier for Move Silently ability")]]; + s8 TS5_HideInShadow [[comment("Dexterity modifier for Hide in Shadows ability")]]; +} [[name(std::format("DEX_{:02d}", std::core::array_index() + 9)),comment("Dexterity modifier for Thief skills")]]; + +// ThiefSkillModifierRace +struct THIEFSKLMODRACE { + s8 TH_1_PickPocket [[comment("Racial modifier for Pick Pockets ability")]]; + s8 TH_2_OpenLock [[comment("Racial modifier for Open Locks ability")]]; + s8 TH_3_FindRemoveTrap [[comment("Racial modifier for Find/Remove Traps ability")]]; + s8 TH_4_MoveSilent [[comment("Racial modifier for Move Silently ability")]]; + s8 TH_5_HideInShadow [[comment("Racial modifier for Hide in Shadows ability")]]; + s8 TH_6_HearNoise [[comment("Racial modifier for Hear Noise ability")]]; + s8 TH_7_ClimbWall [[comment("Racial modifier for Climb Walls ability")]]; + s8 TH_8_ReadLanguage [[comment("Racial modifier for Read Languages ability")]]; +} [[name(std::format("{}", String_Race[(GameID == 1 || GameID == 2 || GameID == 3 || GameID == 8) ? std::core::array_index() +1 : std::core::array_index()].String)),comment("Racial modifier for Thief skills")]]; + + +/******************************* + Miscellaneous Structs +*******************************/ +// CONModifierNonWarrior - Modifier for non-Warriors (i.e. not Fighter/Knight/Paladin/Ranger) - Not sure where warrior modifiers are stored +struct CONHPMODIFIER { + s8 CONHPModifier [[name(std::format("CON_{:02d}", std::core::array_index() + 3)),comment("Constitution modifier to HP per level")]]; +} [[inline]]; + +// ItemRandom - NonRandom Random items - 1-3/5/8 (suspect 8 is not or only partially used) +struct ITEMRANDOM { + u16 NamePart3 [[format("GetItemName"),comment("Index of the string from the ItemName enumeration list for the third part of the item's name")]]; + u16 NamePart2 [[format("GetItemName"),comment("Index of the string from the ItemName enumeration list for the second part of the item's name")]]; + u16 NamePart1 [[format("GetItemName"),comment("Index of the string from the ItemName enumeration list for the first part of the item's name")]]; + u16 Weight [[comment("The item's weight in coins")]]; + u16 Value [[comment("The item's monetary/resell value")]]; + u16 Property3 [[comment("Variable usage depending on item type")]]; + u16 Property2 [[comment("Variable usage depending on item type")]]; + u16 Property1 [[comment("Variable usage depending on item type")]]; +}; + +// SpellBase - Base spell data, sorta like the ITEM base data - Spell specifics like amount of damage/healing, damage type, etc are handled elsewhere +struct SPELLBASE { + match (GameID) { + (1): SPELLCLASS_A Class [[comment("Spell caster class")]]; + (2|4|8|9): SPELLCLASS_B Class [[comment("Spell caster class")]]; + (3|5|6): SPELLCLASS_C Class [[comment("Spell caster class")]]; + (7|10): SPELLCLASS_D Class [[comment("Spell caster class")]]; + } + u8 Level [[comment("The spell's level")]]; + s8 Range_Base [[comment("Base range (-1 is 'Touch')")]]; + u8 Range_Modifier [[comment("Caster level modifier added to Range_Base multiplied by 4")]]; // add formula + u8 Duration_Base [[comment("Base duration (how long its effect lasts) in rounds")]]; + u8 Duration_Modifier [[comment("Caster level modifier added to Duration_Base multiplied by 4")]]; // add formula + AREACOMBAT Area_Combat [[comment("Area or target type when cast in combat")]]; + match (GameID) { + (1|2|5|8): AREACAMP_A Area_Camp [[comment("Target when cast in camp")]]; + (3|4|6|9): AREACAMP_B Area_Camp [[comment("Target when cast in camp")]]; + (7|10): AREACAMP_C Area_Camp [[comment("Target when cast in camp")]]; + } + match (GameID) { + (1 ... 6|8|9): { + SAV_ACTION_A SAV_Action [[comment("Result of a successful saving throw (negate/half damage/etc)")]]; + SAV_TYPE_A SAV_Type [[comment("Type of save to check against on the target for spells where saving throws are used")]]; + u8 EffectID [[comment("Index of the effect applied to the target (0 for none)")]]; + SPELLTYPE_A Type [[comment("Where/when the spell can be cast (camp/combat/both)")]]; + u8 CastTime [[format("FormatCastTime"),comment("Amount of time it takes to cast the spell in segments (tenths of a round)")]]; + u8 AI_Priority [[comment("Ranking value used by the AI to decide which spell it should cast")]]; + bool TargetEnemy [[comment("Indicate if this spell allows targeting enemy characters")]]; + } + (7|10): { + SAV_ACTION_B SAV_Action [[comment("Result of a successful saving throw (negate/half damage/etc)")]]; + SAV_TYPE_B SAV_Type [[comment("Type of save to check against on the target for spells where saving throws are used")]]; + u8 EffectID [[comment("Index of the effect applied to the target (0 for none)")]]; + SPELLTYPE_B Type [[comment("Where/when the spell can be cast (camp/combat/both)")]]; + u8 CastTime [[format("FormatCastTime"),comment("Amount of time it takes to cast the spell in segments (tenths of a round)")]]; + u8 AI_Priority [[comment("Ranking value used by the AI to decide which spell it should cast")]]; + u16 TargetEnemy [[comment("Indicate if this spell allows targeting enemy characters")]]; + } + } + u8 AI_MinTarget [[comment("Minimum number of targets that must be in the spell's area of effect for the AI to pick to cast")]]; +} [[name(std::format("{:03d}: {}", std::core::array_index() +1, std::core::array_index() < std::core::member_count(String_SpellName) ? String_SpellName[std::core::array_index()].String : "Undefined"))]]; + +// TimeConversion +struct TIMECONV { + u16 SegmentRound [[comment("Number of segments in a round")]]; + u16 RoundTurn [[comment("Number of rounds in a turn")]]; + u16 TurnHour [[comment("Number of turns in a hour")]]; + u16 HourDay [[comment("Number of hours in a day")]]; + u16 DayMonth [[comment("Number of days in a month")]]; + u16 MonthYear [[comment("Number of months in a year")]]; + u16 YearCentury [[comment("Number of years in a century")]]; // 256 (or -1) in 1/2/5/6/8 +}; + +// TurnUndeadTypeLevel +struct TURNUNDEAD { +// 4/6-7/9-10 has a level 0 value + if (Type == 0) { + u8 LVL_00 [[format("FormatTurnUndead"),comment("Turn ability at level 0")]]; + } + u8 LVL_01 [[format("FormatTurnUndead"),comment("Turn ability at level 1")]]; + u8 LVL_02 [[format("FormatTurnUndead"),comment("Turn ability at level 2")]]; + u8 LVL_03 [[format("FormatTurnUndead"),comment("Turn ability at level 3")]]; + u8 LVL_04 [[format("FormatTurnUndead"),comment("Turn ability at level 4")]]; + u8 LVL_05 [[format("FormatTurnUndead"),comment("Turn ability at level 5")]]; + u8 LVL_06 [[format("FormatTurnUndead"),comment("Turn ability at level 6")]]; + u8 LVL_07 [[format("FormatTurnUndead"),comment("Turn ability at level 7")]]; + u8 LVL_08 [[format("FormatTurnUndead"),comment("Turn ability at level 8")]]; +// 5 specifies 9-13 instead of bundling them and doesn't have 14+ + if (Type == 5) { + u8 LVL_09 [[format("FormatTurnUndead"),comment("Turn ability at level 9")]]; + u8 LVL_10 [[format("FormatTurnUndead"),comment("Turn ability at level 10")]]; + u8 LVL_11 [[format("FormatTurnUndead"),comment("Turn ability at level 11")]]; + u8 LVL_12 [[format("FormatTurnUndead"),comment("Turn ability at level 12")]]; + u8 LVL_13 [[format("FormatTurnUndead"),comment("Turn ability at level 13")]]; + } +// 1-4/6-10 bundles 9/13 and includes 14+ + else { + u8 LVL_09_13 [[format("FormatTurnUndead"),comment("Turn ability at levels 9-13")]]; + u8 LVL_14Plus [[format("FormatTurnUndead"),comment("Turn ability at levels 14+")]]; + } +} [[name(UndeadLevelName(std::core::array_index())),comment("Cleric/Paladin turn ability by level for Undead of this level")]]; + + +// String Tables - This is obviously incomplete but most aren't all that interesting or useful - I don't know why I added the disk messages :P +STRING String_Alignment[RecordCount[0]] @ Offset[0]; +STRING String_Class[RecordCount[1]] @ Offset[1]; +STRING String_CompassDirection[RecordCount[2]] @ Offset[2]; +STRING String_Diety[RecordCount[3]] @ Offset[3]; +STRING String_DiskMessage[RecordCount[4]] @ Offset[4]; +STRING String_Effect[RecordCount[5]] @ Offset[5]; +STRING String_Gender[RecordCount[6]] @ Offset[6]; +STRING String_IconModify[RecordCount[7]] @ Offset[7]; +STRING String_ItemNamePart[RecordCount[8]] @ Offset[8]; +MAINMENU String_MainMenu[RecordCount[9]] @ Offset[9]; +STRING String_MenuCommand[RecordCount[10]] @ Offset[10]; +STRING String_Money[RecordCount[11]] @ Offset[11]; +STRING String_Race[RecordCount[12]] @ Offset[12]; +STRING String_Robe[RecordCount[13]] @ Offset[13]; +STRING String_SpellLevel[RecordCount[14]] @ Offset[14]; +STRING String_SpellName[RecordCount[15]] @ Offset[15]; +STRING String_Status[RecordCount[16]] @ Offset[16]; +STRING String_TempleSpell[RecordCount[17]] @ Offset[17]; + +// Class Tables +BASEABILITY ClassAbilityMin[RecordCount[18]] @ Offset[18]; +CLASSALIGN ClassAlignmentAllowed[RecordCount[19]] @ Offset[19]; +CLASSALIGN ClassAlignmentAllowedDwarf[RecordCount[20]] @ Offset[20]; +CLASSBASESAVE ClassBaseSavePerLevel[RecordCount[21]] @ Offset[21]; +CLASSARRAY ClassHDLevelMax[RecordCount[22]] @ Offset[22] [[comment("Maximum level for additional Hit Dice per class")]]; +CLASSARRAY ClassHDStartCount[RecordCount[23]] @ Offset[23] [[comment("Starting number of Hit Dice rolled per class")]]; +CLASSARRAYClassHDType[RecordCount[24]] @ Offset[24] [[comment("Dice type (d4/d6/d8/etc) used for Hit Dice per class")]]; +CLASSRESTRICTION ClassItemAllowed[RecordCount[25]] @ Offset[25]; +CLASSMONEYBASE ClassMoneyBase[RecordCount[26]] @ Offset[26]; +CLASSSPELLALLOWED ClassSpellAllowed[RecordCount[27]] @ Offset[27] [[comment(GameID == 10 ? "Unused" : "Available spells per magic class")]]; +CLASSSPELLPERLVL ClassSpellPerLevel[RecordCount[28]] @ Offset[28]; +CLASSTHAC0PERLVL ClassTHAC0PerLevel[RecordCount[29]] @ Offset[29]; +CLASSARRAY ClassTrainCode[RecordCount[30]] @ Offset[30] [[comment("I honestly am not entirely sure how this works :)")]]; +CLASSXPPERLVL ClassXPPerLevel[RecordCount[31]] @ Offset[31]; +CLASSXPPERLVLFIXED ClassXPPerLevelFixed[RecordCount[48]] @ Offset[48]; +CLASSXPSPELLPERLVL ClassXPSpellPerLevel[RecordCount[32]] @ Offset[32]; + +// Race Tables +RACEABILITYLIMIT RaceAbilityLimit[RecordCount[33]] @ Offset[33]; +RACEAGERANGE RaceAgeRange[RecordCount[34]] @ Offset[34]; +RACECLASSAGE RaceClassAge[RecordCount[35]] @ Offset[35]; +RACECLASSALLOWED RaceClassAllowed[RecordCount[36]] @ Offset[36]; + +// Thief Skill Tables +THIEFSKLMODDEX ThiefSkillModifierDEX[RecordCount[37]] @ Offset[37]; +THIEFSKLMODRACE ThiefSkillModifierRace[RecordCount[38]] @ Offset[38]; +THIEFSKLPERLVL ThiefSkillPerLevel[RecordCount[39]] @ Offset[39]; + +// Miscellaneous Tables +CONHPMODIFIER CONModifierNonWarrior[RecordCount[40]] @ Offset[40] [[comment("Constitution modifier to HP for non-Warrior type classes")]]; +ITEMRANDOM ItemRandom[RecordCount[41]] @ Offset[41]; +u32 MoneyConversion[RecordCount[42]] @ Offset[42]; +u8 PortraitBody[RecordCount[43]] @ Offset[43]; +u8 PortraitHead[RecordCount[44]] @ Offset[44]; +SPELLBASE SpellBase[RecordCount[45]] @ Offset[45]; +TIMECONV TimeConversion @ Offset[46]; +TURNUNDEAD TurnUndeadTypeLevel[RecordCount[47]] @ Offset[47]; \ No newline at end of file diff --git a/patterns/GoldBox/GB_ITM-Base.hexpat b/patterns/GoldBox/GB_ITM-Base.hexpat new file mode 100644 index 00000000..f0fb4c0a --- /dev/null +++ b/patterns/GoldBox/GB_ITM-Base.hexpat @@ -0,0 +1,1538 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Item Base +import std.core; +import std.string; + +/********** + This is intended to allow looking up and/or modifying the base item + files for all Gold Box games (D&D, no one cares about Buck Rogers) + + Supported Games: + 01 - Pool of Radiance (ITEMS) + 02 - Curse of the Azure Bonds (ITEMS) + 03 - Secret of the Silver Blades (ITEMS) + 04 - Pools of Darkness (ITEMS) + 05 - Champions of Krynn (ITEMS) + 06 - Death Knights of Krynn (ITEMS) + 07 - The Dark Queen of Krynn (DISK1\ITEMS.DAT) + 08 - Gateway to the Savage Frontier (ITEMS.1) + 09 - Treasures of the Savage Frontier (ITEMS) + 10 - Unlimited Adventures (DISK1\ITEMS.DAT) + + The GameID variable below must be set for to the number in the list above for + the source game, with the exception of 8 which can be auto detected by file size +*********/ +u8 GameID = 0; + +// Get file size +u32 FileSize = std::mem::size(); +// Some games have an unknown 2 byte prefix that needs skipped - Possibly just a file type identifier +u32 Offset = (FileSize == 2048 ? 0x00 : 0x02); +// Bracers handle AC like armor but doesn't have a specific type across all games so need to know which record to ensure is handled correctly +u8 BracerID = (GameID == 1 || GameID == 2 || GameID == 8) ? 77 : 50; + +// Check file is (at least likely) the base ITEM file +if (FileSize != 2048 && FileSize != 2050 && FileSize != 3074) { + std::warning("Unknown file. Exiting."); + return; +} + +// Check GameID is set +if (GameID == 0) { + // Can auto set 8 + if (FileSize == 3074) { + GameID = 8; + std::print("Gateway to the Savage Frontier detected. GameID set to 8."); + } + else { + std::warning("Please set the GameID variable to the source game's number."); + return; + } +} + +// Ensure GameID is in range +if (GameID > 10) { + std::warning("Invalid GameID. Aborting."); + return; +} + +// Abort if GameID doesn't match file size +if (((GameID == 1 || GameID == 2 || GameID == 3 || GameID == 5 || GameID == 6) && FileSize != 2050) || ((GameID == 4 || GameID == 7 || GameID == 9 || GameID == 10) && FileSize != 2048) || (GameID == 8 && FileSize != 3074)) { + std::warning("Invalid file for specified game. Aborting."); + return; +} + +/******************************* + Enumerations +*******************************/ +// Damage Type - 1-3/5-8 +enum ITEMDAMAGETYPE_A:u8 { + Slashing = 0, + Piercing = 1, + Bludgeoning = 128 +}; + +// Damage Type - 4/9-10 +enum ITEMDAMAGETYPE_B:u8 { + Unknown = 0, + PiercingSlashing = 1, + Bludgeoning = 128 +}; + +// Item Restriction +bitfield CLASSRESTRICTION { + MagicUser : 1 [[name("Magic-User")]]; + Cleric : 1; + Thief : 1; + Fighter : 1; + match (GameID) { + (1|2|8): { + Druid : 1 [[name("Druid*"),comment("Unused")]]; + Monk : 1 [[name("Monk*"),comment("Unused")]]; + } + (5|6|7): { + Knight : 1 [[name("Knight")]]; + Druid : 1 [[name("Druid*"),comment("Unused")]]; + } + (_): { + Knight : 1 [[name("Knight*"),comment("Unused")]]; + Druid : 1 [[name("Druid*"),comment("Unused")]]; + } + } + match (GameID) { + (1): { + PaladinRanger : 1 [[name("Paladin/Ranger*"),comment("Unused")]]; + padding : 1; + } + (5|6|7): { + Paladin : 1; + Ranger : 1; + } + (_): { + Paladin : 1 [[comment("Ranger class characters refer to this value")]]; + Ranger : 1 [[name("Ranger**"),comment("Ranger class characters have Paladin flag set\nUnused")]]; + } + } +}; + +/*** + Item Type - Also referred to as "Slot" + This _does_ vary between games, though just by some types above 10/Other being unused in some games + As they aren't set anywhere, there's not much point in making multiple ENUMs that skip them + + This appears to have been defined once in 1 and then reused for every game afterwards +***/ +enum ITEMTYPE:u8 { + Weapon = 0, + Shield = 1, + Armor = 2, + Hands = 3, + Head = 4, + BeltNeck = 5, + Robe = 6, + Cloak = 7, + Boots = 8, + Ring = 9, + Other = 10, + MUScroll = 11, + CLScroll = 12, + LeatherHolySymbol = 74, + BrassKey = 75, + Bracers = 77, + Wand = 78, + PotionOfGiantStrength = 80, + Unknown_81 = 81, + EfreetiBottle = 82, + Unknown_83 = 83, + Pass = 91 +}; + +// Weapon Flag +bitfield WEAPONFLAGARRAY{ + LaunchArrow : 1 [[comment("Requires an equipped arrow to use")]]; + IsRanged : 1 [[comment("Indicates this is a ranged weapon\nWhen set and LaunchArrow/Bolt & IsThrown are not, it does not require any ammo (slings)")]]; + STR_Bonus : 1 [[comment("Add strength bonus to attack")]]; + IsMultiFire : 1 [[comment("Can fire multiple missles in one attack\nUses RateOfFire to determine the number")]]; + IsThrown : 1 [[comment("Indicates the weapon can be thrown\nDepending on weapon can be used in both melee and thrown")]]; + padding : 2; + LaunchBolt : 1 [[comment("Requires an equipped bolt/quarrel to use")]]; +}; + +/******************************* + Functions +*******************************/ + +// AC - Formats Armor/Bracers AC for display +fn ACArmorRead(u8 Input) { + return 10 - (60 - (Input & 127)); +// This can be more easily read as: Input - 178 +// However, I believe the above is how it's actually handled in game +}; + +// AC - Formats non-Armor/Bracers AC for display +fn ACOtherRead(u8 Input) { + if (Input == 0) { + return "-"; + } + else { + return Input & 0x7F; + } +}; + +// AC - Formats Armor/Bracers AC from user input +fn ACArmorWrite(u8 Input) { + return 178 + Input; +}; + +// AC - Formats non-Armor/Bracers AC from user input +fn ACOtherWrite(u8 Input) { + if (Input == 255) { + return 0; + } + else { + return 128 + Input; + } +}; + +/*** + Display Name + This is not an actual enumeration type but an attempt to assign generic names to + all base item records from the item records using it so it's a bit easier to read + + Where the name is "Unused", the record is composed of all 00s and unused + * in the name signifies there are no usages of that record for this game + and the type was deduced (guessed) by comparing to other games + ** in the name signifies an issue with that record in that game +***/ +fn GetDisplayName(u16 ID) { + match (ID) { + // 01 - Pool of Radiance + (0): return "Invalid*"; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Bardiche"; + (4): return "Bec de Corbin"; + (5): return "Bill-Guisarme"; + (6): return "Bo Stick"; + (7): return "Club"; + (8): return "Dagger"; + (9): return "Dart"; + (10): return "Fauchard"; + (11): return "Fauchard-Fork"; + (12): return "Flail"; + (13): return "Military Fork"; + (14): return "Glaive"; + (15): return "Glaive-Guisarme"; + (16): return "Guisarme"; + (17): return "Guisarme-Voulge"; + (18): return "Halberd"; + (19): return "Lucern Hammer"; + (20): return "Hammer"; + (21): return "Javelin"; + (22): return "Jo Stick"; + (23): return "Mace"; + (24): return "Morning Star"; + (25): return "Partisan"; + (26): return "Military Pick"; + (27): return "Awl Pike"; + (28): return "Bolt"; + (29): return "Ranseur"; + (30): return "Scimitar"; + (31): return "Spear"; + (32): return "Spetum"; + (33): return "Quarter Staff"; + (34): return "Bastard Sword"; + (35): return "Broad Sword"; + (36): return "Long Sword"; + (37): return "Short Sword"; + (38): return "Two-Handed Sword"; + (39): return "Trident"; + (40): return "Voulge"; + (41): return "Composite Long Bow"; + (42): return "Composite Short Bow"; + (43): return "Long Bow"; + (44): return "Short Bow"; + (45): return "Fine Composite Long Bow"; + (46): return "Light Crossbow"; + (47): return "Sling"; + (48): return "Unused"; + (49): return "Unused"; + (50): return "Leather Armor"; + (51): return "Padded Armor"; + (52): return "Studded Leather Armor"; + (53): return "Ring Mail"; + (54): return "Scale Mail"; + (55): return "Chain Mail"; + (56): return "Splint Mail"; + (57): return "Banded Mail"; + (58): return "Plate Mail"; + (59): return "Shield"; + (60): return "Scroll of Protection*"; + (61): return "Magic-User Scroll"; + (62): return "Cleric Scroll"; + (63): return "Gauntlets"; + (64): return "Helm*"; + (65): return "Belt*"; + (66): return "Robe*"; + (67): return "Cloak"; + (68): return "Boots"; + (69): return "Ring"; + (70): return "Potions/Misc"; + (71): return "Potions/Misc"; + (72): return "Misc"; + (73): return "Arrow"; + (74): return "Leather Holy Symbol"; + (75): return "Brass Key"; + (76): return "Cursed Necklace"; + (77): return "Bracers"; + (78): return "Wand"; + (79): return "Wand"; + (80): return "Unknown Item*"; + (81): return "Unknown Item*"; + (82): return "Efreeti Bottle"; + (83): return "Unknown Item"; + (84): return "Potion of Giant Strength"; + (85): return "Holy Water Vial"; + (86): return "Flask of Oil"; + (87): return "Boulder"; + (88): return "Unknown Thrown*"; + (89): return "Unknown Melee*"; + (90): return "Ring of Feather Falling"; + (91): return "Pass"; + (92): return "Cloak of Displacement"; + (93): return "Ring of Protection"; + (94): return "Unknown Fine Bow"; + (95): return "Unknown Fine Bow"; + (96): return "Unknown Fine Bow"; + (97): return "Unused"; + (98): return "Unused"; + (99): return "Unused"; + (100): return "Unused"; + (101): return "Unused"; + (102): return "Unused"; + (103): return "Unused"; + (104): return "Unused"; + (105): return "Unused"; + (106): return "Unused"; + (107): return "Unused"; + (108): return "Unused"; + (109): return "Unused"; + (110): return "Unused"; + (111): return "Unused"; + (112): return "Unused"; + (113): return "Unused"; + (114): return "Unused"; + (115): return "Unused"; + (116): return "Unused"; + (117): return "Unused"; + (118): return "Unused"; + (119): return "Unused"; + (120): return "Unused"; + (121): return "Unused"; + (122): return "Unused"; + (123): return "Unused"; + (124): return "Unused"; + (125): return "Unused"; + (126): return "Unused"; + (127): return "Invalid*"; + // 02 - Curse of the Azure Bonds + (128): return "Invalid*"; + (129): return "Battle Axe"; + (130): return "Hand Axe"; + (131): return "Bardiche"; + (132): return "Bec de Corbin"; + (133): return "Bill-Guisarme"; + (134): return "Bo Stick"; + (135): return "Club"; + (136): return "Dagger"; + (137): return "Dart"; + (138): return "Fauchard"; + (139): return "Fauchard-Fork"; + (140): return "Flail"; + (141): return "Military Fork"; + (142): return "Glaive"; + (143): return "Glaive-Guisarme"; + (144): return "Guisarme"; + (145): return "Guisarme-Voulge"; + (146): return "Halberd"; + (147): return "Lucern Hammer"; + (148): return "Hammer"; + (149): return "Javelin"; + (150): return "Jo Stick"; + (151): return "Mace"; + (152): return "Morning Star"; + (153): return "Partisan"; + (154): return "Military Pick"; + (155): return "Awl Pike"; + (156): return "Bolt"; + (157): return "Ranseur"; + (158): return "Scimitar"; + (159): return "Spear"; + (160): return "Spetum"; + (161): return "Quarter Staff"; + (162): return "Bastard Sword"; + (163): return "Broad Sword"; + (164): return "Long Sword"; + (165): return "Short Sword"; + (166): return "Two-Handed Sword"; + (167): return "Trident"; + (168): return "Voulge"; + (169): return "Composite Long Bow"; + (170): return "Composite Short Bow"; + (171): return "Long Bow"; + (172): return "Short Bow"; + (173): return "Fine Composite Long Bow*"; + (174): return "Light Crossbow"; + (175): return "Sling"; + (176): return "Unused"; + (177): return "Unused"; + (178): return "Leather Armor"; + (179): return "Padded Armor"; + (180): return "Studded Leather Armor"; + (181): return "Ring Mail"; + (182): return "Scale Mail"; + (183): return "Chain Mail"; + (184): return "Splint Mail"; + (185): return "Banded Mail"; + (186): return "Plate Mail"; + (187): return "Shield"; + (188): return "Scroll of Protection"; + (189): return "Magic-User Scroll"; + (190): return "Cleric Scroll"; + (191): return "Gauntlets"; + (192): return "Helm"; + (193): return "Belt"; + (194): return "Robe"; + (195): return "Cloak*"; + (196): return "Boots*"; + (197): return "Ring"; + (198): return "Potions/Misc"; + (199): return "Potions/Misc"; + (200): return "Misc*"; + (201): return "Arrow"; + (202): return "Leather Holy Symbol*"; + (203): return "Brass Key*"; + (204): return "Cursed Necklace*"; + (205): return "Bracers"; + (206): return "Wand"; + (207): return "Wand"; + (208): return "Unknown Item*"; + (209): return "Unknown Item*"; + (210): return "Efreeti Bottle*"; + (211): return "Unknown Item"; + (212): return "Potion of Giant Strength"; + (213): return "Holy Water Vial*"; + (214): return "Flask of Oil"; + (215): return "Boulder*"; + (216): return "Unknown Thrown*"; + (217): return "Unknown Melee*"; + (218): return "Ring of Feather Falling*"; + (219): return "Pass*"; + (220): return "Cloak of Displacement"; + (221): return "Ring of Protection"; + (222): return "Drow Mace"; + (223): return "Elfin Chain Mail"; + (224): return "Drow Chain Mail"; + (225): return "Drow Long Sword"; + (226): return "Spine"; + (227): return "Ring of Wizardry"; + (228): return "Dart of Hornet's Nest"; + (229): return "Staff Sling"; + (230): return "Unused"; + (231): return "Unused"; + (232): return "Unused"; + (233): return "Unused"; + (234): return "Unused"; + (235): return "Unused"; + (236): return "Unused"; + (237): return "Unused"; + (238): return "Unused"; + (239): return "Unused"; + (240): return "Unused"; + (241): return "Unused"; + (242): return "Unused"; + (243): return "Unused"; + (244): return "Unused"; + (245): return "Unused"; + (246): return "Unused"; + (247): return "Unused"; + (248): return "Unused"; + (249): return "Unused"; + (250): return "Unused"; + (251): return "Unused"; + (252): return "Unused"; + (253): return "Unused"; + (254): return "Unused"; + (255): return "Invalid*"; + // 03 - Secret of the Silver Blades + (256): return "Invalid*"; + (257): return "Battle Axe"; + (258): return "Hand Axe"; + (259): return "Club*"; + (260): return "Dagger"; + (261): return "Dart"; + (262): return "Hammer"; + (263): return "Javelin"; + (264): return "Mace"; + (265): return "Morning Star"; + (266): return "Military Pick*"; + (267): return "Awl Pike*"; + (268): return "Bolt"; + (269): return "Scimitar"; + (270): return "Spear*"; + (271): return "Quarter Staff"; + (272): return "Bastard Sword*"; + (273): return "Broad Sword"; + (274): return "Long Sword"; + (275): return "Short Sword"; + (276): return "Two-Handed Sword"; + (277): return "Trident"; + (278): return "Composite Long Bow"; + (279): return "Composite Short Bow*"; + (280): return "Long Bow"; + (281): return "Short Bow"; + (282): return "Fine Long Bow"; + (283): return "Light Crossbow"; + (284): return "Sling"; + (285): return "Staff Sling"; + (286): return "Arrow"; + (287): return "Leather Armor"; + (288): return "Ring Mail*"; + (289): return "Scale Mail"; + (290): return "Chain Mail"; + (291): return "Banded Mail"; + (292): return "Plate Mail"; + (293): return "Shield"; + (294): return "Scroll of Protection"; + (295): return "Magic-User Scroll"; + (296): return "Cleric Scroll"; + (297): return "Helm*"; + (298): return "Belt"; + (299): return "Robe*"; + (300): return "Cloak*"; + (301): return "Boots"; + (302): return "Ring"; + (303): return "Potions/Misc"; + (304): return "Mirror"; + (305): return "Misc*"; + (306): return "Bracers"; + (307): return "Wand"; + (308): return "Wand"; + (309): return "Potion of Giant Strength"; + (310): return "Cute Yellow Canary"; + (311): return "Boulder"; + (312): return "Boulder"; + (313): return "Boulder"; + (314): return "Cloak of Displacement"; + (315): return "Ring of Protection"; + (316): return "Mace of Disruption*"; + (317): return "Elfin Chain*"; + (318): return "Drow Chain Mail*"; + (319): return "Drow Long Sword*"; + (320): return "Spine*"; + (321): return "Ring of Wizardry"; + (322): return "Dart of Hornet's Nest"; + (323): return "Hoopak*"; + (324): return "Solamnic Plate*"; + (325): return "Footman's Dragonlance*"; + (326): return "Flail"; + (327): return "Halberd"; + (328): return "Gauntlets"; + (329): return "Bundle of Scrolls"; + (330): return "Leather Holy Symbol*"; + (331): return "Brass Key*"; + (332): return "Belt*"; + (333): return "Bracers*"; + (334): return "Wand*"; + (335): return "Wand*"; + (336): return "Unknown Item*"; + (337): return "Unknown Item*"; + (338): return "Efreeti Bottle*"; + (339): return "Unknown Item"; + (340): return "Potion of Giant Strength*"; + (341): return "Holy Water Vial*"; + (342): return "Flask of Oil*"; + (343): return "Boulder*"; + (344): return "Unknown Thrown*"; + (345): return "Unknown Melee*"; + (346): return "Ring of Feather Falling*"; + (347): return "Pass*"; + (348): return "Cloak of Displacement*"; + (349): return "Ring of Protection*"; + (350): return "Drow Mace*"; + (351): return "Elfin Chain Mail*"; + (352): return "Drow Chain Mail*"; + (353): return "Drow Long Sword*"; + (354): return "Spine*"; + (355): return "Ring of Wizardry*"; + (356): return "Dart of Hornet's Nest*"; + (357): return "Staff Sling*"; + (358): return "Unused"; + (359): return "Unused"; + (360): return "Unused"; + (361): return "Unused"; + (362): return "Unused"; + (363): return "Unused"; + (364): return "Unused"; + (365): return "Unused"; + (366): return "Unused"; + (367): return "Unused"; + (368): return "Unused"; + (369): return "Unused"; + (370): return "Unused"; + (371): return "Unused"; + (372): return "Unused"; + (373): return "Unused"; + (374): return "Unused"; + (375): return "Unused"; + (376): return "Unused"; + (377): return "Unused"; + (378): return "Unused"; + (379): return "Unused"; + (380): return "Unused"; + (381): return "Unused"; + (382): return "Unused"; + (383): return "Invalid*"; + // 04 - Pools of Darkness + (384): return "Unused"; + (385): return "Battle Axe"; + (386): return "Hand Axe"; + (387): return "Club"; + (388): return "Dagger"; + (389): return "Dart"; + (390): return "Hammer"; + (391): return "Javelin"; + (392): return "Mace"; + (393): return "Morning Star"; + (394): return "Military Pick"; + (395): return "Awl Pike"; + (396): return "Bolt"; + (397): return "Scimitar"; + (398): return "Spear"; + (399): return "Quarter Staff"; + (400): return "Bastard Sword"; + (401): return "Broad Sword"; + (402): return "Long Sword"; + (403): return "Short Sword"; + (404): return "Two-Handed Sword"; + (405): return "Trident"; + (406): return "Composite Long Bow"; + (407): return "Composite Short Bow"; + (408): return "Long Bow"; + (409): return "Short Bow"; + (410): return "Fine Long Bow"; + (411): return "Light Crossbow"; + (412): return "Sling"; + (413): return "Staff Sling"; + (414): return "Arrow"; + (415): return "Leather Armor"; + (416): return "Ring Mail"; + (417): return "Scale Mail"; + (418): return "Chain Mail"; + (419): return "Banded Mail"; + (420): return "Plate Mail"; + (421): return "Shield"; + (422): return "Scroll of Protection"; + (423): return "Magic-User Scroll"; + (424): return "Cleric Scroll"; + (425): return "Helm"; + (426): return "Belt"; + (427): return "Robe"; + (428): return "Cloak"; + (429): return "Boots"; + (430): return "Ring"; + (431): return "Potions/Misc"; + (432): return "Mirror"; + (433): return "Misc*"; + (434): return "Bracers"; + (435): return "Wand"; + (436): return "Wand*"; + (437): return "Potion of Giant Strength"; + (438): return "Unknown Item*"; + (439): return "Holy Water Vial*"; + (440): return "Flask of Oil*"; + (441): return "Boulder*"; + (442): return "Cloak of Displacement"; + (443): return "Ring of Protection"; + (444): return "Mace of Disruption*"; + (445): return "Elfin Chain"; + (446): return "Drow Chain Mail"; + (447): return "Drow Long Sword"; + (448): return "Spine*"; + (449): return "Ring of Wizardry"; + (450): return "Dart of Hornet's Nest"; + (451): return "Hoopak*"; + (452): return "Solamnic Plate*"; + (453): return "Footman's Dragonlance*"; + (454): return "Flail"; + (455): return "Halberd**"; + (456): return "Gauntlets"; + (457): return "Vorpal Long Sword"; + (458): return "Blessed Bolt"; + (459): return "Cloak of Protection"; + (460): return "Brass Key*"; + (461): return "Belt*"; + (462): return "Bracers*"; + (463): return "Wand*"; + (464): return "Wand*"; + (465): return "Unknown Item*"; + (466): return "Unknown Item*"; + (467): return "Efreeti Bottle*"; + (468): return "Unknown Item"; + (469): return "Potion of Giant Strength*"; + (470): return "Holy Water Vial*"; + (471): return "Flask of Oil*"; + (472): return "Boulder*"; + (473): return "Unknown Thrown*"; + (474): return "Unknown Melee*"; + (475): return "Ring of Feather Falling*"; + (476): return "Pass*"; + (477): return "Cloak of Displacement*"; + (478): return "Ring of Protection*"; + (479): return "Drow Mace*"; + (480): return "Elfin Chain Mail*"; + (481): return "Drow Chain Mail*"; + (482): return "Drow Long Sword*"; + (483): return "Spine*"; + (484): return "Ring of Wizardry*"; + (485): return "Dart of Hornet's Nest*"; + (486): return "Staff Sling*"; + (487): return "Unused"; + (488): return "Unused"; + (489): return "Unused"; + (490): return "Unused"; + (491): return "Unused"; + (492): return "Unused"; + (493): return "Unused"; + (494): return "Unused"; + (495): return "Unused"; + (496): return "Unused"; + (497): return "Unused"; + (498): return "Unused"; + (499): return "Unused"; + (500): return "Unused"; + (501): return "Unused"; + (502): return "Unused"; + (503): return "Unused"; + (504): return "Unused"; + (505): return "Unused"; + (506): return "Unused"; + (507): return "Unused"; + (508): return "Unused"; + (509): return "Unused"; + (510): return "Unused"; + (511): return "Unused"; + // 05 - Champions of Krynn + (512): return "Invalid*"; + (513): return "Battle Axe"; + (514): return "Hand Axe*"; + (515): return "Club*"; + (516): return "Dagger"; + (517): return "Dart"; + (518): return "Hammer*"; + (519): return "Javelin*"; + (520): return "Mace"; + (521): return "Morning Star*"; + (522): return "Military Pick*"; + (523): return "Awl Pike*"; + (524): return "Bolt*"; + (525): return "Scimitar*"; + (526): return "Spear*"; + (527): return "Quarter Staff"; + (528): return "Bastard Sword*"; + (529): return "Broad Sword"; + (530): return "Long Sword"; + (531): return "Short Sword"; + (532): return "Two-Handed Sword"; + (533): return "Trident*"; + (534): return "Composite Long Bow"; + (535): return "Composite Short Bow*"; + (536): return "Long Bow*"; + (537): return "Short Bow"; + (538): return "Fine Long Bow*"; + (539): return "Light Crossbow*"; + (540): return "Sling"; + (541): return "Staff Sling"; + (542): return "Arrow"; + (543): return "Leather Armor"; + (544): return "Ring Mail"; + (545): return "Scale Mail"; + (546): return "Chain Mail"; + (547): return "Banded Mail"; + (548): return "Plate Mail"; + (549): return "Shield"; + (550): return "Scroll of Protection"; + (551): return "Magic-User Scroll"; + (552): return "Cleric Scroll"; + (553): return "Helm*"; + (554): return "Belt"; + (555): return "Robe*"; + (556): return "Cloak*"; + (557): return "Boots*"; + (558): return "Ring*"; + (559): return "Potions/Misc"; + (560): return "Mirror*"; + (561): return "Misc*"; + (562): return "Bracers"; + (563): return "Wand"; + (564): return "Wand"; + (565): return "Potion of Giant Strength*"; + (566): return "Holy Water Vial*"; + (567): return "Flask of Oil*"; + (568): return "Boulder*"; + (569): return "Unknown Thrown"; + (570): return "Cloak of Displacement"; + (571): return "Ring of Protection"; + (572): return "Mace of Disruption"; + (573): return "Elfin Chain*"; + (574): return "Drow Chain Mail*"; + (575): return "Drow Long Sword**"; + (576): return "Spine*"; + (577): return "Ring of Wizardry*"; + (578): return "Dart of Hornet's Nest*"; + (579): return "Hoopak"; + (580): return "Solamnic Plate"; + (581): return "Footman's Dragonlance"; + (582): return "Flail"; + (583): return "Halberd*"; + (584): return "Gauntlets"; + (585): return "Unused"; + (586): return "Leather Holy Symbol*"; + (587): return "Brass Key*"; + (588): return "Belt*"; + (589): return "Bracers*"; + (590): return "Wand*"; + (591): return "Wand*"; + (592): return "Unknown Item*"; + (593): return "Unknown Item*"; + (594): return "Efreeti Bottle*"; + (595): return "Unknown Item*"; + (596): return "Potion of Giant Strength*"; + (597): return "Holy Water Vial*"; + (598): return "Flask of Oil*"; + (599): return "Boulder*"; + (600): return "Unknown Thrown*"; + (601): return "Unknown Melee*"; + (602): return "Ring of Feather Falling*"; + (603): return "Pass*"; + (604): return "Cloak of Displacement*"; + (605): return "Ring of Protection*"; + (606): return "Drow Mace*"; + (607): return "Elfin Chain Mail*"; + (608): return "Drow Chain Mail*"; + (609): return "Drow Long Sword*"; + (610): return "Spine*"; + (611): return "Ring of Wizardry*"; + (612): return "Dart of Hornet's Nest*"; + (613): return "Staff Sling*"; + (614): return "Unused"; + (615): return "Unused"; + (616): return "Unused"; + (617): return "Unused"; + (618): return "Unused"; + (619): return "Unused"; + (620): return "Unused"; + (621): return "Unused"; + (622): return "Unused"; + (623): return "Unused"; + (624): return "Unused"; + (625): return "Unused"; + (626): return "Unused"; + (627): return "Unused"; + (628): return "Unused"; + (629): return "Unused"; + (630): return "Unused"; + (631): return "Unused"; + (632): return "Unused"; + (633): return "Unused"; + (634): return "Unused"; + (635): return "Unused"; + (636): return "Unused"; + (637): return "Unused"; + (638): return "Unused"; + (639): return "Invalid*"; + // 06 - Death Knights of Krynn + (640): return "Invalid*"; + (641): return "Battle Axe"; + (642): return "Hand Axe*"; + (643): return "Club*"; + (644): return "Dagger"; + (645): return "Dart"; + (646): return "Hammer*"; + (647): return "Javelin*"; + (648): return "Mace"; + (649): return "Morning Star*"; + (650): return "Military Pick*"; + (651): return "Awl Pike*"; + (652): return "Bolt*"; + (653): return "Scimitar"; + (654): return "Spear*"; + (655): return "Quarter Staff"; + (656): return "Bastard Sword*"; + (657): return "Broad Sword*"; + (658): return "Long Sword"; + (659): return "Short Sword"; + (660): return "Two-Handed Sword"; + (661): return "Trident*"; + (662): return "Composite Long Bow"; + (663): return "Composite Short Bow*"; + (664): return "Long Bow"; + (665): return "Short Bow"; + (666): return "Fine Long Bow*"; + (667): return "Light Crossbow*"; + (668): return "Sling"; + (669): return "Staff Sling"; + (670): return "Arrow"; + (671): return "Leather Armor"; + (672): return "Ring Mail*"; + (673): return "Scale Mail*"; + (674): return "Chain Mail"; + (675): return "Banded Mail"; + (676): return "Plate Mail"; + (677): return "Shield"; + (678): return "Scroll of Protection"; + (679): return "Magic-User Scroll"; + (680): return "Cleric Scroll"; + (681): return "Helm*"; + (682): return "Belt*"; + (683): return "Robe*"; + (684): return "Cloak*"; + (685): return "Boots"; + (686): return "Ring*"; + (687): return "Potions/Misc"; + (688): return "Mirror*"; + (689): return "Misc*"; + (690): return "Bracers"; + (691): return "Wand"; + (692): return "Wand"; + (693): return "Potion of Giant Strength*"; + (694): return "Holy Water Vial*"; + (695): return "Flask of Oil*"; + (696): return "Boulder*"; + (697): return "Unknown Thrown"; + (698): return "Cloak of Displacement"; + (699): return "Ring of Protection"; + (700): return "Mace of Disruption*"; + (701): return "Elfin Chain*"; + (702): return "Drow Chain Mail*"; + (703): return "Drow Long Sword*"; + (704): return "Spine*"; + (705): return "Ring of Wizardry*"; + (706): return "Dart of Hornet's Nest"; + (707): return "Hoopak"; + (708): return "Solamnic Plate"; + (709): return "Footman's Dragonlance"; + (710): return "Flail"; + (711): return "Halberd*"; + (712): return "Gauntlets"; + (713): return "Unused"; + (714): return "Leather Holy Symbol*"; + (715): return "Brass Key*"; + (716): return "Belt*"; + (717): return "Bracers*"; + (718): return "Wand*"; + (719): return "Wand*"; + (720): return "Unknown Item*"; + (721): return "Unknown Item*"; + (722): return "Efreeti Bottle*"; + (723): return "Unknown Item"; + (724): return "Potion of Giant Strength*"; + (725): return "Holy Water Vial*"; + (726): return "Flask of Oil*"; + (727): return "Boulder*"; + (728): return "Unknown Thrown*"; + (729): return "Unknown Melee*"; + (730): return "Ring of Feather Falling*"; + (731): return "Pass*"; + (732): return "Cloak of Displacement*"; + (733): return "Ring of Protection*"; + (734): return "Drow Mace*"; + (735): return "Elfin Chain Mail*"; + (736): return "Drow Chain Mail*"; + (737): return "Drow Long Sword*"; + (738): return "Spine*"; + (739): return "Ring of Wizardry*"; + (740): return "Dart of Hornet's Nest*"; + (741): return "Staff Sling*"; + (742): return "Unused"; + (743): return "Unused"; + (744): return "Unused"; + (745): return "Unused"; + (746): return "Unused"; + (747): return "Unused"; + (748): return "Unused"; + (749): return "Unused"; + (750): return "Unused"; + (751): return "Unused"; + (752): return "Unused"; + (753): return "Unused"; + (754): return "Unused"; + (755): return "Unused"; + (756): return "Unused"; + (757): return "Unused"; + (758): return "Unused"; + (759): return "Unused"; + (760): return "Unused"; + (761): return "Unused"; + (762): return "Unused"; + (763): return "Unused"; + (764): return "Unused"; + (765): return "Unused"; + (766): return "Unused"; + (767): return "Invalid*"; + // 07 - The Dark Queen of Krynn + (768): return "Unused"; + (769): return "Battle Axe"; + (770): return "Hand Axe"; + (771): return "Club"; + (772): return "Dagger"; + (773): return "Dart"; + (774): return "Hammer"; + (775): return "Javelin"; + (776): return "Mace"; + (777): return "Morning Star"; + (778): return "Military Pick"; + (779): return "Awl Pike"; + (780): return "Bolt"; + (781): return "Scimitar"; + (782): return "Spear"; + (783): return "Quarter Staff"; + (784): return "Bastard Sword"; + (785): return "Broad Sword"; + (786): return "Long Sword"; + (787): return "Short Sword"; + (788): return "Two-Handed Sword"; + (789): return "Trident"; + (790): return "Composite Long Bow"; + (791): return "Composite Short Bow"; + (792): return "Long Bow"; + (793): return "Short Bow"; + (794): return "Fine Long Bow"; + (795): return "Light Crossbow"; + (796): return "Sling"; + (797): return "Staff Sling"; + (798): return "Arrow"; + (799): return "Leather Armor"; + (800): return "Ring Mail"; + (801): return "Scale Mail"; + (802): return "Chain Mail"; + (803): return "Banded Mail"; + (804): return "Plate Mail"; + (805): return "Shield"; + (806): return "Scroll of Protection"; + (807): return "Magic-User Scroll"; + (808): return "Cleric Scroll"; + (809): return "Helm"; + (810): return "Belt"; + (811): return "Robe"; + (812): return "Cloak"; + (813): return "Boots"; + (814): return "Ring"; + (815): return "Potions/Misc"; + (816): return "Mirror"; + (817): return "Misc*"; + (818): return "Bracers"; + (819): return "Wand"; + (820): return "Wand*"; + (821): return "Potion of Giant Strength"; + (822): return "Unknown Item*"; + (823): return "Holy Water Vial*"; + (824): return "Flask of Oil*"; + (825): return "Boulder*"; + (826): return "Cloak of Displacement"; + (827): return "Ring of Protection"; + (828): return "Mace of Disruption*"; + (829): return "Elfin Chain"; + (830): return "Drow Chain Mail*"; + (831): return "Drow Long Sword*"; + (832): return "Spine*"; + (833): return "Ring of Wizardry"; + (834): return "Dart of Hornet's Nest"; + (835): return "Hoopak"; + (836): return "Solamnic Plate"; + (837): return "Footman's Dragonlance"; + (838): return "Flail"; + (839): return "Halberd**"; + (840): return "Gauntlets"; + (841): return "Bundle of Scrolls*"; + (842): return "Blessed Bolt*"; + (843): return "Cloak of Protection"; + (844): return "Brass Key*"; + (845): return "Belt*"; + (846): return "Bracers*"; + (847): return "Wand*"; + (848): return "Wand*"; + (849): return "Unknown Item*"; + (850): return "Unknown Item*"; + (851): return "Efreeti Bottle*"; + (852): return "Unknown Item*"; + (853): return "Potion of Giant Strength*"; + (854): return "Holy Water Vial*"; + (855): return "Flask of Oil*"; + (856): return "Boulder*"; + (857): return "Unknown Thrown*"; + (858): return "Unknown Melee*"; + (859): return "Ring of Feather Falling*"; + (860): return "Pass*"; + (861): return "Cloak of Displacement*"; + (862): return "Ring of Protection*"; + (863): return "Drow Mace*"; + (864): return "Elfin Chain Mail*"; + (865): return "Drow Chain Mail*"; + (866): return "Drow Long Sword*"; + (867): return "Spine*"; + (868): return "Ring of Wizardry*"; + (869): return "Dart of Hornet's Nest*"; + (870): return "Staff Sling*"; + (871): return "Staff of Striking"; + (872): return "Foethumper**"; + (873): return "Vorpal Long Sword"; + (874): return "Unused"; + (875): return "Unused"; + (876): return "Unused"; + (877): return "Unused"; + (878): return "Unused"; + (879): return "Unused"; + (880): return "Unused"; + (881): return "Unused"; + (882): return "Unused"; + (883): return "Unused"; + (884): return "Unused"; + (885): return "Unused"; + (886): return "Unused"; + (887): return "Unused"; + (888): return "Unused"; + (889): return "Unused"; + (890): return "Unused"; + (891): return "Unused"; + (892): return "Unused"; + (893): return "Unused"; + (894): return "Unused"; + (895): return "Unused"; + // 08 - Gateway to the Savage Frontier + (896): return "Invalid*"; + (897): return "Battle Axe"; + (898): return "Hand Axe"; + (899): return "Bardiche"; + (900): return "Bec de Corbin"; + (901): return "Bill-Guisarme"; + (902): return "Bo Stick"; + (903): return "Club"; + (904): return "Dagger"; + (905): return "Dart"; + (906): return "Fauchard"; + (907): return "Fauchard-Fork"; + (908): return "Flail"; + (909): return "Military Fork"; + (910): return "Glaive"; + (911): return "Glaive-Guisarme"; + (912): return "Guisarme"; + (913): return "Guisarme-Voulge"; + (914): return "Halberd"; + (915): return "Lucern Hammer"; + (916): return "Hammer"; + (917): return "Javelin"; + (918): return "Jo Stick"; + (919): return "Mace"; + (920): return "Morning Star"; + (921): return "Partisan"; + (922): return "Military Pick"; + (923): return "Awl Pike"; + (924): return "Bolt"; + (925): return "Ranseur"; + (926): return "Scimitar"; + (927): return "Spear"; + (928): return "Spetum"; + (929): return "Quarter Staff"; + (930): return "Bastard Sword"; + (931): return "Broad Sword"; + (932): return "Long Sword"; + (933): return "Short Sword"; + (934): return "Two-Handed Sword"; + (935): return "Trident"; + (936): return "Voulge"; + (937): return "Composite Long Bow"; + (938): return "Composite Short Bow"; + (939): return "Long Bow"; + (940): return "Short Bow"; + (941): return "Fine Composite Long Bow*"; + (942): return "Light Crossbow"; + (943): return "Sling"; + (944): return "Unused"; + (945): return "Unused"; + (946): return "Leather Armor"; + (947): return "Padded Armor"; + (948): return "Studded Leather Armor"; + (949): return "Ring Mail"; + (950): return "Scale Mail"; + (951): return "Chain Mail"; + (952): return "Splint Mail"; + (953): return "Banded Mail"; + (954): return "Plate Mail"; + (955): return "Shield"; + (956): return "Scroll of Protection*"; + (957): return "Magic-User Scroll"; + (958): return "Cleric Scroll"; + (959): return "Gauntlets"; + (960): return "Helm"; + (961): return "Belt*"; + (962): return "Robe*"; + (963): return "Cloak"; + (964): return "Boots*"; + (965): return "Ring"; + (966): return "Potions/Misc"; + (967): return "Potions/Misc*"; + (968): return "Misc*"; + (969): return "Arrow"; + (970): return "Leather Holy Symbol*"; + (971): return "Brass Key*"; + (972): return "Cursed Necklace*"; + (973): return "Bracers"; + (974): return "Wand*"; + (975): return "Wand"; + (976): return "Unknown Item*"; + (977): return "Unknown Item*"; + (978): return "Efreeti Bottle*"; + (979): return "Unknown Item*"; + (980): return "Potion of Giant Strength*"; + (981): return "Holy Water Vial"; + (982): return "Flask of Oil"; + (983): return "Boulder"; + (984): return "Unknown Thrown*"; + (985): return "Huge Boulder"; + (986): return "Ring of Feather Falling*"; + (987): return "Pass*"; + (988): return "Cloak of Displacement"; + (989): return "Ring of Protection"; + (990): return "Drow Mace*"; + (991): return "Elfin Chain Mail*"; + (992): return "Drow Chain Mail*"; + (993): return "Drow Long Sword*"; + (994): return "Spine"; + (995): return "Ring of Wizardry*"; + (996): return "Dart of Hornet's Nest"; + (997): return "Staff Sling"; + (998): return "Unused"; + (999): return "Unused"; + (1000): return "Unused"; + (1001): return "Unused"; + (1002): return "Unused"; + (1003): return "Unused"; + (1004): return "Unused"; + (1005): return "Unused"; + (1006): return "Unused"; + (1007): return "Unused"; + (1008): return "Unused"; + (1009): return "Unused"; + (1010): return "Unused"; + (1011): return "Unused"; + (1012): return "Unused"; + (1013): return "Unused"; + (1014): return "Unused"; + (1015): return "Unused"; + (1016): return "Unused"; + (1017): return "Unused"; + (1018): return "Unused"; + (1019): return "Unused"; + (1020): return "Unused"; + (1021): return "Unused"; + (1022): return "Unused"; + (1023): return "Invalid*"; + // 09 - Treasures of the Savage Frontier + (1024): return "Unused"; + (1025): return "Battle Axe"; + (1026): return "Hand Axe"; + (1027): return "Club"; + (1028): return "Dagger"; + (1029): return "Dart"; + (1030): return "Hammer"; + (1031): return "Javelin"; + (1032): return "Mace"; + (1033): return "Morning Star"; + (1034): return "Military Pick"; + (1035): return "Awl Pike"; + (1036): return "Bolt"; + (1037): return "Scimitar"; + (1038): return "Spear"; + (1039): return "Quarter Staff"; + (1040): return "Bastard Sword"; + (1041): return "Broad Sword"; + (1042): return "Long Sword"; + (1043): return "Short Sword"; + (1044): return "Two-Handed Sword"; + (1045): return "Trident"; + (1046): return "Composite Long Bow"; + (1047): return "Composite Short Bow"; + (1048): return "Long Bow"; + (1049): return "Short Bow"; + (1050): return "Fine Long Bow"; + (1051): return "Light Crossbow"; + (1052): return "Sling"; + (1053): return "Staff Sling"; + (1054): return "Arrow"; + (1055): return "Leather Armor"; + (1056): return "Ring Mail"; + (1057): return "Scale Mail"; + (1058): return "Chain Mail"; + (1059): return "Banded Mail"; + (1060): return "Plate Mail"; + (1061): return "Shield"; + (1062): return "Scroll of Protection"; + (1063): return "Magic-User Scroll"; + (1064): return "Cleric Scroll"; + (1065): return "Helm"; + (1066): return "Belt"; + (1067): return "Robe"; + (1068): return "Cloak"; + (1069): return "Boots"; + (1070): return "Ring"; + (1071): return "Potions/Misc"; + (1072): return "Mirror"; + (1073): return "Misc*"; + (1074): return "Bracers"; + (1075): return "Wand"; + (1076): return "Wand"; + (1077): return "Potion of Giant Strength"; + (1078): return "Unknown Item*"; + (1079): return "Holy Water Vial*"; + (1080): return "Flask of Oil*"; + (1081): return "Boulder*"; + (1082): return "Cloak of Displacement"; + (1083): return "Ring of Protection"; + (1084): return "Mace of Disruption*"; + (1085): return "Elfin Chain"; + (1086): return "Drow Chain Mail"; + (1087): return "Drow Long Sword"; + (1088): return "Spine*"; + (1089): return "Ring of Wizardry"; + (1090): return "Dart of Hornet's Nest"; + (1091): return "Hoopak*"; + (1092): return "Solamnic Plate*"; + (1093): return "Footman's Dragonlance*"; + (1094): return "Flail"; + (1095): return "Halberd"; + (1096): return "Gauntlets**"; + (1097): return "Vorpal Long Sword"; + (1098): return "Blessed Bolt"; + (1099): return "Cloak of Protection"; + (1100): return "Brass Key*"; + (1101): return "Belt of Protection"; + (1102): return "Bracers*"; + (1103): return "Wand*"; + (1104): return "Wand*"; + (1105): return "Unknown Item*"; + (1106): return "Unknown Item*"; + (1107): return "Efreeti Bottle*"; + (1108): return "Unknown Item*"; + (1109): return "Potion of Giant Strength*"; + (1110): return "Holy Water Vial*"; + (1111): return "Flask of Oil"; + (1112): return "Boulder*"; + (1113): return "Unknown Thrown*"; + (1114): return "Unknown Melee*"; + (1115): return "Ring of Feather Falling*"; + (1116): return "Staff of Striking"; + (1117): return "Cloak of Displacement*"; + (1118): return "Ring of Protection*"; + (1119): return "Drow Mace*"; + (1120): return "Elfin Chain Mail*"; + (1121): return "Drow Chain Mail*"; + (1122): return "Drow Long Sword*"; + (1123): return "Spine*"; + (1124): return "Ring of Wizardry*"; + (1125): return "Dart of Hornet's Nest*"; + (1126): return "Staff Sling*"; + (1127): return "Unused"; + (1128): return "Unused"; + (1129): return "Unused"; + (1130): return "Unused"; + (1131): return "Unused"; + (1132): return "Unused"; + (1133): return "Unused"; + (1134): return "Unused"; + (1135): return "Unused"; + (1136): return "Unused"; + (1137): return "Unused"; + (1138): return "Unused"; + (1139): return "Unused"; + (1140): return "Unused"; + (1141): return "Unused"; + (1142): return "Unused"; + (1143): return "Unused"; + (1144): return "Unused"; + (1145): return "Unused"; + (1146): return "Unused"; + (1147): return "Unused"; + (1148): return "Unused"; + (1149): return "Unused"; + (1150): return "Unused"; + (1151): return "Unused"; + // 10 - Unlimited Adventures + (1152): return "Unused"; + (1153): return "Battle Axe"; + (1154): return "Hand Axe"; + (1155): return "Club"; + (1156): return "Dagger"; + (1157): return "Dart"; + (1158): return "Hammer"; + (1159): return "Javelin"; + (1160): return "Mace"; + (1161): return "Morning Star"; + (1162): return "Military Pick"; + (1163): return "Awl Pike"; + (1164): return "Bolt"; + (1165): return "Scimitar"; + (1166): return "Spear"; + (1167): return "Quarter Staff"; + (1168): return "Bastard Sword"; + (1169): return "Broad Sword"; + (1170): return "Long Sword"; + (1171): return "Short Sword"; + (1172): return "Two-Handed Sword"; + (1173): return "Trident"; + (1174): return "Composite Long Bow"; + (1175): return "Composite Short Bow"; + (1176): return "Long Bow"; + (1177): return "Short Bow"; + (1178): return "Fine Long Bow"; + (1179): return "Light Crossbow"; + (1180): return "Sling"; + (1181): return "Staff Sling"; + (1182): return "Arrow"; + (1183): return "Leather Armor"; + (1184): return "Ring Mail"; + (1185): return "Scale Mail"; + (1186): return "Chain Mail"; + (1187): return "Banded Mail"; + (1188): return "Plate Mail"; + (1189): return "Shield"; + (1190): return "Scroll of Protection"; + (1191): return "Magic-User Scroll"; + (1192): return "Cleric Scroll"; + (1193): return "Helm"; + (1194): return "Belt"; + (1195): return "Robe"; + (1196): return "Cloak"; + (1197): return "Boots"; + (1198): return "Ring"; + (1199): return "Potions/Misc"; + (1200): return "Mirror"; + (1201): return "Misc*"; + (1202): return "Bracers"; + (1203): return "Wand"; + (1204): return "Wand*"; + (1205): return "Potion of Giant Strength"; + (1206): return "Unknown Item*"; + (1207): return "Holy Water Vial*"; + (1208): return "Flask of Oil*"; + (1209): return "Boulder*"; + (1210): return "Cloak of Displacement"; + (1211): return "Ring of Protection"; + (1212): return "Mace of Disruption*"; + (1213): return "Elfin Chain"; + (1214): return "Drow Chain Mail"; + (1215): return "Drow Long Sword"; + (1216): return "Spine*"; + (1217): return "Ring of Wizardry"; + (1218): return "Dart of Hornet's Nest"; + (1219): return "Hoopak*"; + (1220): return "Solamnic Plate*"; + (1221): return "Footman's Dragonlance*"; + (1222): return "Flail"; + (1223): return "Halberd"; + (1224): return "Gauntlets"; + (1225): return "Bundle of Scrolls*"; + (1226): return "Blessed Bolt"; + (1227): return "Cloak of Protection"; + (1228): return "Brass Key*"; + (1229): return "Belt*"; + (1230): return "Bracers*"; + (1231): return "Wand*"; + (1232): return "Wand*"; + (1233): return "Unknown Item*"; + (1234): return "Unknown Item*"; + (1235): return "Efreeti Bottle*"; + (1236): return "Unknown Item*"; + (1237): return "Potion of Giant Strength*"; + (1238): return "Holy Water Vial*"; + (1239): return "Flask of Oil*"; + (1240): return "Boulder*"; + (1241): return "Unknown Thrown*"; + (1242): return "Unknown Melee*"; + (1243): return "Ring of Feather Falling*"; + (1244): return "Pass*"; + (1245): return "Cloak of Displacement*"; + (1246): return "Ring of Protection*"; + (1247): return "Drow Mace*"; + (1248): return "Elfin Chain Mail*"; + (1249): return "Drow Chain Mail*"; + (1250): return "Drow Long Sword*"; + (1251): return "Spine*"; + (1252): return "Ring of Wizardry*"; + (1253): return "Dart of Hornet's Nest*"; + (1254): return "Staff Sling*"; + (1255): return "Unused"; + (1256): return "Unused"; + (1257): return "Vorpal Long Sword"; + (1258): return "Unused"; + (1259): return "Unused"; + (1260): return "Unused"; + (1261): return "Unused"; + (1262): return "Unused"; + (1263): return "Unused"; + (1264): return "Unused"; + (1265): return "Unused"; + (1266): return "Unused"; + (1267): return "Unused"; + (1268): return "Unused"; + (1269): return "Unused"; + (1270): return "Unused"; + (1271): return "Unused"; + (1272): return "Unused"; + (1273): return "Unused"; + (1274): return "Unused"; + (1275): return "Unused"; + (1276): return "Unused"; + (1277): return "Unused"; + (1278): return "Unused"; + (1279): return "Unused"; + // Error + (_): return "Unknown"; + } +}; + +/******************************* + Structs +*******************************/ +// Base Item struct +struct ITEMBASE { + ITEMTYPE ItemType [[comment("Base item type (i.e. weapon/shield/armor/etc)\nReferred to as \"slot\" by GBC")]]; + // Helper variable for AC formulas + bool IsArmor = (ItemType == 0x02 || BracerID == std::core::array_index()) ? true : false; + u8 Hands [[comment("Number of hands required to equip")]]; + u8 DvL_Dice_Count [[comment("Number of dice to roll when attacking \"large\" enemies")]]; + u8 DvL_Dice_Type [[comment("Type of dice rolled when attacking \"large\" enemies (i.e. d4, d6, etc)")]]; + s8 DvL_Bonus [[comment("Base bonus damage to add to the rolled result when attacking \"large\" enemies\nStacks with item bonuses")]]; + u8 RateOfFire [[comment("Number of missiles that can be launched/thrown in a round multiplied by 2")]]; + u8 AC [[format_read(std::format("{}", IsArmor ? "ACArmorRead" : "ACOtherRead")),format_write(std::format("{}", IsArmor ? "ACArmorWrite" : "ACOtherWrite")),comment("Armor Class\nEnter 255 to set AC to \"-\" (None) for non-armor/defensive items")]]; + match (GameID) { + (4|9|10): ITEMDAMAGETYPE_B DamageType [[comment("Type of damage caused by the weapon\nUsed to determine if target is resistant to the attack")]]; + (_): ITEMDAMAGETYPE_A DamageType [[comment("Type of damage caused by the weapon\nUsed to determine if target is resistant to the attack")]]; + } + u8 Unknown_08 [[comment("Unknown usage")]]; // Noted as a being an IsMelee type flag in 10 but its usage doesn't align and appears to me to be a leftover value from 1 + u8 DvS_Dice_Count [[comment("Number of dice to roll when attacking \"small\" enemies")]]; + u8 DvS_Dice_Type [[comment("Type of dice rolled when attacking \"small\" enemies (i.e. d4, d6, etc)")]]; + s8 DvS_Bonus [[comment("Base bonus damage to add to the rolled result when attacking \"small\" enemies\nStacks with item bonuses")]]; + u8 Range [[comment("Max distance from players for ranged attacks plus 1")]]; + CLASSRESTRICTION ItemRestriction [[comment("Bit array indicating which classes can equip/use the item")]]; + WEAPONFLAGARRAY WeaponFlag [[comment("Bit array containing weapon specific settings\nPrimarily for ranged weapons")]]; // WeaponFlagArray + u8 Unknown_0F [[comment(std::format("{}", GameID == 8 ? "Unknown usage" : "Always 00"))]]; +// Gateway (8) has two additional u32 values at the end of each record - usage unknown + if (GameID == 8) { + u32 Unknown_10 [[comment("Unknown usage")]]; + u32 Unknown_14 [[comment("Unknown usage")]]; + } +} [[name(std::format("{:03d}: {}", std::core::array_index(), GetDisplayName(std::core::array_index() + ((GameID -1) * 128))))]]; + +// Base Items +ITEMBASE ItemList[128] @ Offset; \ No newline at end of file diff --git a/patterns/GoldBox/GB_ITM-Record.hexpat b/patterns/GoldBox/GB_ITM-Record.hexpat new file mode 100644 index 00000000..583acaa5 --- /dev/null +++ b/patterns/GoldBox/GB_ITM-Record.hexpat @@ -0,0 +1,84 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Item Record +#include +#include +import std.core; +import std.string; + +/********** + This is intended to allow looking up and/or modifying the item detail + record files for all Gold Box games (D&D, no one cares about Buck Rogers) + + Supported Games: + 01 - Pool of Radiance (ITEM[1-8].DAX / CHRDAT[A-J]#.ITM / MON[1-8]ITM.DAX) + 02 - Curse of the Azure Bonds (ITEM[1-6].DAX / CHRDAT[A-J]#.SWG / MON[1-6]ITM.DAX) + 03 - Secret of the Silver Blades (ITEM[1-3].DAX / CHRDAT[A-J]#.STF / MON1ITM.DAX) + 04 - Pools of Darkness (ITEM0.DAX / CHRDAT[A-J]#.THG / MON1ITM.DAX) + 05 - Champions of Krynn (ITEM[1-3].DAX / CHRDAT[A-J]#.STF / MON[1-3]ITM.DAX) + 06 - Death Knights of Krynn (ITEM0.DAX / CHRDAT[A-J]#.JNK / MON1ITM.DAX) + 07 - The Dark Queen of Krynn (DISK1\ITEM.DAT) + 08 - Gateway to the Savage Frontier (ITEM[2-8].DAX / CHRDAT[A-J]#.SWG / MON[2-8]ITM.DAX) + 09 - Treasures of the Savage Frontier (ITEM0.DAX / CHRDAT[A-J]#.THG / MON1ITM.DAX) + 10 - Unlimited Adventures (DISK1\ITEM.DAT) + + Standard/Monster items (i.e. ITEM1.DAX) must be decompressed first in order to view the records + This means that in order to edit those you must recompress/recreate the DAX file afterwards + + 7/10 monster record items are strictly pointers to the standard item file and therefore not needed/supported + Additionally, items for CHR/SAV files are stored in the file itself and can be viewed/edited there + + Note: + As the logic for items is also used in the vault and 7/10 CHR/SAV files, all functions/structs/etc + are located in the shared GB_STRUCT_ITM/GB_UTIL_ITM.cs file included above + + The GameID variable below must be set for to the number in the list above for the source game +*********/ +u8 GameID = 0; + +u32 FileSize = std::mem::size(); +u8 RecordSize = 0; + +// Check GameID is set +if (GameID == 0) { + std::warning("Please set the GameID variable to the source game's number."); + return; +} + +// Ensure GameID is in range +if (GameID > 10) { + std::warning("Invalid GameID. Aborting."); + return; +} + +// Get RecordSize +if (GameID == 7) { + RecordSize = 17; +} +else if (GameID == 10) { + RecordSize = 18; +} +// Other games can be variable depending on if CHR/ITM/MON record, so use int truncation to figure out what it is +// CHR/MON/STD: 1-2/5/8 - MON/STD: 3 - CHR/MON: 6 - CHR: 4/9 +else if (FileSize == ((FileSize / 63) * 63)) { + RecordSize = 63; +} +// CHR: 3 +else if (FileSize == ((FileSize / 67) * 67)) { + RecordSize = 67; +} +// STD/MON: 4/9 - STD: 6 +else if (FileSize == ((FileSize / 17) * 17)) { + RecordSize = 17; +} +else { + std::warning("Unknown file. Exiting."); + return; +} + +// Get ItemCount +u8 ItemCount = FileSize / RecordSize; + +// Flag if game has Bundle of # Scrolls item +bool HasBundle = (GameID == 3 || GameID == 4 || GameID == 7 || GameID == 9 || GameID == 10) ? true : false; + +ITEM Item[ItemCount] @ 0x00; \ No newline at end of file diff --git a/patterns/GoldBox/GB_STRUCT.cs b/patterns/GoldBox/GB_STRUCT.cs new file mode 100644 index 00000000..7b720269 --- /dev/null +++ b/patterns/GoldBox/GB_STRUCT.cs @@ -0,0 +1,1363 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Common Structs +#pragma once + +// Attack values +struct ATTACK { + u8 ATK_1_Count [[comment("Number of primary attacks every 2 rounds")]]; + u8 ATK_2_Count [[comment("Number of secondary attacks every 2 rounds")]]; + u8 ATK_1_Rolls [[comment("Number of rolls to make per primary attack")]]; + u8 ATK_2_Rolls [[comment("Number of rolls to make per secondary attack")]]; + u8 ATK_1_Dice [[comment("Dice type (d4/d6/d8/etc) rolled for primary attack")]]; + u8 ATK_2_Dice [[comment("Dice type (d4/d6/d8/etc) rolled for secondary attack")]]; + u8 ATK_1_Modifier [[comment("Damage modifier to apply to primary attack")]]; + u8 ATK_2_Modifier [[comment("Damage modifier to apply to secondary attack")]]; +}; + +// Abilities +struct ABILITY { + if (GameID != 1) { + u8 STR_Base [[comment("Unadjusted strength value")]]; + } + u8 STR_Current [[comment("Adjusted strength ability value")]]; + if (GameID != 1) { + u8 INT_Base [[comment("Unadjusted intelligence ability value")]]; + } + u8 INT_Current [[comment("Adjusted intelligence ability value")]]; + if (GameID != 1) { + u8 WIS_Base [[comment("Unadjusted wisdom ability value")]]; + } + u8 WIS_Current [[comment("Adjusted wisdom ability value")]]; + if (GameID != 1) { + u8 DEX_Base [[comment("Unadjusted dexterity ability value")]]; + } + u8 DEX_Current [[comment("Adjusted dexterity ability value")]]; + if (GameID != 1) { + u8 CON_Base [[comment("Unadjusted constitution ability value")]]; + } + u8 CON_Current [[comment("Adjusted constitution ability value")]]; + if (GameID != 1) { + u8 CHA_Base [[comment("Unadjusted charisma ability value")]]; + } + u8 CHA_Current [[comment("Adjusted charisma ability value")]]; + if (GameID != 1) { + u8 STX_Base [[comment("Unadjusted extraordinary strength ability value")]]; + } + u8 STX_Current [[comment("Adjusted extraordinary strength ability value\nOnly valid when STR_Current = 18 (0x12)")]]; +}; + +// Class Level +struct CLASSLEVEL { + match (GameID) { + (1|2|8): { + u8 LVL_CL [[comment("Cleric level")]]; + u8 LVL_DR [[comment("Druid level\nUnused")]]; + u8 LVL_FT [[comment("Fighter level")]]; + u8 LVL_PD [[comment(std::format("Paladin level{}", GameID == 1 ? "\nUnused" : ""))]]; + u8 LVL_RA [[comment(std::format("Ranger level{}", GameID == 1 ? "\nUnused" : ""))]]; + u8 LVL_MU [[comment("Magic-User level")]]; + u8 LVL_TH [[comment("Thief level")]]; + u8 LVL_MK [[comment("Monk level\nUnused")]]; + } + (3|4|9): { + u8 LVL_CL [[comment("Cleric level")]]; + u8 LVL_DR [[comment("Druid level\nUnused")]]; + u8 LVL_FT [[comment("Fighter level")]]; + u8 LVL_PD [[comment("Paladin level")]]; + u8 LVL_RA [[comment("Ranger level")]]; + u8 LVL_MU [[comment("Magic-User level")]]; + u8 LVL_TH [[comment("Thief level")]]; + } + (5|6): { + u8 LVL_CL [[comment("Cleric level")]]; + u8 LVL_DR [[comment("Druid level\nUnused")]]; + u8 LVL_FT [[comment("Fighter level")]]; + u8 LVL_PD [[comment(std::format("Paladin level{}", GameID == 5 ? "\nUnused" : ""))]]; + u8 LVL_RA [[comment("Ranger level")]]; + u8 LVL_MU [[comment("Magic-User level")]]; + u8 LVL_TH [[comment("Thief level")]]; + u8 LVL_KN [[comment("Knight level")]]; + } + (7|10): { + u8 LVL_CL [[comment("Cleric level")]]; + u8 LVL_KN [[comment(std::format("Knight level{}", GameID == 10 ? "\nUnused" : ""))]]; + u8 LVL_FT [[comment("Fighter level")]]; + u8 LVL_PD [[comment("Paladin level")]]; + u8 LVL_RA [[comment("Ranger level")]]; + u8 LVL_MU [[comment("Magic-User level")]]; + u8 LVL_TH [[comment("Thief level")]]; + } + } +}; + +// Money +struct MONEY { + match (GameID) { + (1|2|3|8): { + u16 MNY_Copper [[comment("Number of copper coins (CP) the character has")]]; + u16 MNY_Silver [[comment("Number of silver coins (SP) the character has")]]; + u16 MNY_Electrum [[comment("Number of electrum coins (EP) the character has")]]; + u16 MNY_Gold [[comment("Number of gold coins (GP) the character has")]]; + u16 MNY_Platinum [[comment("Number of platinum coins (PP) the character has")]]; + } + (5): { + u16 MNY_Silver [[comment("Number of silver coins (SP) the character has")]]; + u16 MNY_Copper [[comment("Number of copper coins (CP) the character has")]]; + u16 MNY_Bronze [[comment("Number of bronze coins (BP) the character has")]]; + u16 MNY_Platinum [[comment("Number of platinum coins (PP) the character has")]]; + u16 MNY_Steel [[comment("Number of steel coins (ST) the character has")]]; + } + (4|9|10): u16 MNY_Platinum [[comment("Number of platinum coins (PP) the character has")]]; + (6|7): u16 MNY_Steel [[comment("Number of steel coins (ST) the character has")]]; + } + u16 MNY_Gem [[comment("Number of unappraised gems the character has")]]; + u16 MNY_Jewelry [[comment("Number of unappraised jewelry the character has")]]; +}; + +// Icon Colors +bitfield COLOR { + COLORNAME Color1 : 4 [[color(std::format("{:06X}", IconColorValue(this)))]]; + COLORNAME Color2 : 4 [[color(std::format("{:06X}", IconColorValue(this)))]]; +}; + +// Combat Icon Part Colors +struct ICO_COLOR { + COLOR Color_Body [[comment("Combat icon body colors")]]; + COLOR Color_Arm [[comment("Combat icon arm colors")]]; + COLOR Color_Leg [[comment("Combat icon leg colors")]]; + COLOR Color_HairFace [[comment("Combat icon hair/face colors")]]; + COLOR Color_Shield [[comment("Combat icon shield colors")]]; + COLOR Color_Weapon [[comment("Combat icon weapon colors")]]; +}; + +// Icon Dimensions +bitfield ICO_DIMENSION { + DIMENSION ICO_Dimension : 7 [[comment("Combat tile dimensions")]]; + bool IsLarge : 1 [[comment("Indicates if character is considered 'Large' for combat calculations")]]; +} [[inline]]; + +// Inventory pointers +struct INVENTORY { + u32 ADDR_Item [[comment("Pointer to the character's item data")]]; + u32 ADDR_Equip_Weapon [[comment("Pointer to the character's equipped weapon")]]; + u32 ADDR_Equip_Shield [[comment("Pointer to the character's equipped shield")]]; + u32 ADDR_Equip_Armor [[comment("Pointer to the character's equipped armor")]]; + u32 ADDR_Equip_Gauntlet [[comment("Pointer to the character's equipped gauntlet")]]; + u32 ADDR_Equip_Helm [[comment("Pointer to the character's equipped helmet")]]; + u32 ADDR_Equip_Belt [[comment("Pointer to the character's equipped belt/necklace")]]; + u32 ADDR_Equip_Robe [[comment("Pointer to the character's equipped robe")]]; + u32 ADDR_Equip_Cloak [[comment("Pointer to the character's equipped cloak")]]; + u32 ADDR_Equip_Boot [[comment("Pointer to the character's equipped boots")]]; + u32 ADDR_Equip_Ring1 [[comment("Pointer to the character's first equipped ring")]]; + u32 ADDR_Equip_Ring2 [[comment("Pointer to the character's second equipped ring")]]; + u32 ADDR_Equip_Arrow [[comment("Pointer to the character's equipped arrows")]]; + u32 ADDR_Equip_Bolt [[comment("Pointer to the character's equipped bolts/quarrels")]]; +}; + +// Saving Throws +struct SAVETHROW { + u8 SAV_1_ParalyzationPoisonDeath [[comment("Paralyzation, Poison, or Death Magic base saving throw")]]; + u8 SAV_2_PetrificationPolymorph [[comment("Petrification or Polymorph base saving throw")]]; + u8 SAV_3_RodStaffWand [[comment("Rod, Staff, or Wand base saving throw")]]; + u8 SAV_4_BreathWeapon [[comment("Breath Weapon base saving throw")]]; + u8 SAV_5_Spell [[comment("Spells base saving throw")]]; +}; + +// Spell class memorization counts +struct SPL_COUNT { + u8 LVL_1 [[comment("Total number of level 1 spells the character can memorize")]]; + u8 LVL_2 [[comment("Total number of level 2 spells the character can memorize")]]; + u8 LVL_3 [[comment("Total number of level 3 spells the character can memorize")]]; + if (Size > 3) { + u8 LVL_4 [[comment("Total number of level 4 spells the character can memorize")]]; + u8 LVL_5 [[comment("Total number of level 5 spells the character can memorize")]]; + } + if (Size > 5) { + u8 LVL_6 [[comment("Total number of level 6 spells the character can memorize")]]; + u8 LVL_7 [[comment("Total number of level 7 spells the character can memorize")]]; + } + if (Size > 7) { + u8 LVL_8 [[comment("Total number of level 8 spells the character can memorize")]]; + } + if (Size > 8) { + u8 LVL_9 [[comment("Total number of level 9 spells the character can memorize")]]; + } +}; + +// Thief Skills +struct THIEFSKILL { + u8 TH_1_PickPocket [[comment("Thief Pick Pockets ability")]]; + u8 TH_2_OpenLock [[comment("Thief Open Locks ability")]]; + u8 TH_3_FindRemoveTrap [[comment("Thief Find/Remove Traps ability")]]; + u8 TH_4_MoveSilent [[comment("Thief Move Silently ability")]]; + u8 TH_5_HideInShadow [[comment("Thief Hide in Shadows ability")]]; + u8 TH_6_HearNoise [[comment("Thief Hear Noise ability")]]; + u8 TH_7_ClimbWall [[comment("Thief Climb Walls ability")]]; + u8 TH_8_ReadLanguage [[comment("Thief Read Languages ability")]]; +}; + +/******************************* + Known Spells (can memorize) +*******************************/ +// Known Spells - 1 +struct SPL_KNOWN01 { + bool CL1_Bless [[comment("CL1: Bless")]]; + bool CL1_Curse [[comment("CL1: Curse")]]; + bool CL1_CureLightWounds [[comment("CL1: Cure Light Wounds")]]; + bool CL1_CauseLightWounds [[comment("CL1: Cause Light Wounds")]]; + bool CL1_DetectMagic [[comment("CL1: Detect Magic")]]; + bool CL1_ProtectionFromEvil [[comment("CL1: Protection from Evil")]]; + bool CL1_ProtectionFromGood [[comment("CL1: Protection from Good")]]; + bool CL1_ResistCold [[comment("CL1: Resist Cold")]]; + bool MU1_BurningHands [[comment("MU1: Burning Hands")]]; + bool MU1_CharmPerson [[comment("MU1: Charm Person")]]; + bool MU1_DetectMagic [[comment("MU1: Detect Magic")]]; + bool MU1_Enlarge [[comment("MU1: Enlarge")]]; + bool MU1_Reduce [[comment("MU1: Reduce")]]; + bool MU1_Friends [[comment("MU1: Friends")]]; + bool MU1_MagicMissile [[comment("MU1: Magic Missile")]]; + bool MU1_ProtectionFromEvil [[comment("MU1: Protection from Evil")]]; + bool MU1_ProtectionFromGood [[comment("MU1: Protection from Good")]]; + bool MU1_ReadMagic [[comment("MU1: Read Magic")]]; + bool MU1_Shield [[comment("MU1: Shield")]]; + bool MU1_ShockingGrasp [[comment("MU1: Shocking Grasp")]]; + bool MU1_Sleep [[comment("MU1: Sleep")]]; + bool CL2_FindTraps [[comment("CL2: Find Traps")]]; + bool CL2_HoldPerson [[comment("CL2: Hold Person")]]; + bool CL2_ResistFire [[comment("CL2: Resist Fire")]]; + bool CL2_Silence15Radius [[comment("CL2: Silence, 15' Radius")]]; + bool CL2_SlowPoison [[comment("CL2: Slow Poison")]]; + bool CL2_SnakeCharm [[comment("CL2: Snake Charm")]]; + bool CL2_SpiritualHammer [[comment("CL2: Spiritual Hammer")]]; + bool MU2_DetectInvisibility [[comment("MU2: Detect Invisibility")]]; + bool MU2_Invisibility [[comment("MU2: Invisibility")]]; + bool MU2_Knock [[comment("MU2: Knock")]]; + bool MU2_MirrorImage [[comment("MU2: Mirror Image")]]; + bool MU2_RayOfEnfeeblement [[comment("MU2: Ray of Enfeeblement")]]; + bool MU2_StinkingCloud [[comment("MU2: Stinking Cloud")]]; + bool MU2_Strength [[comment("MU2: Strength")]]; + bool CL3_AnimateDead [[comment("CL3: Animate Dead")]]; + bool CL3_CureBlindness [[comment("CL3: Cure Blindness")]]; + bool CL3_CauseBlindness [[comment("CL3: Cause Blindness")]]; + bool CL3_CureDisease [[comment("CL3: Cure Disease")]]; + bool CL3_CauseDisease [[comment("CL3: Cause Disease")]]; + bool CL3_DispelMagic [[comment("CL3: Dispel Magic")]]; + bool CL3_Prayer [[comment("CL3: Prayer")]]; + bool CL3_RemoveCurse [[comment("CL3: Remove Curse")]]; + bool CL3_BestowCurse [[comment("CL3: Bestow Curse")]]; + bool MU3_Blink [[comment("MU3: Blink")]]; + bool MU3_DispelMagic [[comment("MU3: Dispel Magic")]]; + bool MU3_Fireball [[comment("MU3: Fireball")]]; + bool MU3_Haste [[comment("MU3: Haste")]]; + bool MU3_HoldPerson [[comment("MU3: Hold Person")]]; + bool MU3_Invisibility10Radius [[comment("MU3: Invisibility, 10' Radius")]]; + bool MU3_LightningBolt [[comment("MU3: Lightning Bolt")]]; + bool MU3_ProtectionFromEvil10Radius [[comment("MU3: Protection from Evil, 10' Radius")]]; + bool MU3_ProtectionFromGood10Radius [[comment("MU3: Protection from Good, 10' Radius")]]; + bool MU3_ProtectionFromNormalMissiles [[comment("MU3: Protection from Normal Missiles")]]; + bool MU3_Slow [[comment("MU3: Slow")]]; + bool CL7_Restoration [[comment("CL7: Restoration")]]; +}; + +// Known Spells - 2 +struct SPL_KNOWN02 { + bool CL1_Bless [[comment("CL1: Bless")]]; + bool CL1_Curse [[comment("CL1: Curse")]]; + bool CL1_CureLightWounds [[comment("CL1: Cure Light Wounds")]]; + bool CL1_CauseLightWounds [[comment("CL1: Cause Light Wounds")]]; + bool CL1_DetectMagic [[comment("CL1: Detect Magic")]]; + bool CL1_ProtectionFromEvil [[comment("CL1: Protection from Evil")]]; + bool CL1_ProtectionFromGood [[comment("CL1: Protection from Good")]]; + bool CL1_ResistCold [[comment("CL1: Resist Cold")]]; + bool MU1_BurningHands [[comment("MU1: Burning Hands")]]; + bool MU1_CharmPerson [[comment("MU1: Charm Person")]]; + bool MU1_DetectMagic [[comment("MU1: Detect Magic")]]; + bool MU1_Enlarge [[comment("MU1: Enlarge")]]; + bool MU1_Reduce [[comment("MU1: Reduce")]]; + bool MU1_Friends [[comment("MU1: Friends")]]; + bool MU1_MagicMissile [[comment("MU1: Magic Missile")]]; + bool MU1_ProtectionFromEvil [[comment("MU1: Protection from Evil")]]; + bool MU1_ProtectionFromGood [[comment("MU1: Protection from Good")]]; + bool MU1_ReadMagic [[comment("MU1: Read Magic")]]; + bool MU1_Shield [[comment("MU1: Shield")]]; + bool MU1_ShockingGrasp [[comment("MU1: Shocking Grasp")]]; + bool MU1_Sleep [[comment("MU1: Sleep")]]; + bool CL2_FindTraps [[comment("CL2: Find Traps")]]; + bool CL2_HoldPerson [[comment("CL2: Hold Person")]]; + bool CL2_ResistFire [[comment("CL2: Resist Fire")]]; + bool CL2_Silence15Radius [[comment("CL2: Silence, 15' Radius")]]; + bool CL2_SlowPoison [[comment("CL2: Slow Poison")]]; + bool CL2_SnakeCharm [[comment("CL2: Snake Charm")]]; + bool CL2_SpiritualHammer [[comment("CL2: Spiritual Hammer")]]; + bool MU2_DetectInvisibility [[comment("MU2: Detect Invisibility")]]; + bool MU2_Invisibility [[comment("MU2: Invisibility")]]; + bool MU2_Knock [[comment("MU2: Knock")]]; + bool MU2_MirrorImage [[comment("MU2: Mirror Image")]]; + bool MU2_RayOfEnfeeblement [[comment("MU2: Ray of Enfeeblement")]]; + bool MU2_StinkingCloud [[comment("MU2: Stinking Cloud")]]; + bool MU2_Strength [[comment("MU2: Strength")]]; + bool IT7_AnimateDead [[comment("IT7: Animate Dead")]]; + bool CL3_CureBlindness [[comment("CL3: Cure Blindness")]]; + bool CL3_CauseBlindness [[comment("CL3: Cause Blindness")]]; + bool CL3_CureDisease [[comment("CL3: Cure Disease")]]; + bool CL3_CauseDisease [[comment("CL3: Cause Disease")]]; + bool CL3_DispelMagic [[comment("CL3: Dispel Magic")]]; + bool CL3_Prayer [[comment("CL3: Prayer")]]; + bool CL3_RemoveCurse [[comment("CL3: Remove Curse")]]; + bool CL3_BestowCurse [[comment("CL3: Bestow Curse")]]; + bool MU3_Blink [[comment("MU3: Blink")]]; + bool MU3_DispelMagic [[comment("MU3: Dispel Magic")]]; + bool MU3_Fireball [[comment("MU3: Fireball")]]; + bool MU3_Haste [[comment("MU3: Haste")]]; + bool MU3_HoldPerson [[comment("MU3: Hold Person")]]; + bool MU3_Invisibility10Radius [[comment("MU3: Invisibility, 10' Radius")]]; + bool MU3_LightningBolt [[comment("MU3: Lightning Bolt")]]; + bool MU3_ProtectionFromEvil10Radius [[comment("MU3: Protection from Evil, 10' Radius")]]; + bool MU3_ProtectionFromGood10Radius [[comment("MU3: Protection from Good, 10' Radius")]]; + bool MU3_ProtectionFromNormalMissiles [[comment("MU3: Protection from Normal Missiles")]]; + bool MU3_Slow [[comment("MU3: Slow")]]; + bool CL7_Restoration [[comment("CL7: Restoration")]]; + bool IT6_PotionOfSpeed [[comment("IT6: Potion of Speed")]]; + bool CL4_CureSeriousWounds [[comment("CL4: Cure Serious Wounds")]]; + bool IT6_PotionOfGiantStrength [[comment("IT6: Potion of Giant Strength")]]; + bool IT6_JavelinOfLightning [[comment("IT6: Javelin of Lightning")]]; + bool IT6_WandOfParalyzation [[comment("IT6: Wand of Paralyzation")]]; + bool IT6_PotionOfHealing [[comment("IT6: Potion of Healing")]]; + bool IT6_DustOfDisappearance [[comment("IT6: Dust of Disappearance")]]; + bool IT6_NecklaceOfMissiles [[comment("IT6: Necklace of Missiles")]]; + bool IT6_WandOfMagicMissiles [[comment("IT6: Wand of Magic Missiles")]]; + bool CL4_CauseSeriousWounds [[comment("CL4: Cause Serious Wounds")]]; + bool CL4_NeutralizePoison [[comment("CL4: Neutralize Poison")]]; + bool CL4_Poison [[comment("CL4: Poison")]]; + bool CL4_ProtectionEvil10Radius [[comment("CL4: Protection Evil, 10' Radius")]]; + bool CL4_SticksToSnakes [[comment("CL4: Sticks to Snakes")]]; + bool CL5_CureCriticalWounds [[comment("CL5: Cure Critical Wounds")]]; + bool CL5_CauseCriticalWounds [[comment("CL5: Cause Critical Wounds")]]; + bool CL5_DispelEvil [[comment("CL5: Dispel Evil")]]; + bool CL5_FlameStrike [[comment("CL5: Flame Strike")]]; + bool CL5_RaiseDead [[comment("CL5: Raise Dead")]]; + bool CL5_SlayLiving [[comment("CL5: Slay Living")]]; + bool DR1_DetectMagic [[comment("DR1: Detect Magic")]]; + bool DR1_Entangle [[comment("DR1: Entangle")]]; + bool DR1_FaerieFire [[comment("DR1: Faerie Fire")]]; + bool DR1_InvisibilityToAnimals [[comment("DR1: Invisibility to Animals")]]; + bool MU4_CharmMonsters [[comment("MU4: Charm Monsters")]]; + bool MU4_Confusion [[comment("MU4: Confusion")]]; + bool MU4_DimensionDoor [[comment("MU4: Dimension Door")]]; + bool MU4_Fear [[comment("MU4: Fear")]]; + bool MU4_FireShield [[comment("MU4: Fire Shield")]]; + bool MU4_Fumble [[comment("MU4: Fumble")]]; + bool MU4_IceStorm [[comment("MU4: Ice Storm")]]; + bool MU4_MinorGlobeOfInvulnerability [[comment("MU4: Minor Globe of Invulnerability")]]; + bool MU4_RemoveCurse [[comment("MU4: Remove Curse")]]; + bool IT5_AnimateDead [[comment("IT5: Animate Dead")]]; + bool MU5_CloudKill [[comment("MU5: Cloud Kill")]]; + bool MU5_ConeOfCold [[comment("MU5: Cone of Cold")]]; + bool MU5_Feeblemind [[comment("MU5: Feeblemind")]]; + bool MU5_HoldMonsters [[comment("MU5: Hold Monsters")]]; + bool IT6_ScrollOfProtDragonBreath [[comment("IT6: Scroll of Prot. Dragon Breath")]]; + bool IT6_ScrollOfProtParalyzation [[comment("IT6: Scroll of Prot. Paralyzation")]]; + bool IT6_PotionOfInvisibility [[comment("IT6: Potion of Invisibility")]]; + bool IT6_WandOfDefoliation [[comment("IT6: Wand of Defoliation")]]; + bool IT6_PotionExtraHealing [[comment("IT6: Potion Extra Healing")]]; + bool MU4_BestowCurse [[comment("MU4: Bestow Curse")]]; +}; + +// Known Spells - 3 +struct SPL_KNOWN03 { + bool CL1_Bless [[comment("CL1: Bless")]]; + bool CL1_Curse [[comment("CL1: Curse")]]; + bool CL1_CureLightWounds [[comment("CL1: Cure Light Wounds")]]; + bool CL1_CauseLightWounds [[comment("CL1: Cause Light Wounds")]]; + bool CL1_DetectMagic [[comment("CL1: Detect Magic")]]; + bool CL1_ProtectionFromEvil [[comment("CL1: Protection from Evil")]]; + bool CL1_ProtectionFromGood [[comment("CL1: Protection from Good")]]; + bool CL1_ResistCold [[comment("CL1: Resist Cold")]]; + bool MU1_BurningHands [[comment("MU1: Burning Hands")]]; + bool MU1_CharmPerson [[comment("MU1: Charm Person")]]; + bool MU1_DetectMagic [[comment("MU1: Detect Magic")]]; + bool MU1_Enlarge [[comment("MU1: Enlarge")]]; + bool MU1_Reduce [[comment("MU1: Reduce")]]; + bool MU1_Friends [[comment("MU1: Friends")]]; + bool MU1_MagicMissile [[comment("MU1: Magic Missile")]]; + bool MU1_ProtectionFromEvil [[comment("MU1: Protection from Evil")]]; + bool MU1_ProtectionFromGood [[comment("MU1: Protection from Good")]]; + bool MU1_ReadMagic [[comment("MU1: Read Magic")]]; + bool MU1_Shield [[comment("MU1: Shield")]]; + bool MU1_ShockingGrasp [[comment("MU1: Shocking Grasp")]]; + bool MU1_Sleep [[comment("MU1: Sleep")]]; + bool CL2_FindTraps [[comment("CL2: Find Traps")]]; + bool CL2_HoldPerson [[comment("CL2: Hold Person")]]; + bool CL2_ResistFire [[comment("CL2: Resist Fire")]]; + bool CL2_Silence15Radius [[comment("CL2: Silence, 15' Radius")]]; + bool CL2_SlowPoison [[comment("CL2: Slow Poison")]]; + bool CL2_SnakeCharm [[comment("CL2: Snake Charm")]]; + bool CL2_SpiritualHammer [[comment("CL2: Spiritual Hammer")]]; + bool MU2_DetectInvisibility [[comment("MU2: Detect Invisibility")]]; + bool MU2_Invisibility [[comment("MU2: Invisibility")]]; + bool MU2_Knock [[comment("MU2: Knock")]]; + bool MU2_MirrorImage [[comment("MU2: Mirror Image")]]; + bool MU2_RayOfEnfeeblement [[comment("MU2: Ray of Enfeeblement")]]; + bool MU2_StinkingCloud [[comment("MU2: Stinking Cloud")]]; + bool MU2_Strength [[comment("MU2: Strength")]]; + bool CL6_Heal [[comment("CL6: Heal")]]; + bool CL3_CureBlindness [[comment("CL3: Cure Blindness")]]; + bool CL3_CauseBlindness [[comment("CL3: Cause Blindness")]]; + bool CL3_CureDisease [[comment("CL3: Cure Disease")]]; + bool CL3_CauseDisease [[comment("CL3: Cause Disease")]]; + bool CL3_DispelMagic [[comment("CL3: Dispel Magic")]]; + bool CL3_Prayer [[comment("CL3: Prayer")]]; + bool CL3_RemoveCurse [[comment("CL3: Remove Curse")]]; + bool CL3_BestowCurse [[comment("CL3: Bestow Curse")]]; + bool MU3_Blink [[comment("MU3: Blink")]]; + bool MU3_DispelMagic [[comment("MU3: Dispel Magic")]]; + bool MU3_Fireball [[comment("MU3: Fireball")]]; + bool MU3_Haste [[comment("MU3: Haste")]]; + bool MU3_HoldPerson [[comment("MU3: Hold Person")]]; + bool MU3_Invisibility10Radius [[comment("MU3: Invisibility, 10' Radius")]]; + bool MU3_LightningBolt [[comment("MU3: Lightning Bolt")]]; + bool MU3_ProtectionFromEvil10Radius [[comment("MU3: Protection from Evil, 10' Radius")]]; + bool MU3_ProtectionFromGood10Radius [[comment("MU3: Protection from Good, 10' Radius")]]; + bool MU3_ProtectionFromNormalMissiles [[comment("MU3: Protection from Normal Missiles")]]; + bool MU3_Slow [[comment("MU3: Slow")]]; + bool CL6_Harm [[comment("CL6: Harm")]]; + bool IT6_PotionOfSpeed [[comment("IT6: Potion of Speed")]]; + bool CL4_CureSeriousWounds [[comment("CL4: Cure Serious Wounds")]]; + bool IT6_PotionOfGiantStrength [[comment("IT6: Potion of Giant Strength")]]; + bool IT6_JavelinOfLightning [[comment("IT6: Javelin of Lightning")]]; + bool IT6_WandOfParalyzation [[comment("IT6: Wand of Paralyzation")]]; + bool IT6_PotionOfHealing [[comment("IT6: Potion of Healing")]]; + bool IT6_ElixirOfYouth [[comment("IT6: Elixir of Youth")]]; + bool IT6_NecklaceOfMissiles [[comment("IT6: Necklace of Missiles")]]; + bool IT6_WandOfMagicMissiles [[comment("IT6: Wand of Magic Missiles")]]; + bool CL4_CauseSeriousWounds [[comment("CL4: Cause Serious Wounds")]]; + bool CL4_NeutralizePoison [[comment("CL4: Neutralize Poison")]]; + bool CL4_Poison [[comment("CL4: Poison")]]; + bool CL4_ProtectionEvil10Radius [[comment("CL4: Protection Evil, 10' Radius")]]; + bool CL4_SticksToSnakes [[comment("CL4: Sticks to Snakes")]]; + bool CL5_CureCriticalWounds [[comment("CL5: Cure Critical Wounds")]]; + bool CL5_CauseCriticalWounds [[comment("CL5: Cause Critical Wounds")]]; + bool CL5_DispelEvil [[comment("CL5: Dispel Evil")]]; + bool CL5_FlameStrike [[comment("CL5: Flame Strike")]]; + bool CL5_RaiseDead [[comment("CL5: Raise Dead")]]; + bool CL5_SlayLiving [[comment("CL5: Slay Living")]]; + bool DR1_DetectMagic [[comment("DR1: Detect Magic")]]; + bool DR1_Entangle [[comment("DR1: Entangle")]]; + bool DR1_FaerieFire [[comment("DR1: Faerie Fire")]]; + bool DR1_InvisibilityToAnimals [[comment("DR1: Invisibility to Animals")]]; + bool MU4_CharmMonsters [[comment("MU4: Charm Monsters")]]; + bool MU4_Confusion [[comment("MU4: Confusion")]]; + bool MU4_DimensionDoor [[comment("MU4: Dimension Door")]]; + bool MU4_Fear [[comment("MU4: Fear")]]; + bool MU4_FireShield [[comment("MU4: Fire Shield")]]; + bool MU4_Fumble [[comment("MU4: Fumble")]]; + bool MU4_IceStorm [[comment("MU4: Ice Storm")]]; + bool MU4_MinorGlobeOfInvulnerability [[comment("MU4: Minor Globe of Invulnerability")]]; + bool MU4_RemoveCurse [[comment("MU4: Remove Curse")]]; + bool DR2_Barkskin [[comment("DR2: Barkskin")]]; + bool MU5_CloudKill [[comment("MU5: Cloud Kill")]]; + bool MU5_ConeOfCold [[comment("MU5: Cone of Cold")]]; + bool MU5_Feeblemind [[comment("MU5: Feeblemind")]]; + bool MU5_HoldMonsters [[comment("MU5: Hold Monsters")]]; + bool IT6_ScrollOfProtDragonBreath [[comment("IT6: Scroll of Prot Dragon Breath")]]; + bool DR2_CharmPersonOrMammal [[comment("DR2: Charm Person or Mammal")]]; + bool IT6_PotionOfInvisibility [[comment("IT6: Potion of Invisibility")]]; + bool DR2_CureLightWounds [[comment("DR2: Cure Light Wounds")]]; + bool IT6_PotionExtraHealing [[comment("IT6: Potion Extra Healing")]]; + bool MU4_BestowCurse [[comment("MU4: Bestow Curse")]]; + bool IT0_ProtectionFromEvil10Radius [[comment("IT0: Protection from Evil 10' Radius")]]; + bool IT0_Silence15Radius [[comment("IT0: Silence 15' radius")]]; + bool IT0_DetectMagic [[comment("IT0: Detect Magic")]]; + bool IT0_RemoveCurse [[comment("IT0: Remove Curse")]]; + bool IT0_Bless [[comment("IT0: Bless")]]; + bool IT0_CharmPerson [[comment("IT0: Charm Person")]]; + bool IT0_BurningHands [[comment("IT0: Burning Hands")]]; + bool DR9_Spell108 [[comment("DR9: spell 108")]]; + bool MU0_Spell109 [[comment("MU0: spell 109")]]; + bool MU6_DeathSpell [[comment("MU6: Death Spell")]]; + bool MU6_Disintegrate [[comment("MU6: Disintegrate")]]; + bool MU6_GlobeOfInvulnerability [[comment("MU6: Globe of Invulnerability")]]; + bool MU6_StoneToFlesh [[comment("MU6: Stone to Flesh")]]; + bool MU6_FleshToStone [[comment("MU6: Flesh to Stone")]]; + bool MU7_DelayedBlastFireball [[comment("MU7: Delayed Blast Fireball")]]; + bool MU7_MassInvisibility [[comment("MU7: Mass Invisibility")]]; + bool MU7_PowerWordStun [[comment("MU7: Power Word Stun")]]; +}; + +// Known Spells - 4 +struct SPL_KNOWN04 { + bool CL1_Bless [[comment("CL1: Bless")]]; + bool CL1_Curse [[comment("CL1: Curse")]]; + bool CL1_CureLightWounds [[comment("CL1: Cure Light Wounds")]]; + bool CL1_CauseLightWounds [[comment("CL1: Cause Light Wounds")]]; + bool CL1_DetectMagic [[comment("CL1: Detect Magic")]]; + bool CL1_ProtectionFromEvil [[comment("CL1: Protection from Evil")]]; + bool CL1_ProtectionFromGood [[comment("CL1: Protection from Good")]]; + bool CL1_ResistCold [[comment("CL1: Resist Cold")]]; + bool MU1_BurningHands [[comment("MU1: Burning Hands")]]; + bool MU1_CharmPerson [[comment("MU1: Charm Person")]]; + bool MU1_DetectMagic [[comment("MU1: Detect Magic")]]; + bool MU1_Enlarge [[comment("MU1: Enlarge")]]; + bool MU1_Reduce [[comment("MU1: Reduce")]]; + bool MU1_Friends [[comment("MU1: Friends")]]; + bool MU1_MagicMissile [[comment("MU1: Magic Missile")]]; + bool MU1_ProtectionFromEvil [[comment("MU1: Protection from Evil")]]; + bool MU1_ProtectionFromGood [[comment("MU1: Protection from Good")]]; + bool MU1_ReadMagic [[comment("MU1: Read Magic")]]; + bool MU1_Shield [[comment("MU1: Shield")]]; + bool MU1_ShockingGrasp [[comment("MU1: Shocking Grasp")]]; + bool MU1_Sleep [[comment("MU1: Sleep")]]; + bool CL2_FindTraps [[comment("CL2: Find Traps")]]; + bool CL2_HoldPerson [[comment("CL2: Hold Person")]]; + bool CL2_ResistFire [[comment("CL2: Resist Fire")]]; + bool CL2_Silence15Radius [[comment("CL2: Silence, 15' Radius")]]; + bool CL2_SlowPoison [[comment("CL2: Slow Poison")]]; + bool CL2_SnakeCharm [[comment("CL2: Snake Charm")]]; + bool CL2_SpiritualHammer [[comment("CL2: Spiritual Hammer")]]; + bool MU2_DetectInvisibility [[comment("MU2: Detect Invisibility")]]; + bool MU2_Invisibility [[comment("MU2: Invisibility")]]; + bool MU2_Knock [[comment("MU2: Knock")]]; + bool MU2_MirrorImage [[comment("MU2: Mirror Image")]]; + bool MU2_RayOfEnfeeblement [[comment("MU2: Ray of Enfeeblement")]]; + bool MU2_StinkingCloud [[comment("MU2: Stinking Cloud")]]; + bool MU2_Strength [[comment("MU2: Strength")]]; + bool CL6_Heal [[comment("CL6: Heal")]]; + bool CL3_CureBlindness [[comment("CL3: Cure Blindness")]]; + bool CL3_CauseBlindness [[comment("CL3: Cause Blindness")]]; + bool CL3_CureDisease [[comment("CL3: Cure Disease")]]; + bool CL3_CauseDisease [[comment("CL3: Cause Disease")]]; + bool CL3_DispelMagic [[comment("CL3: Dispel Magic")]]; + bool CL3_Prayer [[comment("CL3: Prayer")]]; + bool CL3_RemoveCurse [[comment("CL3: Remove Curse")]]; + bool CL3_BestowCurse [[comment("CL3: Bestow Curse")]]; + bool MU3_Blink [[comment("MU3: Blink")]]; + bool MU3_DispelMagic [[comment("MU3: Dispel Magic")]]; + bool MU3_Fireball [[comment("MU3: Fireball")]]; + bool MU3_Haste [[comment("MU3: Haste")]]; + bool MU3_HoldPerson [[comment("MU3: Hold Person")]]; + bool MU3_Invisibility10Radius [[comment("MU3: Invisibility, 10' Radius")]]; + bool MU3_LightningBolt [[comment("MU3: Lightning Bolt")]]; + bool MU3_ProtectionFromEvil10Radius [[comment("MU3: Protection from Evil, 10' Radius")]]; + bool MU3_ProtectionFromGood10Radius [[comment("MU3: Protection from Good, 10' Radius")]]; + bool MU3_ProtectionFromNormalMissiles [[comment("MU3: Protection from Normal Missiles")]]; + bool MU3_Slow [[comment("MU3: Slow")]]; + bool CL6_Harm [[comment("CL6: Harm")]]; + bool IT6_PotionOfSpeed [[comment("IT6: Potion of Speed")]]; + bool CL4_CureSeriousWounds [[comment("CL4: Cure Serious Wounds")]]; + bool IT6_PotionOfGiantStrength [[comment("IT6: Potion of Giant Strength")]]; + bool IT6_JavelinOfLightning [[comment("IT6: Javelin of Lightning")]]; + bool IT6_WandOfParalyzation [[comment("IT6: Wand of Paralyzation")]]; + bool IT6_PotionOfHealing [[comment("IT6: Potion of Healing")]]; + bool IT6_ElixirOfYouth [[comment("IT6: Elixir of Youth")]]; + bool IT6_NecklaceOfMissiles [[comment("IT6: Necklace of Missiles")]]; + bool IT6_WandOfMagicMissiles [[comment("IT6: Wand of Magic Missiles")]]; + bool CL4_CauseSeriousWounds [[comment("CL4: Cause Serious Wounds")]]; + bool CL4_NeutralizePoison [[comment("CL4: Neutralize Poison")]]; + bool CL4_Poison [[comment("CL4: Poison")]]; + bool CL4_ProtectionEvil10Radius [[comment("CL4: Protection Evil, 10' Radius")]]; + bool CL4_SticksToSnakes [[comment("CL4: Sticks to Snakes")]]; + bool CL5_CureCriticalWounds [[comment("CL5: Cure Critical Wounds")]]; + bool CL5_CauseCriticalWounds [[comment("CL5: Cause Critical Wounds")]]; + bool CL5_DispelEvil [[comment("CL5: Dispel Evil")]]; + bool CL5_FlameStrike [[comment("CL5: Flame Strike")]]; + bool CL5_RaiseDead [[comment("CL5: Raise Dead")]]; + bool CL5_SlayLiving [[comment("CL5: Slay Living")]]; + bool DR1_DetectMagic [[comment("DR1: Detect Magic")]]; + bool DR1_Entangle [[comment("DR1: Entangle")]]; + bool DR1_FaerieFire [[comment("DR1: Faerie Fire")]]; + bool DR1_InvisibilityToAnimals [[comment("DR1: Invisibility to Animals")]]; + bool MU4_CharmMonsters [[comment("MU4: Charm Monsters")]]; + bool MU4_Confusion [[comment("MU4: Confusion")]]; + bool MU4_DimensionDoor [[comment("MU4: Dimension Door")]]; + bool MU4_Fear [[comment("MU4: Fear")]]; + bool MU4_FireShield [[comment("MU4: Fire Shield")]]; + bool MU4_Fumble [[comment("MU4: Fumble")]]; + bool MU4_IceStorm [[comment("MU4: Ice Storm")]]; + bool MU4_MinorGlobeOfInvulnerability [[comment("MU4: Minor Globe of Invulnerability")]]; + bool MU4_RemoveCurse [[comment("MU4: Remove Curse")]]; + bool DR2_Barkskin [[comment("DR2: Barkskin")]]; + bool MU5_CloudKill [[comment("MU5: Cloud Kill")]]; + bool MU5_ConeOfCold [[comment("MU5: Cone of Cold")]]; + bool MU5_Feeblemind [[comment("MU5: Feeblemind")]]; + bool MU5_HoldMonsters [[comment("MU5: Hold Monsters")]]; + bool IT6_ScrollOfProtDragonBreath [[comment("IT6: Scroll of Prot Dragon Breath")]]; + bool DR2_CharmPersonOrMammal [[comment("DR2: Charm Person or Mammal")]]; + bool IT6_PotionOfInvisibility [[comment("IT6: Potion of Invisibility")]]; + bool DR2_CureLightWounds [[comment("DR2: Cure Light Wounds")]]; + bool IT6_PotionOfExtraHealing [[comment("IT6: Potion of Extra Healing")]]; + bool MU4_BestowCurse [[comment("MU4: Bestow Curse")]]; + bool CL6_BladeBarrier [[comment("CL6: Blade Barrier")]]; + bool CL7_Restoration [[comment("CL7: Restoration")]]; + bool CL7_EnergyDrain [[comment("CL7: Energy Drain")]]; + bool CL7_Destruction [[comment("CL7: Destruction")]]; + bool CL7_Resurrection [[comment("CL7: Resurrection")]]; + bool DR3_CureDisease [[comment("DR3: Cure Disease")]]; + bool DR3_NeutralizePoison [[comment("DR3: Neutralize Poison")]]; + bool DR3_HoldAnimal [[comment("DR3: Hold Animal")]]; + bool DR3_ProtFromFire [[comment("DR3: Prot. from Fire")]]; + bool MU6_DeathSpell [[comment("MU6: Death Spell")]]; + bool MU6_Disintegrate [[comment("MU6: Disintegrate")]]; + bool MU6_GlobeOfInvulnerability [[comment("MU6: Globe of Invulnerability")]]; + bool MU6_StoneToFlesh [[comment("MU6: Stone to Flesh")]]; + bool MU6_FleshToStone [[comment("MU6: Flesh to Stone")]]; + bool MU7_DelayedBlastFireball [[comment("MU7: Delayed Blast Fireball")]]; + bool MU7_MassInvisibility [[comment("MU7: Mass Invisibility")]]; + bool MU7_PowerWordStun [[comment("MU7: Power Word Stun")]]; + bool MU5_FireTouch [[comment("MU5: Fire Touch"),comment("A bug sets LVL_Sweep value from characters transferred from SotSB (3) here")]]; + bool MU5_IronSkin [[comment("MU5: Iron Skin")]]; + bool MU8_MassCharm [[comment("MU8: Mass Charm")]]; + bool MU8_OttosIrrDance [[comment("MU8: Otto's Irr. Dance")]]; + bool MU8_MindBlank [[comment("MU8: Mind Blank")]]; + bool MU8_PowerWordBlind [[comment("MU8: Power Word Blind")]]; + bool MU9_MeteorSwarm [[comment("MU9: Meteor Swarm")]]; + bool MU9_PowerWordKill [[comment("MU9: Power Word Kill")]]; + bool MU9_MonsterSummoning [[comment("MU9: Monster Summoning")]]; +}; + +// Known Spells - 5 +struct SPL_KNOWN05 { + bool CL1_Bless [[comment("CL1: Bless")]]; + bool CL1_Curse [[comment("CL1: Curse")]]; + bool CL1_CureLightWounds [[comment("CL1: Cure Light Wounds")]]; + bool CL1_CauseLightWounds [[comment("CL1: Cause Light Wounds")]]; + bool CL1_DetectMagic [[comment("CL1: Detect Magic")]]; + bool CL1_ProtectionFromEvil [[comment("CL1: Protection from Evil")]]; + bool CL1_ProtectionFromGood [[comment("CL1: Protection from Good")]]; + bool CL1_ResistCold [[comment("CL1: Resist Cold")]]; + bool MU1_BurningHands [[comment("MU1: Burning Hands")]]; + bool MU1_CharmPerson [[comment("MU1: Charm Person")]]; + bool MU1_DetectMagic [[comment("MU1: Detect Magic")]]; + bool MU1_Enlarge [[comment("MU1: Enlarge")]]; + bool MU1_Reduce [[comment("MU1: Reduce")]]; + bool MU1_Friends [[comment("MU1: Friends")]]; + bool MU1_MagicMissile [[comment("MU1: Magic Missile")]]; + bool MU1_ProtectionFromEvil [[comment("MU1: Protection from Evil")]]; + bool MU1_ProtectionFromGood [[comment("MU1: Protection from Good")]]; + bool MU1_ReadMagic [[comment("MU1: Read Magic")]]; + bool MU1_Shield [[comment("MU1: Shield")]]; + bool MU1_ShockingGrasp [[comment("MU1: Shocking Grasp")]]; + bool MU1_Sleep [[comment("MU1: Sleep")]]; + bool CL2_FindTraps [[comment("CL2: Find Traps")]]; + bool CL2_HoldPerson [[comment("CL2: Hold Person")]]; + bool CL2_ResistFire [[comment("CL2: Resist Fire")]]; + bool CL2_Silence15Radius [[comment("CL2: Silence, 15' Radius")]]; + bool CL2_SlowPoison [[comment("CL2: Slow Poison")]]; + bool CL2_SnakeCharm [[comment("CL2: Snake Charm")]]; + bool CL2_SpiritualHammer [[comment("CL2: Spiritual Hammer")]]; + bool MU2_DetectInvisibility [[comment("MU2: Detect Invisibility")]]; + bool MU2_Invisibility [[comment("MU2: Invisibility")]]; + bool MU2_Knock [[comment("MU2: Knock")]]; + bool MU2_MirrorImage [[comment("MU2: Mirror Image")]]; + bool MU2_RayOfEnfeeblement [[comment("MU2: Ray of Enfeeblement")]]; + bool MU2_StinkingCloud [[comment("MU2: Stinking Cloud")]]; + bool MU2_Strength [[comment("MU2: Strength")]]; + bool IT7_AnimateDead [[comment("IT7: Animate Dead")]]; + bool CL3_CureBlindness [[comment("CL3: Cure Blindness")]]; + bool CL3_CauseBlindness [[comment("CL3: Cause Blindness")]]; + bool CL3_CureDisease [[comment("CL3: Cure Disease")]]; + bool CL3_CauseDisease [[comment("CL3: Cause Disease")]]; + bool CL3_DispelMagic [[comment("CL3: Dispel Magic")]]; + bool CL3_Prayer [[comment("CL3: Prayer")]]; + bool CL3_RemoveCurse [[comment("CL3: Remove Curse")]]; + bool CL3_BestowCurse [[comment("CL3: Bestow Curse")]]; + bool MU3_Blink [[comment("MU3: Blink")]]; + bool MU3_DispelMagic [[comment("MU3: Dispel Magic")]]; + bool MU3_Fireball [[comment("MU3: Fireball")]]; + bool MU3_Haste [[comment("MU3: Haste")]]; + bool MU3_HoldPerson [[comment("MU3: Hold Person")]]; + bool MU3_Invisibility10Radius [[comment("MU3: Invisibility, 10' Radius")]]; + bool MU3_LightningBolt [[comment("MU3: Lightning Bolt")]]; + bool MU3_ProtectionFromEvil10Radius [[comment("MU3: Protection from Evil, 10' Radius")]]; + bool MU3_ProtectionFromGood10Radius [[comment("MU3: Protection from Good, 10' Radius")]]; + bool MU3_ProtectionFromNormalMissiles [[comment("MU3: Protection from Normal Missiles")]]; + bool MU3_Slow [[comment("MU3: Slow")]]; + bool CL7_Restoration [[comment("CL7: Restoration")]]; + bool IT6_PotionOfSpeed [[comment("IT6: Potion of Speed")]]; + bool CL4_CureSeriousWounds [[comment("CL4: Cure Serious Wounds")]]; + bool IT6_PotionOfGiantStrength [[comment("IT6: Potion of Giant Strength")]]; + bool IT6_JavelinOfLightning [[comment("IT6: Javelin of Lightning")]]; + bool IT6_WandOfParalyzation [[comment("IT6: Wand of Paralyzation")]]; + bool IT6_PotionOfHealing [[comment("IT6: Potion of Healing")]]; + bool IT6_DustOfDisappearance [[comment("IT6: Dust of Disappearance")]]; + bool IT6_NecklaceOfMissiles [[comment("IT6: Necklace of Missiles")]]; + bool IT6_WandOfMagicMissiles [[comment("IT6: Wand of Magic Missiles")]]; + bool CL4_CauseSeriousWounds [[comment("CL4: Cause Serious Wounds")]]; + bool CL4_NeutralizePoison [[comment("CL4: Neutralize Poison")]]; + bool CL4_Poison [[comment("CL4: Poison")]]; + bool CL4_ProtectionEvil10Radius [[comment("CL4: Protection Evil, 10' Radius")]]; + bool CL4_SticksToSnakes [[comment("CL4: Sticks to Snakes")]]; + bool CL5_CureCriticalWounds [[comment("CL5: Cure Critical Wounds")]]; + bool CL5_CauseCriticalWounds [[comment("CL5: Cause Critical Wounds")]]; + bool CL5_DispelEvil [[comment("CL5: Dispel Evil")]]; + bool CL5_FlameStrike [[comment("CL5: Flame Strike")]]; + bool CL5_RaiseDead [[comment("CL5: Raise Dead")]]; + bool CL5_SlayLiving [[comment("CL5: Slay Living")]]; + bool DR1_DetectMagic [[comment("DR1: Detect Magic")]]; + bool DR1_Entangle [[comment("DR1: Entangle")]]; + bool DR1_FaerieFire [[comment("DR1: Faerie Fire")]]; + bool DR1_InvisibilityToAnimals [[comment("DR1: Invisibility to Animals")]]; + bool MU4_CharmMonsters [[comment("MU4: Charm Monsters")]]; + bool MU4_Confusion [[comment("MU4: Confusion")]]; + bool MU4_DimensionDoor [[comment("MU4: Dimension Door")]]; + bool MU4_Fear [[comment("MU4: Fear")]]; + bool MU4_FireShield [[comment("MU4: Fire Shield")]]; + bool MU4_Fumble [[comment("MU4: Fumble")]]; + bool MU4_IceStorm [[comment("MU4: Ice Storm")]]; + bool MU4_MinorGlobeOfInvulnerability [[comment("MU4: Minor Globe of Invulnerability")]]; + bool MU4_RemoveCurse [[comment("MU4: Remove Curse")]]; + bool IT5_AnimateDead [[comment("IT5: Animate Dead")]]; + bool MU5_CloudKill [[comment("MU5: Cloud Kill")]]; + bool MU5_ConeOfCold [[comment("MU5: Cone of Cold")]]; + bool MU5_Feeblemind [[comment("MU5: Feeblemind")]]; + bool MU5_HoldMonsters [[comment("MU5: Hold Monsters")]]; + bool IT6_ScrollOfProtDragonBreath [[comment("IT6: Scroll of Prot Dragon Breath")]]; + bool IT6_ScrollOfProtParalyzation [[comment("IT6: Scroll of Prot. Paralyzation")]]; + bool IT6_PotionOfInvisibility [[comment("IT6: Potion of Invisibility")]]; + bool IT6_WandOfDefoliation [[comment("IT6: Wand of Defoliation")]]; + bool IT6_PotionExtraHealing [[comment("IT6: Potion Extra Healing")]]; + bool MU4_BestowCurse [[comment("MU4: Bestow Curse")]]; + bool SP0_ProtectionFromEvil10Radius [[comment("SP0: Protection from Evil 10' Radius")]]; + bool SP0_Silence15Radius [[comment("SP0: Silence 15' radius")]]; + bool SP0_DetectMagic [[comment("SP0: Detect Magic")]]; + bool SP0_RemoveCurse [[comment("SP0: Remove Curse")]]; + bool SP0_Bless [[comment("SP0: Bless")]]; + bool SP0_CharmPerson [[comment("SP0: Charm Person")]]; + bool SP0_BurningHands [[comment("SP0: Burning Hands")]]; +}; + +// Known Spells - 6 - WIZ.SPL_Known - Note: This is using the BOOL enum type, not the standard "bool" type +struct SPL_KNOWN06 { + BOOL CL1_Bless [[comment("CL1: Bless")]]; + BOOL DR2_Barkskin [[comment("DR2: Barkskin")]]; + BOOL CL1_CureLightWounds [[comment("CL1: Cure Light Wounds")]]; + BOOL DR2_CharmPersonMammal [[comment("DR2: Charm Person/Mammal")]]; + BOOL CL1_DetectMagic [[comment("CL1: Detect Magic")]]; + BOOL CL1_ProtectionFromEvil [[comment("CL1: Protection from Evil")]]; + BOOL CL7_Ressurection [[comment("CL7: Resurrection")]]; + BOOL CL1_ResistCold [[comment("CL1: Resist Cold")]]; + BOOL MU1_BurningHands [[comment("MU1: Burning Hands")]]; + BOOL MU1_CharmPerson [[comment("MU1: Charm Person")]]; + BOOL MU1_DetectMagic [[comment("MU1: Detect Magic")]]; + BOOL MU1_Enlarge [[comment("MU1: Enlarge")]]; + BOOL MU1_Reduce [[comment("MU1: Reduce")]]; + BOOL MU1_Friends [[comment("MU1: Friends")]]; + BOOL MU1_MagicMissile [[comment("MU1: Magic Missile")]]; + BOOL MU1_ProtectionFromEvil [[comment("MU1: Protection from Evil")]]; + BOOL CL7_Restoration [[comment("CL7: Restoration")]]; + BOOL MU1_ReadMagic [[comment("MU1: Read Magic")]]; + BOOL MU1_Shield [[comment("MU1: Shield")]]; + BOOL MU1_ShockingGrasp [[comment("MU1: Shocking Grasp")]]; + BOOL MU1_Sleep [[comment("MU1: Sleep")]]; + BOOL CL2_FindTraps [[comment("CL2: Find Traps")]]; + BOOL CL2_HoldPerson [[comment("CL2: Hold Person")]]; + BOOL CL2_ResistFire [[comment("CL2: Resist Fire")]]; + BOOL CL2_Silence15Radius [[comment("CL2: Silence, 15' Radius")]]; + BOOL CL2_SlowPoison [[comment("CL2: Slow Poison")]]; + BOOL CL2_SnakeCharm [[comment("CL2: Snake Charm")]]; + BOOL CL2_SpiritualHammer [[comment("CL2: Spiritual Hammer")]]; + BOOL MU2_DetectInvisibility [[comment("MU2: Detect Invisibility")]]; + BOOL MU2_Invisibility [[comment("MU2: Invisibility")]]; + BOOL MU2_Knock [[comment("MU2: Knock")]]; + BOOL MU2_MirrorImage [[comment("MU2: Mirror Image")]]; + BOOL MU2_RayOfEnfeeblement [[comment("MU2: Ray of Enfeeblement")]]; + BOOL MU2_StinkingCloud [[comment("MU2: Stinking Cloud")]]; + BOOL MU2_Strength [[comment("MU2: Strength")]]; + BOOL IT7_AnimateDead [[comment("IT7: Animate Dead")]]; + BOOL CL3_CureBlindness [[comment("CL3: Cure Blindness")]]; + BOOL CL3_CauseBlindness [[comment("CL3: Cause Blindness")]]; + BOOL CL3_CureDisease [[comment("CL3: Cure Disease")]]; + BOOL CL6_Harm [[comment("CL6: Harm")]]; + BOOL CL3_DispelMagic [[comment("CL3: Dispel Magic")]]; + BOOL CL3_Prayer [[comment("CL3: Prayer")]]; + BOOL CL3_RemoveCurse [[comment("CL3: Remove Curse")]]; + BOOL CL3_BestowCurse [[comment("CL3: Bestow Curse")]]; + BOOL MU3_Blink [[comment("MU3: Blink")]]; + BOOL MU3_DispelMagic [[comment("MU3: Dispel Magic")]]; + BOOL MU3_Fireball [[comment("MU3: Fireball")]]; + BOOL MU3_Haste [[comment("MU3: Haste")]]; + BOOL MU3_HoldPerson [[comment("MU3: Hold Person")]]; + BOOL MU3_Invisibility10Radius [[comment("MU3: Invisibility, 10' Radius")]]; + BOOL MU3_LightningBolt [[comment("MU3: Lightning Bolt")]]; + BOOL MU3_ProtectionFromEvil10Radius [[comment("MU3: Protection from Evil, 10' Radius")]]; + BOOL CL6_Heal [[comment("CL6: Heal")]]; + BOOL MU3_ProtectionFromNormalMissiles [[comment("MU3: Protection from Normal Missiles")]]; + BOOL MU3_Slow [[comment("MU3: Slow")]]; + BOOL MU6_DeathSpell [[comment("MU6: Death Spell")]]; + BOOL IT6_PotionOfSpeed [[comment("IT6: Potion of Speed")]]; + BOOL CL4_CureSeriousWounds [[comment("CL4: Cure Serious Wounds")]]; + BOOL IT6_PotionOfGiantStrength [[comment("IT6: Potion of Giant Strength")]]; + BOOL MU6_Disentegrate [[comment("MU6: Disentegrate")]]; + BOOL IT6_WandOfParalyzation [[comment("IT6: Wand of Paralyzation")]]; + BOOL IT6_PotionOfHealing [[comment("IT6: Potion of Healing")]]; + BOOL MU6_GlobeOfInvulnerability [[comment("MU6: Globe of Invulnerability")]]; + BOOL IT6_NecklaceOfMissiles [[comment("IT6: Necklace of Missiles")]]; + BOOL IT6_WandOfMagicMissiles [[comment("IT6: Wand of Magic Missiles")]]; + BOOL MU6_StoneToFlesh [[comment("MU6: Stone to Flesh")]]; + BOOL CL4_NeutralizePoison [[comment("CL4: Neutralize Poison")]]; + BOOL CL4_Poison [[comment("CL4: Poison")]]; + BOOL CL4_ProtectionEvil10Radius [[comment("CL4: Protection Evil, 10' Radius")]]; + BOOL CL4_SticksToSnakes [[comment("CL4: Sticks to Snakes")]]; + BOOL CL5_CureCriticalWounds [[comment("CL5: Cure Critical Wounds")]]; + BOOL MU6_FleshToStone [[comment("MU6: Flesh to Stone")]]; + BOOL CL5_DispelEvil [[comment("CL5: Dispel Evil")]]; + BOOL CL5_FlameStrike [[comment("CL5: Flame Strike")]]; + BOOL CL5_RaiseDead [[comment("CL5: Raise Dead")]]; + BOOL CL5_SlayLiving [[comment("CL5: Slay Living")]]; + BOOL DR1_DetectMagic [[comment("DR1: Detect Magic")]]; + BOOL DR1_Entangle [[comment("DR1: Entangle")]]; + BOOL DR1_FaerieFire [[comment("DR1: Faerie Fire")]]; + BOOL DR1_InvisibilityToAnimals [[comment("DR1: Invisibility to Animals")]]; + BOOL MU4_CharmMonsters [[comment("MU4: Charm Monsters")]]; + BOOL MU4_Confusion [[comment("MU4: Confusion")]]; + BOOL MU4_DimensionDoor [[comment("MU4: Dimension Door")]]; + BOOL MU4_Fear [[comment("MU4: Fear")]]; + BOOL MU4_FireShield [[comment("MU4: Fire Shield")]]; + BOOL MU4_Fumble [[comment("MU4: Fumble")]]; + BOOL MU4_IceStorm [[comment("MU4: Ice Storm")]]; + BOOL MU4_MinorGlobeOfInvulnerability [[comment("MU4: Minor Globe of Invulnerability")]]; + BOOL MU4_RemoveCurse [[comment("MU4: Remove Curse")]]; + BOOL MU5_IronSkin [[comment("MU5: Iron Skin")]]; + BOOL MU5_CloudKill [[comment("MU5: Cloud Kill")]]; + BOOL MU5_ConeOfCold [[comment("MU5: Cone of Cold")]]; + BOOL MU5_Feeblemind [[comment("MU5: Feeblemind")]]; + BOOL MU5_HoldMonsters [[comment("MU5: Hold Monsters")]]; + BOOL IT6_ScrollOfProtDragonBreath [[comment("IT6: Scroll of Prot Dragon Breath")]]; + BOOL IT6_ElixirOfYouth [[comment("IT6: Elixir of Youth")]]; + BOOL IT6_PotionOfInvisibility [[comment("IT6: Potion of Invisibility")]]; + BOOL MU5_FireTouch [[comment("MU5: Fire Touch")]]; + BOOL IT6_PotionExtraHealing [[comment("IT6: Potion Extra Healing")]]; + BOOL MU4_BestowCurse [[comment("MU4: Bestow Curse")]]; + BOOL SP0_ProtectionFromEvil10Radius [[comment("SP0: Protection from Evil 10' Radius")]]; + BOOL SP0_Silence15Radius [[comment("SP0: Silence 15' radius")]]; + BOOL SP0_DetectMagic [[comment("SP0: Detect Magic")]]; + BOOL SP0_RemoveCurse [[comment("SP0: Remove Curse")]]; + BOOL SP0_Bless [[comment("SP0: Bless")]]; + BOOL SP0_CharmPerson [[comment("SP0: Charm Person")]]; + BOOL SP0_BurningHands [[comment("SP0: Burning Hands")]]; + BOOL MU7_DelayBlastFireball [[comment("MU7: Delay Blast Fireball")]]; + BOOL MU7_MassInvisibility [[comment("MU7: Mass Invisibility")]]; + BOOL MU7_PowerWordStun [[comment("MU7: Power Word Stun")]]; + BOOL MU8_MassCharm [[comment("MU8: Mass Charm")]]; + BOOL MU8_MindBlank [[comment("MU8: Mind Blank")]]; + BOOL MU8_OttosIrresitableDance [[comment("MU8: Otto's Irresitable Dance")]]; + BOOL MU8_PowerWordBlind [[comment("MU8: Power Word Blind")]]; +}; + +// Known Spells - 7 +bitfield SPL_KNOWN07 { + CL1_Bless : 1 [[comment("CL1: Bless")]]; + EV1_Curse : 1 [[comment("EV1: Curse")]]; + CL1_CureLightWounds : 1 [[comment("CL1: Cure Light Wounds")]]; + EV1_CauseLightWounds : 1 [[comment("EV1: Cause Light Wounds")]]; + CL1_DetectMagic : 1 [[comment("CL1: Detect Magic")]]; + CL1_ProtectionFromEvil : 1 [[comment("CL1: Protection from Evil")]]; + EV1_ProtectionFromGood : 1 [[comment("EV1: Protection from Good")]]; + CL1_ResistCold : 1 [[comment("CL1: Resist Cold")]]; + MU1_BurningHands : 1 [[comment("MU1: Burning Hands")]]; + MU1_CharmPerson : 1 [[comment("MU1: Charm Person")]]; + MU1_DetectMagic : 1 [[comment("MU1: Detect Magic")]]; + MU1_Enlarge : 1 [[comment("MU1: Enlarge")]]; + MU1_Reduce : 1 [[comment("MU1: Reduce")]]; + MU1_Friends : 1 [[comment("MU1: Friends")]]; + MU1_MagicMissile : 1 [[comment("MU1: Magic Missile")]]; + MU1_ProtectionFromEvil : 1 [[comment("MU1: Protection from Evil")]]; + MU1_ProtectionFromGood : 1 [[comment("MU1: Protection from Good")]]; + MU1_ReadMagic : 1 [[comment("MU1: Read Magic")]]; + MU1_Shield : 1 [[comment("MU1: Shield")]]; + MU1_ShockingGrasp : 1 [[comment("MU1: Shocking Grasp")]]; + MU1_Sleep : 1 [[comment("MU1: Sleep")]]; + CL2_FindTraps : 1 [[comment("CL2: Find Traps")]]; + CL2_HoldPerson : 1 [[comment("CL2: Hold Person")]]; + CL2_ResistFire : 1 [[comment("CL2: Resist Fire")]]; + CL2_Silence15Radius : 1 [[comment("CL2: Silence, 15' Radius")]]; + CL2_SlowPoison : 1 [[comment("CL2: Slow Poison")]]; + CL2_SnakeCharm : 1 [[comment("CL2: Snake Charm")]]; + CL2_SpiritualHammer : 1 [[comment("CL2: Spiritual Hammer")]]; + MU2_DetectInvisibility : 1 [[comment("MU2: Detect Invisibility")]]; + MU2_Invisibility : 1 [[comment("MU2: Invisibility")]]; + MU2_Knock : 1 [[comment("MU2: Knock")]]; + MU2_MirrorImage : 1 [[comment("MU2: Mirror Image")]]; + MU2_RayOfEnfeeblement : 1 [[comment("MU2: Ray of Enfeeblement")]]; + MU2_StinkingCloud : 1 [[comment("MU2: Stinking Cloud")]]; + MU2_Strength : 1 [[comment("MU2: Strength")]]; + CL6_Heal : 1 [[comment("CL6: Heal")]]; + CL3_CureBlindness : 1 [[comment("CL3: Cure Blindness")]]; + EV3_CauseBlindness : 1 [[comment("EV3: Cause Blindness")]]; + CL3_CureDisease : 1 [[comment("CL3: Cure Disease")]]; + EV3_CauseDisease : 1 [[comment("EV3: Cause Disease")]]; + CL3_DispelMagic : 1 [[comment("CL3: Dispel Magic")]]; + CL3_Prayer : 1 [[comment("CL3: Prayer")]]; + CL3_RemoveCurse : 1 [[comment("CL3: Remove Curse")]]; + EV3_BestowCurse : 1 [[comment("EV3: Bestow Curse")]]; + MU3_Blink : 1 [[comment("MU3: Blink")]]; + MU3_DispelMagic : 1 [[comment("MU3: Dispel Magic")]]; + MU3_Fireball : 1 [[comment("MU3: Fireball")]]; + MU3_Haste : 1 [[comment("MU3: Haste")]]; + MU3_HoldPerson : 1 [[comment("MU3: Hold Person")]]; + MU3_Invisibility10Radius : 1 [[comment("MU3: Invisibility, 10' Radius")]]; + MU3_LightningBolt : 1 [[comment("MU3: Lightning Bolt")]]; + MU3_ProtectionFromEvil10Radius : 1 [[comment("MU3: Protection from Evil, 10' Radius")]]; + MU3_ProtectionFromGood10Radius : 1 [[comment("MU3: Protection from Good, 10' Radius")]]; + MU3_ProtectionFromNormalMissiles : 1 [[comment("MU3: Protection from Normal Missiles")]]; + MU3_Slow : 1 [[comment("MU3: Slow")]]; + EV6_Harm : 1 [[comment("EV6: Harm")]]; + SP0_ProtectionFromEvil10Radius : 1 [[comment("SP0: Protection from Evil 10' Radius")]]; + CL4_CureSeriousWounds : 1 [[comment("CL4: Cure Serious Wounds")]]; + SP0_Silence15Radius : 1 [[comment("SP0: Silence 15' radius")]]; + SP0_DetectMagic : 1 [[comment("SP0: Detect Magic")]]; + SP0_RemoveCurse : 1 [[comment("SP0: Remove Curse")]]; + SP0_Bless : 1 [[comment("SP0: Bless")]]; + SP0_CharmPerson : 1 [[comment("SP0: Charm Person")]]; + SP0_BurningHands : 1 [[comment("SP0: Burning Hands")]]; + IT6_WandOfMagicMissiles : 1 [[comment("IT6: Wand of Magic Missiles")]]; + EV4_CauseSeriousWounds : 1 [[comment("EV4: Cause Serious Wounds")]]; + CL4_NeutralizePoison : 1 [[comment("CL4: Neutralize Poison")]]; + EV4_Poison : 1 [[comment("EV4: Poison")]]; + CL4_ProtectionEvil10Radius : 1 [[comment("CL4: Protection Evil, 10' Radius")]]; + CL4_SticksToSnakes : 1 [[comment("CL4: Sticks to Snakes")]]; + CL5_CureCriticalWounds : 1 [[comment("CL5: Cure Critical Wounds")]]; + EV5_CauseCriticalWounds : 1 [[comment("EV5: Cause Critical Wounds")]]; + CL5_DispelEvil : 1 [[comment("CL5: Dispel Evil")]]; + CL5_FlameStrike : 1 [[comment("CL5: Flame Strike")]]; + CL5_RaiseDead : 1 [[comment("CL5: Raise Dead")]]; + EV5_SlayLiving : 1 [[comment("EV5: Slay Living")]]; + DR1_DetectMagic : 1 [[comment("DR1: Detect Magic")]]; + DR1_Entangle : 1 [[comment("DR1: Entangle")]]; + DR1_FaerieFire : 1 [[comment("DR1: Faerie Fire")]]; + DR1_InvisibilityToAnimals : 1 [[comment("DR1: Invisibility to Animals")]]; + MU4_CharmMonsters : 1 [[comment("MU4: Charm Monsters")]]; + MU4_Confusion : 1 [[comment("MU4: Confusion")]]; + MU4_DimensionDoor : 1 [[comment("MU4: Dimension Door")]]; + MU4_Fear : 1 [[comment("MU4: Fear")]]; + MU4_FireShield : 1 [[comment("MU4: Fire Shield")]]; + MU4_Fumble : 1 [[comment("MU4: Fumble")]]; + MU4_IceStorm : 1 [[comment("MU4: Ice Storm")]]; + MU4_MinorGlobeOfInvulnerability : 1 [[comment("MU4: Minor Globe of Invulnerability")]]; + MU4_RemoveCurse : 1 [[comment("MU4: Remove Curse")]]; + DR2_Barkskin : 1 [[comment("DR2: Barkskin")]]; + MU5_CloudKill : 1 [[comment("MU5: Cloud Kill")]]; + MU5_ConeOfCold : 1 [[comment("MU5: Cone of Cold")]]; + MU5_Feeblemind : 1 [[comment("MU5: Feeblemind")]]; + MU5_HoldMonsters : 1 [[comment("MU5: Hold Monsters")]]; + IT6_ScrollOfProtection : 1 [[comment("IT6: Scroll of Protection")]]; + DR2_CharmPersonOrMammal : 1 [[comment("DR2: Charm Person or Mammal")]]; + IT6_PotionOfInvisibility : 1 [[comment("IT6: Potion of Invisibility")]]; + DR2_CureLightWounds : 1 [[comment("DR2: Cure Light Wounds")]]; + IT6_PotionOfExtraHealing : 1 [[comment("IT6: Potion of Extra Healing")]]; + MU4_BestowCurse : 1 [[comment("MU4: Bestow Curse")]]; + CL6_BladeBarrier : 1 [[comment("CL6: Blade Barrier")]]; + CL7_Restoration : 1 [[comment("CL7: Restoration")]]; + EV7_EnergyDrain : 1 [[comment("EV7: Energy Drain")]]; + EV7_Destruction : 1 [[comment("EV7: Destruction")]]; + CL7_Resurrection : 1 [[comment("CL7: Resurrection")]]; + DR3_CureDisease : 1 [[comment("DR3: Cure Disease")]]; + DR3_NeutralizePoison : 1 [[comment("DR3: Neutralize Poison")]]; + DR3_HoldAnimal : 1 [[comment("DR3: Hold Animal")]]; + DR3_ProtFromFire : 1 [[comment("DR3: Prot. from Fire")]]; + MU6_DeathSpell : 1 [[comment("MU6: Death Spell")]]; + MU6_Disintegrate : 1 [[comment("MU6: Disintegrate")]]; + MU6_GlobeOfInvulnerability : 1 [[comment("MU6: Globe of Invulnerability")]]; + MU6_StoneToFlesh : 1 [[comment("MU6: Stone to Flesh")]]; + MU6_FleshToStone : 1 [[comment("MU6: Flesh to Stone")]]; + MU7_DelayedBlastFireball : 1 [[comment("MU7: Delayed Blast Fireball")]]; + MU7_MassInvisibility : 1 [[comment("MU7: Mass Invisibility")]]; + MU7_PowerWordStun : 1 [[comment("MU7: Power Word Stun")]]; + MU5_FireTouch : 1 [[comment("MU5: Fire Touch")]]; + MU5_IronSkin : 1 [[comment("MU5: Iron Skin")]]; + MU8_MassCharm : 1 [[comment("MU8: Mass Charm")]]; + MU8_OttosIrrDance : 1 [[comment("MU8: Otto's Irr. Dance")]]; + MU8_MindBlank : 1 [[comment("MU8: Mind Blank")]]; + MU8_PowerWordBlind : 1 [[comment("MU8: Power Word Blind")]]; + MU9_MeteorSwarm : 1 [[comment("MU9: Meteor Swarm")]]; + MU9_PowerWordKill : 1 [[comment("MU9: Power Word Kill")]]; + MU9_MonsterSummoning : 1 [[comment("MU9: Monster Summoning")]]; + IT6_PotionOfSpeed : 1 [[comment("IT6: Potion of Speed")]]; + IT6_PotionOfGiantStrength : 1 [[comment("IT6: Potion of Giant Strength")]]; +}; + +// Known Spells - 8 +struct SPL_KNOWN08 { + bool CL1_Bless [[comment("CL1: Bless")]]; + bool CL1_Curse [[comment("CL1: Curse")]]; + bool CL1_CureLightWounds [[comment("CL1: Cure Light Wounds")]]; + bool CL1_CauseLightWounds [[comment("CL1: Cause Light Wounds")]]; + bool CL1_DetectMagic [[comment("CL1: Detect Magic")]]; + bool CL1_ProtectionFromEvil [[comment("CL1: Protection from Evil")]]; + bool CL1_ProtectionFromGood [[comment("CL1: Protection from Good")]]; + bool CL1_ResistCold [[comment("CL1: Resist Cold")]]; + bool MU1_BurningHands [[comment("MU1: Burning Hands")]]; + bool MU1_CharmPerson [[comment("MU1: Charm Person")]]; + bool MU1_DetectMagic [[comment("MU1: Detect Magic")]]; + bool MU1_Enlarge [[comment("MU1: Enlarge")]]; + bool MU1_Reduce [[comment("MU1: Reduce")]]; + bool MU1_Friends [[comment("MU1: Friends")]]; + bool MU1_MagicMissile [[comment("MU1: Magic Missile")]]; + bool MU1_ProtectionFromEvil [[comment("MU1: Protection from Evil")]]; + bool MU1_ProtectionFromGood [[comment("MU1: Protection from Good")]]; + bool MU1_ReadMagic [[comment("MU1: Read Magic")]]; + bool MU1_Shield [[comment("MU1: Shield")]]; + bool MU1_ShockingGrasp [[comment("MU1: Shocking Grasp")]]; + bool MU1_Sleep [[comment("MU1: Sleep")]]; + bool CL2_FindTraps [[comment("CL2: Find Traps")]]; + bool CL2_HoldPerson [[comment("CL2: Hold Person")]]; + bool CL2_ResistFire [[comment("CL2: Resist Fire")]]; + bool CL2_Silence15Radius [[comment("CL2: Silence, 15' Radius")]]; + bool CL2_SlowPoison [[comment("CL2: Slow Poison")]]; + bool CL2_SnakeCharm [[comment("CL2: Snake Charm")]]; + bool CL2_SpiritualHammer [[comment("CL2: Spiritual Hammer")]]; + bool MU2_DetectInvisibility [[comment("MU2: Detect Invisibility")]]; + bool MU2_Invisibility [[comment("MU2: Invisibility")]]; + bool MU2_Knock [[comment("MU2: Knock")]]; + bool MU2_MirrorImage [[comment("MU2: Mirror Image")]]; + bool MU2_RayOfEnfeeblement [[comment("MU2: Ray of Enfeeblement")]]; + bool MU2_StinkingCloud [[comment("MU2: Stinking Cloud")]]; + bool MU2_Strength [[comment("MU2: Strength")]]; + bool IT7_AnimateDead [[comment("IT7: Animate Dead")]]; + bool CL3_CureBlindness [[comment("CL3: Cure Blindness")]]; + bool CL3_CauseBlindness [[comment("CL3: Cause Blindness")]]; + bool CL3_CureDisease [[comment("CL3: Cure Disease")]]; + bool CL3_CauseDisease [[comment("CL3: Cause Disease")]]; + bool CL3_DispelMagic [[comment("CL3: Dispel Magic")]]; + bool CL3_Prayer [[comment("CL3: Prayer")]]; + bool CL3_RemoveCurse [[comment("CL3: Remove Curse")]]; + bool CL3_BestowCurse [[comment("CL3: Bestow Curse")]]; + bool MU3_Blink [[comment("MU3: Blink")]]; + bool MU3_DispelMagic [[comment("MU3: Dispel Magic")]]; + bool MU3_Fireball [[comment("MU3: Fireball")]]; + bool MU3_Haste [[comment("MU3: Haste")]]; + bool MU3_HoldPerson [[comment("MU3: Hold Person")]]; + bool MU3_Invisibility10Radius [[comment("MU3: Invisibility, 10' Radius")]]; + bool MU3_LightningBolt [[comment("MU3: Lightning Bolt")]]; + bool MU3_ProtectionFromEvil10Radius [[comment("MU3: Protection from Evil, 10' Radius")]]; + bool MU3_ProtectionFromGood10Radius [[comment("MU3: Protection from Good, 10' Radius")]]; + bool MU3_ProtectionFromNormalMissiles [[comment("MU3: Protection from Normal Missiles")]]; + bool MU3_Slow [[comment("MU3: Slow")]]; + bool CL7_Restoration [[comment("CL7: Restoration")]]; + bool IT6_PotionOfSpeed [[comment("IT6: Potion of Speed")]]; + bool CL4_CureSeriousWounds [[comment("CL4: Cure Serious Wounds")]]; + bool IT6_PotionOfGiantStrength [[comment("IT6: Potion of Giant Strength")]]; + bool IT6_JavelinOfLightning [[comment("IT6: Javelin of Lightning")]]; + bool IT6_WandOfParalyzation [[comment("IT6: Wand of Paralyzation")]]; + bool IT6_PotionOfHealing [[comment("IT6: Potion of Healing")]]; + bool IT6_DustOfDisappearance [[comment("IT6: Dust of Disappearance")]]; + bool IT6_NecklaceOfMissiles [[comment("IT6: Necklace of Missiles")]]; + bool IT6_WandOfMagicMissiles [[comment("IT6: Wand of Magic Missiles")]]; + bool CL4_CauseSeriousWounds [[comment("CL4: Cause Serious Wounds")]]; + bool CL4_NeutralizePoison [[comment("CL4: Neutralize Poison")]]; + bool CL4_Poison [[comment("CL4: Poison")]]; + bool CL4_ProtectionEvil10Radius [[comment("CL4: Protection Evil, 10' Radius")]]; + bool CL4_SticksToSnakes [[comment("CL4: Sticks to Snakes")]]; + bool CL5_CureCriticalWounds [[comment("CL5: Cure Critical Wounds")]]; + bool CL5_CauseCriticalWounds [[comment("CL5: Cause Critical Wounds")]]; + bool CL5_DispelEvil [[comment("CL5: Dispel Evil")]]; + bool CL5_FlameStrike [[comment("CL5: Flame Strike")]]; + bool CL5_RaiseDead [[comment("CL5: Raise Dead")]]; + bool CL5_SlayLiving [[comment("CL5: Slay Living")]]; + bool DR1_DetectMagic [[comment("DR1: Detect Magic")]]; + bool DR1_Entangle [[comment("DR1: Entangle")]]; + bool DR1_FaerieFire [[comment("DR1: Faerie Fire")]]; + bool DR1_InvisibilityToAnimals [[comment("DR1: Invisibility to Animals")]]; + bool MU4_CharmMonsters [[comment("MU4: Charm Monsters")]]; + bool MU4_Confusion [[comment("MU4: Confusion")]]; + bool MU4_DimensionDoor [[comment("MU4: Dimension Door")]]; + bool MU4_Fear [[comment("MU4: Fear")]]; + bool MU4_FireShield [[comment("MU4: Fire Shield")]]; + bool MU4_Fumble [[comment("MU4: Fumble")]]; + bool MU4_IceStorm [[comment("MU4: Ice Storm")]]; + bool MU4_MinorGlobeOfInvulnerability [[comment("MU4: Minor Globe of Invulnerability")]]; + bool MU4_RemoveCurse [[comment("MU4: Remove Curse")]]; + bool IT5_AnimateDead [[comment("IT5: Animate Dead")]]; + bool MU5_CloudKill [[comment("MU5: Cloud Kill")]]; + bool MU5_ConeOfCold [[comment("MU5: Cone of Cold")]]; + bool MU5_Feeblemind [[comment("MU5: Feeblemind")]]; + bool MU5_HoldMonsters [[comment("MU5: Hold Monsters")]]; + bool IT6_ScrollOfProtDragonBreath [[comment("IT6: Scroll of Prot. Dragon Breath")]]; + bool IT6_ScrollOfProtParalyzation [[comment("IT6: Scroll of Prot. Paralyzation")]]; + bool IT6_PotionOfInvisibility [[comment("IT6: Potion of Invisibility")]]; + bool IT6_WandOfDefoliation [[comment("IT6: Wand of Defoliation")]]; + bool IT6_PotionExtraHealing [[comment("IT6: Potion Extra Healing")]]; + bool MU4_BestowCurse [[comment("MU4: Bestow Curse")]]; +}; + +// Known Spells - 9 +struct SPL_KNOWN09 { + bool CL1_Bless [[comment("CL1: Bless")]]; + bool CL1_Curse [[comment("CL1: Curse")]]; + bool CL1_CureLightWounds [[comment("CL1: Cure Light Wounds")]]; + bool CL1_CauseLightWounds [[comment("CL1: Cause Light Wounds")]]; + bool CL1_DetectMagic [[comment("CL1: Detect Magic")]]; + bool CL1_ProtectionFromEvil [[comment("CL1: Protection from Evil")]]; + bool CL1_ProtectionFromGood [[comment("CL1: Protection from Good")]]; + bool CL1_ResistCold [[comment("CL1: Resist Cold")]]; + bool MU1_BurningHands [[comment("MU1: Burning Hands")]]; + bool MU1_CharmPerson [[comment("MU1: Charm Person")]]; + bool MU1_DetectMagic [[comment("MU1: Detect Magic")]]; + bool MU1_Enlarge [[comment("MU1: Enlarge")]]; + bool MU1_Reduce [[comment("MU1: Reduce")]]; + bool MU1_Friends [[comment("MU1: Friends")]]; + bool MU1_MagicMissile [[comment("MU1: Magic Missile")]]; + bool MU1_ProtectionFromEvil [[comment("MU1: Protection from Evil")]]; + bool MU1_ProtectionFromGood [[comment("MU1: Protection from Good")]]; + bool MU1_ReadMagic [[comment("MU1: Read Magic")]]; + bool MU1_Shield [[comment("MU1: Shield")]]; + bool MU1_ShockingGrasp [[comment("MU1: Shocking Grasp")]]; + bool MU1_Sleep [[comment("MU1: Sleep")]]; + bool CL2_FindTraps [[comment("CL2: Find Traps")]]; + bool CL2_HoldPerson [[comment("CL2: Hold Person")]]; + bool CL2_ResistFire [[comment("CL2: Resist Fire")]]; + bool CL2_Silence15Radius [[comment("CL2: Silence, 15' Radius")]]; + bool CL2_SlowPoison [[comment("CL2: Slow Poison")]]; + bool CL2_SnakeCharm [[comment("CL2: Snake Charm")]]; + bool CL2_SpiritualHammer [[comment("CL2: Spiritual Hammer")]]; + bool MU2_DetectInvisibility [[comment("MU2: Detect Invisibility")]]; + bool MU2_Invisibility [[comment("MU2: Invisibility")]]; + bool MU2_Knock [[comment("MU2: Knock")]]; + bool MU2_MirrorImage [[comment("MU2: Mirror Image")]]; + bool MU2_RayOfEnfeeblement [[comment("MU2: Ray of Enfeeblement")]]; + bool MU2_StinkingCloud [[comment("MU2: Stinking Cloud")]]; + bool MU2_Strength [[comment("MU2: Strength")]]; + bool CL6_Heal [[comment("CL6: Heal")]]; + bool CL3_CureBlindness [[comment("CL3: Cure Blindness")]]; + bool CL3_CauseBlindness [[comment("CL3: Cause Blindness")]]; + bool CL3_CureDisease [[comment("CL3: Cure Disease")]]; + bool CL3_CauseDisease [[comment("CL3: Cause Disease")]]; + bool CL3_DispelMagic [[comment("CL3: Dispel Magic")]]; + bool CL3_Prayer [[comment("CL3: Prayer")]]; + bool CL3_RemoveCurse [[comment("CL3: Remove Curse")]]; + bool CL3_BestowCurse [[comment("CL3: Bestow Curse")]]; + bool MU3_Blink [[comment("MU3: Blink")]]; + bool MU3_DispelMagic [[comment("MU3: Dispel Magic")]]; + bool MU3_Fireball [[comment("MU3: Fireball")]]; + bool MU3_Haste [[comment("MU3: Haste")]]; + bool MU3_HoldPerson [[comment("MU3: Hold Person")]]; + bool MU3_Invisibility10Radius [[comment("MU3: Invisibility, 10' Radius")]]; + bool MU3_LightningBolt [[comment("MU3: Lightning Bolt")]]; + bool MU3_ProtectionFromEvil10Radius [[comment("MU3: Protection from Evil, 10' Radius")]]; + bool MU3_ProtectionFromGood10Radius [[comment("MU3: Protection from Good, 10' Radius")]]; + bool MU3_ProtectionFromNormalMissiles [[comment("MU3: Protection from Normal Missiles")]]; + bool MU3_Slow [[comment("MU3: Slow")]]; + bool CL6_Harm [[comment("CL6: Harm")]]; + bool IT6_PotionOfSpeed [[comment("IT6: Potion of Speed")]]; + bool CL4_CureSeriousWounds [[comment("CL4: Cure Serious Wounds")]]; + bool IT6_PotionOfGiantStrength [[comment("IT6: Potion of Giant Strength")]]; + bool IT6_JavelinOfLightning [[comment("IT6: Javelin of Lightning")]]; + bool IT6_WandOfParalyzation [[comment("IT6: Wand of Paralyzation")]]; + bool IT6_PotionOfHealing [[comment("IT6: Potion of Healing")]]; + bool IT6_ElixirOfYouth [[comment("IT6: Elixir of Youth")]]; + bool IT6_NecklaceOfMissiles [[comment("IT6: Necklace of Missiles")]]; + bool IT6_WandOfMagicMissiles [[comment("IT6: Wand of Magic Missiles")]]; + bool CL4_CauseSeriousWounds [[comment("CL4: Cause Serious Wounds")]]; + bool CL4_NeutralizePoison [[comment("CL4: Neutralize Poison")]]; + bool CL4_Poison [[comment("CL4: Poison")]]; + bool CL4_ProtectionEvil10Radius [[comment("CL4: Protection Evil, 10' Radius")]]; + bool CL4_SticksToSnakes [[comment("CL4: Sticks to Snakes")]]; + bool CL5_CureCriticalWounds [[comment("CL5: Cure Critical Wounds")]]; + bool CL5_CauseCriticalWounds [[comment("CL5: Cause Critical Wounds")]]; + bool CL5_DispelEvil [[comment("CL5: Dispel Evil")]]; + bool CL5_FlameStrike [[comment("CL5: Flame Strike")]]; + bool CL5_RaiseDead [[comment("CL5: Raise Dead")]]; + bool CL5_SlayLiving [[comment("CL5: Slay Living")]]; + bool DR1_DetectMagic [[comment("DR1: Detect Magic")]]; + bool DR1_Entangle [[comment("DR1: Entangle")]]; + bool DR1_FaerieFire [[comment("DR1: Faerie Fire")]]; + bool DR1_InvisibilityToAnimals [[comment("DR1: Invisibility to Animals")]]; + bool MU4_CharmMonsters [[comment("MU4: Charm Monsters")]]; + bool MU4_Confusion [[comment("MU4: Confusion")]]; + bool MU4_DimensionDoor [[comment("MU4: Dimension Door")]]; + bool MU4_Fear [[comment("MU4: Fear")]]; + bool MU4_FireShield [[comment("MU4: Fire Shield")]]; + bool MU4_Fumble [[comment("MU4: Fumble")]]; + bool MU4_IceStorm [[comment("MU4: Ice Storm")]]; + bool MU4_MinorGlobeOfInvulnerability [[comment("MU4: Minor Globe of Invulnerability")]]; + bool MU4_RemoveCurse [[comment("MU4: Remove Curse")]]; + bool DR2_Barkskin [[comment("DR2: Barkskin")]]; + bool MU5_CloudKill [[comment("MU5: Cloud Kill")]]; + bool MU5_ConeOfCold [[comment("MU5: Cone of Cold")]]; + bool MU5_Feeblemind [[comment("MU5: Feeblemind")]]; + bool MU5_HoldMonsters [[comment("MU5: Hold Monsters")]]; + bool IT6_ScrollOfProtDragonBreath [[comment("IT6: Scroll of Prot. Dragon Breath")]]; + bool DR2_CharmPersonOrMammal [[comment("DR2: Charm Person or Mammal")]]; + bool IT6_PotionOfInvisibility [[comment("IT6: Potion of Invisibility")]]; + bool DR2_CureLightWounds [[comment("DR2: Cure Light Wounds")]]; + bool IT6_PotionOfExtraHealing [[comment("IT6: Potion of Extra Healing")]]; + bool MU4_BestowCurse [[comment("MU4: Bestow Curse")]]; + bool CL6_BladeBarrier [[comment("CL6: Blade Barrier")]]; + bool CL7_Restoration [[comment("CL7: Restoration")]]; + bool CL7_EnergyDrain [[comment("CL7: Energy Drain")]]; + bool CL7_Destruction [[comment("CL7: Destruction")]]; + bool CL7_Resurrection [[comment("CL7: Resurrection")]]; + bool DR3_CureDisease [[comment("DR3: Cure Disease")]]; + bool DR3_NeutralizePoison [[comment("DR3: Neutralize Poison")]]; + bool DR3_HoldAnimal [[comment("DR3: Hold Animal")]]; + bool DR3_ProtFromFire [[comment("DR3: Prot. from Fire")]]; + bool MU6_DeathSpell [[comment("MU6: Death Spell")]]; + bool MU6_Disintegrate [[comment("MU6: Disintegrate")]]; + bool MU6_GlobeOfInvulnerability [[comment("MU6: Globe of Invulnerability")]]; + bool MU6_StoneToFlesh [[comment("MU6: Stone to Flesh")]]; + bool MU6_FleshToStone [[comment("MU6: Flesh to Stone")]]; + bool MU7_DelayedBlastFireball [[comment("MU7: Delayed Blast Fireball")]]; + bool MU7_MassInvisibility [[comment("MU7: Mass Invisibility")]]; + bool MU7_PowerWordStun [[comment("MU7: Power Word Stun")]]; + bool MU5_FireTouch [[comment("MU5: Fire Touch")]]; + bool MU5_IronSkin [[comment("MU5: Iron Skin")]]; + bool MU8_MassCharm [[comment("MU8: Mass Charm")]]; + bool MU8_OttosIrrDance [[comment("MU8: Otto's Irr. Dance")]]; + bool MU8_MindBlank [[comment("MU8: Mind Blank")]]; + bool MU8_PowerWordBlind [[comment("MU8: Power Word Blind")]]; + bool MU9_MeteorSwarm [[comment("MU9: Meteor Swarm")]]; + bool MU9_PowerWordKill [[comment("MU9: Power Word Kill")]]; + bool MU9_MonsterSummoning [[comment("MU9: Monster Summoning")]]; +}; + +// Known Spells - 10 +bitfield SPL_KNOWN10 { + CL1_Bless : 1 [[comment("CL1: Bless")]]; + CL1_Curse : 1 [[comment("CL1: Curse")]]; + CL1_CureLightWounds : 1 [[comment("CL1: Cure Light Wounds")]]; + CL1_CauseLightWounds : 1 [[comment("CL1: Cause Light Wounds")]]; + CL1_DetectMagic : 1 [[comment("CL1: Detect Magic")]]; + CL1_ProtectionFromEvil : 1 [[comment("CL1: Protection from Evil")]]; + CL1_ProtectionFromGood : 1 [[comment("CL1: Protection from Good")]]; + CL1_ResistCold : 1 [[comment("CL1: Resist Cold")]]; + MU1_BurningHands : 1 [[comment("MU1: Burning Hands")]]; + MU1_CharmPerson : 1 [[comment("MU1: Charm Person")]]; + MU1_DetectMagic : 1 [[comment("MU1: Detect Magic")]]; + MU1_Enlarge : 1 [[comment("MU1: Enlarge")]]; + MU1_Reduce : 1 [[comment("MU1: Reduce")]]; + MU1_Friends : 1 [[comment("MU1: Friends")]]; + MU1_MagicMissile : 1 [[comment("MU1: Magic Missile")]]; + MU1_ProtectionFromEvil : 1 [[comment("MU1: Protection from Evil")]]; + MU1_ProtectionFromGood : 1 [[comment("MU1: Protection from Good")]]; + MU1_ReadMagic : 1 [[comment("MU1: Read Magic")]]; + MU1_Shield : 1 [[comment("MU1: Shield")]]; + MU1_ShockingGrasp : 1 [[comment("MU1: Shocking Grasp")]]; + MU1_Sleep : 1 [[comment("MU1: Sleep")]]; + CL2_FindTraps : 1 [[comment("CL2: Find Traps")]]; + CL2_HoldPerson : 1 [[comment("CL2: Hold Person")]]; + CL2_ResistFire : 1 [[comment("CL2: Resist Fire")]]; + CL2_Silence15Radius : 1 [[comment("CL2: Silence, 15' Radius")]]; + CL2_SlowPoison : 1 [[comment("CL2: Slow Poison")]]; + CL2_SnakeCharm : 1 [[comment("CL2: Snake Charm")]]; + CL2_SpiritualHammer : 1 [[comment("CL2: Spiritual Hammer")]]; + MU2_DetectInvisibility : 1 [[comment("MU2: Detect Invisibility")]]; + MU2_Invisibility : 1 [[comment("MU2: Invisibility")]]; + MU2_Knock : 1 [[comment("MU2: Knock")]]; + MU2_MirrorImage : 1 [[comment("MU2: Mirror Image")]]; + MU2_RayOfEnfeeblement : 1 [[comment("MU2: Ray of Enfeeblement")]]; + MU2_StinkingCloud : 1 [[comment("MU2: Stinking Cloud")]]; + MU2_Strength : 1 [[comment("MU2: Strength")]]; + CL6_Heal : 1 [[comment("CL6: Heal")]]; + CL3_CureBlindness : 1 [[comment("CL3: Cure Blindness")]]; + CL3_CauseBlindness : 1 [[comment("CL3: Cause Blindness")]]; + CL3_CureDisease : 1 [[comment("CL3: Cure Disease")]]; + CL3_CauseDisease : 1 [[comment("CL3: Cause Disease")]]; + CL3_DispelMagic : 1 [[comment("CL3: Dispel Magic")]]; + CL3_Prayer : 1 [[comment("CL3: Prayer")]]; + CL3_RemoveCurse : 1 [[comment("CL3: Remove Curse")]]; + CL3_BestowCurse : 1 [[comment("CL3: Bestow Curse")]]; + MU3_Blink : 1 [[comment("MU3: Blink")]]; + MU3_DispelMagic : 1 [[comment("MU3: Dispel Magic")]]; + MU3_Fireball : 1 [[comment("MU3: Fireball")]]; + MU3_Haste : 1 [[comment("MU3: Haste")]]; + MU3_HoldPerson : 1 [[comment("MU3: Hold Person")]]; + MU3_Invisibility10Radius : 1 [[comment("MU3: Invisibility, 10' Radius")]]; + MU3_LightningBolt : 1 [[comment("MU3: Lightning Bolt")]]; + MU3_ProtectionFromEvil10Radius : 1 [[comment("MU3: Protection from Evil, 10' Radius")]]; + MU3_ProtectionFromGood10Radius : 1 [[comment("MU3: Protection from Good, 10' Radius")]]; + MU3_ProtectionFromNormalMissiles : 1 [[comment("MU3: Protection from Normal Missiles")]]; + MU3_Slow : 1 [[comment("MU3: Slow")]]; + CL6_Harm : 1 [[comment("CL6: Harm")]]; + SP0_ProtectionFromEvil10Radius : 1 [[comment("SP0: Protection from Evil 10' Radius")]]; + CL4_CureSeriousWounds : 1 [[comment("CL4: Cure Serious Wounds")]]; + SP0_Silence15Radius : 1 [[comment("SP0: Silence 15' radius")]]; + SP0_DetectMagic : 1 [[comment("SP0: Detect Magic")]]; + SP0_RemoveCurse : 1 [[comment("SP0: Remove Curse")]]; + SP0_Bless : 1 [[comment("SP0: Bless")]]; + SP0_CharmPerson : 1 [[comment("SP0: Charm Person")]]; + SP0_BurningHands : 1 [[comment("SP0: Burning Hands")]]; + IT6_WandOfMagicMissiles : 1 [[comment("IT6: Wand of Magic Missiles")]]; + CL4_CauseSeriousWounds : 1 [[comment("CL4: Cause Serious Wounds")]]; + CL4_NeutralizePoison : 1 [[comment("CL4: Neutralize Poison")]]; + CL4_Poison : 1 [[comment("CL4: Poison")]]; + CL4_ProtectionEvil10Radius : 1 [[comment("CL4: Protection Evil, 10' Radius")]]; + CL4_SticksToSnakes : 1 [[comment("CL4: Sticks to Snakes")]]; + CL5_CureCriticalWounds : 1 [[comment("CL5: Cure Critical Wounds")]]; + CL5_CauseCriticalWounds : 1 [[comment("CL5: Cause Critical Wounds")]]; + CL5_DispelEvil : 1 [[comment("CL5: Dispel Evil")]]; + CL5_FlameStrike : 1 [[comment("CL5: Flame Strike")]]; + CL5_RaiseDead : 1 [[comment("CL5: Raise Dead")]]; + CL5_SlayLiving : 1 [[comment("CL5: Slay Living")]]; + DR1_DetectMagic : 1 [[comment("DR1: Detect Magic")]]; + DR1_Entangle : 1 [[comment("DR1: Entangle")]]; + DR1_FaerieFire : 1 [[comment("DR1: Faerie Fire")]]; + DR1_InvisibilityToAnimals : 1 [[comment("DR1: Invisibility to Animals")]]; + MU4_CharmMonsters : 1 [[comment("MU4: Charm Monsters")]]; + MU4_Confusion : 1 [[comment("MU4: Confusion")]]; + MU4_DimensionDoor : 1 [[comment("MU4: Dimension Door")]]; + MU4_Fear : 1 [[comment("MU4: Fear")]]; + MU4_FireShield : 1 [[comment("MU4: Fire Shield")]]; + MU4_Fumble : 1 [[comment("MU4: Fumble")]]; + MU4_IceStorm : 1 [[comment("MU4: Ice Storm")]]; + MU4_MinorGlobeOfInvulnerability : 1 [[comment("MU4: Minor Globe of Invulnerability")]]; + MU4_RemoveCurse : 1 [[comment("MU4: Remove Curse")]]; + DR2_Barkskin : 1 [[comment("DR2: Barkskin")]]; + MU5_CloudKill : 1 [[comment("MU5: Cloud Kill")]]; + MU5_ConeOfCold : 1 [[comment("MU5: Cone of Cold")]]; + MU5_Feeblemind : 1 [[comment("MU5: Feeblemind")]]; + MU5_HoldMonsters : 1 [[comment("MU5: Hold Monsters")]]; + IT6_ScrollOfProtDragonBreath : 1 [[comment("IT6: Scroll of Prot Dragon Breath")]]; + DR2_CharmPersonOrMammal : 1 [[comment("DR2: Charm Person or Mammal")]]; + IT6_PotionOfInvisibility : 1 [[comment("IT6: Potion of Invisibility")]]; + DR2_CureLightWounds : 1 [[comment("DR2: Cure Light Wounds")]]; + IT6_PotionOfExtraHealing : 1 [[comment("IT6: Potion of Extra Healing")]]; + MU4_BestowCurse : 1 [[comment("MU4: Bestow Curse")]]; + CL6_BladeBarrier : 1 [[comment("CL6: Blade Barrier")]]; + CL7_Restoration : 1 [[comment("CL7: Restoration")]]; + CL7_EnergyDrain : 1 [[comment("CL7: Energy Drain")]]; + CL7_Destruction : 1 [[comment("CL7: Destruction")]]; + CL7_Resurrection : 1 [[comment("CL7: Resurrection")]]; + DR3_CureDisease : 1 [[comment("DR3: Cure Disease")]]; + DR3_NeutralizePoison : 1 [[comment("DR3: Neutralize Poison")]]; + DR3_HoldAnimal : 1 [[comment("DR3: Hold Animal")]]; + DR3_ProtFromFire : 1 [[comment("DR3: Prot. from Fire")]]; + MU6_DeathSpell : 1 [[comment("MU6: Death Spell")]]; + MU6_Disintegrate : 1 [[comment("MU6: Disintegrate")]]; + MU6_GlobeOfInvulnerability : 1 [[comment("MU6: Globe of Invulnerability")]]; + MU6_StoneToFlesh : 1 [[comment("MU6: Stone to Flesh")]]; + MU6_FleshToStone : 1 [[comment("MU6: Flesh to Stone")]]; + MU7_DelayedBlastFireball : 1 [[comment("MU7: Delayed Blast Fireball")]]; + MU7_MassInvisibility : 1 [[comment("MU7: Mass Invisibility")]]; + MU7_PowerWordStun : 1 [[comment("MU7: Power Word Stun")]]; + MU5_FireTouch : 1 [[comment("MU5: Fire Touch")]]; + MU5_IronSkin : 1 [[comment("MU5: Iron Skin")]]; + MU8_MassCharm : 1 [[comment("MU8: Mass Charm")]]; + MU8_OttosIrrDance : 1 [[comment("MU8: Otto's Irr. Dance")]]; + MU8_MindBlank : 1 [[comment("MU8: Mind Blank")]]; + MU8_PowerWordBlind : 1 [[comment("MU8: Power Word Blind")]]; + MU9_MeteorSwarm : 1 [[comment("MU9: Meteor Swarm")]]; + MU9_PowerWordKill : 1 [[comment("MU9: Power Word Kill")]]; + MU9_MonsterSummoning : 1 [[comment("MU9: Monster Summoning")]]; + IT6_PotionOfSpeed : 1 [[comment("IT6: Potion of Speed")]]; + IT6_PotionOfGiantStrength : 1 [[comment("IT6: Potion of Giant Strength")]]; +}; + +// Spells Memorized +bitfield SPL_MEMORIZED { + match (GameID) { + (1): SPL_NAME01 MemorizedSpell : 7 [[name(std::format("{:02d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (2): SPL_NAME02 MemorizedSpell : 7 [[name(std::format("{:02d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (3): SPL_NAME03 MemorizedSpell : 7 [[name(std::format("{:03d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (4): SPL_NAME04 MemorizedSpell : 7 [[name(std::format("{:03d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (5): SPL_NAME05 MemorizedSpell : 7 [[name(std::format("{:02d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (6): SPL_NAME06 MemorizedSpell : 7 [[name(std::format("{:03d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (7): SPL_NAME07 MemorizedSpell : 7 [[name(std::format("{:03d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (8): SPL_NAME08 MemorizedSpell : 7 [[name(std::format("{:02d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (9): SPL_NAME09 MemorizedSpell : 7 [[name(std::format("{:03d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + (10): SPL_NAME10 MemorizedSpell : 7 [[name(std::format("{:03d}: MemorizedSpell", std::core::array_index())),comment("Spell currently memorized (available to cast) by the character")]]; + } + match (GameID) { + (8): bool IsCast : 1 [[name(std::format("{:02d}: IsCast", std::core::array_index())),comment("Indicates if spell has already been cast")]]; + (4|6|7|9|10): bool IsCast : 1 [[name(std::format("{:03d}: IsCast", std::core::array_index())),comment("Indicates if spell has already been cast")]]; + (_): padding : 1; + } +} [[inline]]; \ No newline at end of file diff --git a/patterns/GoldBox/GB_STRUCT_ITM.cs b/patterns/GoldBox/GB_STRUCT_ITM.cs new file mode 100644 index 00000000..fded8ed5 --- /dev/null +++ b/patterns/GoldBox/GB_STRUCT_ITM.cs @@ -0,0 +1,81 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Common Item Structs +#pragma once + +// Item Flags +bitfield ITEMFLAGARRAY { + HideNamePart1 : 1 [[comment("Indicates if NamePart1 is identified\ni.e. is displayed")]]; + HideNamePart2 : 1 [[comment("Indicates if NamePart2 is identified\ni.e. is displayed")]]; + HideNamePart3 : 1 [[comment("Indicates if NamePart3 is identified\ni.e. is displayed")]]; + match (GameID) { + (4|10): { + padding : 2; + Unknown_05 : 1 [[name("Unknown_05**"),comment(std::format("{}\nLikely error", GameID == 6 ? "Only set on invalid item" : "Only set on Dagger +4"))]]; + Unknown_06 : 1 [[name("Unknown_06**"),comment(std::format("{}\nLikely error", GameID == 6 ? "Only set on invalid item" : "Only set on Bolt +4"))]]; + } + (5|6|7): { + IsBlackRobe : 1 [[name(std::format("{}", GameID == 6 ? "IsBlackRobe**" : "IsBlackRobe*")),comment(std::format("{}", GameID == 6 ? "Only set on invalid item\nLikely error" : "Unused"))]]; + IsWhiteRobe : 1 [[comment("Indicates if item is Red Robe Mage only\nUsed by scrolls only")]]; + IsRedRobe : 1 [[comment("Indicates if item is Red Robe Mage only\nUsed by scrolls only")]]; + if (GameID == 7) { + Unknown_06 : 1 [[comment("Only set on Bolt +4\nLikely error")]]; + } + } + (8): { + padding : 3; + Unknown_06 : 1 [[comment("Set on some MON/NPC equipment and found/reward items like the Luskan pirate treasure (SwordOfIcewindDale/etc)\nUnknown purpose")]]; + } + } +}; + +// Item Detail struct +struct ITEM { +// Used in CHR/MON/STD/VLT: 1-3/5/8 - CHR/MON/VLT: 6 - CHR/VLT: 4/9 + if (RecordSize > 62) { + u8 DisplayName_Length [[comment("Number of characters in description field to read")]]; + char DisplayName[DisplayName_Length] [[comment("Display name for the item in the UI\nThese are only really valid in save item files as they're often incorrect/have errors in standard item/enemy files")]]; + padding[41 - DisplayName_Length]; + u32 ADDR_NextItem [[comment("Pointer to next item in file\n0x00000000 if last item")]]; + } +// Used in all + u8 BaseTypeID [[comment("Index of the base record for this item in the ITEMS file")]]; + u8 NamePart3 [[format("GetItemNamePart"),comment("String index for the 3rd part of item name\n0x00 if item does not have a 3rd part")]]; +// Get NamePart1 to check if Bundle of - is string index 77 in all games it's used in (3-4/7/9-10) + u8 NamePartID1 @ $ +1 [[hidden]]; +// NamePart2 is the original bundle quantity (Quantity is current) for Bundle of # Scrolls so direct convert value instead of lookup + u8 NamePart2 [[format(std::format("{}", HasBundle && NamePartID1 == 77 ? "std::string::to_string" : "GetItemNamePart")),comment("String index for the 2nd part of item name\n0x00 if item does not have a 2nd part")]]; + u8 NamePart1 [[format("GetItemNamePart"),comment("String index for the 1st part of item name\nThis should always have a value")]]; +// 7/10 varies column order (for some reason?) + match (GameID) { + (7|10): { + s16 Weight [[comment("The item's weight in coins")]]; + s16 Value [[comment("The item's monetary/resell value")]]; + s8 Bonus [[comment("+ or - to apply to AC/THAC0\nIs also used for XP value of magical treasure\n(XP = Bonus * 400)")]]; + s8 SaveBonus [[comment("The bonus to saves for magic armor/rings")]]; + bool IsEquipped [[comment("Indicates if item is equipped")]]; + ITEMFLAGARRAY ItemFlag [[comment("Flag array used primarily for setting which NamePart strings to display for items that need identified")]]; + bool IsCursed [[comment("Indicates if an item is cursed\ni.e. you can't unequip it")]]; + u8 Quantity [[comment("Total number of stacked items\nIf 0, there is 1 item and it cannot be stacked")]]; + } + (_): { + s8 Bonus [[comment("+ or - to apply to AC/THAC0\nIs also used for XP value of magical treasure\n(XP = Bonus * 400)")]]; + s8 SaveBonus [[comment("The bonus to saves for magic armor/rings")]]; + bool IsEquipped [[comment(std::format("Indicates if item is equipped{}", (GameID == 3 || GameID == 5 || GameID == 6 || GameID == 8) ? "\nSet to 0x80 (128) on some MON/NPC items\nUnknown usage" : ""))]]; + ITEMFLAGARRAY ItemFlag [[comment("Flag array used primarily for setting which NamePart strings to display for items that need identified")]]; + bool IsCursed [[comment("Indicates if an item is cursed\ni.e. you can't unequip it")]]; + s16 Weight [[comment("The item's weight in coins")]]; + u8 Quantity [[comment("Total number of stacked items\nIf 0, there is 1 item and it cannot be stacked")]]; + s16 Value [[comment("The item's monetary/resell value")]]; + } + } +// Could clean these up but think it would make editing a bit messy/confusing + u8 Property3 [[comment("Variable usage, depending on item type")]]; + u8 Property2 [[comment("Variable usage, depending on item type")]]; + u8 Property1 [[comment("Variable usage, depending on item type")]]; + match (RecordSize) { + // 10 only + (18): u8 Unknown_11 [[comment("Always 0x00")]]; + // 3 only + (67): u32 ADDR_NextSubItem [[comment("Pointer to next sub-item in file\nUsed for Bundles of # Scrolls")]]; + } +} [[name(std::format("{}: {}", FormatIndex(std::core::array_index(), ItemCount), GetDisplayName(NamePart1, NamePart2, NamePart3, Quantity)))]]; \ No newline at end of file diff --git a/patterns/GoldBox/GB_UTIL.cs b/patterns/GoldBox/GB_UTIL.cs new file mode 100644 index 00000000..18b83971 --- /dev/null +++ b/patterns/GoldBox/GB_UTIL.cs @@ -0,0 +1,97 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Common Functions + +// Formatting function for AC/THAC0 (RW) +fn FormatACTHAC0 (u8 Input) { + s8 Val = 60 - Input; + return Val; +}; + +// Formatting function for ICO_Body +fn FormatICOBody (u8 Input) { + u8 IconSize @ $ + 2; + return ((IconSize -1) * 64) + Input; +}; + +// Formatting function for ICO_Head (2 functions due to offset to ICO_Size) +fn FormatICOHead (u8 Input) { + u8 IconSize @ $ + 3; + return ((IconSize -1) * 64) + Input; +}; + +// Function to iterate through player character SFX records to get count - 7/10 only +fn GetSFXCount(u8 RecordLength) { + // Only called if SFX exists so start at 1 + u8 SFXCount = 1; + u8 NextEffectOffset = RecordLength == 10 ? 6 : 5; + +// Iterate from current offset to check NextEffect address - Should break before but sanity check on mem::size to ensure in bounds + for (u32 CurrentOffset = $, CurrentOffset <= (std::mem::size() - RecordLength), CurrentOffset = (CurrentOffset + RecordLength)) { + // Get NextEffect address + u32 ADDR_NextEffect @ CurrentOffset + NextEffectOffset; + // Break if 0 + if (ADDR_NextEffect == 0) { + break; + } + // Add to count if another effect exists + else { + SFXCount += 1; + } + } + return SFXCount; +}; + +// Color attribute function for ICO_COLOR.COLOR - returns RGB value of icon colors (unused 7/10) +fn IconColorValue(auto Input) { + if (Input == COLORNAME::DarkGray) { + return 0x555555; + } + if (Input == COLORNAME::Blue) { + return 0x0000AA; + } + if (Input == COLORNAME::Green) { + return 0x00AA00; + } + if (Input == COLORNAME::Cyan) { + return 0x00AAAA; + } + if (Input == COLORNAME::Red) { + return 0xAA0000; + } + if (Input == COLORNAME::Magenta) { + return 0xAA00AA; + } + if (Input == COLORNAME::Brown) { + return 0xAA5500; + } + if (Input == COLORNAME::LightGray) { + return 0xAAAAAA; + } + if (Input == COLORNAME::Black) { + return 0x000000; + } + if (Input == COLORNAME::BrightBlue) { + return 0x5555FF; + } + if (Input == COLORNAME::BrightGreen) { + return 0x55FF55; + } + if (Input == COLORNAME::BrightCyan) { + return 0x55FFFF; + } + if (Input == COLORNAME::BrightRed) { + return 0xFF5555; + } + if (Input == COLORNAME::BrightMagenta) { + return 0xFF55FF; + } + if (Input == COLORNAME::BrightYellow) { + return 0xFFFF55; + } + if (Input == COLORNAME::BrightWhite) { + return 0xFFFFFF; + } + else { + return 0x000000; + } +}; \ No newline at end of file diff --git a/patterns/GoldBox/GB_UTIL_ITM.cs b/patterns/GoldBox/GB_UTIL_ITM.cs new file mode 100644 index 00000000..9e6a234b --- /dev/null +++ b/patterns/GoldBox/GB_UTIL_ITM.cs @@ -0,0 +1,1898 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Common Item Functions +#pragma once + +// Item Name Part - 01 - Pool of Radiance +fn GetItemNamePart01(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Bardiche"; + (4): return "Bec de Corbin"; + (5): return "Bill-Guisarme"; + (6): return "Bo Stick"; + (7): return "Club"; + (8): return "Dagger"; + (9): return "Dart"; + (10): return "Fauchard"; + (11): return "Fauchard-Fork"; + (12): return "Flail"; + (13): return "Military Fork"; + (14): return "Glaive"; + (15): return "Glaive-Guisarme"; + (16): return "Guisarme"; + (17): return "Guisarme-Voulge"; + (18): return "Halberd"; + (19): return "Lucern Hammer"; + (20): return "Hammer"; + (21): return "Javelin"; + (22): return "Jo Stick"; + (23): return "Mace"; + (24): return "Morning Star"; + (25): return "Partisan"; + (26): return "Military Pick"; + (27): return "Awl Pike"; + (28): return "Quarrel"; + (29): return "Ranseur"; + (30): return "Scimitar"; + (31): return "Spear"; + (32): return "Spetum"; + (33): return "Quarter Staff"; + (34): return "Bastard Sword"; + (35): return "Broad Sword"; + (36): return "Long Sword"; + (37): return "Short Sword"; + (38): return "Two-Handed Sword"; + (39): return "Trident"; + (40): return "Voulge"; + (41): return "Composite Long Bow"; + (42): return "Composite Short Bow"; + (43): return "Long Bow"; + (44): return "Short Bow"; + (45): return "Heavy Crossbow"; + (46): return "Light Crossbow"; + (47): return "Sling"; + (48): return "Mail"; + (49): return "Armor"; + (50): return "Leather"; + (51): return "Padded"; + (52): return "Studded"; + (53): return "Ring"; + (54): return "Scale"; + (55): return "Chain"; + (56): return "Splint"; + (57): return "Banded"; + (58): return "Plate"; + (59): return "Shield"; + (60): return "Woods"; + (61): return "Arrow"; + (62): return "Invalid"; + (63): return "Invalid"; + (64): return "Potion"; + (65): return "Scroll"; + (66): return "Ring"; + (67): return "Rod"; + (68): return "Stave"; + (69): return "Wand"; + (70): return "Jug"; + (71): return "Amulet"; + (72): return "Apparatus"; + (73): return "Bag"; + (74): return "Beaker"; + (75): return "Boat"; + (76): return "Book"; + (77): return "Boots"; + (78): return "Bowl"; + (79): return "Bracers"; + (80): return "Brazier"; + (81): return "Brooch"; + (82): return "Broom"; + (83): return "Purse"; + (84): return "Candle"; + (85): return "Carpet"; + (86): return "Censer"; + (87): return "Chime"; + (88): return "Cloak"; + (89): return "Crystal"; + (90): return "Cube"; + (91): return "Cubic"; + (92): return "Fortress"; + (93): return "Decanter"; + (94): return "Deck"; + (95): return "Drums"; + (96): return "Dust"; + (97): return "Eyes"; + (98): return "Figurine"; + (99): return "Flask"; + (100): return "Gauntlets"; + (101): return "Gem"; + (102): return "Girdle"; + (103): return "Helm"; + (104): return "Horn"; + (105): return "Horseshoes"; + (106): return "Incense"; + (107): return "Stone"; + (108): return "Instrument"; + (109): return "Javelin"; + (110): return "Jewel"; + (111): return "Ointment"; + (112): return "Libram"; + (113): return "Lyre"; + (114): return "Manual"; + (115): return "Mattock"; + (116): return "Maul"; + (117): return "Medallion"; + (118): return "Mirror"; + (119): return "Necklace"; + (120): return "Net"; + (121): return "Pigment"; + (122): return "Pearl"; + (123): return "Periapt"; + (124): return "Phylactery"; + (125): return "Pipes"; + (126): return "Hole"; + (127): return "Token"; + (128): return "Robe"; + (129): return "Rope"; + (130): return "Rug"; + (131): return "Saw"; + (132): return "Scarab"; + (133): return "Spade"; + (134): return "Sphere"; + (135): return "Invalid"; + (136): return "Talisman"; + (137): return "Tome"; + (138): return "Trident"; + (139): return "Grimoire"; + (140): return "Well"; + (141): return "Wings"; + (142): return "Vial"; + (143): return "Lantern"; + (144): return "Invalid"; + (145): return "Oil"; + (146): return "10 ft. Pole"; + (147): return "50 ft. Rope"; + (148): return "Iron"; + (149): return "Thf Prickly Tools"; + (150): return "Iron Rations"; + (151): return "Standard Rations"; + (152): return "Holy Symbol"; + (153): return "Holy Water Vial"; + (154): return "Unholy Water Vial"; + (155): return "Barding"; + (156): return "Dragon"; + (157): return "Lightning"; + (158): return "Saddle"; + (159): return "Small Raft"; + (160): return "Cart"; + (161): return "Wagon"; + (162): return "+1"; + (163): return "+2"; + (164): return "+3"; + (165): return "+4"; + (166): return "+5"; + (167): return "of"; + (168): return "Invalid"; + (169): return "Cloak"; + (170): return "Displacement"; + (171): return "Torches"; + (172): return "Oil"; + (173): return "Speed"; + (174): return "Tapestry"; + (175): return "Bodily Health"; + (176): return "Copper"; + (177): return "Silver"; + (178): return "Electrum"; + (179): return "Gold"; + (180): return "Platinum"; + (181): return "Ointment"; + (182): return "Keoghtum's"; + (183): return "Sheet"; + (184): return "Strength"; + (185): return "Healing"; + (186): return "Holding"; + (187): return "Extra"; + (188): return "Gaseous Form"; + (189): return "Slipperiness"; + (190): return "Jewelled"; + (191): return "Flying"; + (192): return "Treasure Finding"; + (193): return "Fear"; + (194): return "Disappearance"; + (195): return "Statuette"; + (196): return "Fungus"; + (197): return "Chain"; + (198): return "Pendant"; + (199): return "Broach"; + (200): return "of Seeking"; + (201): return "-1"; + (202): return "-2"; + (203): return "-3"; + (204): return "Lightning Bolt"; + (205): return "Fire Resistance"; + (206): return "Magic Missiles"; + (207): return "Save"; + (208): return "Clerical Scroll"; + (209): return "Magic User Scroll"; + (210): return "with 1 Spell"; + (211): return "with 2 Spells"; + (212): return "with 3 Spells"; + (213): return "Protection Scroll"; + (214): return "Jewelry"; + (215): return "Fine"; + (216): return "Huge"; + (217): return "Bone"; + (218): return "Brass"; + (219): return "Key"; + (220): return "AC 2"; + (221): return "AC 6"; + (222): return "AC 4"; + (223): return "AC 3"; + (224): return "of Protection"; + (225): return "Paralyzation"; + (226): return "Ogre Power"; + (227): return "Invisibility"; + (228): return "Missiles"; + (229): return "Elvenkind"; + (230): return "Rotting"; + (231): return "Covered"; + (232): return "Efreeti"; + (233): return "Bottle"; + (234): return "Missile Attractor"; + (235): return "of Maglubiyet"; + (236): return "Secr Door & Trap Det"; + (237): return "Gd Dragon Control"; + (238): return "Feather Falling"; + (239): return "Giant Strength"; + (240): return "Restoring Level(s)"; + (241): return "Flame Tongue"; + (242): return "Fireballs"; + (243): return "Spiritual"; + (244): return "Boulder"; + (245): return "Diamond"; + (246): return "Emerald"; + (247): return "Opal"; + (248): return "Saphire"; + (249): return "of Tyr"; + (250): return "of Tempus"; + (251): return "of Sune"; + (252): return "Wooden"; + (253): return "+3 vs Undead"; + (254): return "Pass"; + (255): return "Cursed"; + } +}; + +// Item Name Part - 02 - Curse of the Azure Bonds +fn GetItemNamePart02(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Bardiche"; + (4): return "Bec de Corbin"; + (5): return "Bill-Guisarme"; + (6): return "Bo Stick"; + (7): return "Club"; + (8): return "Dagger"; + (9): return "Dart"; + (10): return "Fauchard"; + (11): return "Fauchard-Fork"; + (12): return "Flail"; + (13): return "Military Fork"; + (14): return "Glaive"; + (15): return "Glaive-Guisarme"; + (16): return "Guisarme"; + (17): return "Guisarme-Voulge"; + (18): return "Halberd"; + (19): return "Lucern Hammer"; + (20): return "Hammer"; + (21): return "Javelin"; + (22): return "Jo Stick"; + (23): return "Mace"; + (24): return "Morning Star"; + (25): return "Partisan"; + (26): return "Military Pick"; + (27): return "Awl Pike"; + (28): return "Quarrel"; + (29): return "Ranseur"; + (30): return "Scimitar"; + (31): return "Spear"; + (32): return "Spetum"; + (33): return "Quarter Staff"; + (34): return "Bastard Sword"; + (35): return "Broad Sword"; + (36): return "Long Sword"; + (37): return "Short Sword"; + (38): return "Two-Handed Sword"; + (39): return "Trident"; + (40): return "Voulge"; + (41): return "Composite Long Bow"; + (42): return "Composite Short Bow"; + (43): return "Long Bow"; + (44): return "Short Bow"; + (45): return "Heavy Crossbow"; + (46): return "Light Crossbow"; + (47): return "Sling"; + (48): return "Mail"; + (49): return "Armor"; + (50): return "Leather"; + (51): return "Padded"; + (52): return "Studded"; + (53): return "Ring"; + (54): return "Scale"; + (55): return "Chain"; + (56): return "Splint"; + (57): return "Banded"; + (58): return "Plate"; + (59): return "Shield"; + (60): return "Woods"; + (61): return "Arrow"; + (62): return "Invalid"; + (63): return "Invalid"; + (64): return "Potion"; + (65): return "Scroll"; + (66): return "Ring"; + (67): return "Rod"; + (68): return "Stave"; + (69): return "Wand"; + (70): return "Jug"; + (71): return "Amulet"; + (72): return "Dragon Breath"; + (73): return "Bag"; + (74): return "Defoliation"; + (75): return "Ice Storm"; + (76): return "Book"; + (77): return "Boots"; + (78): return "Hornets Nest"; + (79): return "Bracers"; + (80): return "Piercing"; + (81): return "Brooch"; + (82): return "Elfin Chain"; + (83): return "Wizardry"; + (84): return "AC10"; + (85): return "Dexterity"; + (86): return "Fumbling"; + (87): return "Chime"; + (88): return "Cloak"; + (89): return "Crystal"; + (90): return "Cube"; + (91): return "Cubic"; + (92): return "the Dwarves"; + (93): return "Decanter"; + (94): return "Gloves"; + (95): return "Drums"; + (96): return "Dust"; + (97): return "Thievery"; + (98): return "Hat"; + (99): return "Flask"; + (100): return "Gauntlets"; + (101): return "Gem"; + (102): return "Girdle"; + (103): return "Helm"; + (104): return "Horn"; + (105): return "Stupidity"; + (106): return "Incense"; + (107): return "Stone"; + (108): return "Ioun Stone"; + (109): return "Javelin"; + (110): return "Jewel"; + (111): return "Ointment"; + (112): return "Pale Blue"; + (113): return "Scarlet and"; + (114): return "Manual"; + (115): return "Incandescent"; + (116): return "Deep Red"; + (117): return "Pink"; + (118): return "Mirror"; + (119): return "Necklace"; + (120): return "and Green"; + (121): return "Blue"; + (122): return "Pearl"; + (123): return "Powerlessness"; + (124): return "Vermin"; + (125): return "Pipes"; + (126): return "Hole"; + (127): return "Dragon Slayer"; + (128): return "Robe"; + (129): return "Rope"; + (130): return "Frost Brand"; + (131): return "Berserker"; + (132): return "Scarab"; + (133): return "Spade"; + (134): return "Sphere"; + (135): return "Blessed"; + (136): return "Talisman"; + (137): return "Tome"; + (138): return "Trident"; + (139): return "Grimoire"; + (140): return "Well"; + (141): return "Wings"; + (142): return "Vial"; + (143): return "Lantern"; + (144): return "Invalid"; + (145): return "Flask of Oil"; + (146): return "10 ft. Pole"; + (147): return "50 ft. Rope"; + (148): return "Iron"; + (149): return "Thf Prickly Tools"; + (150): return "Iron Rations"; + (151): return "Standard Rations"; + (152): return "Holy Symbol"; + (153): return "Holy Water Vial"; + (154): return "Unholy Water Vial"; + (155): return "Barding"; + (156): return "Dragon"; + (157): return "Lightning"; + (158): return "Saddle"; + (159): return "Staff"; + (160): return "Drow"; + (161): return "Wagon"; + (162): return "+1"; + (163): return "+2"; + (164): return "+3"; + (165): return "+4"; + (166): return "+5"; + (167): return "of"; + (168): return "Vulnerability"; + (169): return "Cloak"; + (170): return "Displacement"; + (171): return "Torches"; + (172): return "Oil"; + (173): return "Speed"; + (174): return "Tapestry"; + (175): return "Spine"; + (176): return "Copper"; + (177): return "Silver"; + (178): return "Electrum"; + (179): return "Gold"; + (180): return "Platinum"; + (181): return "Ointment"; + (182): return "Keoghtum's"; + (183): return "Sheet"; + (184): return "Strength"; + (185): return "Healing"; + (186): return "Holding"; + (187): return "Extra"; + (188): return "Gaseous Form"; + (189): return "Slipperiness"; + (190): return "Jewelled"; + (191): return "Flying"; + (192): return "Treasure Finding"; + (193): return "Fear"; + (194): return "Disappearance"; + (195): return "Statuette"; + (196): return "Fungus"; + (197): return "Chain"; + (198): return "Pendant"; + (199): return "Broach"; + (200): return "of Seeking"; + (201): return "-1"; + (202): return "-2"; + (203): return "-3"; + (204): return "Lightning Bolt"; + (205): return "Fire Resistance"; + (206): return "Magic Missiles"; + (207): return "Save"; + (208): return "Clrc Scroll"; + (209): return "MU Scroll"; + (210): return "with 1 Spell"; + (211): return "with 2 Spells"; + (212): return "with 3 Spells"; + (213): return "Prot. Scroll"; + (214): return "Jewelry"; + (215): return "Fine"; + (216): return "Huge"; + (217): return "Bone"; + (218): return "Brass"; + (219): return "Key"; + (220): return "AC 2"; + (221): return "AC 6"; + (222): return "AC 4"; + (223): return "AC 3"; + (224): return "of Prot."; + (225): return "Paralyzation"; + (226): return "Ogre Power"; + (227): return "Invisibility"; + (228): return "Missiles"; + (229): return "Elvenkind"; + (230): return "Rotting"; + (231): return "Covered"; + (232): return "Efreeti"; + (233): return "Bottle"; + (234): return "Missile Attractor"; + (235): return "of Maglubiyet"; + (236): return "Secr Door & Trap Det"; + (237): return "Gd Dragon Control"; + (238): return "Feather Falling"; + (239): return "Giant Strength"; + (240): return "Restoring Level(s)"; + (241): return "Flame Tongue"; + (242): return "Fireballs"; + (243): return "Spiritual"; + (244): return "Boulder"; + (245): return "Diamond"; + (246): return "Emerald"; + (247): return "Opal"; + (248): return "Saphire"; + (249): return "of Tyr"; + (250): return "of Tempus"; + (251): return "of Sune"; + (252): return "Wooden"; + (253): return "+3 vs Undead"; + (254): return "Pass"; + (255): return "Cursed"; + } +}; + +// Item Name Part - 03 - Secret of the Silver Blades +fn GetItemNamePart03(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Club"; + (4): return "Dagger"; + (5): return "Dart"; + (6): return "Hammer"; + (7): return "Javelin"; + (8): return "Mace"; + (9): return "Morning Star"; + (10): return "Military Pick"; + (11): return "Awl Pike"; + (12): return "Quarrel"; + (13): return "Scimitar"; + (14): return "Spear"; + (15): return "Quarter Staff"; + (16): return "Bastard Sword"; + (17): return "Broad Sword"; + (18): return "Long Sword"; + (19): return "Short Sword"; + (20): return "Two-Handed Sword"; + (21): return "Trident"; + (22): return "Composite Long Bow"; + (23): return "Composite Short Bow"; + (24): return "Long Bow"; + (25): return "Short Bow"; + (26): return "Fine"; + (27): return "Light Crossbow"; + (28): return "Sling"; + (29): return "Staff"; + (30): return "Arrow"; + (31): return "Leather"; + (32): return "Ring"; + (33): return "Scale"; + (34): return "Chain"; + (35): return "Banded"; + (36): return "Plate"; + (37): return "Shield"; + (38): return "Cler"; + (39): return "Scroll"; + (40): return "Mage"; + (41): return "Helm"; + (42): return "Belt"; + (43): return "Robe"; + (44): return "Cloak"; + (45): return "Boots"; + (46): return "Ring"; + (47): return "Mail"; + (48): return "Armor"; + (49): return "of Prot"; + (50): return "Bracers"; + (51): return "Wand"; + (52): return "Elixer"; + (53): return "Potion"; + (54): return "Youth"; + (55): return "Ruby"; + (56): return "Boulder"; + (57): return "Dragon Breath"; + (58): return "Displacement"; + (59): return "Eyes"; + (60): return "Drow"; + (61): return "Elven Chain"; + (62): return "Ice Storm"; + (63): return "Saphire"; + (64): return "Emerald"; + (65): return "Wizardry"; + (66): return "Hornet's Nest"; + (67): return "Fire Resistance"; + (68): return "Stone"; + (69): return "Good Luck"; + (70): return "Flail"; + (71): return "Halberd"; + (72): return "Gauntlets"; + (73): return "Periapt"; + (74): return "Health"; + (75): return "Invalid"; + (76): return "Invalid"; + (77): return "Bundle of"; + (78): return "Ogre Power"; + (79): return "Girdle"; + (80): return "Giant Strength"; + (81): return "Mirror"; + (82): return "Necklace"; + (83): return "Dragon"; + (84): return "vs Giants"; + (85): return "Diamond"; + (86): return "Invalid"; + (87): return "Invalid"; + (88): return "Lightning"; + (89): return "Fireballs"; + (90): return "of"; + (91): return "Vulnerability"; + (92): return "Speed"; + (93): return "Silver"; + (94): return "Extra"; + (95): return "Healing"; + (96): return "Charming"; + (97): return "Fear"; + (98): return "Magic Missiles"; + (99): return "Missiles"; + (100): return "1 Spell"; + (101): return "2 Spells"; + (102): return "3 Spells"; + (103): return "Paralyzation"; + (104): return "Invisibility"; + (105): return "Cute Yellow Canary"; + (106): return "AC 10"; + (107): return "AC 6"; + (108): return "AC 4"; + (109): return "AC 3"; + (110): return "AC 2"; + (111): return "+1"; + (112): return "+2"; + (113): return "+3"; + (114): return "+4"; + (115): return "+5"; + (116): return "-1"; + (117): return "-2"; + (118): return "-3"; + (119): return "Spiritual"; + (120): return "Gem"; + (121): return "Jewelry"; + (_): return "Invalid"; + } +}; + +// Item Name Part - 04 - Pools of Darkness +fn GetItemNamePart04(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Club"; + (4): return "Dagger"; + (5): return "Dart"; + (6): return "Hammer"; + (7): return "Javelin"; + (8): return "Mace"; + (9): return "Morning Star"; + (10): return "Military Pick"; + (11): return "Awl Pike"; + (12): return "Bolt"; + (13): return "Scimitar"; + (14): return "Spear"; + (15): return "Quarter Staff"; + (16): return "Bastard Sword"; + (17): return "Broad Sword"; + (18): return "Long Sword"; + (19): return "Short Sword"; + (20): return "Two-Handed Sword"; + (21): return "Trident"; + (22): return "Composite Long Bow"; + (23): return "Composite Short Bow"; + (24): return "Long Bow"; + (25): return "Short Bow"; + (26): return "Fine"; + (27): return "Light Crossbow"; + (28): return "Sling"; + (29): return "Staff"; + (30): return "Arrow"; + (31): return "Leather"; + (32): return "Ring"; + (33): return "Scale"; + (34): return "Chain"; + (35): return "Banded"; + (36): return "Plate"; + (37): return "Shield"; + (38): return "Cleric"; + (39): return "Scroll"; + (40): return "Mage"; + (41): return "Helm"; + (42): return "Belt"; + (43): return "Robe"; + (44): return "Cloak"; + (45): return "Boots"; + (46): return "Ring"; + (47): return "Mail"; + (48): return "Armor"; + (49): return "of Prot"; + (50): return "Bracers"; + (51): return "Wand"; + (52): return "Elixir"; + (53): return "Potion"; + (54): return "Youth"; + (55): return "Ruby"; + (56): return "Boulder"; + (57): return "Dragon Breath"; + (58): return "Displacement"; + (59): return "Eyes"; + (60): return "Drow"; + (61): return "Elfin Chain"; + (62): return "Ice Storm"; + (63): return "Saphire"; + (64): return "Emerald"; + (65): return "Wizardry"; + (66): return "Hornet's Nest"; + (67): return "Fire Resistance"; + (68): return "Stone"; + (69): return "Good Luck"; + (70): return "Flail"; + (71): return "Halberd"; + (72): return "Gauntlets"; + (73): return "Periapt"; + (74): return "Health"; + (75): return "Cursed"; + (76): return "Blessed"; + (77): return "Bundle of"; + (78): return "Ogre Power"; + (79): return "Girdle"; + (80): return "Giant Strength"; + (81): return "Mirror"; + (82): return "Necklace"; + (83): return "Dragon"; + (84): return "vs Giants"; + (85): return "Vorpal"; + (86): return "Cold Resistance"; + (87): return "Diamond"; + (88): return "Lightning"; + (89): return "Fireballs"; + (90): return "of"; + (91): return "Vulnerability"; + (92): return "Speed"; + (93): return "Silver"; + (94): return "Extra"; + (95): return "Healing"; + (96): return "Charming"; + (97): return "Fear"; + (98): return "Magic Missiles"; + (99): return "Missiles"; + (100): return "1 Spell"; + (101): return "2 Spells"; + (102): return "3 Spells"; + (103): return "Paralyzation"; + (104): return "Invisibility"; + (105): return "Cute Yellow Canary"; + (106): return "AC 10"; + (107): return "AC 6"; + (108): return "AC 4"; + (109): return "AC 3"; + (110): return "AC 2"; + (111): return "+1"; + (112): return "+2"; + (113): return "+3"; + (114): return "+4"; + (115): return "+5"; + (116): return "-1"; + (117): return "-2"; + (118): return "-3"; + (119): return "Electrical Immunity"; + (120): return "Gaze Resistance"; + (121): return "Spiritual"; + (122): return "Gem"; + (123): return "Jewelry"; + (124): return "Blinking"; + (125): return "from Evil"; + (_): return "Invalid"; + } +}; + +// Item Name Part - 05 - Champions of Krynn +fn GetItemNamePart05(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Club"; + (4): return "Dagger"; + (5): return "Dart"; + (6): return "Hammer"; + (7): return "Javelin"; + (8): return "Mace"; + (9): return "Morning Star"; + (10): return "Military Pick"; + (11): return "Awl Pike"; + (12): return "Quarrel"; + (13): return "Scimitar"; + (14): return "Spear"; + (15): return "Quarter Staff"; + (16): return "Bastard Sword"; + (17): return "Broad Sword"; + (18): return "Long Sword"; + (19): return "Short Sword"; + (20): return "Two-Handed Sword"; + (21): return "Trident"; + (22): return "Composite Long Bow"; + (23): return "Composite Short Bow"; + (24): return "Long Bow"; + (25): return "Short Bow"; + (26): return "Fine"; + (27): return "Light Crossbow"; + (28): return "Sling"; + (29): return "Staff"; + (30): return "Arrow"; + (31): return "Leather"; + (32): return "Ring"; + (33): return "Scale"; + (34): return "Chain"; + (35): return "Banded"; + (36): return "Plate"; + (37): return "Shield"; + (38): return "Cler"; + (39): return "Scroll"; + (40): return "MU Scroll"; + (41): return "Helm"; + (42): return "Belt"; + (43): return "Robe"; + (44): return "Cloak"; + (45): return "Boots"; + (46): return "Ring"; + (47): return "Mail"; + (48): return "Armor"; + (49): return "of Prot"; + (50): return "Bracers"; + (51): return "Wand"; + (52): return "Amulet"; + (53): return "Potion"; + (54): return "Holy Water"; + (55): return "Ruby"; + (56): return "Boulder"; + (57): return "Dragon Breath"; + (58): return "Displacement"; + (59): return "Bag"; + (60): return "Drow"; + (61): return "Elven Chain"; + (62): return "Ice Storm"; + (63): return "Saphire"; + (64): return "Emerald"; + (65): return "Wizardry"; + (66): return "Hornet's Nest"; + (67): return "Hoopak"; + (68): return "Solamnic Plate"; + (69): return "Dragonlance"; + (70): return "Flail"; + (71): return "Halberd"; + (72): return "Gauntlets"; + (73): return "Periapt"; + (74): return "Proof vs Poison"; + (75): return "Dust"; + (76): return "Disappearance"; + (77): return "Disruption"; + (78): return "Ogre Power"; + (79): return "Girdle"; + (80): return "Giant Strength"; + (81): return "Mirror"; + (82): return "Necklace"; + (83): return "Dragon"; + (84): return "vs Reptiles"; + (85): return "Frost Brand"; + (86): return "Berserker"; + (87): return "Diamond"; + (88): return "Lightning"; + (89): return "Fireballs"; + (90): return "of"; + (91): return "Vulnerability"; + (92): return "Speed"; + (93): return "Silver"; + (94): return "Extra"; + (95): return "Healing"; + (96): return "Opening"; + (97): return "Fear"; + (98): return "Magic Missiles"; + (99): return "Missiles"; + (100): return "1 Spell"; + (101): return "2 Spells"; + (102): return "3 Spell"; + (103): return "Paralyzation"; + (104): return "Invisibility"; + (105): return "Footman's"; + (106): return "AC 10"; + (107): return "AC 6"; + (108): return "AC 4"; + (109): return "AC 3"; + (110): return "AC 2"; + (111): return "+1"; + (112): return "+2"; + (113): return "+3"; + (114): return "+4"; + (115): return "+5"; + (116): return "-1"; + (117): return "-2"; + (118): return "-3"; + (119): return "White"; + (120): return "Red"; + (121): return "Spiritual"; + (122): return "Gem"; + (123): return "Jewelry"; + (_): return "Invalid"; + } +}; + +// Item Name Part - 06 - Death Knights of Krynn +fn GetItemNamePart06(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Club"; + (4): return "Dagger"; + (5): return "Dart"; + (6): return "Hammer"; + (7): return "Javelin"; + (8): return "Mace"; + (9): return "Morning Star"; + (10): return "Military Pick"; + (11): return "Awl Pike"; + (12): return "Quarrel"; + (13): return "Scimitar"; + (14): return "Spear"; + (15): return "Quarter Staff"; + (16): return "Bastard Sword"; + (17): return "Broad Sword"; + (18): return "Long Sword"; + (19): return "Short Sword"; + (20): return "Two-Handed Sword"; + (21): return "Trident"; + (22): return "Composite Long Bow"; + (23): return "Composite Short Bow"; + (24): return "Long Bow"; + (25): return "Short Bow"; + (26): return "Fine"; + (27): return "Light Crossbow"; + (28): return "Sling"; + (29): return "Staff"; + (30): return "Arrow"; + (31): return "Leather"; + (32): return "Ring"; + (33): return "Scale"; + (34): return "Chain"; + (35): return "Banded"; + (36): return "Plate"; + (37): return "Shield"; + (38): return "Cler"; + (39): return "Scroll"; + (40): return "MU Scroll"; + (41): return "Helm"; + (42): return "Belt"; + (43): return "Robe"; + (44): return "Cloak"; + (45): return "Boots"; + (46): return "Ring"; + (47): return "Mail"; + (48): return "Armor"; + (49): return "of Prot"; + (50): return "Bracers"; + (51): return "Wand"; + (52): return "Amulet"; + (53): return "Potion"; + (54): return "Holy Water"; + (55): return "Ruby"; + (56): return "Boulder"; + (57): return "Dragon Breath"; + (58): return "Displacement"; + (59): return "Bag"; + (60): return "Drow"; + (61): return "Elven Chain"; + (62): return "Ice Storm"; + (63): return "Saphire"; + (64): return "Emerald"; + (65): return "Wizardry"; + (66): return "Hornet's Nest"; + (67): return "Hoopak"; + (68): return "Solamnic Plate"; + (69): return "Dragonlance"; + (70): return "Flail"; + (71): return "Halberd"; + (72): return "Gauntlets"; + (73): return "Periapt"; + (74): return "Proof vs Poison"; + (75): return "Elixir of Youth"; + (76): return "Eyes of Charming"; + (77): return "Disruption"; + (78): return "Ogre Power"; + (79): return "Girdle"; + (80): return "Giant Strength"; + (81): return "Mirror"; + (82): return "Necklace"; + (83): return "Dragon"; + (84): return "vs Reptiles"; + (85): return "Frost Brand"; + (86): return "Berserker"; + (87): return "Diamond"; + (88): return "Lightning"; + (89): return "Fireballs"; + (90): return "of"; + (91): return "Vulnerability"; + (92): return "Speed"; + (93): return "Silver"; + (94): return "Extra"; + (95): return "Healing"; + (96): return "Olin's"; + (97): return "Fear"; + (98): return "Magic Missiles"; + (99): return "Missiles"; + (100): return "1 Spell"; + (101): return "2 Spells"; + (102): return "3 Spell"; + (103): return "Paralyzation"; + (104): return "Invisibility"; + (105): return "Footman's"; + (106): return "AC 10"; + (107): return "AC 6"; + (108): return "AC 4"; + (109): return "AC 3"; + (110): return "AC 2"; + (111): return "+1"; + (112): return "+2"; + (113): return "+3"; + (114): return "+4"; + (115): return "+5"; + (116): return "-1"; + (117): return "-2"; + (118): return "-3"; + (119): return "White"; + (120): return "Red"; + (121): return "Spiritual"; + (122): return "Gem"; + (123): return "Jewelry"; + (124): return "Blank"; + (125): return "Item"; + (_): return "Invalid"; + } +}; + +// Item Name Part - 07 - The Dark Queen of Krynn +fn GetItemNamePart07(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Club"; + (4): return "Dagger"; + (5): return "Dart"; + (6): return "Hammer"; + (7): return "Javelin"; + (8): return "Mace"; + (9): return "Morning Star"; + (10): return "Military Pick"; + (11): return "Awl Pike"; + (12): return "Bolt"; + (13): return "Scimitar"; + (14): return "Spear"; + (15): return "Quarter Staff"; + (16): return "Bastard Sword"; + (17): return "Broad Sword"; + (18): return "Long Sword"; + (19): return "Short Sword"; + (20): return "Two-Handed Sword"; + (21): return "Trident"; + (22): return "Composite Long Bow"; + (23): return "Composite Short Bow"; + (24): return "Long Bow"; + (25): return "Short Bow"; + (26): return "Fine"; + (27): return "Light Crossbow"; + (28): return "Sling"; + (29): return "Staff"; + (30): return "Arrow"; + (31): return "Leather"; + (32): return "Ring"; + (33): return "Scale"; + (34): return "Chain"; + (35): return "Banded"; + (36): return "Plate"; + (37): return "Shield"; + (38): return "Cleric"; + (39): return "Scroll"; + (40): return "Mage"; + (41): return "Helm"; + (42): return "Belt"; + (43): return "Robe"; + (44): return "Cloak"; + (45): return "Boots"; + (46): return "Ring"; + (47): return "Mail"; + (48): return "Armor"; + (49): return "of Prot"; + (50): return "Bracers"; + (51): return "Wand"; + (52): return "Elixir"; + (53): return "Potion"; + (54): return "Youth"; + (55): return "Ruby"; + (56): return "Boulder"; + (57): return "Dragon Breath"; + (58): return "Displacement"; + (59): return "Eyes"; + (60): return "Drow"; + (61): return "Elfin Chain"; + (62): return "Ice Storm"; + (63): return "Saphire"; + (64): return "Emerald"; + (65): return "Wizardry"; + (66): return "Hornet's Nest"; + (67): return "Fire Resistance"; + (68): return "Stone"; + (69): return "Good Luck"; + (70): return "Flail"; + (71): return "Halberd"; + (72): return "Gauntlets"; + (73): return "Periapt"; + (74): return "Health"; + (75): return "Cursed"; + (76): return "Blessed"; + (77): return "Bundle of"; + (78): return "Ogre Power"; + (79): return "Girdle"; + (80): return "Giant Strength"; + (81): return "Mirror"; + (82): return "Necklace"; + (83): return "Dragon"; + (84): return "vs Giants"; + (85): return "Vorpal"; + (86): return "Cold Resistance"; + (87): return "Diamond"; + (88): return "Lightning"; + (89): return "Fireballs"; + (90): return "of"; + (91): return "Vulnerability"; + (92): return "Speed"; + (93): return "Silver"; + (94): return "Extra"; + (95): return "Healing"; + (96): return "Charming"; + (97): return "Fear"; + (98): return "Magic Missiles"; + (99): return "Missiles"; + (100): return "1 Spell"; + (101): return "2 Spells"; + (102): return "3 Spells"; + (103): return "Paralyzation"; + (104): return "Invisibility"; + (105): return "Cute Yellow Canary"; + (106): return "AC 10"; + (107): return "AC 6"; + (108): return "AC 4"; + (109): return "AC 3"; + (110): return "AC 2"; + (111): return "+1"; + (112): return "+2"; + (113): return "+3"; + (114): return "+4"; + (115): return "+5"; + (116): return "-1"; + (117): return "-2"; + (118): return "-3"; + (119): return "Electrical Immunity"; + (120): return "Gaze Resistance"; + (121): return "Spiritual"; + (122): return "Gem"; + (123): return "Blinking"; + (124): return "Invalid"; + (125): return "from Evil"; + (126): return "Hoopak"; + (127): return "Dragonlance"; + (128): return "Striking"; + (129): return "Disruption"; + (130): return "Dragon Slayer"; + (131): return "Foethumper"; + (132): return "Solamnic"; + (133): return "Petrification"; + (134): return "Free Action"; + (135): return "Footman's"; + (136): return "Red Mage"; + (137): return "White Mage"; + (138): return "Quarrel"; + (139): return "Cler"; + (140): return "MU Scroll"; + (141): return "Amulet"; + (142): return "Bag"; + (143): return "Solamnic Plate"; + (144): return "Proof vs Poison"; + (145): return "Elixir of Youth"; + (146): return "Eyes of Charming"; + (147): return "vs Reptiles"; + (148): return "Frost Brand"; + (149): return "Berserker"; + (150): return "Olin's"; + (151): return "Blank"; + (_): return "Invalid"; + } +}; + +// Item Name Part - 08 - Gateway to the Savage Frontier +fn GetItemNamePart08(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Bardiche"; + (4): return "Bec de Corbin"; + (5): return "Bill-Guisarme"; + (6): return "Bo Stick"; + (7): return "Club"; + (8): return "Dagger"; + (9): return "Dart"; + (10): return "Fauchard"; + (11): return "Fauchard-Fork"; + (12): return "Flail"; + (13): return "Military Fork"; + (14): return "Glaive"; + (15): return "Glaive-Guisarme"; + (16): return "Guisarme"; + (17): return "Guisarme-Voulge"; + (18): return "Halberd"; + (19): return "Lucern Hammer"; + (20): return "Hammer"; + (21): return "Javelin"; + (22): return "Jo Stick"; + (23): return "Mace"; + (24): return "Morning Star"; + (25): return "Partisan"; + (26): return "Military Pick"; + (27): return "Awl Pike"; + (28): return "Quarrel"; + (29): return "Ranseur"; + (30): return "Scimitar"; + (31): return "Spear"; + (32): return "Spetum"; + (33): return "Quarter Staff"; + (34): return "Bastard Sword"; + (35): return "Broad Sword"; + (36): return "Long Sword"; + (37): return "Short Sword"; + (38): return "Two-Handed Sword"; + (39): return "Trident"; + (40): return "Voulge"; + (41): return "Composite Long Bow"; + (42): return "Composite Short Bow"; + (43): return "Long Bow"; + (44): return "Short Bow"; + (45): return "Heavy Crossbow"; + (46): return "Light Crossbow"; + (47): return "Sling"; + (48): return "Mail"; + (49): return "Armor"; + (50): return "Leather"; + (51): return "Padded"; + (52): return "Studded"; + (53): return "Ring"; + (54): return "Scale"; + (55): return "Chain"; + (56): return "Splint"; + (57): return "Banded"; + (58): return "Plate"; + (59): return "Shield"; + (60): return "Woods"; + (61): return "Arrow"; + (62): return "Banite"; + (63): return "Robes"; + (64): return "Potion"; + (65): return "Scroll"; + (66): return "Ring"; + (67): return "Rod"; + (68): return "Stave"; + (69): return "Wand"; + (70): return "Jug"; + (71): return "Amulet"; + (72): return "Dragon Breath"; + (73): return "Bag"; + (74): return "Defoliation"; + (75): return "Ice Storm"; + (76): return "Book"; + (77): return "Boots"; + (78): return "Hornets Nest"; + (79): return "Bracers"; + (80): return "Piercing"; + (81): return "Brooch"; + (82): return "Elfin Chain"; + (83): return "Wizardry"; + (84): return "AC10"; + (85): return "Dexterity"; + (86): return "Fumbling"; + (87): return "Chime"; + (88): return "Cloak"; + (89): return "Crystal"; + (90): return "Cube"; + (91): return "Cubic"; + (92): return "Dwarven"; + (93): return "Decanter"; + (94): return "Gloves"; + (95): return "Drums"; + (96): return "Dust"; + (97): return "Thievery"; + (98): return "Hat"; + (99): return "Flask"; + (100): return "Gauntlets"; + (101): return "Gem"; + (102): return "Girdle"; + (103): return "Helm"; + (104): return "Horn"; + (105): return "Stupidity"; + (106): return "Incense"; + (107): return "Stone"; + (108): return "Ioun Stone"; + (109): return "Javelin"; + (110): return "Jewel"; + (111): return "Ointment"; + (112): return "Scrawled Note"; + (113): return "Scarlet and"; + (114): return "Manual"; + (115): return "Incandescent"; + (116): return "Deep Red"; + (117): return "Pink"; + (118): return "Mirror"; + (119): return "Necklace"; + (120): return "and Green"; + (121): return "Blue"; + (122): return "Pearl"; + (123): return "Powerlessness"; + (124): return "Vermin"; + (125): return "Pipes"; + (126): return "Hole"; + (127): return "Dragon Slayer"; + (128): return "Robe"; + (129): return "Rope"; + (130): return "Frost Brand"; + (131): return "Berserker"; + (132): return "Scarab"; + (133): return "Spade"; + (134): return "Sphere"; + (135): return "Blessed"; + (136): return "Talisman"; + (137): return "of the Glacier"; + (138): return "Trident"; + (139): return "Stunning"; + (140): return "Well"; + (141): return "Wings"; + (142): return "Vial"; + (143): return "Lantern"; + (144): return "of Icewind Dale"; + (145): return "Flask of Oil"; + (146): return "10 ft. Pole"; + (147): return "50 ft. Rope"; + (148): return "Iron"; + (149): return "Thf Prickly Tools"; + (150): return "Iron Rations"; + (151): return "Standard Rations"; + (152): return "Holy Symbol"; + (153): return "Holy Water Vial"; + (154): return "Unholy Water Vial"; + (155): return "Barding"; + (156): return "Dragon"; + (157): return "Lightning"; + (158): return "Saddle"; + (159): return "Staff"; + (160): return "Drow"; + (161): return "Wagon"; + (162): return "+1"; + (163): return "+2"; + (164): return "+3"; + (165): return "+4"; + (166): return "+5"; + (167): return "of"; + (168): return "Vulnerability"; + (169): return "Cloak"; + (170): return "Displacement"; + (171): return "Torches"; + (172): return "Oil"; + (173): return "Speed"; + (174): return "Tapestry"; + (175): return "Spine"; + (176): return "Copper"; + (177): return "Silver"; + (178): return "Electrum"; + (179): return "Gold"; + (180): return "Platinum"; + (181): return "Ointment"; + (182): return "Button"; + (183): return "Sheet"; + (184): return "Strength"; + (185): return "Healing"; + (186): return "Holding"; + (187): return "Extra"; + (188): return "Gaseous Form"; + (189): return "Slipperiness"; + (190): return "Jewelled"; + (191): return "Flying"; + (192): return "Treasure Finding"; + (193): return "Fear"; + (194): return "Disappearance"; + (195): return "Statuette"; + (196): return "Fungus"; + (197): return "Chain"; + (198): return "Pendant"; + (199): return "Broach"; + (200): return "of Striking"; + (201): return "-1"; + (202): return "-2"; + (203): return "-3"; + (204): return "Lightning Bolt"; + (205): return "Fire Resistance"; + (206): return "Magic Missiles"; + (207): return "Save"; + (208): return "Clrc Scroll"; + (209): return "MU Scroll"; + (210): return "with 1 Spell"; + (211): return "with 2 Spells"; + (212): return "with 3 Spells"; + (213): return "Prot. Scroll"; + (214): return "Jewelry"; + (215): return "Fine"; + (216): return "Huge"; + (217): return "Bone"; + (218): return "Brass"; + (219): return "Key"; + (220): return "AC 2"; + (221): return "AC 6"; + (222): return "AC 4"; + (223): return "AC 3"; + (224): return "of Prot."; + (225): return "Paralyzation"; + (226): return "Map"; + (227): return "Invisibility"; + (228): return "Missiles"; + (229): return "Elven"; + (230): return "Rotting"; + (231): return "Covered"; + (232): return "Efreeti"; + (233): return "Bottle"; + (234): return "Missile Attractor"; + (235): return "Letter"; + (236): return "Secr Door & Trap Det"; + (237): return "with Squid Emblem"; + (238): return "Feather Falling"; + (239): return "Giant Strength"; + (240): return "Restoring Level(s)"; + (241): return "Flame Tongue"; + (242): return "Fireballs"; + (243): return "Spiritual"; + (244): return "Boulder"; + (245): return "Diamond"; + (246): return "Emerald"; + (247): return "Opal"; + (248): return "Saphire"; + (249): return "Sword"; + (250): return "of Stonecutting"; + (251): return "Meteorite Ore"; + (252): return "Wooden"; + (253): return "+2 vs Undead"; + (254): return "Pass"; + (255): return "Cursed"; + } +}; + +// Item Name Part - 09 - Treasures of the Savage Frontier +fn GetItemNamePart09(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Club"; + (4): return "Dagger"; + (5): return "Dart"; + (6): return "Hammer"; + (7): return "Javelin"; + (8): return "Mace"; + (9): return "Morning Star"; + (10): return "Military Pick"; + (11): return "Awl Pike"; + (12): return "Bolt"; + (13): return "Scimitar"; + (14): return "Spear"; + (15): return "Quarter Staff"; + (16): return "Bastard Sword"; + (17): return "Broad Sword"; + (18): return "Long Sword"; + (19): return "Short Sword"; + (20): return "Two-Handed Sword"; + (21): return "Trident"; + (22): return "Composite Long Bow"; + (23): return "Composite Short Bow"; + (24): return "Long Bow"; + (25): return "Short Bow"; + (26): return "Fine"; + (27): return "Light Crossbow"; + (28): return "Sling"; + (29): return "Staff"; + (30): return "Arrow"; + (31): return "Leather"; + (32): return "Ring"; + (33): return "Scale"; + (34): return "Chain"; + (35): return "Banded"; + (36): return "Plate"; + (37): return "Shield"; + (38): return "Cleric"; + (39): return "Scroll"; + (40): return "Mage"; + (41): return "Helm"; + (42): return "Belt"; + (43): return "Robe"; + (44): return "Cloak"; + (45): return "Boots"; + (46): return "Ring"; + (47): return "Mail"; + (48): return "Armor"; + (49): return "of Prot."; + (50): return "Bracers"; + (51): return "Wand"; + (52): return "Elixir"; + (53): return "Potion"; + (54): return "Youth"; + (55): return "Ruby"; + (56): return "Boulder"; + (57): return "Dragon Breath"; + (58): return "Displacement"; + (59): return "Eyes"; + (60): return "Drow"; + (61): return "Elfin Chain"; + (62): return "Ice Storm"; + (63): return "Saphire"; + (64): return "Emerald"; + (65): return "Wizardry"; + (66): return "Hornet's Nest"; + (67): return "Fire Resistance"; + (68): return "Stone"; + (69): return "Good Luck"; + (70): return "Flail"; + (71): return "Halberd"; + (72): return "Gauntlets"; + (73): return "Periapt"; + (74): return "Health"; + (75): return "Cursed"; + (76): return "Blessed"; + (77): return "Bundle of"; + (78): return "Ogre Power"; + (79): return "Girdle"; + (80): return "Giant Strength"; + (81): return "Mirror"; + (82): return "Necklace"; + (83): return "Dragon"; + (84): return "vs Giants"; + (85): return "Vorpal"; + (86): return "Cold Resistance"; + (87): return "Diamond"; + (88): return "Lightning"; + (89): return "Fireballs"; + (90): return "of"; + (91): return "Vulnerability"; + (92): return "Speed"; + (93): return "Silver"; + (94): return "Extra"; + (95): return "Healing"; + (96): return "Charming"; + (97): return "Fear"; + (98): return "Magic Missiles"; + (99): return "Missiles"; + (100): return "1 Spell"; + (101): return "2 Spells"; + (102): return "3 Spells"; + (103): return "Paralyzation"; + (104): return "Invisibility"; + (105): return "Cute Yellow Canary"; + (106): return "AC 10"; + (107): return "AC 6"; + (108): return "AC 4"; + (109): return "AC 3"; + (110): return "AC 2"; + (111): return "+1"; + (112): return "+2"; + (113): return "+3"; + (114): return "+4"; + (115): return "Broken"; + (116): return "-1"; + (117): return "-2"; + (118): return "-3"; + (119): return "Electrical Immunity"; + (120): return "Gaze Resistance"; + (121): return "Spiritual"; + (122): return "Gem"; + (123): return "Jewelry"; + (124): return "Blinking"; + (125): return "from Evil"; + (126): return "Lucky Paper"; + (127): return "of Icewind Dale"; + (128): return "of the Glacier"; + (129): return "of Stonecutting"; + (130): return "of Defoliation"; + (131): return "Sword"; + (132): return "Splint"; + (133): return "Leilon"; + (134): return "Waterdeep"; + (135): return "Mintarn"; + (136): return "Orlumbor"; + (137): return "Daggerford"; + (138): return "Neverwinter"; + (139): return "Yartar"; + (140): return "Longsaddle"; + (141): return "Ruathym"; + (142): return "Luskan"; + (143): return "Mirabar"; + (144): return "Real"; + (145): return "Authentic"; + (146): return "Battle-used"; + (147): return "Large"; + (148): return "Farrberjik"; + (149): return "Furry"; + (150): return "Black Crystal"; + (151): return "Certificate"; + (152): return "Golden"; + (153): return "Bloodaxe"; + (154): return "Redshield"; + (155): return "Shearhammer"; + (156): return "Northhelm"; + (157): return "Tyrant's Trident"; + (158): return "of Stalking"; + (159): return "Squid Shield"; + (160): return "Redflame Armor"; + (161): return "Seahelm"; + (162): return "Map"; + (163): return "Spell Enhancing"; + (164): return "Striking"; + (165): return "Rod"; + (166): return "Stone to Flesh"; + (167): return "Lined"; + (168): return "Firepot"; + (169): return "Flask"; + (170): return "Kraken"; + (171): return "the"; + (172): return "Cold"; + (173): return "Firedock"; + (174): return "Treasure"; + (175): return "Oil"; + (176): return "Cold"; + (177): return "MU Scroll"; + (178): return "Normalcy"; + (179): return "Farms"; + (180): return "High Captains"; + (181): return "Tunnels"; + (_): return "Invalid"; + } +}; +// Item Name Part - 10 - Unlimited Adventures +fn GetItemNamePart10(u8 Input) { + match(Input) { + (0): return ""; + (1): return "Battle Axe"; + (2): return "Hand Axe"; + (3): return "Club"; + (4): return "Dagger"; + (5): return "Dart"; + (6): return "Hammer"; + (7): return "Javelin"; + (8): return "Mace"; + (9): return "Morning Star"; + (10): return "Military Pick"; + (11): return "Awl Pike"; + (12): return "Bolt"; + (13): return "Scimitar"; + (14): return "Spear"; + (15): return "Quarter Staff"; + (16): return "Bastard Sword"; + (17): return "Broad Sword"; + (18): return "Long Sword"; + (19): return "Short Sword"; + (20): return "Two-Handed Sword"; + (21): return "Trident"; + (22): return "Composite Long Bow"; + (23): return "Composite Short Bow"; + (24): return "Long Bow"; + (25): return "Short Bow"; + (26): return "Fine"; + (27): return "Light Crossbow"; + (28): return "Sling"; + (29): return "Staff"; + (30): return "Arrow"; + (31): return "Leather"; + (32): return "Ring"; + (33): return "Scale"; + (34): return "Chain"; + (35): return "Banded"; + (36): return "Plate"; + (37): return "Shield"; + (38): return "Cleric"; + (39): return "Scroll"; + (40): return "Mage"; + (41): return "Helm"; + (42): return "Belt"; + (43): return "Robe"; + (44): return "Cloak"; + (45): return "Boots"; + (46): return "Ring"; + (47): return "Mail"; + (48): return "Armor"; + (49): return "of Prot"; + (50): return "Bracers"; + (51): return "Wand"; + (52): return "Elixir"; + (53): return "Potion"; + (54): return "Youth"; + (55): return "Ruby"; + (56): return "Boulder"; + (57): return "Dragon Breath"; + (58): return "Displacement"; + (59): return "Eyes"; + (60): return "Drow"; + (61): return "Elfin Chain"; + (62): return "Ice Storm"; + (63): return "Sapphire"; + (64): return "Emerald"; + (65): return "Wizardry"; + (66): return "Hornet's Nest"; + (67): return "Fire Resistance"; + (68): return "Stone"; + (69): return "Good Luck"; + (70): return "Flail"; + (71): return "Halberd"; + (72): return "Gauntlets"; + (73): return "Periapt"; + (74): return "Health"; + (75): return "Cursed"; + (76): return "Blessed"; + (77): return "Bundle of"; + (78): return "Ogre Power"; + (79): return "Girdle"; + (80): return "Giant Strength"; + (81): return "Mirror"; + (82): return "Necklace"; + (83): return "Dragon"; + (84): return "vs Giants"; + (85): return "Vorpal"; + (86): return "Cold Resistance"; + (87): return "Diamond"; + (88): return "Lightning"; + (89): return "Fireballs"; + (90): return "of"; + (91): return "Vulnerability"; + (92): return "Speed"; + (93): return "Silver"; + (94): return "Extra"; + (95): return "Healing"; + (96): return "Charming"; + (97): return "Fear"; + (98): return "Magic Missiles"; + (99): return "Missiles"; + (100): return "1 Spell"; + (101): return "2 Spells"; + (102): return "3 Spells"; + (103): return "Paralyzation"; + (104): return "Invisibility"; + (105): return "Cute Yellow Canary"; + (106): return "AC 10"; + (107): return "AC 6"; + (108): return "AC 4"; + (109): return "AC 3"; + (110): return "AC 2"; + (111): return "+1"; + (112): return "+2"; + (113): return "+3"; + (114): return "+4"; + (115): return "+5"; + (116): return "-1"; + (117): return "-2"; + (118): return "-3"; + (119): return "Electric Immunity"; + (120): return "Gaze Resistance"; + (121): return "Spiritual"; + (122): return "Gem"; + (123): return "Jewelry"; + (124): return "Blinking"; + (125): return "from Evil"; + (_): return "Invalid"; + } +}; + +// Function to simplify calling the GetItemNamePart## functions in GetDisplayName function/ITEM struct +fn GetItemNamePart (u8 Input) { + if (GameID == 1) { + return GetItemNamePart01(Input); + } + if (GameID == 2) { + return GetItemNamePart02(Input); + } + if (GameID == 3) { + return GetItemNamePart03(Input); + } + if (GameID == 4) { + return GetItemNamePart04(Input); + } + if (GameID == 5) { + return GetItemNamePart05(Input); + } + if (GameID == 6) { + return GetItemNamePart06(Input); + } + if (GameID == 7) { + return GetItemNamePart07(Input); + } + if (GameID == 8) { + return GetItemNamePart08(Input); + } + if (GameID == 9) { + return GetItemNamePart09(Input); + } + if (GameID == 10) { + return GetItemNamePart10(Input); + } +}; + +// Function to 0 pad array index in Item display names because of OCD +fn FormatIndex(u8 IndexID, u8 ItemCount) { + if (ItemCount < 10) { + return std::string::to_string(IndexID); + } + else if (ItemCount < 100) { + return std::format("{:02d}", IndexID); + } + else { + return std::format("{:03d}", IndexID); + } +}; + +// Helper function used in GetDisplayName to identify if a string is a word to be made plural (i.e. add "s") for stacked items +fn IsPluralWord(str Input) { + str NamePart = std::string::to_lower(Input); + if (NamePart == "arrow" || NamePart == "bolt" || NamePart == "boulder" || NamePart == "chain" || NamePart == "dart" || NamePart == "javelin" || NamePart == "lucky paper" || NamePart == "quarrel") { + return true; + } + return false; +}; + +// Function to build Item display names from name parts +fn GetDisplayName(u8 NamePartID1, u8 NamePartID2, u8 NamePartID3, u8 Quantity) { + str Prefix = ""; + str NamePart1 = GetItemNamePart(NamePartID1); + str NamePart2 = std::format("{}{}", NamePartID1 > 0 ? " " : "", GetItemNamePart(NamePartID2)); + str NamePart3 = std::format("{}{}", (NamePartID1 > 0 || NamePartID2 > 0) ? " " : "", GetItemNamePart(NamePartID3)); + +// Prefix Quantity except for Scroll Bundles which is handled separately - Hoopak in 7 has Quantity set erroneously to 1 + if (Quantity > 0 && NamePart1 != "Bundle of" && NamePart1 != "Hoopak") { + Prefix = std::string::to_string(Quantity) + " "; + } +// Make plural if Quantity > 1 + if (Quantity > 1 && NamePart1 != "Bundle of" && NamePart1 != "Hoopak") { + // Get the last character of each word, need to do multiple checks so better to grab once as variables + str LastChar1 = std::string::substr(NamePart1, std::string::length(NamePart1) - 1, 1); + str LastChar2 = NamePartID2 == 0 ? "" : std::string::substr(NamePart2, std::string::length(NamePart2) - 1, 1); + str LastChar3 = NamePartID3 == 0 ? "" : std::string::substr(NamePart3, std::string::length(NamePart3) - 1, 1); + + // Pick word to plurize + if (LastChar1 != "s" && !(LastChar1 >= "0" && LastChar1 <= "9") && NamePart1 != "Tapestry" && ((NamePartID2 == 0 && NamePartID3 == 0) || IsPluralWord(NamePart1))) { + NamePart1 = NamePart1 + "s"; + } + else if (NamePartID2 > 0) { + if (LastChar2 != "s" && !(LastChar2 >= "0" && LastChar2 <= "9") && NamePart2 != "Tapestry" && NamePartID3 == 0 && !IsPluralWord(NamePart1)) { + NamePart2 = NamePart2 + "s"; + } + } + else if (NamePartID3 > 0) { + if (LastChar3 != "s" && !(LastChar3 >= "0" && LastChar3 <= "9") && NamePart3 != "Tapestry" && !IsPluralWord(NamePart1)) { + NamePart3 = NamePart3 + "s"; + } + } + } +// Bundle of # Scrolls handling + if (NamePart1 == "Bundle of") { + NamePart1 = "Bundle of " + std::string::to_string(Quantity); + // This is the original bundle quantity, not a string index, so clear value + NamePart2 = ""; + // Tack on plural "s" if Quantity > 1 + if (Quantity > 1 && !std::string::ends_with(NamePart3, "s")) { + NamePart3 = NamePart3 + "s"; + } + } + + return std::format("{}{}{}{}", Prefix, NamePart1, NamePart2, NamePart3); +}; \ No newline at end of file diff --git a/patterns/GoldBox/GB_VLT.hexpat b/patterns/GoldBox/GB_VLT.hexpat new file mode 100644 index 00000000..11e2fdb5 --- /dev/null +++ b/patterns/GoldBox/GB_VLT.hexpat @@ -0,0 +1,105 @@ +#pragma author Draxinusom +#pragma description Gold Box Games - Vault +#include +#include +import std.core; +import std.string; + +/********** + This is intended to allow looking up and/or modifying the vault files + for all Gold Box games that have them (D&D, no one cares about Buck Rogers) + + Supported Games: + 03 - Secret of the Silver Blades (VAULT.DAT) + 04 - Pools of Darkness (VAULT[A-J].DAT) + 06 - Death Knights of Krynn (VAULT[A-J].DAT) + 07 - The Dark Queen of Krynn (VAULT[A-J].DAT) + 08 - Gateway to the Savage Frontier (VAULT.[A-J]) + 09 - Treasures of the Savage Frontier (VAULT[A-J].DAT) + 10 - Unlimited Adventures (VAULT[A-J].DAT) + + Unsupported Games: + 01 - Pool of Radiance + 02 - Curse of the Azure Bonds + 05 - Champions of Krynn + + The GameID variable below must be set for to the number in the list of + supported games above for the source game +**********/ +u8 GameID = 0; + +u32 FileSize = std::mem::size(); +u8 RecordSize = 0; +u8 ItemCount = 0; +u32 Offset = 0; + +// Check GameID is set +if (GameID == 0) { + std::warning("Please set the GameID variable to the source game's number."); + return; +} + +// Ensure GameID is in range +if (GameID > 10) { + std::warning("Invalid GameID. Aborting."); + return; +} +// Ensure specified game _has_ a Vault +if (GameID < 3 || GameID == 5) { + std::warning("Specified GameID for game that does not have a vault. Aborting."); + return; +} + +// Get RecordSize +if (GameID == 7 || GameID == 10) { + RecordSize = GameID == 7 ? 17 : 18; + u8 RecordCount @ 0x0E; + ItemCount = RecordCount; + Offset = 0x0E; +} +else { + RecordSize = GameID == 3 ? 67 : 63; + Offset = (GameID == 3 || GameID == 8) ? 0x1C : 0x0C; + ItemCount = (FileSize - Offset) / RecordSize; +} + +// Check file is likely a vault file +if (GameID == 7 || GameID == 10) { + if (FileSize != (GameID == 7 ? 866 : 916)) { + std::warning("File is not a valid vault file or incorrect GameID specified.\nAborting."); + return; + } +} +else if (Offset + (ItemCount * RecordSize) != FileSize) { + std::warning("File is not a valid vault file or incorrect GameID specified.\nAborting."); + return; +} + +// Flag if game uses steel instead of platinum (Krynn games) +bool IsSteel = (GameID == 6 || GameID == 7); +// Flag if game has Bundle of # Scrolls item +bool HasBundle = (GameID == 3 || GameID == 4 || GameID == 7 || GameID == 9 || GameID == 10) ? true : false; + +// Money +struct MONEY { + if (GameID == 3 || GameID == 8) { + s32 MNY_Copper [[name("Copper (CP)"),comment("Copper coins (CP) stored in the vault")]]; + s32 MNY_Silver [[name("Silver (SP)"),comment("Silver coins (SP) stored in the vault")]]; + s32 MNY_Electrum [[name("Electrum (EP)"),comment("Electrum coins (EP) stored in the vault")]]; + s32 MNY_Gold [[name("Gold (GP)"),comment("Gold coins (GP) stored in the vault")]]; + } + s32 MNY_SteelPlatinum [[name(std::format("{}", IsSteel ? "Steel (SP)" : "Platinum (PP)")),comment(std::format("{} coins ({}P) stored in the vault", IsSteel ? "Steel" : "Platinum", IsSteel ? "S" : "P"))]]; + s32 MNY_Gem [[name("Gems"),comment("Unappraised gems stored in the vault")]]; + s32 MNY_Jewelry [[name("Jewelry"),comment("Unappraised jewelry stored in the vault")]]; +} [[comment("Money stored in the vault")]]; + +// Wrapper struct for ITEM used to help make returning NumberOfItems (7/10) dynamic +struct ITEMVAULT { + if (GameID == 7 || GameID == 10) { + u16 NumberOfItems [[name("Number of items"),comment("Number of items stored in the vault\nUpdate this number to match new count if adding/removing items")]]; + } + ITEM Item[ItemCount] [[inline]]; +}; + +MONEY Money @ 0x00; +ITEMVAULT Item @ Offset [[comment("Items stored in the vault")]]; \ No newline at end of file diff --git a/tests/patterns/test_data/GB_CHR.hexpat.qsv b/tests/patterns/test_data/GB_CHR.hexpat.qsv new file mode 100644 index 00000000..68d45751 Binary files /dev/null and b/tests/patterns/test_data/GB_CHR.hexpat.qsv differ