// Latest version should always be at top of file so it is default! state("Ato", "1.1.7.0") { int room : 0x00D452D4; double gameTimer : 0x00B35220, 0x48, 0x10, 0x6A20, 0xE0; double difficulty : 0x00B35220, 0x48, 0x10, 0x6A20, 0x150; double fileCreated : 0x00B35220, 0x48, 0x10, 0x6A20, 0x1E0; double phase : 0x00B35220, 0x48, 0x10, 0x6A20, 0xD0; double orb1 : 0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x00; double orb2 :0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x10; double orb3 : 0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x20; double win : 0x00B35220, 0x48, 0x10, 0x6A20, 0x70, 0x90, 0x200; double bossrush : 0x00B35220, 0x48, 0x10, 0x5660, 0x00; double grasscut : 0x00B35220, 0x48, 0x10, 0x6A20, 0x40; double talismans :0x00B35220, 0x48, 0x10, 0x6A20, 0x170; double maxMP : 0x00B35220, 0x48, 0x10, 0x6A20, 0x180; double coinCount : 0x00B35220, 0x48, 0x10, 0x6A20, 0x1C0; } state("Ato", "1.1.6.0") { int room : 0x00D452D4; double gameTimer : 0x00B35220, 0x48, 0x10, 0x6A20, 0xE0; double difficulty : 0x00B35220, 0x48, 0x10, 0x6A20, 0x150; double fileCreated : 0x00B35220, 0x48, 0x10, 0x6A20, 0x1E0; double phase : 0x00B35220, 0x48, 0x10, 0x6A20, 0xD0; double orb1 : 0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x00; double orb2 :0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x10; double orb3 : 0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x20; double win : 0x00B35220, 0x48, 0x10, 0x6A20, 0x70, 0x90, 0x200; double bossrush : 0x00B35220, 0x48, 0x10, 0x5660, 0x00; double grasscut : 0x00B35220, 0x48, 0x10, 0x6A20, 0x40; double talismans :0x00B35220, 0x48, 0x10, 0x6A20, 0x170; double maxMP : 0x00B35220, 0x48, 0x10, 0x6A20, 0x180; double coinCount : 0x00B35220, 0x48, 0x10, 0x6A20, 0x1C0; } state("Ato", "1.1.5.0") { int room : 0x00D452D4; double gameTimer : 0x00B35220, 0x48, 0x10, 0x6A20, 0xE0; double difficulty : 0x00B35220, 0x48, 0x10, 0x6A20, 0x150; double fileCreated : 0x00B35220, 0x48, 0x10, 0x6A20, 0x1E0; double phase : 0x00B35220, 0x48, 0x10, 0x6A20, 0xD0; double orb1 : 0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x00; double orb2 :0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x10; double orb3 : 0x00B35220, 0x48, 0x10, 0x6A20, 0x100, 0x90, 0x20; double win : 0x00B35220, 0x48, 0x10, 0x6A20, 0x70, 0x90, 0x200; double bossrush : 0x00B35220, 0x48, 0x10, 0x5670, 0x00; double grasscut : 0x00B35220, 0x48, 0x10, 0x6A20, 0x40; double talismans :0x00B35220, 0x48, 0x10, 0x6A20, 0x170; double maxMP : 0x00B35220, 0x48, 0x10, 0x6A20, 0x180; double coinCount : 0x00B35220, 0x48, 0x10, 0x6A20, 0x1C0; } state("Ato", "1.1.4.0") { int room : 0x0088E0C8; double gameTimer : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0xE0; double difficulty : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0x150; double fileCreated : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0x1E0; double phase : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0xD0; double orb1 : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0x100, 0x90, 0x00; double orb2 :0x0067D5B0, 0x48, 0x10, 0x52C0, 0x100, 0x90, 0x10; double orb3 : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0x100, 0x90, 0x20; double win : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0x70, 0x90, 0x200; double bossrush : 0x0067D5B0, 0x48, 0x10, 0x3F10, 0x00; double grasscut : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0x40; double talismans :0x0067D5B0, 0x48, 0x10, 0x52C0, 0x170; double maxMP : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0x180; double coinCount : 0x0067D5B0, 0x48, 0x10, 0x52C0, 0x1C0; } state("Ato", "1.1.3.0") { int room : 0x006F9C30; double gameTimer : 0x00707918, 0x30, 0x84C, 0x190; double difficulty : 0x00707918, 0x30, 0x84C, 0x200; double fileCreated : 0x00707918, 0x30, 0x84C, 0x290; double phase : 0x00707918, 0x30, 0x84C, 0x180; double orb1 : 0x00707918, 0x30, 0x84C, 0x1B0, 0x64, 0x00; double orb2 : 0x00707918, 0x30, 0x84C, 0x1B0, 0x64, 0x10; double orb3 : 0x00707918, 0x30, 0x84C, 0x1B0, 0x64, 0x20; double win : 0x00707918, 0x30, 0x84C, 0x120, 0x64, 0x200; double bossrush : 0x00707918, 0x30, 0x8C4, 0x10; double grasscut : 0x00707918, 0x30, 0x84C, 0xF0; double talismans : 0x00707918, 0x30, 0x84C, 0x220; double maxMP : 0x00707918, 0x30, 0x84C, 0x230; double coinCount : 0x00707918, 0x30, 0x84C, 0x270; } state("Ato", "1.1.2.0") { int room : 0x006F9C30; double gameTimer : 0x00707918, 0x30, 0x84C, 0x190; double difficulty : 0x00707918, 0x30, 0x84C, 0x200; double fileCreated : 0x00707918, 0x30, 0x84C, 0x290; double phase : 0x00707918, 0x30, 0x84C, 0x180; double orb1 : 0x00707918, 0x30, 0x84C, 0x1B0, 0x64, 0x00; double orb2 : 0x00707918, 0x30, 0x84C, 0x1B0, 0x64, 0x10; double orb3 : 0x00707918, 0x30, 0x84C, 0x1B0, 0x64, 0x20; double win : 0x00707918, 0x30, 0x84C, 0x120, 0x64, 0x200; double bossrush : 0x00707918, 0x30, 0x8C4, 0x10; double grasscut : 0x00707918, 0x30, 0x84C, 0xF0; double talismans : 0x00707918, 0x30, 0x84C, 0x220; double maxMP : 0x00707918, 0x30, 0x84C, 0x230; double coinCount : 0x00707918, 0x30, 0x84C, 0x270; } state("Ato", "1.1.1.0") { int room : 0x006F9C30; double gameTimer : 0x00707918, 0x30, 0xC24, 0x190; double difficulty : 0x00707918, 0x30, 0xC24, 0x200; double fileCreated : 0x00707918, 0x30, 0xC24, 0x290; double phase : 0x00707918, 0x30, 0xC24, 0x180; double orb1 : 0x00707918, 0x30, 0xC24, 0x1B0, 0x64, 0x00; double orb2 : 0x00707918, 0x30, 0xC24, 0x1B0, 0x64, 0x10; double orb3 : 0x00707918, 0x30, 0xC24, 0x1B0, 0x64, 0x20; double win : 0x00707918, 0x30, 0xC24, 0x120, 0x64, 0x200; double bossrush : 0x00707918, 0x30, 0x8C4, 0x50; double grasscut : 0x00707918, 0x30, 0xC24, 0xF0; double talismans : 0x00707918, 0x30, 0xC24, 0x220; double maxMP : 0x00707918, 0x30, 0xC24, 0x230; double coinCount : 0x00707918, 0x30, 0xC24, 0x270; } state("Ato", "1.1.0.0") { int room : 0x006F9C30; double gameTimer : 0x00707918, 0x30, 0xC24, 0x1A0; double difficulty : 0x00707918, 0x30, 0xC24, 0x210; double fileCreated : 0x00707918, 0x30, 0xC24, 0x280; double phase : 0x00707918, 0x30, 0xC24, 0x190; double orb1 : 0x00707918, 0x30, 0xC24, 0x1C0, 0x64, 0x00; double orb2 : 0x00707918, 0x30, 0xC24, 0x1C0, 0x64, 0x10; double orb3 : 0x00707918, 0x30, 0xC24, 0x1C0, 0x64, 0x20; double win : 0x00707918, 0x30, 0xC24, 0x130, 0x64, 0x200; double bossrush : 0x00707918, 0x30, 0x8C4, 0x30; double grasscut : 0x00707918, 0x30, 0xC24, 0x100; double talismans : 0x00707918, 0x30, 0xC24, 0x230; double maxMP : 0x00707918, 0x30, 0xC24, 0x240; double coinCount : 0x00; } state("Ato", "1.0.9.0") { int room : 0x006F0B70; double gameTimer : 0x006FE860, 0x30, 0x12C, 0x170; double difficulty : 0x006FE860, 0x30, 0x12C, 0x1E0; double fileCreated : 0x006FE860, 0x30, 0x12C, 0x260; double phase : 0x006FE860, 0x30, 0x12C, 0x160; double orb1 : 0x006FE860, 0x30, 0x12C, 0x190, 0x64, 0x00; double orb2 : 0x006FE860, 0x30, 0x12C, 0x190, 0x64, 0x10; double orb3 : 0x006FE860, 0x30, 0x12C, 0x190, 0x64, 0x20; double win : 0x006FE860, 0x30, 0x12C, 0x100, 0x64, 0x200; double bossrush : 0x006FE860, 0x30, 0xC60, 0x10; double grasscut : 0x006FE860, 0x30, 0x12C, 0xD0; double talismans : 0x006FE860, 0x30, 0x12C, 0x200; double maxMP : 0x006FE860, 0x30, 0x12C, 0x210; double coinCount : 0x00; } state("Ato", "1.0.8.0") { int room : 0x00722248; double gameTimer : 0x00511D80, 0x2C, 0x10, 0xEE8, 0x380; double difficulty : 0x00511D80, 0x2C, 0x10, 0xEE8, 0x3F0; double fileCreated : 0x00511D80, 0x2C, 0x10, 0xEE8, 0x470; double phase : 0x00511D80, 0x2C, 0x10, 0xEE8, 0x370; double orb1 : 0x00511D80, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x00; double orb2 : 0x00511D80, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x10; double orb3 : 0x00511D80, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x20; double win : 0x00511D80, 0x2C, 0x10, 0xA8, 0x70, 0x6C, 0x200; double bossrush : 0x00511D80, 0x2C, 0x10, 0x4308, 0x00; double grasscut : 0x00; double talismans : 0x00511D80, 0x2C, 0x10, 0xEE8, 0x410; double maxMP : 0x00511D80, 0x2C, 0x10, 0xEE8, 0x420; double coinCount : 0x00; } state("Ato", "1.0.7.2") { int room : 0x0071B1F8; double gameTimer : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x380; double difficulty : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x3F0; double fileCreated : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x480; double phase : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x370; double orb1 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x00; double orb2 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x10; double orb3 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x20; double win : 0x0050AE10, 0x2C, 0x10, 0xA8, 0x70, 0x6C, 0x200; double bossrush : 0x0050AE10, 0x2C, 0x10, 0x150, 0x100; double grasscut : 0x00; double talismans : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x410; double maxMP : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x420; double coinCount : 0x00; } state("Ato", "1.0.7.1") { int room : 0x0071B1F8; double gameTimer : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x380; double difficulty : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x3F0; double fileCreated : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x470; double phase : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x370; double orb1 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x00; double orb2 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x10; double orb3 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x20; double win : 0x0050AE10, 0x2C, 0x10, 0xA8, 0x70, 0x6C, 0x200; double bossrush : 0x0050AE10, 0x2C, 0x10, 0x150, 0x100; double grasscut : 0x00; double talismans : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x410; double maxMP : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x420; double coinCount : 0x00; } state("Ato", "1.0.7.0") { int room : 0x0071B1F8; double gameTimer : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x380; double difficulty : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x3F0; double fileCreated : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x470; double phase : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x370; double orb1 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x00; double orb2 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x10; double orb3 : 0x0050AE10, 0x2C, 0x10, 0x480, 0x30, 0x6C, 0x20; double win : 0x0050AE10, 0x2C, 0x10, 0xA8, 0x70, 0x6C, 0x200; double bossrush : 0x0050AE10, 0x2C, 0x10, 0x150, 0x100; double grasscut : 0x00; double talismans : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x410; double maxMP : 0x0050AE10, 0x2C, 0x10, 0xEE8, 0x420; double coinCount : 0x00; } state("Ato", "1.0.6.11") { int room : 0x006F6E60; double gameTimer : 0x004E6A68, 0x2C, 0x10, 0x114, 0x490; double difficulty : 0x004E6A68, 0x2C, 0x10, 0x114, 0x500; double fileCreated : 0x004E6A68, 0x2C, 0x10, 0x114, 0x580; double phase : 0x004E6A68, 0x2C, 0x10, 0x114, 0x480; double orb1 : 0x004E6A68, 0x2C, 0x10, 0x240, 0x00, 0x26C, 0x00; double orb2 : 0x004E6A68, 0x2C, 0x10, 0x240, 0x00, 0x26C, 0x10; double orb3 : 0x004E6A68, 0x2C, 0x10, 0x240, 0x00, 0x26C, 0x20; double win : 0x004E6A68, 0x2C, 0x10, 0x240, 0x00, 0xEC, 0x200; double bossrush : 0x004E6A68, 0x2C, 0x10, 0x54, 0x730; double grasscut : 0x00; double talismans : 0x004E6A68, 0x2C, 0x10, 0x114, 0x520; double maxMP : 0x004E6A68, 0x2C, 0x10, 0x114, 0x530; double coinCount : 0x00; } state("Ato", "1.0.6.10") { int room : 0x006EFE10; double gameTimer : 0x004E0AAC, 0x94, 0x10, 0x80, 0x570; double difficulty : 0x004E0AAC, 0x94, 0x10, 0x80, 0x420; double fileCreated : 0x004E0AAC, 0x94, 0x10, 0x80, 0x660; double phase : 0x004E0AAC, 0x94, 0x10, 0x80, 0x560; double orb1 : 0x004E0AB0, 0xD8, 0x28, 0xD0, 0x18, 0x300; double orb2 : 0x004E0AB0, 0xD8, 0x28, 0xD0, 0x18, 0x310; double orb3 : 0x004E0AB0, 0xD8, 0x28, 0xD0, 0x18, 0x320; double win : 0x004DF9A4, 0x2C, 0x10, 0x240, 0x20, 0x6C, 0x200; double bossrush : 0x004E0AAC, 0x5C, 0x10, 0x2C, 0x10, 0x00, 0x980; double grasscut : 0x00; double talismans : 0x004E0AAC, 0x94, 0x10, 0x80, 0x440; double maxMP : 0x004E0AAC, 0x94, 0x10, 0x80, 0x450; double coinCount : 0x00; } state("Ato", "1.0.6.9") { int room : 0x006EFE10; double gameTimer : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x70; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x60; double orb1 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x300; double orb2 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x310; double orb3 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x320; double win : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x00, 0x6C, 0x200; double bossrush : 0x004CE070, 0x00, 0x2C, 0x10, 0x330, 0x700; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.6.8") { int room : 0x006EFE10; double gameTimer : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x70; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x60; double orb1 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x300; double orb2 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x310; double orb3 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x320; double win : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x00, 0x6C, 0x200; double bossrush : 0x004CE070, 0x00, 0x2C, 0x10, 0x54, 0x620; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.6.7") { int room : 0x006EFE10; double gameTimer : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x70; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x60; double orb1 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x300; double orb2 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x310; double orb3 : 0x004E0AB0, 0xD0, 0x28, 0xD0, 0x58, 0x320; double win : 0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x00, 0x6C, 0x200; double bossrush : 0x004CE070, 0x00, 0x2C, 0x10, 0x54, 0x630; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.6.3") { int room : 0x006C2DB8; double gameTimer : 0x004B2780, 0x2C, 0x10, 0x120, 0x80; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004B2780, 0x2C, 0x10, 0x120, 0x70; double orb1 : 0x004B2780, 0x2C, 0x10, 0x120, 0x40, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x120, 0x40, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x120, 0x40, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0xE04, 0x40, 0x04, 0x04, 0x200; double bossrush : 0x004B2780, 0x2C, 0x10, 0x108, 0x6D0; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.6.0") { int room : 0x006C2DB8; double gameTimer : 0x004B2780, 0x2C, 0x10, 0x120, 0x50; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004B2780, 0x2C, 0x10, 0x120, 0x40; double orb1 : 0x004B2780, 0x2C, 0x10, 0x120, 0x10, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x120, 0x10, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x120, 0x10, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0xE04, 0x10, 0x04, 0x04, 0x200; double bossrush : 0x004B2780, 0x2C, 0x10, 0x108, 0xD0; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.5.1") { int room : 0x006C2DB8; double gameTimer : 0x004B2780, 0x2C, 0x10, 0x120, 0x50; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004B2780, 0x2C, 0x10, 0x120, 0x30; double orb1 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0xE04, 0x00, 0x04, 0x04, 0x200; double bossrush : 0x00; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.5.0") { int room : 0x006C2DB8; double gameTimer : 0x004B2780, 0x2C, 0x10, 0x120, 0x50; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004B2780, 0x2C, 0x10, 0x120, 0x30; double orb1 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0xE04, 0x00, 0x04, 0x04, 0x200; double bossrush : 0x00; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.4.1") { int room : 0x006C2DB8; double gameTimer : 0x004B2780, 0x2C, 0x10, 0x120, 0x50; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004B2780, 0x2C, 0x10, 0x120, 0x30; double orb1 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0xE04, 0x00, 0x04, 0x04, 0x200; double bossrush : 0x00; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.4.0") { int room : 0x006C2DB8; double gameTimer : 0x004B2780, 0x2C, 0x10, 0x120, 0x50; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004B2780, 0x2C, 0x10, 0x120, 0x30; double orb1 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0xE04, 0x00, 0x04, 0x04, 0x200; double bossrush : 0x00; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.3.0") { int room : 0x006C2DB8; double gameTimer : 0x004B2780, 0x2C, 0x10, 0x120, 0x50; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004B2780, 0x2C, 0x10, 0x120, 0x30; double orb1 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0xE04, 0x00, 0x04, 0x04, 0x200; double bossrush : 0x00; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.2.0") { int room : 0x006C2DB8; double gameTimer : 0x004A1164, 0x00, 0x2C, 0x10, 0x120, 0x80; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004A1164, 0x00, 0x2C, 0x10, 0x120, 0x60; double orb1 : 0x004B2780, 0x2C, 0x10, 0x888, 0x10, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x888, 0x10, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x888, 0x10, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x04, 0x04, 0x200; double bossrush : 0x00; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } state("Ato", "1.0.1.0") { int room : 0x006C2DB8; double gameTimer : 0x004A1164, 0x00, 0x2C, 0x10, 0x120, 0x80; double difficulty : 0x00; double fileCreated : 0x00; double phase : 0x004A1164, 0x00, 0x2C, 0x10, 0x120, 0x60; double orb1 : 0x004B2780, 0x2C, 0x10, 0x888, 0x10, 0x44, 0x04, 0x00; double orb2 : 0x004B2780, 0x2C, 0x10, 0x888, 0x10, 0x44, 0x04, 0x10; double orb3 : 0x004B2780, 0x2C, 0x10, 0x888, 0x10, 0x44, 0x04, 0x20; double win : 0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x04, 0x04, 0x200; double bossrush : 0x00; double grasscut : 0x00; double talismans : 0x00; double maxMP : 0x00; double coinCount : 0x00; } startup { Action DebugOutput = (text) => { print("[Autosplitter] "+text); }; vars.DebugOutput = DebugOutput; // SETTINGS settings.Add("autostart", true, "Auto-start when starting a new file."); settings.Add("progression_splits", true, "Progression Splits"); settings.Add("boss_splits", false, "Boss Splits (Excluding final boss)"); settings.Add("scroll_splits", false, "Scroll Splits"); settings.Add("arena_splits", false, "Arena Splits"); settings.Add("rune_splits", false, "Runes"); settings.Add("misc_splits", true, "Misc. Splits"); settings.CurrentDefaultParent = "progression_splits"; settings.Add("split_phase", true, "Split after destruction cutscene."); settings.Add("split_orb1", true, "Split on collecting blue orb."); settings.Add("split_orb2", true, "Split on collecting pink orb."); settings.Add("split_orb3", true, "Split on collecting yellow orb."); settings.Add("split_demonblade", true, "Split on collecting demon blade."); settings.Add("split_rebirth", true, "Split on defeating final boss (Rebirth.)"); settings.CurrentDefaultParent = "boss_splits"; settings.Add("boss_0", true, "Rogue"); settings.Add("boss_1", true, "Jin"); settings.Add("boss_2", true, "Guardian"); settings.Add("boss_3", true, "Ninja"); settings.Add("boss_4", true, "Acolyte"); settings.Add("boss_5", true, "Bandit"); settings.Add("boss_6", true, "Geisha"); settings.Add("boss_7", true, "Berserker"); settings.Add("boss_8", true, "Sentinel"); settings.Add("boss_9", true, "Samurai"); settings.Add("boss_10", true, "Warden"); settings.Add("boss_11", true, "Twins"); settings.Add("boss_12", true, "Shadow Jin"); settings.Add("boss_13", true, "Phantom Shin"); settings.Add("boss_14", true, "Vagrant"); settings.Add("boss_15", true, "Mother"); settings.Add("boss_16", true, "Father"); settings.Add("boss_17", true, "Child"); settings.Add("boss_18", true, "Ancient Warrior"); settings.Add("boss_19", true, "Yari"); settings.Add("boss_20", true, "Deceiver"); settings.Add("boss_21", false, "Blameless"); settings.Add("boss_22", false, "Cross Blade"); settings.Add("boss_23", false, "Dagger Man"); settings.Add("boss_24", false, "Turtle"); settings.Add("boss_25", false, "Champ"); settings.Add("boss_26", true, "Tiny Warrior"); settings.Add("boss_27", true, "Archer"); settings.Add("boss_28", true, "Tempest"); settings.Add("boss_29", true, "Monk"); settings.Add("boss_30", true, "Leader"); settings.Add("boss_31", true, "Demon"); settings.Add("boss_owl", true, "Owl"); settings.CurrentDefaultParent = "scroll_splits"; settings.Add("dash_count", true, "Dash (+2 Upgrades)"); settings.Add("double_jump", true, "Double Jump"); settings.Add("speed_charge", true, "Speed Charge"); settings.Add("dodge", true, "Dodge (+Upgrade)"); settings.Add("vision", true, "Vision"); settings.Add("ewls", true, "Electric Wind Lethal Strike"); settings.Add("crystal", true, "Crystal Break"); settings.Add("spell_spin", true, "Spin Spell (+Upgrade)"); settings.Add("spell_throw", true, "Throw Spell (+Upgrade)"); settings.Add("spell_down", true, "Down Spell (+Upgrade)"); settings.Add("fatal_draw", true, "Fatal Draw (+Upgrade)"); settings.Add("triple_slash", true, "Triple Slash"); settings.Add("meditate", true, "Meditate"); settings.Add("parry", true, "Parry/Counter"); settings.CurrentDefaultParent = "arena_splits"; settings.Add("arena_0", true, "Spin Arena"); settings.Add("arena_1", true, "Armor Arena"); settings.Add("arena_2", true, "Throw Arena"); settings.Add("arena_3", true, "Fatal Arena"); settings.CurrentDefaultParent = "rune_splits"; settings.Add("rune_0", true, "Echo"); settings.Add("rune_1", true, "Agility"); settings.Add("rune_2", true, "Mind"); settings.Add("rune_3", true, "Juggernaut"); settings.Add("rune_4", true, "Flurry"); settings.Add("rune_5", true, "Risk"); settings.CurrentDefaultParent = "misc_splits"; settings.Add("boss_rush", true, "Boss Rush"); settings.SetToolTip("boss_rush", "Split after each room is defeated in Boss Rush mode."); settings.Add("grass_percent", false, "Grass%"); settings.SetToolTip("grass_percent", "Split after cutting the final piece of grass in the game."); settings.Add("split_talisman", false, "Talismans"); settings.SetToolTip("split_talisman", "Split after collecting each talisman piece."); settings.Add("split_coin", false, "Coins"); settings.SetToolTip("split_coin", "Split after collecting each coin."); settings.Add("split_magic", false, "Magic Bars"); settings.SetToolTip("split_magic", "Split after collecting each extra magic bar."); // POINTER WATCHERS // Set up memory watchers for boss splits. Since they're sequential, it's easier to do in a loop than one by one. vars.GetDemonbladeWatcher = (Func)((int[] abilityOffsets) => { var baseOffset = abilityOffsets[0]; int[] demonbladeOffsets = new int[abilityOffsets.Length]; Array.Copy(abilityOffsets, 1, demonbladeOffsets, 0, abilityOffsets.Length - 1); demonbladeOffsets[demonbladeOffsets.Length - 1] = 0x1E0; return new MemoryWatcher(new DeepPointer(baseOffset, demonbladeOffsets)); }); vars.GetBossWatchers = (Func>)((int[] achievementOffsets) => { var dict = new Dictionary(); var baseOffset = achievementOffsets[0]; for (int i = 0; i <= 31; i++) { // Copy the offsets minus the first one and append the offset for the individual ability int[] currentOffsets = new int[achievementOffsets.Length]; Array.Copy(achievementOffsets, 1, currentOffsets, 0, achievementOffsets.Length - 1); currentOffsets[currentOffsets.Length - 1] = 0x10 * i; var watcher = new MemoryWatcher(new DeepPointer(baseOffset, currentOffsets)); dict.Add("boss_" + i.ToString(), watcher); } int[] owlOffsets = new int[achievementOffsets.Length]; Array.Copy(achievementOffsets, 1, owlOffsets, 0, achievementOffsets.Length - 1); owlOffsets[owlOffsets.Length - 1] = 0x580; dict.Add("boss_owl", new MemoryWatcher(new DeepPointer(baseOffset, owlOffsets))); return dict; }); vars.GetArenaWatchers = (Func>)((int[] achievementOffsets) => { var dict = new Dictionary(); var baseOffset = achievementOffsets[0]; for (int i = 0; i <= 3; i++) { // Copy the offsets minus the first one and append the offset for the individual achievement int[] currentOffsets = new int[achievementOffsets.Length]; Array.Copy(achievementOffsets, 1, currentOffsets, 0, achievementOffsets.Length - 1); currentOffsets[currentOffsets.Length - 1] = 0x210 + 0x10 * i; var watcher = new MemoryWatcher(new DeepPointer(baseOffset, currentOffsets)); dict.Add("arena_" + i.ToString(), watcher); } return dict; }); vars.GetScrollWatchers = (Func>)((int[] abilityOffsets) => { var dict = new Dictionary(); var scrollOffsets = new Dictionary() { { "dash_count", 0x10 }, { "double_jump", 0x20 }, { "speed_charge", 0x40 }, { "dodge", 0x70 }, { "vision", 0x90 }, { "ewls", 0xA0 }, { "crystal", 0xB0 }, { "spell_spin", 0x100 }, { "spell_throw", 0x110 }, { "spell_down", 0x120 }, { "fatal_draw", 0x130 }, { "triple_slash", 0x150 }, { "meditate", 0x160 }, { "parry", 0x170 } }; var baseOffset = abilityOffsets[0]; foreach (KeyValuePair kvp in scrollOffsets) { // Copy the offsets minus the first one and append the offset for the individual ability int[] currentOffsets = new int[abilityOffsets.Length]; Array.Copy(abilityOffsets, 1, currentOffsets, 0, abilityOffsets.Length - 1); currentOffsets[currentOffsets.Length - 1] = kvp.Value; // vars.DebugOutput("All offsets: " + string.Join(", ", Array.ConvertAll(currentOffsets, off => off.ToString()))); var watcher = new MemoryWatcher(new DeepPointer(baseOffset, currentOffsets)); dict.Add(kvp.Key, watcher); } return dict; }); vars.GetRuneWatchers = (Func>)((int[] runeOffsets) => { var dict = new Dictionary(); var baseOffset = runeOffsets[0]; for (int i = 0; i <= 5; i++) { // Copy the offsets minus the first one and append the offset for the individual achievement int[] currentOffsets = new int[runeOffsets.Length]; Array.Copy(runeOffsets, 1, currentOffsets, 0, runeOffsets.Length - 1); currentOffsets[currentOffsets.Length - 1] = 0x10 + 0x10 * i; var watcher = new MemoryWatcher(new DeepPointer(baseOffset, currentOffsets)); dict.Add("rune_" + i.ToString(), watcher); } return dict; }); // Keep track of total run based on game time. (Stored in milliseconds) vars.savedTime = 0; // Important room numbers for splitting vars.menuRoom = 5; vars.introRoom = 6; } init { // looks like "1.0.2.0" version = modules.First().FileVersionInfo.ProductVersion; vars.DebugOutput("INITIALIZED with version: " + version); // ARRAY/LIST POINTERS // We'd have to put each individual value in state to set these up. To allow us to increment // the offset and add all the ones we need programatically, we set these in init instead. int[] abilityOffsets; int[] achievementOffsets; int[] runeOffsets; switch(version) { case "1.0.1.0": abilityOffsets = new int[] {0x004B38B4, 0x24, 0x08, 0x50, 0x14, 0x30, 0xA98, 0x00, 0x04, 0x04}; achievementOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x04, 0x04}; runeOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x04, 0x0C}; break; case "1.0.2.0": abilityOffsets = new int[] {0x0048BBF4, 0x24, 0x2C, 0x270, 0x20, 0x14}; achievementOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0x120, 0x00, 0x04, 0x04}; runeOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0xC3C, 0x00, 0x04, 0x04}; break; case "1.0.3.0": case "1.0.4.0": case "1.0.4.1": case "1.0.5.0": case "1.0.5.1": abilityOffsets = new int[] {0x0048BBF4, 0x24, 0x2C, 0x270, 0x20, 0x14}; achievementOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0xE04, 0x00, 0x04, 0x04}; runeOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0x69C, 0x50, 0x04, 0x04}; break; case "1.0.6.0": case "1.0.6.1": case "1.0.6.2": abilityOffsets = new int[] {0x0048BBF4, 0x24, 0x2C, 0x270, 0x10, 0x14}; achievementOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0xE04, 0x10, 0x04, 0x04}; runeOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0x69C, 0x60, 0x04, 0x04}; break; case "1.0.6.3": case "1.0.6.4": case "1.0.6.5": case "1.0.6.6": abilityOffsets = new int[] {0x0048BBF4, 0x24, 0x2C, 0x270, 0x10, 0x14}; achievementOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0xE04, 0x40, 0x04, 0x04}; runeOffsets = new int[] {0x004B2780, 0x2C, 0x10, 0x69C, 0x90, 0x04, 0x04}; break; case "1.0.6.7": case "1.0.6.8": case "1.0.6.9": abilityOffsets = new int[] {0x004CE070, 0x00, 0x2C, 0x10, 0x9E4, 0x00, 0x16C}; achievementOffsets = new int[] {0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x00, 0x6C}; runeOffsets = new int[] {0x004CE070, 0x00, 0x2C, 0x10, 0x90, 0x00, 0xEC}; break; case "1.0.6.10": abilityOffsets = new int[] {0x004E0AAC, 0x94, 0x10, 0x100, 0x440, 0x3EC}; achievementOffsets = new int[] {0x004DF9A4, 0x2C, 0x10, 0x240, 0x20, 0x6C}; runeOffsets = new int[] {0x004DF9A4, 0x2C, 0x10, 0x240, 0x20, 0xEC}; break; case "1.0.6.11": abilityOffsets = new int[] {0x004E6A68, 0x2C, 0x10, 0x9F0, 0x30, 0x6C}; achievementOffsets = new int[] {0x004E6A68, 0x2C, 0x10, 0x240, 0x00, 0xEC}; runeOffsets = new int[] {0x004E6A68, 0x2C, 0x10, 0x240, 0x20, 0xEC}; break; case "1.0.7.0": case "1.0.7.1": case "1.0.7.2": abilityOffsets = new int[] {0x0050AE10, 0x2C, 0x10, 0x480, 0x70, 0x6C}; achievementOffsets = new int[] {0x0050AE10, 0x2C, 0x10, 0xA8, 0x70, 0x6C}; runeOffsets = new int[] {0x0050AE10, 0x2C, 0x10, 0xA8, 0xA0, 0x6C}; break; case "1.0.8.0": abilityOffsets = new int[] {0x00511D80, 0x2C, 0x10, 0x480, 0x70, 0x6C}; achievementOffsets = new int[] {0x00511D80, 0x2C, 0x10, 0xA8, 0x70, 0x6C}; runeOffsets = new int[] {0x00511D80, 0x2C, 0x10, 0xA8, 0xA0, 0x6C}; break; case "1.0.9.0": abilityOffsets = new int[] {0x006FE860, 0x30, 0x12C, 0x1D0, 0x64}; achievementOffsets = new int[] {0x006FE860, 0x30, 0x12C, 0x100, 0x64}; runeOffsets = new int[] {0x006FE860, 0x30, 0x12C, 0x130, 0x64}; break; case "1.1.0.0": abilityOffsets = new int[] {0x00707918, 0x30, 0xC24, 0x200, 0x64}; achievementOffsets = new int[] {0x00707918, 0x30, 0xC24, 0x130, 0x64}; runeOffsets = new int[] {0x00707918, 0x30, 0xC24, 0x160, 0x64}; break; case "1.1.1.0": abilityOffsets = new int[] {0x00707918, 0x30, 0xC24, 0x1F0, 0x64}; achievementOffsets = new int[] {0x00707918, 0x30, 0xC24, 0x120, 0x64}; runeOffsets = new int[] {0x00707918, 0x30, 0xC24, 0x150, 0x64}; break; case "1.1.2.0": case "1.1.3.0": abilityOffsets = new int[] {0x00707918, 0x30, 0x84C, 0x1F0, 0x64}; achievementOffsets = new int[] {0x00707918, 0x30, 0x84C, 0x120, 0x64}; runeOffsets = new int[] {0x00707918, 0x30, 0x84C, 0x150, 0x64}; break; case "1.1.4.0": abilityOffsets = new int[] {0x0067D5B0, 0x48, 0x10, 0x52C0, 0x140, 0x90}; achievementOffsets = new int[] {0x0067D5B0, 0x48, 0x10, 0x52C0, 0x70, 0x90}; runeOffsets = new int[] {0x0067D5B0, 0x48, 0x10, 0x52C0, 0xA0, 0x90}; break; case "1.1.5.0": case "1.1.6.0": case "1.1.7.0": default: abilityOffsets = new int[] {0x00B35220, 0x48, 0x10, 0x6A20, 0x140, 0x90}; achievementOffsets = new int[] {0x00B35220, 0x48, 0x10, 0x6A20, 0x70, 0x90}; runeOffsets = new int[] {0x00B35220, 0x48, 0x10, 0x6A20, 0xA0, 0x90}; break; } vars.bossWatchers = vars.GetBossWatchers(achievementOffsets); vars.DebugOutput("Boss watcher count: " + vars.bossWatchers.Count.ToString()); vars.arenaWatchers = vars.GetArenaWatchers(achievementOffsets); vars.DebugOutput("Arena watcher count: " + vars.arenaWatchers.Count.ToString()); vars.scrollWatchers = vars.GetScrollWatchers(abilityOffsets); vars.DebugOutput("Scroll watcher count: " + vars.scrollWatchers.Count.ToString()); vars.runeWatchers = vars.GetRuneWatchers(runeOffsets); vars.DebugOutput("Rune watcher count: " + vars.runeWatchers.Count.ToString()); vars.demonbladeWatcher = vars.GetDemonbladeWatcher(abilityOffsets); } exit { timer.IsGameTimePaused = true; } update { // Disable if version not detected if (version == "") return false; // This can happen if the run is reset if (timer.CurrentPhase == TimerPhase.NotRunning && vars.savedTime > 0) { vars.savedTime = 0; } // Return to menu on One Hit difficulty stops run if (timer.CurrentPhase == TimerPhase.Running && current.difficulty == 5 && current.room < vars.introRoom && old.room >= vars.introRoom) { timer.CurrentPhase = TimerPhase.Paused; } vars.demonbladeWatcher.Update(game); foreach (var currentWatcher in vars.bossWatchers) { currentWatcher.Value.Update(game); } foreach (var currentWatcher in vars.arenaWatchers) { currentWatcher.Value.Update(game); } foreach (var currentWatcher in vars.scrollWatchers) { currentWatcher.Value.Update(game); } foreach (var currentWatcher in vars.runeWatchers) { currentWatcher.Value.Update(game); } } start { if (settings["autostart"] && current.room >= vars.introRoom && old.room == vars.menuRoom) { // Seems to be a race condition where the game might render a few frames before this is hit. For that reason, // gameTimer isn't guaranteed to be 0. Checking for < 60 gives it a full second of slop so we shouldn't have problems. vars.DebugOutput("Game Timer: " + current.gameTimer.ToString()); if (current.gameTimer < 60 || current.bossrush == 1) { vars.DebugOutput("Timer started"); return true; } } } reset { // Reset when starting boss rush because the run must restart if they were on the main menu // Also do the same for One Hit if ( (current.bossrush == 1 && old.bossrush == 0 && vars.savedTime != 0) || (current.difficulty == 5 && vars.savedTime != 0 && current.room >= vars.introRoom && old.room == vars.menuRoom) || (current.fileCreated == 0 && current.room == vars.menuRoom) ) { return timer.CurrentPhase == TimerPhase.Running || timer.CurrentPhase == TimerPhase.Paused; } return false; } onReset { vars.DebugOutput("Timer reset"); vars.savedTime = 0; } split { // Don't split on main menu. if (current.room == vars.menuRoom) { return false; } // This should happen at room 11 just after the main boss defeats you and takes your child if (settings["split_phase"] && current.phase == 1 && old.phase == 0 && current.bossrush == 0) { vars.DebugOutput("Phase change split."); return true; } // Split on room change during boss rush. if (settings["boss_rush"] && current.bossrush == 1 && current.room != old.room && current.room > vars.menuRoom) { vars.DebugOutput("Boss rush split."); vars.DebugOutput("Old Room: " + old.room); vars.DebugOutput("New Room: " + current.room); return true; } // Split on orb collection if relevant setting is on. if ((settings["split_orb1"] && current.orb1 == 1 && old.orb1 == 0) || (settings["split_orb2"] && current.orb2 == 1 && old.orb2 == 0) || (settings["split_orb3"] && current.orb3 == 1 && old.orb3 == 0)) { vars.DebugOutput("Orb collected split."); return true; } // Split on demonblade collection if relevant setting is on. if (settings["split_demonblade"] && vars.demonbladeWatcher.Current == 1 && vars.demonbladeWatcher.Old == 0) { vars.DebugOutput("Demonblade collected split."); return true; } // Split on game finish. Only works if this is the first time the game has been won with the current save file. if (settings["split_rebirth"] && current.win == 1 && old.win == 0) { vars.DebugOutput("Game finish split."); return true; } // Split on final grass cut. if (settings["grass_percent"] && current.grasscut >= 22137 && old.grasscut < 22137) { vars.DebugOutput("Grass% final split."); return true; } // Split on coins collected if (settings["split_coin"] && current.coinCount > old.coinCount) { vars.DebugOutput("Coin collected split."); return true; } // Split on talismans collected if (settings["split_talisman"] && current.talismans != old.talismans) { vars.DebugOutput("Talisman collected split."); return true; } // Split on magic collected if (settings["split_magic"] && current.maxMP > old.maxMP && current.orb1 == old.orb1 && current.orb2 == old.orb2 && current.orb3 == old.orb3) { vars.DebugOutput("Magic bar collected split."); return true; } // Split on each boss if the appropriate setting is activated foreach (KeyValuePair kvp in vars.bossWatchers) { double oldVal = kvp.Value.Old == null ? 0d : (double)kvp.Value.Old; double currentVal = kvp.Value.Current == null ? 0d : (double)kvp.Value.Current; if (settings[kvp.Key] && oldVal == 0 && currentVal > 0 && current.bossrush == 0) { vars.DebugOutput("Boss kill " + kvp.Key + " split."); return true; } } // Split on each arena complete if the appropriate setting is activated foreach (KeyValuePair kvp in vars.arenaWatchers) { double oldVal = kvp.Value.Old == null ? 0d : (double)kvp.Value.Old; double currentVal = kvp.Value.Current == null ? 0d : (double)kvp.Value.Current; if (settings[kvp.Key] && oldVal == 0 && currentVal > 0 && current.bossrush == 0) { vars.DebugOutput("Arena complete " + kvp.Key + " split."); return true; } } // Split on each scroll obtained if the appropriate setting is activated foreach (KeyValuePair kvp in vars.scrollWatchers) { double oldVal = kvp.Value.Old == null ? 0d : (double)kvp.Value.Old; double currentVal = kvp.Value.Current == null ? 0d : (double)kvp.Value.Current; if (settings[kvp.Key] && currentVal > oldVal) { vars.DebugOutput("Obtained scroll " + kvp.Key + " split."); return true; } } // Split on each rune obtained if the appropriate setting is activated foreach (KeyValuePair kvp in vars.runeWatchers) { double oldVal = kvp.Value.Old == null ? 0d : (double)kvp.Value.Old; double currentVal = kvp.Value.Current == null ? 0d : (double)kvp.Value.Current; if (settings[kvp.Key] && currentVal > oldVal) { vars.DebugOutput("Obtained rune " + kvp.Key + " split."); return true; } } } isLoading { return current.room <= vars.introRoom; } gameTime { // Pause game time while on main menu. This is to prevent timer jumps when loading save file. if (current.room <= vars.menuRoom) { timer.SetGameTime(new TimeSpan(0)); return TimeSpan.FromMilliseconds(vars.savedTime); } // gameTime is frames rendered. Game runs at 60 fps double ms = current.gameTimer * (1000d / 60d); double oldMs = old.gameTimer * (1000d / 60d); if (ms > oldMs) { vars.savedTime = ms; } // Game display rounds up to the nearest hundredth, although a frame is much longer // so such precision doesn't really matter. But it looks more consistent. return TimeSpan.FromMilliseconds(Math.Round(vars.savedTime / 10d) * 10d); }