diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c16a15af..a6671cbc9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -255,7 +255,7 @@ jobs: - name: Download OK bot id: download-ok run: | - python ./tools/download_tool.py OK ok --tag v0.1.3 + python ./tools/download_tool.py OK ok --tag v0.1.4 - name: Run OK command id: ok-command diff --git a/.vscode/settings.json b/.vscode/settings.json index 09e36b599..861363e42 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,11 @@ { "[c]": { "files.encoding": "utf8", - "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" + "editor.defaultFormatter": "xaver.clang-format" }, "[cpp]": { "files.encoding": "utf8", - "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" + "editor.defaultFormatter": "xaver.clang-format" }, "[python]": { "editor.defaultFormatter": "ms-python.black-formatter" @@ -19,5 +19,5 @@ ".clangd": "yaml" }, // Disable C/C++ IntelliSense, use clangd instead - "C_Cpp.intelliSenseEngine": "disabled", + "C_Cpp.intelliSenseEngine": "default", } diff --git a/src/SB/Core/gc/iMix.c b/src/SB/Core/gc/iMix.c index e69de29bb..e1fba9861 100644 --- a/src/SB/Core/gc/iMix.c +++ b/src/SB/Core/gc/iMix.c @@ -0,0 +1,691 @@ +#include "iMix.h" + +static struct MIXChannel __MIXChannel[64]; + +static unsigned int __MIXSoundMode; +static int __MIXDvdStreamAttenUser; +static int __MIXDvdStreamAttenCurrent; + +unsigned short __MIXVolumeTable[] = +{ + 0x0, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x2, 0x2, + 0x2, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x4, 0x4, + 0x4, 0x4, 0x4, 0x4, + 0x4, 0x4, 0x4, 0x4, + 0x4, 0x4, 0x4, 0x4, + 0x4, 0x4, 0x4, 0x4, + 0x4, 0x5, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, + 0x5, 0x5, 0x5, 0x5, + 0x5, 0x6, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, + 0x6, 0x6, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x8, 0x8, + 0x8, 0x8, 0x8, 0x8, + 0x8, 0x8, 0x8, 0x8, + 0x9, 0x9, 0x9, 0x9, + 0x9, 0x9, 0x9, 0x9, + 0x9, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xA, 0xA, + 0xA, 0xA, 0xB, 0xB, + 0xB, 0xB, 0xB, 0xB, + 0xB, 0xC, 0xC, 0xC, + 0xC, 0xC, 0xC, 0xC, + 0xD, 0xD, 0xD, 0xD, + 0xD, 0xD, 0xD, 0xE, + 0xE, 0xE, 0xE, 0xE, + 0xE, 0xF, 0xF, 0xF, + 0xF, 0xF, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x12, + 0x12, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x14, 0x14, + 0x14, 0x14, 0x15, 0x15, + 0x15, 0x15, 0x16, 0x16, + 0x16, 0x16, 0x17, 0x17, + 0x17, 0x18, 0x18, 0x18, + 0x18, 0x19, 0x19, 0x19, + 0x1A, 0x1A, 0x1A, 0x1A, + 0x1B, 0x1B, 0x1B, 0x1C, + 0x1C, 0x1C, 0x1D, 0x1D, + 0x1D, 0x1E, 0x1E, 0x1E, + 0x1F, 0x1F, 0x20, 0x20, + 0x20, 0x21, 0x21, 0x21, + 0x22, 0x22, 0x23, 0x23, + 0x23, 0x24, 0x24, 0x25, + 0x25, 0x26, 0x26, 0x26, + 0x27, 0x27, 0x28, 0x28, + 0x29, 0x29, 0x2A, 0x2A, + 0x2B, 0x2B, 0x2C, 0x2C, + 0x2D, 0x2D, 0x2E, 0x2E, + 0x2F, 0x2F, 0x30, 0x31, + 0x31, 0x32, 0x32, 0x33, + 0x33, 0x34, 0x35, 0x35, + 0x36, 0x37, 0x37, 0x38, + 0x38, 0x39, 0x3A, 0x3A, + 0x3B, 0x3C, 0x3D, 0x3D, + 0x3E, 0x3F, 0x3F, 0x40, + 0x41, 0x42, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x46, + 0x47, 0x48, 0x49, 0x4A, + 0x4B, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, + 0x52, 0x53, 0x54, 0x55, + 0x56, 0x57, 0x58, 0x59, + 0x5A, 0x5B, 0x5C, 0x5D, + 0x5E, 0x5F, 0x60, 0x61, + 0x62, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x6A, 0x6B, + 0x6C, 0x6D, 0x6F, 0x70, + 0x71, 0x72, 0x74, 0x75, + 0x76, 0x78, 0x79, 0x7B, + 0x7C, 0x7E, 0x7F, 0x80, + 0x82, 0x83, 0x85, 0x87, + 0x88, 0x8A, 0x8B, 0x8D, + 0x8F, 0x90, 0x92, 0x94, + 0x95, 0x97, 0x99, 0x9B, + 0x9C, 0x9E, 0xA0, 0xA2, + 0xA4, 0xA6, 0xA8, 0xAA, + 0xAB, 0xAD, 0xAF, 0xB2, + 0xB4, 0xB6, 0xB8, 0xBA, + 0xBC, 0xBE, 0xC0, 0xC3, + 0xC5, 0xC7, 0xCA, 0xCC, + 0xCE, 0xD1, 0xD3, 0xD6, + 0xD8, 0xDB, 0xDD, 0xE0, + 0xE2, 0xE5, 0xE7, 0xEA, + 0xED, 0xF0, 0xF2, 0xF5, + 0xF8, 0xFB, 0xFE, 0x101, + 0x104, 0x107, 0x10A, 0x10D, + 0x110, 0x113, 0x116, 0x11A, + 0x11D, 0x120, 0x124, 0x127, + 0x12A, 0x12E, 0x131, 0x135, + 0x138, 0x13C, 0x140, 0x143, + 0x147, 0x14B, 0x14F, 0x153, + 0x157, 0x15B, 0x15F, 0x163, + 0x167, 0x16B, 0x16F, 0x173, + 0x178, 0x17C, 0x180, 0x185, + 0x189, 0x18E, 0x193, 0x197, + 0x19C, 0x1A1, 0x1A6, 0x1AB, + 0x1AF, 0x1B4, 0x1BA, 0x1BF, + 0x1C4, 0x1C9, 0x1CE, 0x1D4, + 0x1D9, 0x1DF, 0x1E4, 0x1EA, + 0x1EF, 0x1F5, 0x1FB, 0x201, + 0x207, 0x20D, 0x213, 0x219, + 0x21F, 0x226, 0x22C, 0x232, + 0x239, 0x240, 0x246, 0x24D, + 0x254, 0x25B, 0x262, 0x269, + 0x270, 0x277, 0x27E, 0x286, + 0x28D, 0x295, 0x29D, 0x2A4, + 0x2AC, 0x2B4, 0x2BC, 0x2C4, + 0x2CC, 0x2D5, 0x2DD, 0x2E6, + 0x2EE, 0x2F7, 0x300, 0x309, + 0x312, 0x31B, 0x324, 0x32D, + 0x337, 0x340, 0x34A, 0x354, + 0x35D, 0x367, 0x371, 0x37C, + 0x386, 0x390, 0x39B, 0x3A6, + 0x3B1, 0x3BB, 0x3C7, 0x3D2, + 0x3DD, 0x3E9, 0x3F4, 0x400, + 0x40C, 0x418, 0x424, 0x430, + 0x43D, 0x449, 0x456, 0x463, + 0x470, 0x47D, 0x48A, 0x498, + 0x4A5, 0x4B3, 0x4C1, 0x4CF, + 0x4DD, 0x4EC, 0x4FA, 0x509, + 0x518, 0x527, 0x536, 0x546, + 0x555, 0x565, 0x575, 0x586, + 0x596, 0x5A6, 0x5B7, 0x5C8, + 0x5D9, 0x5EB, 0x5FC, 0x60E, + 0x620, 0x632, 0x644, 0x657, + 0x66A, 0x67D, 0x690, 0x6A4, + 0x6B7, 0x6CB, 0x6DF, 0x6F4, + 0x708, 0x71D, 0x732, 0x748, + 0x75D, 0x773, 0x789, 0x79F, + 0x7B6, 0x7CD, 0x7E4, 0x7FB, + 0x813, 0x82B, 0x843, 0x85C, + 0x874, 0x88E, 0x8A7, 0x8C1, + 0x8DA, 0x8F5, 0x90F, 0x92A, + 0x945, 0x961, 0x97D, 0x999, + 0x9B5, 0x9D2, 0x9EF, 0xA0D, + 0xA2A, 0xA48, 0xA67, 0xA86, + 0xAA5, 0xAC5, 0xAE5, 0xB05, + 0xB25, 0xB47, 0xB68, 0xB8A, + 0xBAC, 0xBCF, 0xBF2, 0xC15, + 0xC39, 0xC5D, 0xC82, 0xCA7, + 0xCCC, 0xCF2, 0xD19, 0xD3F, + 0xD67, 0xD8E, 0xDB7, 0xDDF, + 0xE08, 0xE32, 0xE5C, 0xE87, + 0xEB2, 0xEDD, 0xF09, 0xF36, + 0xF63, 0xF91, 0xFBF, 0xFEE, + 0x101D, 0x104D, 0x107D, 0x10AE, + 0x10DF, 0x1111, 0x1144, 0x1177, + 0x11AB, 0x11DF, 0x1214, 0x124A, + 0x1280, 0x12B7, 0x12EE, 0x1326, + 0x135F, 0x1399, 0x13D3, 0x140D, + 0x1449, 0x1485, 0x14C2, 0x14FF, + 0x153E, 0x157D, 0x15BC, 0x15FD, + 0x163E, 0x1680, 0x16C3, 0x1706, + 0x174A, 0x178F, 0x17D5, 0x181C, + 0x1863, 0x18AC, 0x18F5, 0x193F, + 0x198A, 0x19D5, 0x1A22, 0x1A6F, + 0x1ABE, 0x1B0D, 0x1B5D, 0x1BAE, + 0x1C00, 0x1C53, 0x1CA7, 0x1CFC, + 0x1D52, 0x1DA9, 0x1E01, 0x1E5A, + 0x1EB4, 0x1F0F, 0x1F6B, 0x1FC8, + 0x2026, 0x2086, 0x20E6, 0x2148, + 0x21AA, 0x220E, 0x2273, 0x22D9, + 0x2341, 0x23A9, 0x2413, 0x247E, + 0x24EA, 0x2557, 0x25C6, 0x2636, + 0x26A7, 0x271A, 0x278E, 0x2803, + 0x287A, 0x28F2, 0x296B, 0x29E6, + 0x2A62, 0x2AE0, 0x2B5F, 0x2BDF, + 0x2C61, 0x2CE5, 0x2D6A, 0x2DF1, + 0x2E79, 0x2F03, 0x2F8E, 0x301B, + 0x30AA, 0x313A, 0x31CC, 0x325F, + 0x32F5, 0x338C, 0x3425, 0x34BF, + 0x355B, 0x35FA, 0x369A, 0x373C, + 0x37DF, 0x3885, 0x392C, 0x39D6, + 0x3A81, 0x3B2F, 0x3BDE, 0x3C90, + 0x3D43, 0x3DF9, 0x3EB1, 0x3F6A, + 0x4026, 0x40E5, 0x41A5, 0x4268, + 0x432C, 0x43F4, 0x44BD, 0x4589, + 0x4657, 0x4727, 0x47FA, 0x48D0, + 0x49A8, 0x4A82, 0x4B5F, 0x4C3E, + 0x4D20, 0x4E05, 0x4EEC, 0x4FD6, + 0x50C3, 0x51B2, 0x52A4, 0x5399, + 0x5491, 0x558C, 0x5689, 0x578A, + 0x588D, 0x5994, 0x5A9D, 0x5BAA, + 0x5CBA, 0x5DCD, 0x5EE3, 0x5FFC, + 0x6119, 0x6238, 0x635C, 0x6482, + 0x65AC, 0x66D9, 0x680A, 0x693F, + 0x6A77, 0x6BB2, 0x6CF2, 0x6E35, + 0x6F7B, 0x70C6, 0x7214, 0x7366, + 0x74BC, 0x7616, 0x7774, 0x78D6, + 0x7A3D, 0x7BA7, 0x7D16, 0x7E88, + 0x7FFF, 0x817B, 0x82FB, 0x847F, + 0x8608, 0x8795, 0x8927, 0x8ABE, + 0x8C59, 0x8DF9, 0x8F9E, 0x9148, + 0x92F6, 0x94AA, 0x9663, 0x9820, + 0x99E3, 0x9BAB, 0x9D79, 0x9F4C, + 0xA124, 0xA302, 0xA4E5, 0xA6CE, + 0xA8BC, 0xAAB0, 0xACAA, 0xAEAA, + 0xB0B0, 0xB2BC, 0xB4CE, 0xB6E5, + 0xB904, 0xBB28, 0xBD53, 0xBF84, + 0xC1BC, 0xC3FA, 0xC63F, 0xC88B, + 0xCADD, 0xCD37, 0xCF97, 0xD1FE, + 0xD46D, 0xD6E3, 0xD960, 0xDBE4, + 0xDE70, 0xE103, 0xE39E, 0xE641, + 0xE8EB, 0xEB9E, 0xEE58, 0xF11B, + 0xF3E6, 0xF6B9, 0xF994, 0xFC78, + 0xFF64 +}; + +int __MIXPanTable[] = +{ + 0x0, 0x0, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFE, 0xFFFFFFFE, + 0xFFFFFFFD, 0xFFFFFFFD, 0xFFFFFFFC, 0xFFFFFFFC, + 0xFFFFFFFC, 0xFFFFFFFB, 0xFFFFFFFB, 0xFFFFFFFB, + 0xFFFFFFFA, 0xFFFFFFFA, 0xFFFFFFF9, 0xFFFFFFF9, + 0xFFFFFFF9, 0xFFFFFFF8, 0xFFFFFFF8, 0xFFFFFFF7, + 0xFFFFFFF7, 0xFFFFFFF6, 0xFFFFFFF6, 0xFFFFFFF6, + 0xFFFFFFF5, 0xFFFFFFF5, 0xFFFFFFF4, 0xFFFFFFF4, + 0xFFFFFFF3, 0xFFFFFFF3, 0xFFFFFFF2, 0xFFFFFFF2, + 0xFFFFFFF2, 0xFFFFFFF1, 0xFFFFFFF1, 0xFFFFFFF0, + 0xFFFFFFF0, 0xFFFFFFEF, 0xFFFFFFEF, 0xFFFFFFEE, + 0xFFFFFFEE, 0xFFFFFFED, 0xFFFFFFEC, 0xFFFFFFEC, + 0xFFFFFFEB, 0xFFFFFFEB, 0xFFFFFFEA, 0xFFFFFFEA, + 0xFFFFFFE9, 0xFFFFFFE9, 0xFFFFFFE8, 0xFFFFFFE7, + 0xFFFFFFE7, 0xFFFFFFE6, 0xFFFFFFE6, 0xFFFFFFE5, + 0xFFFFFFE4, 0xFFFFFFE4, 0xFFFFFFE3, 0xFFFFFFE2, + 0xFFFFFFE2, 0xFFFFFFE1, 0xFFFFFFE0, 0xFFFFFFDF, + 0xFFFFFFDF, 0xFFFFFFDE, 0xFFFFFFDD, 0xFFFFFFDC, + 0xFFFFFFDC, 0xFFFFFFDB, 0xFFFFFFDA, 0xFFFFFFD9, + 0xFFFFFFD8, 0xFFFFFFD8, 0xFFFFFFD7, 0xFFFFFFD6, + 0xFFFFFFD5, 0xFFFFFFD4, 0xFFFFFFD3, 0xFFFFFFD2, + 0xFFFFFFD1, 0xFFFFFFD0, 0xFFFFFFCF, 0xFFFFFFCE, + 0xFFFFFFCD, 0xFFFFFFCC, 0xFFFFFFCA, 0xFFFFFFC9, + 0xFFFFFFC8, 0xFFFFFFC7, 0xFFFFFFC5, 0xFFFFFFC4, + 0xFFFFFFC3, 0xFFFFFFC1, 0xFFFFFFC0, 0xFFFFFFBE, + 0xFFFFFFBD, 0xFFFFFFBB, 0xFFFFFFB9, 0xFFFFFFB8, + 0xFFFFFFB6, 0xFFFFFFB4, 0xFFFFFFB2, 0xFFFFFFB0, + 0xFFFFFFAD, 0xFFFFFFAB, 0xFFFFFFA9, 0xFFFFFFA6, + 0xFFFFFFA3, 0xFFFFFFA0, 0xFFFFFF9D, 0xFFFFFF9A, + 0xFFFFFF96, 0xFFFFFF92, 0xFFFFFF8D, 0xFFFFFF88, + 0xFFFFFF82, 0xFFFFFF7B, 0xFFFFFF74, 0xFFFFFF6A, + 0xFFFFFF5D, 0xFFFFFF4C, 0xFFFFFF2E, 0xFFFFFC78 +}; + +short __MIX_DPL2_front[] = +{ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, + 0xFFFE, 0xFFFE, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFC, 0xFFFC, 0xFFFC, + 0xFFFB, 0xFFFB, 0xFFFA, 0xFFFA, + 0xFFFA, 0xFFF9, 0xFFF9, 0xFFF8, + 0xFFF8, 0xFFF7, 0xFFF7, 0xFFF6, + 0xFFF5, 0xFFF5, 0xFFF4, 0xFFF4, + 0xFFF3, 0xFFF2, 0xFFF2, 0xFFF1, + 0xFFF0, 0xFFEF, 0xFFEF, 0xFFEE, + 0xFFED, 0xFFEC, 0xFFEB, 0xFFEB, + 0xFFEA, 0xFFE9, 0xFFE8, 0xFFE7, + 0xFFE6, 0xFFE5, 0xFFE4, 0xFFE3, + 0xFFE2, 0xFFE1, 0xFFE0, 0xFFDE, + 0xFFDD, 0xFFDC, 0xFFDB, 0xFFDA, + 0xFFD8, 0xFFD7, 0xFFD6, 0xFFD4, + 0xFFD3, 0xFFD1, 0xFFD0, 0xFFCE, + 0xFFCC, 0xFFCB, 0xFFC9, 0xFFC7, + 0xFFC6, 0xFFC4, 0xFFC2, 0xFFC0, + 0xFFBE, 0xFFBC, 0xFFBA, 0xFFB7, + 0xFFB5, 0xFFB3, 0xFFB0, 0xFFAE, + 0xFFAB, 0xFFA8, 0xFFA6, 0xFFA3, + 0xFFA0, 0xFF9C, 0xFF99, 0xFF96, + 0xFF92, 0xFF8E, 0xFF8A, 0xFF86, + 0xFF82, 0xFF7D, 0xFF78, 0xFF73, + 0xFF6E, 0xFF68, 0xFF61, 0xFF5A, + 0xFF53, 0xFF4B, 0xFF42, 0xFF37, + 0xFF2C, 0xFF1F, 0xFF0F, 0xFEFB, + 0xFEE2, 0xFEBF, 0xFE83, 0xFC40 +}; + +short __MIX_DPL2_rear[] = +{ + 0xFFC3, 0xFFC3, 0xFFC4, 0xFFC5, + 0xFFC5, 0xFFC6, 0xFFC6, 0xFFC7, + 0xFFC8, 0xFFC8, 0xFFC9, 0xFFC9, + 0xFFCA, 0xFFCB, 0xFFCB, 0xFFCC, + 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCE, + 0xFFCF, 0xFFCF, 0xFFD0, 0xFFD0, + 0xFFD1, 0xFFD1, 0xFFD2, 0xFFD2, + 0xFFD3, 0xFFD3, 0xFFD4, 0xFFD4, + 0xFFD5, 0xFFD5, 0xFFD6, 0xFFD6, + 0xFFD7, 0xFFD7, 0xFFD8, 0xFFD8, + 0xFFD9, 0xFFD9, 0xFFDA, 0xFFDA, + 0xFFDA, 0xFFDB, 0xFFDB, 0xFFDC, + 0xFFDC, 0xFFDD, 0xFFDD, 0xFFDD, + 0xFFDE, 0xFFDE, 0xFFDF, 0xFFDF, + 0xFFE0, 0xFFE0, 0xFFE0, 0xFFE1, + 0xFFE1, 0xFFE1, 0xFFE2, 0xFFE2, + 0xFFE3, 0xFFE3, 0xFFE3, 0xFFE4, + 0xFFE4, 0xFFE4, 0xFFE5, 0xFFE5, + 0xFFE5, 0xFFE6, 0xFFE6, 0xFFE6, + 0xFFE7, 0xFFE7, 0xFFE7, 0xFFE8, + 0xFFE8, 0xFFE8, 0xFFE9, 0xFFE9, + 0xFFE9, 0xFFEA, 0xFFEA, 0xFFEA, + 0xFFEB, 0xFFEB, 0xFFEB, 0xFFEC, + 0xFFEC, 0xFFEC, 0xFFEC, 0xFFED, + 0xFFED, 0xFFED, 0xFFEE, 0xFFEE, + 0xFFEE, 0xFFEE, 0xFFEF, 0xFFEF, + 0xFFEF, 0xFFEF, 0xFFF0, 0xFFF0, + 0xFFF0, 0xFFF0, 0xFFF1, 0xFFF1, + 0xFFF1, 0xFFF1, 0xFFF2, 0xFFF2, + 0xFFF2, 0xFFF2, 0xFFF3, 0xFFF3, + 0xFFF3, 0xFFF3, 0xFFF3, 0xFFF4, + 0xFFF4, 0xFFF4, 0xFFF4, 0xFFF5 +}; + +static int __MIXGetVolume(int param_1) +{ + if (param_1 <= -0x388) + { + return 0; + } + if (0x3c <= param_1) + { + return 0xff64; + } + return __MIXVolumeTable[param_1 + 0x388]; +} + +static int __MIXSetPan(struct MIXChannel *param_1) +{ + int iVar1 = *(int *)((int)param_1 + 0x14); + int iVar3 = *(int *)((int)param_1 + 0x18); + + int iVar2 = 0x7f - iVar1; + int iVar4 = 0x7f - iVar3; + + if (__MIXSoundMode == 3) + { + param_1->data[8] = __MIX_DPL2_front[iVar1]; + param_1->data[9] = __MIX_DPL2_front[iVar2]; + param_1->data[10] = __MIX_DPL2_front[iVar4]; + param_1->data[11] = __MIX_DPL2_front[iVar3]; + param_1->data[12] = __MIX_DPL2_rear[iVar2]; + param_1->data[13] = __MIX_DPL2_rear[iVar1]; + } + else + { + param_1->data[8] = __MIXPanTable[iVar1]; + param_1->data[9] = __MIXPanTable[iVar2]; + param_1->data[10] = __MIXPanTable[iVar4]; + param_1->data[11] = __MIXPanTable[iVar3]; + } +} + +static void __MIXResetChannel(struct MIXChannel *param_1) +{ + param_1->data[1] = 0x50000000; + param_1->data[2] = 0; + param_1->data[3] = 0xfffffc40; + param_1->data[4] = 0xfffffc40; + param_1->data[7] = 0; + param_1->data[5] = 0x40; + param_1->data[6] = 0x7f; + + *(unsigned short*)(¶m_1->data[23]) = 0; + *(unsigned short*)(¶m_1->data[22]) = 0; + *(unsigned short*)(¶m_1->data[21]) = 0; + *(unsigned short*)(¶m_1->data[20]) = 0; + *(unsigned short*)(¶m_1->data[19]) = 0; + *(unsigned short*)(¶m_1->data[18]) = 0; + *(unsigned short*)(¶m_1->data[17]) = 0; + *(unsigned short*)(¶m_1->data[16]) = 0; + *(unsigned short*)(¶m_1->data[15]) = 0; + *(unsigned short*)(¶m_1->data[14]) = 0; + + __MIXSetPan(param_1); +} + +static int __MIXClampPan(int param) +{ + int retval; + if (param < 0) + { + return 0; + } + retval = 0x7f; + if (param <= 0x7f) + { + retval = param; + } + return retval; +} + +void MIXInit() +{ + int iVar1 = 0; + do + { + __MIXResetChannel((struct MIXChannel *)&__MIXChannel[iVar1]); + iVar1++; + } while (iVar1 < 0x40); + __MIXDvdStreamAttenCurrent = 0; + __MIXDvdStreamAttenUser = 0; + __MIXSoundMode = OSGetSoundMode(); +} + +void MIXInitChannel(int param_1, unsigned int param_2, int param_3, int param_4, int param_5, int param_6, int param_7, int param_8) +{ + struct MIXChannel* chan = &__MIXChannel[*(int *)((int)param_1 + 0x18)]; + + short sVar1; + unsigned short uVar2; + unsigned short uVar4; + + chan->data[0] = param_1; + chan->data[1] = param_2 & 7; + chan->data[2] = param_3; + chan->data[3] = param_4; + chan->data[4] = param_5; + chan->data[5] = param_6; + chan->data[6] = param_7; + chan->data[7] = param_8; + + __MIXSetPan( chan); + + if ( (chan->data[1] & 4)) + { + *(unsigned short *)( &chan->data[0xe]) = 0; + } + else + { + *(unsigned short *)( &chan->data[0xe]) = __MIXGetVolume(param_3); + } + + + uVar4 = 0; + + switch ((int)__MIXSoundMode) + { + case 0: + *(unsigned short *)(&chan->data[0xf]) = __MIXGetVolume(chan->data[7]+ chan->data[10]); + *(unsigned short *)(&chan->data[0x10]) = __MIXGetVolume(chan->data[7] + chan->data[10]); + *(unsigned short *)(&chan->data[0x11]) = __MIXGetVolume(chan->data[7] + chan->data[11]); + if ((chan->data[1] & 1U) != 0) + { + *(unsigned short *)(&chan->data[0x12]) = __MIXGetVolume(chan->data[3] + chan->data[10] ); + *(unsigned short *)(&chan->data[0x13]) = __MIXGetVolume(chan->data[3] + chan->data[10] ); + *(unsigned short *)(&chan->data[0x14]) = __MIXGetVolume(chan->data[3] + chan->data[11] - 0x3c); + } + else + { + *(unsigned short *)(&chan->data[0x12]) = __MIXGetVolume(chan->data[7] + chan->data[3] + chan->data[10]); + *(unsigned short *)(&chan->data[0x13]) = __MIXGetVolume(chan->data[7] + chan->data[3] + chan->data[10] ); + *(unsigned short *)(&chan->data[0x14]) = __MIXGetVolume(chan->data[7] + chan->data[3] + chan->data[11] - 0x3c); + + } + + if (chan->data[1] & 2) + { + + *(unsigned short *)(&chan->data[0x15]) = __MIXGetVolume(chan->data[4] + chan->data[10]); + *(unsigned short *)(&chan->data[0x16]) = __MIXGetVolume(chan->data[4] + chan->data[10]); + *(unsigned short *)(&chan->data[0x17]) = __MIXGetVolume(chan->data[4] + chan->data[11] - 0x3c); + } + else + { + *(unsigned short *)(&chan->data[0x15]) = __MIXGetVolume(chan->data[7] + chan->data[4] + chan->data[10]); + *(unsigned short *)(&chan->data[0x16]) = __MIXGetVolume(chan->data[7] + chan->data[4] + chan->data[10]); + *(unsigned short *)(&chan->data[0x17]) = __MIXGetVolume(chan->data[7] + chan->data[4] + chan->data[11] - 0x3c); + } + + + + break; + + case 1: + case 2: + *(unsigned short *)(&chan->data[0xf]) = __MIXGetVolume(chan->data[7] + chan->data[8] + chan->data[10]); + *(unsigned short *)(&chan->data[0x10]) = __MIXGetVolume(chan->data[7] + chan->data[9] + chan->data[10]); + *(unsigned short *)(&chan->data[0x11]) = __MIXGetVolume(chan->data[7] + chan->data[11]); + + if ( (chan->data[1] & 1) != 0) + { + *(unsigned short *)(&chan->data[0x12]) = __MIXGetVolume(chan->data[3] + chan->data[8] + chan->data[10]); + *(unsigned short *)(&chan->data[0x13]) = __MIXGetVolume(chan->data[3] + chan->data[9] + chan->data[10]); + *(unsigned short *)(&chan->data[0x14]) = __MIXGetVolume(chan->data[3] + chan->data[11] + -0x3c); + } + else + { + *(unsigned short *)(&chan->data[0x12]) = __MIXGetVolume(chan->data[7] + chan->data[3] + chan->data[8] + chan->data[10]); + *(unsigned short *)(&chan->data[0x13]) = __MIXGetVolume(chan->data[7] + chan->data[3] + chan->data[9] + chan->data[10]); + *(unsigned short *)(&chan->data[0x14]) = __MIXGetVolume(chan->data[7] + chan->data[3] + chan->data[11] + -0x3c); + } + if (chan->data[1] & 2U) + { + *(unsigned short *)(&chan->data[0x15]) = __MIXGetVolume(chan->data[4] + chan->data[8] + chan->data[10]); + *(unsigned short *)(&chan->data[0x16]) = __MIXGetVolume(chan->data[4] + chan->data[9] + chan->data[10]); + *(unsigned short *)(&chan->data[0x17]) = __MIXGetVolume(chan->data[4] + chan->data[11] + -0x3c); + } + else + { + *(unsigned short *)(&chan->data[0x15]) = __MIXGetVolume(chan->data[7] + chan->data[4] + chan->data[8] + chan->data[10]); + *(unsigned short *)(&chan->data[0x16]) = __MIXGetVolume(chan->data[7] + chan->data[4] + chan->data[9] + chan->data[10]); + *(unsigned short *)(&chan->data[0x17]) = __MIXGetVolume(chan->data[7] + chan->data[4] + chan->data[11] + -0x3c); + } + break; + + case 3: + *(unsigned short *)(&chan->data[15]) = __MIXGetVolume(chan->data[7] + chan->data[8] + chan->data[10]); + *(unsigned short *)(&chan->data[16]) = __MIXGetVolume(chan->data[7] + chan->data[9] + chan->data[10]); + *(unsigned short *)(&chan->data[21]) = __MIXGetVolume(chan->data[7] + chan->data[12] + chan->data[11]); + *(unsigned short *)(&chan->data[22]) = __MIXGetVolume(chan->data[7] + chan->data[13] + chan->data[11]); + + if ((chan->data[1] & 1) != 0) + { + *(unsigned short *)(&chan->data[0x12]) = __MIXGetVolume(chan->data[3] + chan->data[8] + chan->data[10] ); + *(unsigned short *)(&chan->data[0x13]) = __MIXGetVolume(chan->data[3] + chan->data[9] + chan->data[10] ); + *(unsigned short *)(&chan->data[0x14]) = __MIXGetVolume(chan->data[3] + chan->data[12] + chan->data[11]); + *(unsigned short *)(&chan->data[0x17]) = __MIXGetVolume(chan->data[3] + chan->data[13] + chan->data[11]); + } + else + { + *(unsigned short *)(&chan->data[0x12]) = __MIXGetVolume(chan->data[7] + chan->data[3] + chan->data[8] + chan->data[10]); + *(unsigned short *)(&chan->data[0x13]) = __MIXGetVolume(chan->data[7] + chan->data[3]+ chan->data[9]+ chan->data[10] ); + *(unsigned short *)(&chan->data[0x14]) = __MIXGetVolume(chan->data[7] + chan->data[3] + chan->data[12] + chan->data[11]); + *(unsigned short *)(&chan->data[0x17]) = __MIXGetVolume(chan->data[7] + chan->data[3]+ chan->data[13] + chan->data[11]); + } + + uVar4 |= 0x4000; + break; + + } + + OSDisableInterrupts(); + + *(unsigned short *)((int)param_1 + 0x19c) = *(unsigned short *)(&chan->data[0xe]); // Target sets to r4 instead of r3. + *(unsigned short *)((int)param_1 + 0x19e) = 0; + if ( (*(unsigned short *)((int)param_1 + 0x14a) = *(unsigned short *)(&chan->data[0xf])) ) + { + uVar4 |= 1; + } + + *(unsigned short *)((int)param_1 + 0x14c) = 0; + + if (*(unsigned short *)(param_1 + 0x14e) = *(unsigned short *)(&chan->data[0x10])) + { + uVar4 = uVar4 | 2; + } + *(unsigned short *)(param_1 + 0x150) = 0; + + if (*(unsigned short *)(param_1 + 0x152) = *(unsigned short *)(&chan->data[0x12])) + { + uVar4 = uVar4 | 0x10; + } + *(unsigned short *)((int)param_1 + 0x154) = 0; + if (*(unsigned short *)((int)param_1 + 0x156) = *(unsigned short *)(&chan->data[0x13])) + { + uVar4 = uVar4 | 0x20; + } + *(unsigned short *)(param_1 + 0x158) = 0; + if (*(unsigned short *)(param_1 + 0x15a) = *(unsigned short *)(&chan->data[0x15])) + { + uVar4 = uVar4 | 0x200; + } + *(unsigned short *)(param_1 + 0x15c) = 0; + if (*(unsigned short *)(param_1 + 0x15e) = *(unsigned short *)(&chan->data[0x16])) + { + uVar4 = uVar4 | 0x400; + } + *(unsigned short *)(param_1 + 0x160) = 0; + ; + if (*(unsigned short *)(param_1 + 0x162) = *(unsigned short *)(&chan->data[0x17])) + { + uVar4 = uVar4 | 0x1000; + } + *(unsigned short *)(param_1 + 0x164) = 0; + if (*(unsigned short *)((int)param_1 + 0x166) = *(unsigned short *)(&chan->data[0x11])) + { + uVar4 = uVar4 | 4; + } + *(unsigned short *)((int)param_1 + 0x168) = 0; + if (*(unsigned short *)(param_1 + 0x16a) = *(unsigned short *)(&chan->data[0x14])) + { + uVar4 = uVar4 | 0x80; + } + *(unsigned short *)((int)param_1 + 0x16c) = 0; + *(unsigned short *)((int)param_1 + 0x144) = uVar4; + *(unsigned int *)(param_1 + 0x1c) = *(unsigned int *)(param_1 + 0x1c) | 0x212; + OSRestoreInterrupts(); + +} + +void MIXReleaseChannel(int* param_1) +{ + __MIXChannel[*(param_1 + 6)].data[0] = 0; +} + +void MIXAdjustInput(int* param_1, int param_2) +{ + int* handle = &__MIXChannel[*(param_1 + 6)].data[0]; + handle[2] += param_2; + handle[1] |= 0x10000000; +} + +int MIXGetInput(int* param_1) +{ + int* handle = &__MIXChannel[*(param_1 + 6)].data[0]; + return handle[2]; +} + +void MIXAdjustPan(int* param_1, int param_2) +{ + struct MIXChannel* chan = &__MIXChannel[*(param_1 + 6)]; + int* handle = &__MIXChannel[*(param_1 + 6)].data[0]; + handle[5] = __MIXClampPan(handle[5] + param_2); + __MIXSetPan(chan); + chan->data[1] |= 0x40000000; +} + +int MIXGetPan(int* param_1) +{ + int* handle = &__MIXChannel[*(param_1 + 6)].data[0]; + return handle[5]; +} + +void MIXUnMute(int* param_1) +{ + int* handle = &__MIXChannel[*(param_1 + 6)].data[0]; + handle[1] &= ~4; + handle[1] |= 0x10000000; +} + +void MIXAdjustFader(int* param_1, int param_2) +{ + int* handle = &__MIXChannel[*(param_1 + 6)].data[0]; + handle[7] += param_2; + handle[1] |= 0x40000000; +} + +int MIXGetFader(int* param_1) +{ + int* handle = &__MIXChannel[*(param_1 + 6)].data[0]; + return handle[7]; +} \ No newline at end of file diff --git a/src/SB/Core/gc/iMix.h b/src/SB/Core/gc/iMix.h index 93eaa61e3..1f4983281 100644 --- a/src/SB/Core/gc/iMix.h +++ b/src/SB/Core/gc/iMix.h @@ -1,11 +1,23 @@ #ifndef IMIX_H #define IMIX_H -#include "iSnd.h" +#ifdef __cplusplus +extern "C" +{ +#endif + struct _AXVPB; -extern "C" { -void MIXUnMute(_AXVPB* p); +void MIXUnMute(int* param_1); + +// No DWARF data for this structure so this is entirely guesswork. +struct MIXChannel +{ + int data[24]; +}; + +#ifdef __cplusplus } +#endif #endif diff --git a/src/SB/Core/gc/iSnd.cpp b/src/SB/Core/gc/iSnd.cpp index 7ac9e89af..1f9d9f3e3 100644 --- a/src/SB/Core/gc/iSnd.cpp +++ b/src/SB/Core/gc/iSnd.cpp @@ -61,7 +61,7 @@ U32 iVolFromX(F32 param1) void iSndVolUpdate(xSndVoiceInfo* info, vinfo* vinfo) { - MIXUnMute(vinfo->voice); + MIXUnMute((int*)vinfo->voice); xSndInternalUpdateVoicePos(info); if ((info->flags & 8) != 0) { diff --git a/src/SB/Core/x/xCM.cpp b/src/SB/Core/x/xCM.cpp index 49d8e1cff..c4a8984cb 100644 --- a/src/SB/Core/x/xCM.cpp +++ b/src/SB/Core/x/xCM.cpp @@ -1,3 +1,115 @@ #include "xCM.h" +#include "xEvent.h" #include + +volatile static F32 credits_time; +static xCreditsData* credits_data; +static U32 credits_parentID; + +F32 dtscale; + +static void xCMprep(xCreditsData* data) +{ + /* + data seems to point to this general structure: + 0x00 - xCMheader + 0x18 - xCMcredits + 0x50 - xCMpreset* presets_array[xCMcredits.num_presets] + - xCMhunk* hunk_array[?] + */ + + char* dp; // In the DWARF. Don't know what this is used for. + xCMheader* hdr = (xCMheader*)data; + + if (hdr->magic != 0xBEEEEEEF) + { + return; + } + + xCMcredits* cp = (xCMcredits *)(&hdr[1]); + while ((int)cp - (int)data < hdr->total_size) + { + xCMpreset* pp = (xCMpreset*)(&cp[1]); + xCMhunk* hp = (xCMhunk*)(&pp[cp->num_presets]); + + for ( ; (int)hp - (int)cp < cp->credits_size; hp = (xCMhunk*)((int)hp + hp->hunk_size)) + { + switch (pp[hp->preset].align) + { + case 0: + case 1: + case 2: + case 3: + + if (hdr->state == 0) + { + if (hp->text1 != NULL) + { + hp->text1 -= (int)data; + } + if (hp->text2 != NULL) + { + hp->text2 -= (int)data; + } + } + else + { + if (hp->text1 != NULL) + { + hp->text1 += (int)data; + } + if (hp->text2 != NULL) + { + hp->text2 += (int)data; + } + } + break; + } + } + cp = (xCMcredits*)hp; + } + + hdr->state = hdr->state == 0 ? 1 : 0; +} + +void xCMupdate(F32 time) +{ + if (credits_data != 0) + { + credits_time += (time * dtscale); + if (credits_time >= *(F32*)((int)&credits_data->dummy + 0x10)) + { + xCMstop(); + } + } +} + +void xCMrender() +{ + xCMrender(credits_time, credits_data); +} + +void xCMstart(xCreditsData* data, F32 time, xBase* parent) +{ + if ((credits_data = data) != NULL) + { + credits_time = 0.0f; + + if (parent != NULL) + { + credits_parentID = parent->id; + } + } +} + +// Equivalent: scheduling +void xCMstop() +{ + credits_time = 10000.0f; + credits_data = NULL; + if (credits_parentID != 0) + { + zEntEvent(credits_parentID, 0x212); + } +} diff --git a/src/SB/Core/x/xCM.h b/src/SB/Core/x/xCM.h index 5062a5d20..e0ceb582a 100644 --- a/src/SB/Core/x/xCM.h +++ b/src/SB/Core/x/xCM.h @@ -2,6 +2,7 @@ #define XCM_H #include +#include "xColor.h" #include "xBase.h" struct xCreditsData @@ -9,8 +10,87 @@ struct xCreditsData U32 dummy; }; +class xCMheader +{ + // total size: 0x18 +public: + unsigned int magic; // offset 0x0, size 0x4 + unsigned int version; // offset 0x4, size 0x4 + unsigned int crdID; // offset 0x8, size 0x4 + unsigned int state; // offset 0xC, size 0x4 + float total_time; // offset 0x10, size 0x4 + unsigned int total_size; // offset 0x14, size 0x4 +}; + +class sxy +{ + // total size: 0x8 +public: + float x; // offset 0x0, size 0x4 + float y; // offset 0x4, size 0x4 +}; + +class fade +{ + // total size: 0x8 +public: + float start; // offset 0x0, size 0x4 + float end; // offset 0x4, size 0x4 +}; + +class xCMtextbox +{ + // total size: 0x20 +public: + unsigned int font; // offset 0x0, size 0x4 + class iColor_tag color; // offset 0x4, size 0x4 + class sxy char_size; // offset 0x8, size 0x8 + class sxy char_spacing; // offset 0x10, size 0x8 + class sxy box; // offset 0x18, size 0x8 +}; + +class xCMpreset +{ + // total size: 0x4C +public: + unsigned short num; // offset 0x0, size 0x2 + unsigned short align; // offset 0x2, size 0x2 + float delay; // offset 0x4, size 0x4 + float innerspace; // offset 0x8, size 0x4 + class xCMtextbox box[2]; // offset 0xC, size 0x40 +}; + +class xCMhunk +{ + // total size: 0x18 +public: + unsigned int hunk_size; // offset 0x0, size 0x4 + unsigned int preset; // offset 0x4, size 0x4 + float t0; // offset 0x8, size 0x4 + float t1; // offset 0xC, size 0x4 + char * text1; // offset 0x10, size 0x4 + char * text2; // offset 0x14, size 0x4 +}; + +class xCMcredits +{ + // total size: 0x38 +public: + unsigned int credits_size; // offset 0x0, size 0x4 + float len; // offset 0x4, size 0x4 + unsigned int flags; // offset 0x8, size 0x4 + sxy in; // offset 0xC, size 0x8 + sxy out; // offset 0x14, size 0x8 + float scroll_rate; // offset 0x1C, size 0x4 + float lifetime; // offset 0x20, size 0x4 + fade fin; // offset 0x24, size 0x8 + fade fout; // offset 0x2C, size 0x8 + unsigned int num_presets; // offset 0x34, size 0x4 +}; + void xCMupdate(F32 dt); void xCMrender(); +void xCMrender(F32 time, xCreditsData* data); void xCMstart(xCreditsData* data, F32, xBase* parent); void xCMstop(); diff --git a/src/SB/Core/x/xCamera.h b/src/SB/Core/x/xCamera.h index cc609bce5..b7780fdb1 100644 --- a/src/SB/Core/x/xCamera.h +++ b/src/SB/Core/x/xCamera.h @@ -223,14 +223,18 @@ void xCameraEnd(xCamera* cam, F32 seconds, S32 update_scrn_fx); void xCameraShowRaster(xCamera* cam); F32 xCameraGetFOV(const xCamera* cam); void xCameraSetFOV(xCamera* cam, F32 fov); -void xCameraMove(xCamera* cam, U32 flags, F32 dgoal, F32 hgoal, F32 pgoal, - F32 tm, F32 tm_acc, F32 tm_dec); +void xCameraMove(xCamera* cam, U32 flags, F32 dgoal, F32 hgoal, F32 pgoal, F32 tm, F32 tm_acc, + F32 tm_dec); void xCameraMove(xCamera* cam, const xVec3& loc); +void xCameraMove(xCamera* cam, const xVec3& loc, F32 maxSpeed); +void xCameraFOV(xCamera* cam, F32 fov, F32 maxSpeed, F32 dt); void xCameraRotate(xCamera* cam, const xMat3x3& m, F32 time, F32 accel, F32 decl); +void xCameraLookYPR(xCamera* cam, U32 flags, F32 yaw, F32 pitch, F32 roll, F32 tm, F32 tm_acc, + F32 tm_dec); F32 xCameraGetFOV(const xCamera* cam); void xCameraDoCollisions(S32 do_collis, S32 owner); void xCameraSetTargetMatrix(xCamera* cam, xMat4x3* mat); -void xCameraFXShake(F32 maxTime, F32 magnitude, F32 cycleMax, F32 rotate_magnitude, - F32 radius, xVec3* epicenter, xVec3* player); +void xCameraFXShake(F32 maxTime, F32 magnitude, F32 cycleMax, F32 rotate_magnitude, F32 radius, + xVec3* epicenter, xVec3* player); #endif diff --git a/src/SB/Core/x/xCutsceneMgr.h b/src/SB/Core/x/xCutsceneMgr.h index 7b287f8d8..922b87b63 100644 --- a/src/SB/Core/x/xCutsceneMgr.h +++ b/src/SB/Core/x/xCutsceneMgr.h @@ -35,6 +35,8 @@ struct xCutsceneMgr : xBase U32 stop; // 0x18 xCutsceneZbufferHack* zhack; F32 oldfov; + + void UpdateAndRender(F32); }; #endif diff --git a/src/SB/Core/x/xFX.h b/src/SB/Core/x/xFX.h index d09479ad1..4f85a47e0 100644 --- a/src/SB/Core/x/xFX.h +++ b/src/SB/Core/x/xFX.h @@ -110,6 +110,7 @@ void xFXFireworksLaunch(F32 countdownTime, const xVec3* pos, F32 fuelTime); void xFXFireworksUpdate(F32 dt); void xFXStreakInit(); void xFXStreakUpdate(F32 dt); +void xFXStreakUpdate(U32 streakID, const xVec3*, const xVec3*); void xFXStreakRender(); void xFXStreakStop(U32); void xFXShineInit(); diff --git a/src/SB/Core/x/xMath3.cpp b/src/SB/Core/x/xMath3.cpp index c3454ec39..a612628d9 100644 --- a/src/SB/Core/x/xMath3.cpp +++ b/src/SB/Core/x/xMath3.cpp @@ -4,12 +4,14 @@ #include #include -#include "iMath.h" // icos and isin +#include "iMath.h" +#include "xMath.h" // icos and isin #include "xClimate.h" // xMat3x3Identity #include "xMathInlines.h" // xasin, xatan2 //#include "xVec3Inlines.h" // xVec3Init, imported, realized xClimate has a declaration as well though. -xVec3 g_O3 = { 0, 0, 0 }; +const xVec3 g_O3 = { 0, 0, 0 }; +const xQuat g_IQ = { 0.0f, 0.0f, 0.0f, 1.0f }; S32 xPointInBox(const xBox* b, const xVec3* p) { @@ -248,32 +250,33 @@ void xMat4x3MoveLocalUp(xMat4x3* m, F32 mag) /* xMat3x3GetEuler (xMat3x3 const *, xVec3 *) */ void xMat3x3GetEuler(const xMat3x3* m, xVec3* a) { - F32 temp_f31; - F32 var_f1; - F32 var_f30; + F32 yaw = -xasin(m->at.y); + + F32 roll; + F32 pitch; - temp_f31 = -xasin(m->at.y); - if (temp_f31 < 1.5707964f) + if (yaw < (PI / 2)) { - if (temp_f31 > -1.5707964f) + if (yaw > -(PI / 2)) { - var_f30 = xatan2(m->at.x, m->at.z); - var_f1 = xatan2(m->right.y, m->up.y); + pitch = xatan2(m->at.x, m->at.z); + roll = xatan2(m->right.y, m->up.y); } else { - var_f30 = -xatan2(-m->up.x, m->up.x); - var_f1 = 0.0f; + pitch = -xatan2(-m->up.x, m->right.x); + roll = 0.0f; } } else { - var_f1 = 0.0f; - var_f30 = xatan2(-m->up.x, m->right.x); + pitch = xatan2(-m->up.x, m->right.x); + roll = 0.0f; } - a->x = var_f30; - a->y = temp_f31; - a->z = var_f1; + + a->x = pitch; + a->y = yaw; + a->z = roll; } /* xMat3x3Euler (xMat3x3 *, xVec3 const *) */ @@ -285,48 +288,31 @@ void xMat3x3Euler(xMat3x3* m, const xVec3* ypr) /* xQuatToMat (xQuat const *, xMat3x3 *) */ void xQuatToMat(const xQuat* q, xMat3x3* m) { - F32 temp_f10; - F32 temp_f11; - F32 temp_f12; - F32 temp_f13; - F32 temp_f1; - F32 temp_f2; - F32 temp_f3; - F32 temp_f3_2; - F32 temp_f4; - F32 temp_f4_2; - F32 temp_f5; - F32 temp_f5_2; - F32 temp_f6; - F32 temp_f7; - F32 temp_f8; - F32 temp_f9; + F32 tx = (2.0f * q->v.x); + F32 ty = (2.0f * q->v.y); + F32 tz = (2.0f * q->v.z); + F32 tsx = tx * q->s; + F32 tsy = ty * q->s; + F32 tsz = tz * q->s; + F32 txx = tx * q->v.x; + F32 txy = ty * q->v.x; + F32 txz = tz * q->v.x; + F32 tyy = ty * q->v.y; + F32 tyz = tz * q->v.y; + F32 tzz = tz * q->v.z; + + m->right.x = (1.0f - tyy) - tzz; + m->right.y = txy - tsz; + m->right.z = txz + tsy; + + m->up.x = txy + tsz; + m->up.y = (1.0f - tzz) - txx; + m->up.z = tyz - tsx; + + m->at.x = txz - tsy; + m->at.y = tyz + tsx; + m->at.z = (1.0f - txx) - tyy; - temp_f5 = q->v.y; - temp_f1 = q->v.z; - temp_f2 = 2.0f * temp_f5; - temp_f4 = q->v.x; - temp_f7 = 2.0f * temp_f1; - temp_f3 = q->s; - temp_f6 = 2.0f * temp_f4; - temp_f12 = temp_f2 * temp_f5; - temp_f13 = temp_f7 * temp_f1; - temp_f9 = temp_f7 * temp_f3; - temp_f10 = temp_f2 * temp_f4; - temp_f8 = temp_f2 * temp_f3; - temp_f11 = temp_f7 * temp_f4; - m->right.x = (1.0f - temp_f12) - temp_f13; - temp_f4_2 = temp_f6 * temp_f4; - m->right.y = temp_f10 - temp_f9; - temp_f3_2 = temp_f6 * temp_f3; - temp_f5_2 = temp_f7 * temp_f5; - m->right.z = temp_f11 + temp_f8; - m->up.x = temp_f10 + temp_f9; - m->up.y = (1.0f - temp_f13) - temp_f4_2; - m->up.z = temp_f5_2 - temp_f3_2; - m->at.x = temp_f11 - temp_f8; - m->at.y = temp_f5_2 + temp_f3_2; - m->at.z = (1.0f - temp_f4_2) - temp_f12; m->flags = 0; } @@ -404,6 +390,28 @@ void xQuatFromMat(xQuat* q, const xMat3x3* m) // } } +void xQuatFromAxisAngle(xQuat* q, const xVec3* a, F32 t) +{ + F32 t_2; + + if (t == 0.0f) + { + xQuatCopy(q, &g_IQ); + } + else + { + t_2 = isin(t * 0.5f); + q->s = icos((t * 0.5f)); + xVec3SMul(&q->v, a, t_2); + } +} + +void xQuatToAxisAngle(const xQuat* q, xVec3* a, F32* t) +{ + *t = 2.0f * xacos(q->s); + xVec3Normalize(a, &q->v); +} + /* xQuatSlerp (xQuat *, xQuat const *, xQuat const *, float) */ void xQuatSlerp(xQuat* q, const xQuat* a, const xQuat* b, F32 t) { @@ -589,6 +597,74 @@ void xMat3x3ScaleC(xMat3x3* m, F32 x, F32 y, F32 z) void xMat3x3RMulRotY(xMat3x3* o, const xMat3x3* m, F32 t) { + F32 cos = icos(t); + F32 sin = isin(t); + if (o == m) + { + F32 temp = o->right.z; + o->right.z = ((cos * o->right.z) - (sin * o->right.x)); + o->right.x = ((cos * o->right.x) + (sin * temp)); + + temp = o->up.z; + o->up.z = ((cos * temp) - (sin * o->up.x)); + o->up.x = ((cos * o->up.x) + (sin * temp)); + + temp = o->at.z; + o->at.z = ((cos * temp) - (sin * o->at.x)); + o->at.x = ((cos * o->at.x) + (sin * temp)); + } + else + { + o->right.x = (cos * m->right.x + (sin * m->right.z)); + o->right.y = m->right.y; + o->right.z = (cos * m->right.z - (sin * m->right.x)); + + o->up.x = (cos * m->up.x + (sin * m->up.z)); + o->up.y = m->up.y; + o->up.z = (cos * m->up.z - (sin * m->up.x)); + + o->at.x = (cos * m->at.x + (sin * m->at.z)); + o->at.y = m->at.y; + o->at.z = (cos * m->at.z - (sin * m->at.x)); + + o->flags = 0; + } +} + +void xMat3x3Transpose(xMat3x3* o, const xMat3x3* m) +{ + F32 temp; + + if (o == m) + { + temp = o->right.y; + o->right.y = o->up.x; + o->up.x = temp; + + temp = o->right.z; + o->right.z = o->at.x; + o->at.x = temp; + + temp = o->up.z; + o->up.z = o->at.y; + o->at.y = temp; + + return; + } + + o->right.x = m->right.x; + o->right.y = m->up.x; + o->right.z = m->at.x; + + o->up.x = m->right.y; + o->up.y = m->up.y; + o->up.z = m->at.y; + + o->at.x = m->right.z; + o->at.y = m->up.z; + o->at.z = m->at.z; + + o->flags = 0; } /* xMat3x3Mul (xMat3x3 *, xMat3x3 const *, xMat3x3 const *) */ @@ -674,6 +750,17 @@ void xBoxFromRay(xBox& box, const xRay3& ray) { } +void xBoxUnion(xBox& a, const xBox& b, const xBox& c) +{ + a.upper.x = MAX(b.upper.x, c.upper.x); + a.upper.y = MAX(b.upper.y, c.upper.y); + a.upper.z = MAX(b.upper.z, c.upper.z); + + a.lower.x = MIN(b.lower.x, c.lower.x); + a.lower.y = MIN(b.lower.y, c.lower.y); + a.lower.z = MIN(b.lower.z, c.lower.z); +} + void xMat3x3LMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) { } diff --git a/src/SB/Core/x/xMath3.h b/src/SB/Core/x/xMath3.h index 5d683b3de..dbfda11a5 100644 --- a/src/SB/Core/x/xMath3.h +++ b/src/SB/Core/x/xMath3.h @@ -1,6 +1,8 @@ #ifndef XMATH3_H #define XMATH3_H +#include "xMath.h" + #include "xVec3.h" #include "xVec3Inlines.h" @@ -76,9 +78,11 @@ struct xLine3 struct xRay3; -extern xVec3 g_O3; +extern const xQuat g_IQ; +extern const xVec3 g_O3; extern xVec3 g_X3; extern xVec3 g_Y3; +extern xVec3 g_NY3; extern xVec3 g_Z3; extern xMat4x3 g_I3; extern xVec3 g_Onez; @@ -89,7 +93,9 @@ void xMat4x3Mul(xMat4x3* o, const xMat4x3* a, const xMat4x3* b); void xMat3x3Euler(xMat3x3* m, F32 yaw, F32 pitch, F32 roll); void xMat4x3Toworld(xVec3* o, const xMat4x3* m, const xVec3* v); void xMat3x3RotC(xMat3x3* m, F32 _x, F32 _y, F32 _z, F32 t); +void xMat3x3RotX(xMat3x3* m, F32 t); void xMat3x3RotY(xMat3x3* m, F32 t); +void xMat3x3RotZ(xMat3x3* m, F32 t); void xMat3x3MulRotC(xMat3x3* o, xMat3x3* m, F32 _x, F32 _y, F32 _z, F32 t); void xMat4x3Identity(xMat4x3* m); void xMat3x3Normalize(xMat3x3* o, const xMat3x3* m); @@ -107,9 +113,11 @@ F32 xQuatGetAngle(const xQuat* q); void xQuatFromMat(xQuat* q, const xMat3x3* m); void xQuatSlerp(xQuat* q, const xQuat* a, const xQuat* b, F32 t); void xQuatConj(xQuat* o, const xQuat* q); +void xQuatCopy(xQuat*, const xQuat*); void xMat3x3LookAt(xMat3x3* m, const xVec3* pos, const xVec3* at); F32 xMat3x3LookVec(xMat3x3* m, const xVec3* at); void xBoxInitBoundOBB(xBox* o, const xBox* b, const xMat4x3* m); +void xBoxUnion(xBox& a, const xBox& b, const xBox& c); void xMat3x3Scale(xMat3x3* m, const xVec3* s); void xMat3x3ScaleC(xMat3x3* m, F32 x, F32 y, F32 z); void xMat3x3RMulRotY(xMat3x3* o, const xMat3x3* m, F32 t); diff --git a/src/SB/Core/x/xMathInlines.h b/src/SB/Core/x/xMathInlines.h index 4aec695d7..bf7db9547 100644 --- a/src/SB/Core/x/xMathInlines.h +++ b/src/SB/Core/x/xMathInlines.h @@ -13,6 +13,9 @@ F32 xpow(F32 x, F32 y); F32 SQ(F32 x); +F32 LERP(F32 x, F32 y, F32 z); +U8 LERP(float x, U8 y, U8 z); + void xsqrtfast(F32& out, F32 x); #endif diff --git a/src/SB/Core/x/xSnd.cpp b/src/SB/Core/x/xSnd.cpp index 0cf0c6839..44db85071 100644 --- a/src/SB/Core/x/xSnd.cpp +++ b/src/SB/Core/x/xSnd.cpp @@ -15,6 +15,8 @@ extern F32 _598; extern F32 _599; extern xSndGlobals gSnd; +static S32 faders_active; + void xSndInit() { iSndInit(); @@ -86,6 +88,49 @@ void xSndResume() sDelayedPaused = 0; } +void xSndPauseAll(U32 pause_effects, U32 pause_streams) +{ + sDelayedPaused = pause_effects; + + for (U32 i = 0; i < 0x40; i++) + { + if (gSnd.voice[i].flags & 1) + { + if (gSnd.voice[i].flags & 2) + { + iSndPause(gSnd.voice[i].sndID, pause_effects); + } + else if (gSnd.voice[i].flags & 4) + { + iSndPause(gSnd.voice[i].sndID, pause_streams); + } + } + } +} + +void xSndPauseCategory(U32 mask, U32 pause) +{ + for (U32 i = 0; i < 0x40; i++) + { + if ((gSnd.voice[i].flags & 1) && (mask & 1 << gSnd.voice[i].category)) + { + iSndPause(gSnd.voice[i].sndID, pause); + } + } +} + +void xSndStopAll(U32 mask) +{ + for (U32 i = 0; i < 0x40; i++) + { + if ((gSnd.voice[i].flags & 1) && (mask & 1 << gSnd.voice[i].category)) + { + iSndStop(gSnd.voice[i].sndID); + } + } + xSndDelayedInit(); +} + void xSndSetCategoryVol(sound_category category, F32 vol) { gSnd.categoryVolFader[category] = vol; @@ -101,6 +146,32 @@ void xSndDelayedInit() sDelayedPaused = 0; } +void xSndAddDelayed(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, xEnt* parentEnt, xVec3* pos, F32 innerRadius, F32 outerRadius, sound_category category, F32 delay) +{ + _xSndDelayed* snd = &sDelayedSnd[0]; + + for (U32 i = 0x10; i != 0; i--) + { + if (snd->delay <= 0.0f) + { + snd->id = id; + snd->vol = vol; + snd->pitch = pitch; + snd->priority = priority; + snd->flags = flags; + snd->parentID = parentID; + snd->parentEnt = parentEnt; + snd->pos = pos; + snd->innerRadius = innerRadius; + snd->outerRadius = outerRadius; + snd->category = category; + snd->delay = delay; + return; + } + snd++; + } +} + void xSndCalculateListenerPosition() { xMat4x3* pMat; @@ -129,53 +200,36 @@ void xSndCalculateListenerPosition() void xSndInternalUpdateVoicePos(xSndVoiceInfo* pVoice) { - U32 flags = pVoice->flags; - xVec3* ent; - - if ((flags & 1) != 0) + if ((pVoice->flags & 1) && (pVoice->flags & 8)) { - // FIXME: WIP - // if ((flags & 8) != 0) - // { - // if ((flags & 0x10) != 0) - // { - // if (pVoice->parentPos == (xVec3*)0x0) - // { - // if (pVoice->parentID == 0) - // { - // if ((flags & 8) == 0) - // { - // pVoice->actualPos = gSnd.pos; - // } - // } - // else - // { - // ent = pVoice->parentID & 0xfffffffc); - // if ((flags & 0x800) == 0) - // { - // if ((? & 1) == 0) - // { - // pVoice->flags = flags & 0xffffffef; - // } - // else - // { - // pxVar2 = (xVec3*)xEntGetPos((xEnt*)ent); - // xVec3Copy(pVoice->actualPos, ent); - // } - // } - // else - // { - // pVoice->actualPos = ent; - // } - // } - // } - // else - // { - // pVoice->actualPos = pVoice->parentPos; - // } - // } - // xSndProcessSoundPos(pVoice->actualPos, pVoice->playPos); - // } + if (pVoice->flags & 0x10) + { + if (pVoice->parentPos != NULL) + { + pVoice->actualPos = *pVoice->parentPos; + } + else if (pVoice->parentID != 0) + { + xEnt* ent = (xEnt*)(pVoice->parentID & 0xfffffffc); // uhh... + if (pVoice->flags & 0x800) + { + pVoice->actualPos = *(xVec3*)(ent); + } + else if (ent->baseFlags & 1) + { + xVec3Copy(&pVoice->actualPos, xEntGetPos(ent)); + } + else + { + pVoice->flags &= 0xffffffef; + } + } + else if (!(pVoice->flags & 8)) + { + pVoice->actualPos = gSnd.pos; + } + } + xSndProcessSoundPos(&pVoice->actualPos, &pVoice->playPos); } } @@ -193,7 +247,7 @@ void xSndSetListenerData(sound_listener_type listenerType, const xMat4x3* matrix * This code appears to be correct but there appears to be a possibility * of accessing this array out of bounds. * It may be possible the dwarf data for sound_listener_type is incorrect - * Otherwise it could be a potential bug + * Otherwise it could be a potential bug * (Gamecube audio bug source????) */ int i = (int)listenerType; @@ -304,6 +358,34 @@ void xSndSetExternalCallback(void (*callback)(U32)) iSndSetExternalCallback(callback); } +void reset_faders() +{ + faders_active = 0; +} + +class fade_data { + // total size: 0x18 +public: + unsigned char in; // offset 0x0, size 0x1 + unsigned int handle; // offset 0x4, size 0x4 + float start_delay; // offset 0x8, size 0x4 + float time; // offset 0xC, size 0x4 + float end_time; // offset 0x10, size 0x4 + float volume; // offset 0x14, size 0x4 + + void operator=(const fade_data& rhs); +}; + +void fade_data::operator=(const fade_data& rhs) +{ + in = rhs.in; + handle = rhs.handle; + start_delay = rhs.start_delay; + time = rhs.time; + end_time = rhs.end_time; + volume = rhs.volume; +} + U32 xSndStreamReady(U32 owner) { xSndVoiceInfo* begin = gSnd.voice; @@ -313,7 +395,14 @@ U32 xSndStreamReady(U32 owner) { if (v->lock_owner == owner) { - return (v->flags & 1) >> 5; // FIXME: Missing cntlzw instruction. + if (v->flags & 1) + { + return 0; + } + else + { + return 1; + } } } diff --git a/src/SB/Game/zCamera.cpp b/src/SB/Game/zCamera.cpp index d2c395f91..80e766758 100644 --- a/src/SB/Game/zCamera.cpp +++ b/src/SB/Game/zCamera.cpp @@ -94,7 +94,7 @@ static F32 rewardTiltTime = 1.5f; static F32 rewardTiltAmount = -0.22f; extern zGlobals globals; -extern xVec3 g_O3; +extern const xVec3 g_O3; extern F32 gSkipTimeFlythrough; extern F32 zCamera_f_75_0; // 75.0 @@ -287,6 +287,118 @@ static F32 MatrixSpeed(zFlyKey keys[]) return xacos(m) * zCamera_f_114_592 * zCamera_f_30_0; } +static S32 zCameraFlyUpdate(xCamera* cam, F32 dt) +{ + S32 i; + S32 flyIdx; + S32 numKeys; + S32 flySize; + F32 flyLerp; + F32 flyFrame; + zFlyKey keys[4]; + F32 matdiff1; + F32 matdiff2; + F32 matdiff3; + xMat3x3 tmpMat; + xQuat quats[2]; + xQuat qresult; + + if ((globals.pad0->pressed & 0x50000) && zcam_flytime > gSkipTimeFlythrough) + { + zcam_flytime = 0.033333335f * zcam_flysize; + } + + flyFrame = 30.0f * zcam_flytime; + numKeys = std::floorf(flyFrame); + flyLerp = flyFrame - std::floorf(flyFrame); + + flySize = (S32)(zcam_flysize >> 6) - 1; + if (!(numKeys < flySize)) + { + return 0; + } + + flyIdx = numKeys; + if (numKeys - 1 >= 0) + { + flyIdx = numKeys - 1; + } + + keys[0] = *((zFlyKey*)zcam_flydata + flyIdx); + keys[1] = *((zFlyKey*)zcam_flydata + numKeys); + keys[2] = *((zFlyKey*)zcam_flydata + (numKeys + 1)); + + flyIdx = numKeys + 1; + if (numKeys + 2 < flySize) + { + flyIdx = numKeys + 2; + } + + keys[3] = *((zFlyKey*)zcam_flydata + flyIdx); + + // Reverses the byte order (endianness) of 64 4-byte blocks + U8* framePtr = (U8*)&keys[0].frame; + for (i = 64; i > 0; i--) + { + S8 tmp1 = *framePtr; + S8 tmp2 = *(framePtr + 1); + *framePtr = *(framePtr + 3); + *(framePtr + 1) = *(framePtr + 2); + *(framePtr + 2) = tmp2; + *(framePtr + 3) = tmp1; + + framePtr += 4; + } + + if (0 < numKeys) + { + matdiff1 = TranSpeed(&keys[0]); + matdiff2 = TranSpeed(&keys[1]); + matdiff3 = TranSpeed(&keys[2]); + + if (matdiff2 > 10.0f && matdiff2 > 5.0f * matdiff1 && matdiff2 > 5.0f * matdiff3) + { + flyLerp = 0.0f; + } + else + { + matdiff1 = MatrixSpeed(&keys[0]); + matdiff2 = MatrixSpeed(&keys[1]); + matdiff3 = MatrixSpeed(&keys[2]); + + if (matdiff2 > 45.0f && matdiff2 > matdiff1 * 5.0f && matdiff2 > matdiff3 * 5.0f) + { + flyLerp = 0.0f; + } + } + } + + for (i = 0; i < 2; i++) + { + tmpMat.right.x = -keys[i + 1].matrix[0]; + tmpMat.right.y = -keys[i + 1].matrix[1]; + tmpMat.right.z = -keys[i + 1].matrix[2]; + + tmpMat.up.x = keys[i + 1].matrix[3]; + tmpMat.up.y = keys[i + 1].matrix[4]; + tmpMat.up.z = keys[i + 1].matrix[5]; + + tmpMat.at.x = -keys[i + 1].matrix[6]; + tmpMat.at.y = -keys[i + 1].matrix[7]; + tmpMat.at.z = -keys[i + 1].matrix[8]; + + xQuatFromMat(&quats[i], &tmpMat); + } + + xQuatSlerp(&qresult, &quats[0], &quats[1], flyLerp); + xQuatToMat(&qresult, &cam->mat); + xVec3Lerp(&cam->mat.pos, (xVec3*)&keys[1].matrix[9], (xVec3*)&keys[2].matrix[9], flyLerp); + + zcam_flytime += dt; + + return 1; +} + void zCameraFlyStart(U32 assetID) { st_PKR_ASSET_TOCINFO info; @@ -315,6 +427,161 @@ void zCameraFlyStart(U32 assetID) } } +static void zCameraFlyRestoreBackup(xCamera* backup) +{ + globals.camera.mat = backup->mat; + globals.camera.omat = backup->omat; + globals.camera.mbasis = backup->mbasis; + globals.camera.bound = backup->bound; + globals.camera.focus = backup->focus; + + globals.camera.flags = backup->flags; + globals.camera.tmr = backup->tmr; + globals.camera.tm_acc = backup->tm_acc; + globals.camera.tm_dec = backup->tm_dec; + globals.camera.ltmr = backup->ltmr; + globals.camera.ltm_acc = backup->ltm_acc; + globals.camera.ltm_dec = backup->ltm_dec; + globals.camera.dmin = backup->dmin; + globals.camera.dmax = backup->dmax; + globals.camera.dcur = backup->dcur; + globals.camera.dgoal = backup->dgoal; + globals.camera.hmin = backup->hmin; + globals.camera.hmax = backup->hmax; + globals.camera.hcur = backup->hcur; + globals.camera.hgoal = backup->hgoal; + globals.camera.pmin = backup->pmin; + globals.camera.pmax = backup->pmax; + globals.camera.pcur = backup->pcur; + globals.camera.pgoal = backup->pgoal; + globals.camera.depv = backup->depv; + globals.camera.hepv = backup->hepv; + globals.camera.pepv = backup->pepv; + globals.camera.orn_epv = backup->orn_epv; + globals.camera.yaw_epv = backup->yaw_epv; + globals.camera.pitch_epv = backup->pitch_epv; + globals.camera.roll_epv = backup->roll_epv; + globals.camera.orn_cur = backup->orn_cur; + globals.camera.orn_goal = backup->orn_goal; + globals.camera.orn_diff = backup->orn_diff; + globals.camera.yaw_cur = backup->yaw_cur; + globals.camera.yaw_goal = backup->yaw_goal; + globals.camera.pitch_cur = backup->pitch_cur; + globals.camera.pitch_goal = backup->pitch_goal; + globals.camera.roll_cur = backup->roll_cur; + globals.camera.roll_goal = backup->roll_goal; + globals.camera.dct = backup->dct; + globals.camera.dcd = backup->dcd; + globals.camera.dccv = backup->dccv; + globals.camera.dcsv = backup->dcsv; + globals.camera.hct = backup->hct; + globals.camera.hcd = backup->hcd; + globals.camera.hccv = backup->hccv; + globals.camera.hcsv = backup->hcsv; + globals.camera.pct = backup->pct; + globals.camera.pcd = backup->pcd; + globals.camera.pccv = backup->pccv; + globals.camera.pcsv = backup->pcsv; + globals.camera.orn_ct = backup->orn_ct; + globals.camera.orn_cd = backup->orn_cd; + globals.camera.orn_ccv = backup->orn_ccv; + globals.camera.orn_csv = backup->orn_csv; + globals.camera.yaw_ct = backup->yaw_ct; + globals.camera.yaw_cd = backup->yaw_cd; + globals.camera.yaw_ccv = backup->yaw_ccv; + globals.camera.yaw_csv = backup->yaw_csv; + globals.camera.pitch_ct = backup->pitch_ct; + globals.camera.pitch_cd = backup->pitch_cd; + globals.camera.pitch_ccv = backup->pitch_ccv; + globals.camera.pitch_csv = backup->pitch_csv; + globals.camera.roll_ct = backup->roll_ct; + globals.camera.roll_cd = backup->roll_cd; + globals.camera.roll_ccv = backup->roll_ccv; + globals.camera.roll_csv = backup->roll_csv; +} + +static S32 zCameraRewardUpdate(xCamera* cam, F32 dt) +{ + xCameraUpdate(cam, dt); + + xVec3 v = { 0.0f, 0.0f, 0.0f }; + + xVec3Copy(&v, (xVec3*)&globals.player.ent.model->Mat->pos); + v.y -= 0.7f; + + if (zcam_near) + { + if (globals.player.s->pcType == ePlayer_SB) + { + rewardMove = 1.3f; + rewardMoveSpeed = 0.68f; + rewardZoomSpeed = 7.1f; + rewardZoomAmount = 108.0f; + rewardTiltTime = 1.5f; + rewardTiltAmount = -0.22f; + } + else if (globals.player.s->pcType == ePlayer_Patrick) + { + rewardMove = 1.6f; + rewardMoveSpeed = 0.68f; + rewardZoomSpeed = 7.1f; + rewardZoomAmount = 108.0f; + rewardTiltTime = 1.0f; + rewardTiltAmount = -0.25f; + } + else if (globals.player.s->pcType == ePlayer_Sandy) + { + rewardMove = 1.3f; + rewardMoveSpeed = 0.68f; + rewardZoomSpeed = 7.1f; + rewardZoomAmount = 108.0f; + rewardTiltTime = 1.5f; + rewardTiltAmount = -0.22f; + } + } + else + { + if (globals.player.s->pcType == ePlayer_SB) + { + rewardMove = 1.5f; + rewardMoveSpeed = 1.1f; + rewardZoomSpeed = 5.9f; + rewardZoomAmount = 100.0f; + rewardTiltTime = 1.5f; + rewardTiltAmount = -0.2f; + } + else if (globals.player.s->pcType == ePlayer_Patrick) + { + rewardMove = 1.5f; + rewardMoveSpeed = 1.1f; + rewardZoomSpeed = 5.9f; + rewardZoomAmount = 100.0f; + rewardTiltTime = 1.5f; + rewardTiltAmount = -0.2f; + } + else if (globals.player.s->pcType == ePlayer_Sandy) + { + rewardMove = 1.5f; + rewardMoveSpeed = 1.1f; + rewardZoomSpeed = 5.9f; + rewardZoomAmount = 100.0f; + rewardTiltTime = 1.5f; + rewardTiltAmount = -0.2f; + } + } + + if (xVec3Dist2((xVec3*)&globals.player.ent.model->Mat->pos, &globals.camera.mat.pos) > + SQR(rewardMove)) + { + xCameraMove(cam, v, rewardMoveSpeed * dt); + xCameraFOV(cam, rewardZoomAmount, rewardZoomSpeed, dt); + xCameraLookYPR(cam, 0x0, globals.camera.yaw_cur, rewardTiltAmount, globals.camera.roll_cur, + rewardTiltTime, 0.1f, 0.1f); + } + + return 1; +} + void zCameraFreeLookSetGoals(xCamera* cam, F32 pitch_s, F32& dgoal, F32& hgoal, F32& pitch_goal, F32& lktm, F32 dt) { @@ -511,6 +778,65 @@ S32 zCameraGetConvers() return zcam_convers; } +void zCameraSetConvers(S32 on) +{ + xCamera& cam = globals.camera; + zcam_convers = on; + static U8 saved = 0; + + if (on) + { + cam = zcam_backupconvers; + saved = 1; + zcam_dest = NULL; + zcam_tmr = 0.0f; + } + else + { + xCameraSetFOV(&cam, 75.0f); + zcam_fovcurr = 75.0f; + + if (saved) + { + zCameraFlyRestoreBackup(&zcam_backupconvers); + xCameraMove(&cam, 0x2E, cam.dcur, cam.hcur, cam.pcur, 0.0f, 0.0f, 0.0f); + saved = 0; + } + } +} + +void zCameraDoTrans(xCamAsset* asset, F32 ttime) +{ + xMat3x3 m; + + zcam_dest = asset; + + ttime = ttime > 0.0f ? ttime : asset->trans_time; + + zcam_tmr = ttime; + zcam_ttm = ttime; + + if (ttime <= 0.0f) + { + globals.camera.mat.right = asset->right; + globals.camera.mat.up = asset->up; + globals.camera.mat.at = asset->at; + globals.camera.mat.pos = asset->pos; + + zcam_fovcurr = asset->fov; + zcam_fovdest = asset->fov; + } + else + { + m.right = asset->right; + m.up = asset->up; + m.at = asset->at; + + xQuatFromMat(&zcam_quat, &m); + zcam_fovdest = asset->fov; + } +} + void zCameraTranslate(xCamera* cam, F32 x, F32 y, F32 z) { cam->mat.pos.x += x; @@ -521,6 +847,24 @@ void zCameraTranslate(xCamera* cam, F32 x, F32 y, F32 z) cam->tran_accum.z += z; } +void zCameraEnableWallJump(xCamera* cam, const xVec3& collNormal) +{ + if (wall_jump_enabled != WJVS_ENABLED) + { + wall_jump_enabled = WJVS_ENABLING; + } + + xVec3 up = { 0.0f, 0.0f, 0.0f }; + + xVec3Cross(&wall_jump_view, &collNormal, &up); + xVec3Normalize(&wall_jump_view, &wall_jump_view); + + if (xVec3Dot(&wall_jump_view, &globals.camera.mat.at) < 0.0f) + { + xVec3Sub(&wall_jump_view, &g_O3, &wall_jump_view); + } +} + void zCameraDisableWallJump(xCamera* cam) { if (wall_jump_enabled != WJVS_DISABLED) diff --git a/src/SB/Game/zEnt.h b/src/SB/Game/zEnt.h index 71673cef3..48edaa307 100644 --- a/src/SB/Game/zEnt.h +++ b/src/SB/Game/zEnt.h @@ -26,15 +26,15 @@ struct zEnt : xEnt void checkpoint_collision_hack(zEnt* ent); char* zParamGetString(xModelAssetParam* param, U32 size, char* tok, char* def); -S32 zParamGetFloatList(xModelAssetParam* param, U32 size, const char* tok, S32 count, - F32* def, F32* result); +S32 zParamGetFloatList(xModelAssetParam* param, U32 size, const char* tok, S32 count, F32* def, + F32* result); void zEntGetShadowParams(xEnt* ent, xVec3* center, F32* radius, xEntShadow::radius_enum rtype); S32 zParamGetVector(xModelAssetParam* param, U32 size, const char* tok, xVec3 result, xVec3*); S32 zParamGetVector(xModelAssetParam* param, U32 size, char* tok, xVec3 result, xVec3*); S32 zParamGetFloatList(xModelAssetParam* param, U32 size, char* tok, S32 count, F32* def, - F32* result); + F32* result); S32 zParamGetFloatList(xModelAssetParam* param, U32 size, char* tok, S32 count, F32* def, - F32* result); + F32* result); F32 zParamGetFloat(xModelAssetParam* param, U32 size, const char* tok, F32 def); F32 zParamGetFloat(xModelAssetParam* param, U32 size, char* tok, F32 def); S32 zParamGetInt(xModelAssetParam* param, U32 size, const char* tok, S32 def); @@ -57,7 +57,7 @@ void zEntInit(zEnt* ent, xEntAsset* asset, U32 type); // TODO: Misplaced Inlines/Weak functions WEAK void xModelAnimCollStop(xModelInstance& m); WEAK xMat4x3* xEntGetFrame(const xEnt* ent); -WEAK void xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, - const xVec3* pos, F32 radius, sound_category category, F32 delay); +WEAK void xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, const xVec3* pos, + F32 radius, sound_category category, F32 delay); #endif diff --git a/src/SB/Game/zEntHangable.cpp b/src/SB/Game/zEntHangable.cpp index 30999a894..3e8192212 100644 --- a/src/SB/Game/zEntHangable.cpp +++ b/src/SB/Game/zEntHangable.cpp @@ -1,5 +1,125 @@ -#include "xMath3.h" -#include "xVec3.h" +#include "xBase.h" +#include "xEnt.h" +#include "xLinkAsset.h" +#include "xString.h" +#include "zParEmitter.h" +#include + #include "zEntHangable.h" -#include +static zParEmitter* sCandleEmitter; +static zParEmitter* sCandleSmokeEmitter; +static U32 sChandelierHash; +static zParEmitter* sMountEmitter; + +void zEntHangable_SetupFX() +{ + sCandleEmitter = zParEmitterFind("PAREMIT_CHAND_CANDLE"); + sCandleSmokeEmitter = zParEmitterFind("PAREMIT_CHAND_CANDLE_SMOKE"); + sChandelierHash = xStrHash("rlii0006"); + sMountEmitter = zParEmitterFind("PAREMIT_HANGABLE_MOUNT"); +} + +static void HangableSetup(zEntHangable* ent, xEntAsset* asset) +{ + xEntHangableAsset* hangAsset; + xVec3* center; + xMat3x3 hackMat; +} + +void zEntHangable_Init(void* a, void* b) +{ + zEntHangable_Init((zEntHangable*)a, (xEntAsset*)b); +} + +void zEntHangable_Init(zEntHangable* ent, xEntAsset* asset) +{ + zEntInit(ent, asset, 'HANG'); + + if (ent->linkCount) + { + // TODO: Not quite correct + ent->link = (xLinkAsset*)(ent->asset + 1); + } + else + { + ent->link = NULL; + } + + HangableSetup(ent, asset); +} + +static void zEntHangable_UpdateFX(zEntHangable* ent) +{ + xVec3 offset_rlii0006[8]; + xVec3* local_offset; + xParEmitterCustomSettings info; + zParEmitter* emitter; + S32 i; +} + +void zEntHangable_Update(zEntHangable* ent, xScene*, F32 dt) +{ + xVec3 unitHang; +} + +static void zEntHangableMountFX(zEntHangable*) +{ +} + +S32 zEntHangableEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase*) +{ + zEntHangable* ent; // r20 + zEnt* follow; // r2 + // FloatAndVoid dist; // r29+0x20C + return 0; +} + +static bool HangableIsMovingTooMuch(xVec3* a, xVec3* b, xVec3* c, xVec3* d) +{ + return false; +} + +void zEntHangable_SetMatrix(zEntHangable* ent, F32 f) +{ +} + +void zEntHangable_Save(zEntHangable* ent, xSerial* s) +{ + zEntSave(ent, s); +} + +void zEntHangable_Load(zEntHangable* ent, xSerial* s) +{ + zEntLoad(ent, s); +} + +void zEntHangable_Reset(zEntHangable* ent) +{ + zEntHangable_SetShaggy(ent, NULL); + zEntHangable_SetFollow(ent, NULL); + xEntReset(ent); + HangableSetup(ent, ent->asset); +} + +void zEntHangable_SetShaggy(zEntHangable* ent, zEnt* b) +{ +} + +void zEntHangable_FollowUpdate(zEntHangable* ent) +{ + xVec3* center; +} + +void zEntHangable_SetFollow(zEntHangable* ent, zEnt* b) +{ + if (b) + { + ent->follow = b; + zEntHangable_FollowUpdate(ent); + } + else if (ent->follow) + { + ent->follow = NULL; + } +} diff --git a/src/SB/Game/zEntHangable.h b/src/SB/Game/zEntHangable.h index 5335607db..afa9702a8 100644 --- a/src/SB/Game/zEntHangable.h +++ b/src/SB/Game/zEntHangable.h @@ -35,8 +35,11 @@ struct zEntHangable : zEnt void zEntHangable_SetupFX(); void zEntHangable_Init(void* ent, void* asset); +void zEntHangable_Init(zEntHangable*, xEntAsset*); void zEntHangable_Save(zEntHangable* ent, xSerial* s); void zEntHangable_Load(zEntHangable* ent, xSerial* s); void zEntHangable_Reset(zEntHangable* ent); +void zEntHangable_SetShaggy(zEntHangable* ent, zEnt* b); +void zEntHangable_SetFollow(zEntHangable* ent, zEnt* b); #endif diff --git a/src/SB/Game/zEntPlayer.cpp b/src/SB/Game/zEntPlayer.cpp index f50225e65..1f34675cf 100644 --- a/src/SB/Game/zEntPlayer.cpp +++ b/src/SB/Game/zEntPlayer.cpp @@ -3890,7 +3890,7 @@ void zEntPlayer_GiveLevelPickupCurrentLevel(S32 quantity) xVec3* GetPosVec(xBase* base) { - xVec3* vec = &g_O3; + xVec3* vec = (xVec3*)&g_O3; switch (base->baseType) { diff --git a/src/SB/Game/zFX.h b/src/SB/Game/zFX.h index 3918de9a5..35ff9442b 100644 --- a/src/SB/Game/zFX.h +++ b/src/SB/Game/zFX.h @@ -88,8 +88,11 @@ void xDebugAddTweak(const char* unk1, const char* unk2, const tweak_callback* un xFXRing* zFXMuscleArmWave(const xVec3* pos); +void zFX_SpawnBubbleTrail(const xVec3*, unsigned int); void zFX_SpawnBubbleTrail(const xVec3* pos, unsigned int num, const xVec3* pos_rnd, const xVec3* vel_rnd); +void zFX_SpawnBubbleTrail(const xVec3*, const xVec3*, const xVec3*, const xVec3*, unsigned int, + const xVec3*, const xVec3*, float); void zFX_SpawnBubbleMenuTrail(const xVec3* pos, U32 num, const xVec3* pos_rnd, const xVec3* vel_rnd); diff --git a/src/SB/Game/zNPCFXCinematic.cpp b/src/SB/Game/zNPCFXCinematic.cpp index ab3ca25c4..55d859e50 100644 --- a/src/SB/Game/zNPCFXCinematic.cpp +++ b/src/SB/Game/zNPCFXCinematic.cpp @@ -1,15 +1,695 @@ #include "xVec3.h" #include "xMath3.h" +#include "xParEmitter.h" #include "zNPCFXCinematic.h" #include -#include "xCutscene.h" + +static S32 init = 0; void zNPCFXShutdown() { } +void zNPCFXCinematic_Init() +{ + if (!init) + { + init = 1; + } +} + +void NCIN_Par_BPLANK_JET_1_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_BPLANK_JET_1"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_BPLANK_JET_2_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_BPLANK_JET_2"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_BPLANK_SBB_FLAMES_1_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_SBB_FLAMES_1"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_BPLANK_SBB_FLAMES_2_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_SBB_FLAMES_2"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_BPLANK_SBB_JET_1_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_SBB_JET_1"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_BPLANK_SBB_JET_2_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_SBB_JET_2"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_BPLANK_SBB_SMOKE_1_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_SBB_SMOKE_1"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_BPLANK_SBB_SMOKE_2_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_SBB_SMOKE_2"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_CIN_BIGDUP_SMOKE_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_CIN_BIGUP_SMOKE"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_CIN_BIGDUP_SPAWN_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_CIN_BIGUP_SPAWN"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Par_CIN_PLATFORM_JETS_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + fxrec->fxdata.pardata.emitter = zParEmitterFind("PAREMIT_CIN_PLATFORM_JETS"); + + if (fxrec->fxdata.pardata.emitter->tasset) + { + if (fxrec->fxdata.pardata.emitter->tasset->emit_type != 15) + { + fxrec->fxdata.pardata.emitter = NULL; + } + } + } + + if (fxrec->fxdata.pardata.emitter == NULL) + { + fxrec->flg_stat |= 4; + return; + } + + F32& float_accum = fxrec->pos_A[1].y; + + if (float_accum < 0.0f) + { + U8 val = fxrec->fxdata.pardata.emitter->emit_pad[0]; + float_accum = 20.0f + val; + } + + fxrec->pos_B[0] = 5.0f; +} + +void NCIN_Generic_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } +} + +void NCIN_BubSlam(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (!(fxrec->flg_stat & 2)) + { + return; + } + + switch (fxrec->typ_ncinfx) + { + case 3: + zFX_SpawnBubbleSlam(&fxrec->pos_A[0], 64, fxrec->tym_beg, fxrec->tym_end, fxrec->tym_end); + break; + case 2: + zFX_SpawnBubbleSlam(&fxrec->pos_A[0], 128, fxrec->tym_beg, fxrec->tym_end, fxrec->tym_end); + break; + default: + break; + } +} + +void NCIN_BubTrailBone_AR(const zCutsceneMgr*, NCINEntry* fxrec, RpAtomic*, RwMatrixTag*, U32 num_1, U32 num_2) +{ + S32 ifx = fxrec->pos_A[1].x; + S32 ify = fxrec->pos_A[1].y; + + if (num_1 != ifx) + { + return; + } + + xVec3 pos = fxrec->pos_A[2]; + + if (ify > 0) + { + xVec3& offset = fxrec->pos_B[ify]; + pos += offset; + } + + zFX_SpawnBubbleTrail(&pos, 1); +} + +void NCIN_BubHit(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + else + { + if (fxrec->flg_stat & 2) + { + zFX_SpawnBubbleHit(&fxrec->pos_A[0], 16); + } + + zFX_SpawnBubbleHit(&fxrec->pos_A[0], 3); + } +} + +void NCIN_Zapper(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + + if (fxrec->idx_anim == 29 || fxrec->idx_anim == 8) + { + if (fxrec->fxdata.lytdata.lyt_zap != NULL) + { + zLightningKill(fxrec->fxdata.lytdata.lyt_zap); + } + + fxrec->fxdata.lytdata.lyt_zap = NULL; + } + return; + } + + if (fxrec->flg_stat & 2) + { + memset(&fxrec->fxdata.arcdata.lightning, 0, sizeof(fxrec->fxdata.arcdata.lightning)); + } + + if (fxrec->fxdata.lytdata.lyt_zap == NULL) + { + fxrec->flg_stat |= 4; + } +} + +void NCIN_HammerShock(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + zFXHammer(&fxrec->pos_A[0]); + fxrec->flg_stat |= 4; + } +} + +void NCIN_HammerStreak_Upd(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + + xFXStreakStop(fxrec->fxdata.strkdata.sid_horz); + xFXStreakStop(fxrec->fxdata.strkdata.sid_vert); + + fxrec->fxdata.strkdata.sid_horz = 57005; + fxrec->fxdata.strkdata.sid_vert = 57005; + + return; + } + + if (fxrec->flg_stat & 2) + { + en_npcstreak styp_h = NPC_STRK_HAMMERSMASH_HORZ; + en_npcstreak styp_v = NPC_STRK_HAMMERSMASH_VERT; + + fxrec->fxdata.strkdata.sid_horz = NPCC_StreakCreate(styp_h); + fxrec->fxdata.strkdata.sid_vert = NPCC_StreakCreate(styp_v); + } +} + +void NCIN_HammerStreak_AR(const zCutsceneMgr*, NCINEntry* fxrec, RpAtomic*, RwMatrixTag*, U32 num_1, + U32 num_2) +{ + if (num_2 != 2) + { + return; + } + + U32 sid_vert = fxrec->fxdata.strkdata.sid_vert; + U32 sid_horz = fxrec->fxdata.strkdata.sid_horz; +} + +void NCIN_WaterSplash(const zCutsceneMgr*, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + return; + } + + if (fxrec->flg_stat & 2) + { + const F32 splash_radius = -1.0f; + + NPCC_MakeASplash(&fxrec->pos_A[0], splash_radius); + fxrec->flg_stat |= 4; + } +} + +void NCIN_HazProjShoot(const zCutsceneMgr* mgr, NCINEntry* fxrec, S32 param) +{ + if (param != 0) + { + fxrec->flg_stat |= 4; + + if (fxrec->fxdata.hazdata.npchaz->flg_hazard) + { + fxrec->fxdata.hazdata.npchaz->MarkForRecycle(); + } + return; + } + + if (fxrec->flg_stat & 2) + { + S32 type = fxrec->fxdata.hazdata.npchaz->typ_hazard; + S32 haztype = 10; + + if (type == 11) + { + haztype = 18; + } + else if (type >= 10 && type < 13) + { + haztype = (type == 12) ? 16 : 10; + } + + NPCHazard* haz = HAZ_Acquire(); + + if (!haz) + { + return; + } + + if (!haz->ConfigHelper((en_npchaz)haztype)) + { + return; + } + + haz->SetNPCOwner(NULL); + fxrec->fxdata.hazdata.npchaz = haz; + haz->flg_hazard &= ~128; + + xVec3 delta = fxrec->pos_B[0] - fxrec->pos_A[0]; + F32 len = delta.length(); + + F32 height = fxrec->tym_beg - fxrec->tym_end; + + if (height < 0.01f) + { + height = 1.0f; + } + + haz->pos_hazard = delta; + haz->Start(&fxrec->pos_A[0], height); + } + + if (fxrec->fxdata.hazdata.npchaz) + { + if (fxrec->fxdata.hazdata.npchaz->typ_hazard != 11) + { + fxrec->fxdata.hazdata.npchaz->flg_hazard &= ~0xF000; + } + else + { + fxrec->flg_stat |= 4; + } + } +} + +void NCIN_HazTTSteam_Upd(const zCutsceneMgr* manager, NCINEntry* fxrec, S32 param) +{ +} + +void NCIN_HazTTSteam_AR(const zCutsceneMgr* cutsceneMgr, NCINEntry* fxrec, RpAtomic* atomic, + RwMatrixTag* matrix, U32 num_1, U32 num_2) +{ +} + void clamp_bone_index(NCINEntry*, RpAtomic*) { } @@ -19,7 +699,30 @@ void NPCCone::TextureSet(RwRaster* raster) rast_cone = raster; } +void NPCCone::UVSliceSet(F32 u, F32 v) +{ + this->uv_tip[2] = u; + this->uv_slice[1] = v; +} + +void NPCCone::UVBaseSet(F32 u, F32 v) +{ + this->uv_tip[0] = u; + this->uv_tip[1] = v; +} + +void NPCCone::ColorSet(RwRGBA top, RwRGBA bot) +{ + this->rgba_top = top; + this->rgba_bot = bot; +} + void NPCCone::RadiusSet(F32 conefloat) { rad_cone = conefloat; } + +void NPARMgmt::KillAll() +{ + this->cnt_active = 0; +} diff --git a/src/SB/Game/zNPCFXCinematic.h b/src/SB/Game/zNPCFXCinematic.h index 9a520b442..361788736 100644 --- a/src/SB/Game/zNPCFXCinematic.h +++ b/src/SB/Game/zNPCFXCinematic.h @@ -3,11 +3,14 @@ #include #include "zCutsceneMgr.h" +#include "zNPCSupplement.h" #include "xVec3.h" #include "zLightning.h" #include "zNPCHazard.h" #include "zParEmitter.h" #include "zShrapnel.h" +#include "rwcore.h" + void zNPCFXStartup(); void zNPCFXShutdown(); @@ -15,6 +18,7 @@ S32 zNPCFXCutscenePrep(const xScene*, F32, const zCutsceneMgr* csnmgr); void zNPCFXCutscene(const xScene*, F32, const zCutsceneMgr* csnmgr); void zNPCFXCutsceneDone(const xScene*, F32, const zCutsceneMgr* csnmgr); + struct NCINLyt { zLightning* lyt_zap; @@ -190,6 +194,9 @@ struct NPCCone F32 uv_tip[2]; F32 uv_slice[2]; void TextureSet(RwRaster* raster); + void UVSliceSet(F32 u, F32 v); + void UVBaseSet(F32 u, F32 v); + void ColorSet(RwRGBA top, RwRGBA bot); void RadiusSet(F32); }; diff --git a/src/SB/Game/zNPCGoalAmbient.cpp b/src/SB/Game/zNPCGoalAmbient.cpp index 1604e2dba..be4f30b7d 100644 --- a/src/SB/Game/zNPCGoalAmbient.cpp +++ b/src/SB/Game/zNPCGoalAmbient.cpp @@ -1,9 +1,208 @@ #include +#include "xMath.h" #include "xMath3.h" #include "xVec3.h" #include "zNPCGoalAmbient.h" #include "zNPCSndTable.h" +#include "xMathInlines.h" +#include "zNPCSupplement.h" +#include "zGlobals.h" + +S32 zNPCGoalJellyBumped::Enter(F32 dt, void* updCtxt) +{ + zNPCJelly* npc; + xVec3 dir_aim; + + npc = (zNPCJelly*)psyche->clt_owner; + + ExtractAimDir(&dir_aim); + CalcEndPoint(&pos_grindin, &dir_aim); + + pos_bumpin = *npc->Pos(); + + npc->cnt_angerLevel -= 40; + npc->hitpoints--; + + npc->SndPlayRandom(NPC_STYP_OUCH); + + npc->ActLikeOctopus(); + + StreakPrep(); + + return zNPCGoalPushAnim::Enter(dt, updCtxt); +} + +S32 zNPCGoalJellyBumped::Exit(F32 dt, void* updCtxt) +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + npc->VelStop(); + + StreakDone(); + + npc->SndPlayRandom(NPC_STYP_DEATHJELLY); + npc->ActLikeOctopus(); + + return zNPCGoalPushAnim::Exit(dt, updCtxt); +} + +S32 zNPCGoalJellyBumped::Process(en_trantype* trantyp, F32 dt, void* updCxt, xScene* xscn) +{ + S32 nextgoal = 0; + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + xVec3 pos; + F32 pam; + + PlayWithAnimSpd(); + MoveSwoosh(dt); + + npc->JellyBoneWorldPos(&pos, -1); + + zFX_SpawnBubbleTrail(&pos, 0x4); + + StreakUpdate(); + + pam = npc->AnimTimeRemain(NULL) / npc->AnimDuration(NULL); + pam = CLAMP(pam, 0.01f, 1.0f); + + if (npc->hitpoints < 1) + { + npc->SetAlpha(pam); + } + + if (npc->hitpoints < 1 && pam < 0.01f) + { + *trantyp = GOAL_TRAN_SET; + nextgoal = 'NGN5'; + } + + if (*trantyp != GOAL_TRAN_NONE) + { + return nextgoal; + } + + return zNPCGoalPushAnim::Process(trantyp, dt, updCxt, xscn); +} + +void LERP(float dt, xVec3* pos_update, const xVec3*, const xVec3*); +F32 SMOOTH(float, float, float); + +void zNPCGoalJellyBumped::MoveSwoosh(F32 dt) +{ + F32 pos_factor; + xVec3 pos_update; + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + + pos_factor = SQ(npc->AnimTimeRemain(NULL)) / SQ(npc->AnimDuration(NULL)); + pos_factor = 1.0f - pos_factor; + pos_factor = CLAMP(pos_factor, 0.01f, 1.0f); + + LERP(pos_factor, &pos_update, &pos_bumpin, &pos_grindin); + npc->frame->mat.pos = pos_update; + + npc->frame->mode |= 0x1; +} + +void zNPCGoalJellyBumped::PlayWithAnimSpd() +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + + F32 pos_factor = npc->AnimTimeRemain(NULL) / npc->AnimDuration(NULL); + pos_factor = CLAMP(pos_factor, 0.01f, 1.0f); + pos_factor = SMOOTH(pos_factor, 1.0f, 3.0f); + + npc->AnimCurSingle()->CurrentSpeed = pos_factor; +} + +void zNPCGoalJellyBumped::StreakPrep() +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + if (npc->SelfType() == 'NTA1') + { + streakID = NPCC_StreakCreate(NPC_STRK_TOSSEDJELLYBLUE); + } + else + { + streakID = NPCC_StreakCreate(NPC_STRK_TOSSEDJELLY); + } +} + +void zNPCGoalJellyBumped::StreakDone() +{ + xFXStreakStop(streakID); + streakID = 0xDEAD; +} + +void zNPCGoalJellyBumped::StreakUpdate() +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + xVec3 bone_pos1; + xVec3 bone_pos2; + + npc->JellyBoneWorldPos(&bone_pos1, 2); + npc->JellyBoneWorldPos(&bone_pos2, 3); + + xFXStreakUpdate(streakID, (const xVec3*)&bone_pos1, (const xVec3*)&bone_pos2); +} + +void zNPCGoalJellyBumped::ExtractAimDir(xVec3* dir_aim) +{ + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + F32 length; + + if (flg_info & 0x10) + { + npc->XZVecToPos(dir_aim, (const xVec3*)&pos_bumper, NULL); + } + else + { + npc->XZVecToPlayer(dir_aim, NULL); + } + + flg_info = 0x0; + + xVec3Inv(dir_aim, dir_aim); + + dir_aim->y = 0.0f; + + length = dir_aim->length(); + if (length < 1e-5f) + { + *dir_aim = *NPCC_faceDir(&globals.player.ent); + } + else + { + *dir_aim /= length; + } +} + +F32 zNPCGoalJellyBumped::CalcEndPoint(xVec3* pos_end, const xVec3* dir_aim) +{ + xCollis colrec; + S32 rc; + + F32 dst_toEndPnt = 4.0f; + zNPCJelly* npc = (zNPCJelly*)psyche->clt_owner; + xVec3 vec = *dir_aim * dst_toEndPnt; + xVec3 pos = *npc->Pos() + vec; + + memset(&colrec, 0, sizeof(colrec)); + colrec.flags = 0x1F00; + + rc = npc->HaveLOSToPos(&pos, 4.0f, globals.sceneCur, NULL, &colrec); + if (rc) + { + *pos_end = pos; + dst_toEndPnt = 4.0f; + } + else + { + dst_toEndPnt = colrec.dist; + *pos_end = *npc->Pos() + *dir_aim * dst_toEndPnt; + } + + return dst_toEndPnt; +} S32 zNPCGoalJellyAttack::Enter(F32 arg0, void* arg1) { diff --git a/src/SB/Game/zNPCGoalAmbient.h b/src/SB/Game/zNPCGoalAmbient.h index 60203fbef..937c26be3 100644 --- a/src/SB/Game/zNPCGoalAmbient.h +++ b/src/SB/Game/zNPCGoalAmbient.h @@ -33,4 +33,23 @@ struct zNPCGoalJellyAttack : zNPCGoalPushAnim S32 ZapperUpdate(); }; +struct zNPCGoalJellyBumped : zNPCGoalPushAnim +{ + xVec3 pos_bumper; + xVec3 pos_bumpin; + xVec3 pos_grindin; + U32 streakID; + + S32 Enter(F32 dt, void* updCtxt); + S32 Exit(F32 dt, void* updCtxt); + S32 Process(en_trantype* trantyp, F32 dt, void* updCxt, xScene* xscn); + void MoveSwoosh(F32 dt); + void PlayWithAnimSpd(); + void StreakPrep(); + void StreakDone(); + void StreakUpdate(); + void ExtractAimDir(xVec3* dir); + F32 CalcEndPoint(xVec3* pos_end, const xVec3* dir_aim); +}; + #endif diff --git a/src/SB/Game/zNPCHazard.cpp b/src/SB/Game/zNPCHazard.cpp index de073479d..a3bb7920a 100644 --- a/src/SB/Game/zNPCHazard.cpp +++ b/src/SB/Game/zNPCHazard.cpp @@ -17,7 +17,7 @@ extern S32 g_cnt_activehaz; extern NPCHazard* g_haz_uvAnimQue[27]; extern RpAtomic* g_hazard_rawModel[30]; extern xAnimTable* g_haz_animTable[30]; -extern xVec3 g_O3; +extern const xVec3 g_O3; extern F32 _958_Hazard; // 0.0f extern F32 _959_Hazard; // 1.0f extern F32 _1041_Hazard; // -1.0f diff --git a/src/SB/Game/zNPCMessenger.cpp b/src/SB/Game/zNPCMessenger.cpp index cd0785848..7e8a686c6 100644 --- a/src/SB/Game/zNPCMessenger.cpp +++ b/src/SB/Game/zNPCMessenger.cpp @@ -1,14 +1,16 @@ #include "zNPCMessenger.h" +#include "xordarray.h" #include static NPCPSData g_postoffice; -void zNPCCommon::Stun(F32) +NPCPSData* NPCPS_postOffice() { + return &g_postoffice; } -void zNPCMSg_Startup() +void zNPCCommon::Stun(F32) { } @@ -43,6 +45,13 @@ void NPCPS_copyMsgInfo(NPCMsg*, NPCMsg*, float) void NPCPS_queMessage(NPCMsg*) { + // LW - 50% match + // probably a simple fix + NPCPSData* tempQue; + + tempQue = NPCPS_postOffice(); + + XOrdAppend(((st_XORDEREDARRAY*)tempQue + 0x2), NULL); } S32 NPCPS_flagForMID(en_NPC_MSG_ID) @@ -68,25 +77,30 @@ void NPCPS_CltPoolReset(NPCPSData*) { } -NPCPSData* NPCPS_postOffice() +void NPCPS_grabMsg() { - return &g_postoffice; } -void NPCPS_grabMsg() +void NPCPS_freeMsg(NPCMsg*) { } -void NPCPS_freeMsg(NPCMsg*) +void zNPCMsg_Startup() { + NPCPSData* tempStartup; + + tempStartup = NPCPS_postOffice(); + NPCPS_CltPoolInit(tempStartup, 0x20); + NPCPS_MsgPoolInit(tempStartup, 0x40); } void zNPCMsg_SceneReset() { - // 57% there but not quite - NPCPS_CltPoolReset(NPCPS_postOffice()); - NPCPS_MsgPoolReset(NPCPS_postOffice()); - return; + NPCPSData* tempReset; + + tempReset = NPCPS_postOffice(); + NPCPS_CltPoolReset(tempReset); + NPCPS_MsgPoolReset(tempReset); } void zNPCMsg_Timestep(xScene*, float) diff --git a/src/SB/Game/zNPCSpawner.cpp b/src/SB/Game/zNPCSpawner.cpp index 5a89ef58d..c7349973b 100644 --- a/src/SB/Game/zNPCSpawner.cpp +++ b/src/SB/Game/zNPCSpawner.cpp @@ -130,18 +130,287 @@ void zNPCSpawner::Reset() void zNPCSpawner::MapPreferred() { - for (S32 i = 0; i < 0x10; i++) + for (S32 i = 0; i < 16; i++) { SMNPCStatus* npc_stat = &this->npcpool[i]; if (npc_stat->npc != NULL) { - // FIXME - // zMovePoint* sp = (zMovePoint*)npc_stat->npc->FirstAssigned(); - // if (sp != NULL&& /*TODO*/) - // { - // npc_stat->sp_prefer = sp; - // } + zMovePoint* sp = (zMovePoint*)npc_stat->npc->FirstAssigned(); + if (sp != NULL) + { + SMSPStatus* sp_stat = StatForSP(sp, 0); + if (sp_stat != NULL) + { + npc_stat->sp_prefer = sp; + sp_stat->npc_prefer = npc_stat->npc; + } + } + } + } +} + +void zNPCSpawner::Timestep(F32 dt) +{ + if (flg_spawner & 0x8) + { + ChildHeartbeat(dt); + } + + if (flg_spawner & 0x10) + { + ChildCleanup(dt); + } + + if (!(flg_spawner & 0x4)) + { + tmr_wave = -1.0f > tmr_wave - dt ? -1.0f : tmr_wave - dt; + + switch (wavemode) + { + case SM_WAVE_DISCREET: + UpdateDiscreet(dt); + break; + case SM_WAVE_CONTINUOUS: + UpdateContinuous(dt); + break; + } + } +} + +void zNPCSpawner::UpdateDiscreet(F32 dt) +{ + SMSPStatus* spstat = NULL; + + switch (wavestat) + { + case SM_STAT_BEGIN: + FillPending(); + + if (pendlist.cnt > 0) + { + wavestat = SM_STAT_INPROG; + zEntEvent(npc_owner, eEventDuploWaveBegin); + + flg_spawner &= ~0x20; + } + + tmr_wave = tym_delay; + + break; + case SM_STAT_INPROG: + if (pendlist.cnt < 1) + { + wavestat = SM_STAT_MARKTIME; + } + else if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + wavestat = SM_STAT_ABORT; + } + else if (tmr_wave < 0.0f) + { + SMNPCStatus* npcstat = NextPendingNPC(0); + if (npcstat != NULL) + { + spstat = SelectSP(npcstat); + } + + if (!(spstat == NULL)) + { + SpawnBeastie(npcstat, spstat); + } + + tmr_wave = tym_delay * (0.25f * (xurand() - 0.5f)) + tym_delay; + } + + break; + case SM_STAT_MARKTIME: + if (actvlist.cnt < 1) + { + wavestat = SM_STAT_DONE; + } + else if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + wavestat = SM_STAT_ABORT; } + + break; + case SM_STAT_ABORT: + if (actvlist.cnt < 1) + { + wavestat = SM_STAT_DONE; + } + + ClearPending(); + + break; + case SM_STAT_DONE: + if (!(flg_spawner & 0x20)) + { + zEntEvent(npc_owner, eEventDuploWaveComplete); + } + + if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + if (!(flg_spawner & 0x20)) + { + flg_spawner |= 0x20; + + zEntEvent(npc_owner, eEventDuploExpiredMaxNPC); + zEntEvent(npc_owner, eEventDuploSuperDuperDone); + + if (flg_spawner & 0x2) + { + zEntEvent(npc_owner, eEventDuploDuperIsDoner); + } + } + } + else + { + if (flg_spawner & 0x2) + { + if (!(flg_spawner & 0x20)) + { + flg_spawner |= 0x20; + + zEntEvent(npc_owner, eEventDuploSuperDuperDone); + zEntEvent(npc_owner, eEventDuploDuperIsDoner); + } + } + else + { + wavestat = SM_STAT_BEGIN; + } + } + + break; + default: + break; + } +} + +void zNPCSpawner::UpdateContinuous(F32 dt) +{ + SMSPStatus* spstat = NULL; + + switch (wavestat) + { + case SM_STAT_BEGIN: + FillPending(); + + if (pendlist.cnt > 0) + { + wavestat = SM_STAT_INPROG; + zEntEvent(npc_owner, eEventDuploWaveBegin); + + flg_spawner &= ~0x20; + } + + tmr_wave = tym_delay; + + break; + case SM_STAT_INPROG: + if (pendlist.cnt < 1) + { + wavestat = SM_STAT_MARKTIME; + } + else if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + wavestat = SM_STAT_ABORT; + } + else if (tmr_wave < 0.0f) + { + SMNPCStatus* npcstat = NextPendingNPC(0); + if (npcstat != NULL) + { + spstat = SelectSP(npcstat); + } + + if (!(spstat == NULL)) + { + SpawnBeastie(npcstat, spstat); + } + + tmr_wave = tym_delay * (0.25f * (xurand() - 0.5f)) + tym_delay; + } + + break; + // MarkTime case is the significantly different one between this function and UpdateDiscreet + case SM_STAT_MARKTIME: + if (flg_spawner & 0x2) + { + wavestat = SM_STAT_ABORT; + } + else if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + wavestat = SM_STAT_ABORT; + } + else + { + if (tmr_wave < 0.0f) + { + tmr_wave = tym_delay * (0.25f * (xurand() - 0.5f)) + tym_delay; + + ReFillPending(); + + if (pendlist.cnt > 0) + { + wavestat = SM_STAT_INPROG; + } + } + else if (pendlist.cnt > 0) + { + wavestat = SM_STAT_INPROG; + } + } + + break; + case SM_STAT_ABORT: + if (actvlist.cnt < 1) + { + wavestat = SM_STAT_DONE; + } + + ClearPending(); + + break; + case SM_STAT_DONE: + if (!(flg_spawner & 0x20)) + { + zEntEvent(npc_owner, eEventDuploWaveComplete); + } + + if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + if (!(flg_spawner & 0x20)) + { + flg_spawner |= 0x20; + + zEntEvent(npc_owner, eEventDuploExpiredMaxNPC); + zEntEvent(npc_owner, eEventDuploSuperDuperDone); + + if (flg_spawner & 0x2) + { + zEntEvent(npc_owner, eEventDuploDuperIsDoner); + } + } + } + else + { + if (flg_spawner & 0x2) + { + if (!(flg_spawner & 0x20)) + { + flg_spawner |= 0x20; + + zEntEvent(npc_owner, eEventDuploSuperDuperDone); + zEntEvent(npc_owner, eEventDuploDuperIsDoner); + } + } + } + + break; + default: + break; } } diff --git a/src/SB/Game/zNPCSpawner.h b/src/SB/Game/zNPCSpawner.h index 615fa42fa..d6e9033c6 100644 --- a/src/SB/Game/zNPCSpawner.h +++ b/src/SB/Game/zNPCSpawner.h @@ -90,16 +90,18 @@ struct zNPCSpawner : RyzMemData // NextPendingNPC. void ClearActive(); void ClearPending(); - SMNPCStatus* NextPendingNPC( S32 arg0 ); + SMNPCStatus* NextPendingNPC(S32 arg0); st_XORDEREDARRAY* FillPending(); st_XORDEREDARRAY* ReFillPending(); void SetNPCStatus(zNPCCommon* npc, en_SM_NPC_STATUS status); SMNPCStatus* StatForNPC(zNPCCommon* npc); + SMSPStatus* StatForSP(zMovePoint* mp, S32 arg0); S32 SpawnBeastie(SMNPCStatus* npcstat, SMSPStatus* spstat); SMNPCStatus* ToastedBeastie(zNPCCommon* npc); void ChildHeartbeat(F32 dt); + void ChildCleanup(F32 dt); }; void zNPCSpawner_Startup(); diff --git a/src/SB/Game/zNPCSupplement.cpp b/src/SB/Game/zNPCSupplement.cpp index 9a0171d88..439ed1558 100644 --- a/src/SB/Game/zNPCSupplement.cpp +++ b/src/SB/Game/zNPCSupplement.cpp @@ -1,8 +1,10 @@ #include "zNPCSupplement.h" #include "zNPCSupport.h" +#include "zNPCTypeRobot.h" #include "zGame.h" #include "zGameExtras.h" #include "zGlobals.h" +#include "xCutsceneMgr.h" #include "xFX.h" #include "xMath.h" @@ -17,21 +19,10 @@ extern S32 g_gameExtrasFlags; extern S32 g_mon; // month extern S32 g_day; // day extern S32 g_isSpecialDay; +static S8 g_shadCachesInUseFlags[16]; extern StreakInfo info_950; -extern F32 _907_1_0; -extern F32 _1022_2_0; - -extern F32 _1558_10_0; // 10.0 -extern F32 _1559_0_2857143; // 0.2857143 -extern F32 _1560_0_5714286; // 0.5714286 -extern F32 _1561_0_125; // 0.125 -extern F32 _918_0_25; // 0.25 -extern F32 _1018_0_375; // 0.375 -extern F32 _909_0_5; // 0.5 -extern F32 _1562_0_625; // 0.625 - void NPCSupplement_Startup() { return; @@ -109,20 +100,23 @@ void NPAR_CheckSpecials() g_isSpecialDay = g_gameExtrasFlags & 0b111110111; } -// WIP void NPAR_Timestep(F32 dt) { S32 isPawzd = zGameIsPaused(); - S32 isCine = !(globals.cmgr && globals.cmgr); - + S32 isCine = (globals.cmgr != NULL) && (((xCutsceneMgr*)(globals.cmgr))->csn != NULL); NPAR_CheckSpecials(); - for (int i = 0; i < 12; i++) + NPARMgmt* mgr; + for (S32 i = 0; i < 12; i++, mgr++) { - if (!isPawzd) + mgr = &g_npar_mgmt[i]; + if (1 <= mgr->cnt_active) { - if (isCine || g_npar_mgmt[i].flg_npar & 2) + if (!isPawzd || ((mgr->flg_npar & 1))) { - UpdateAndRender(g_npar_mgmt[i], dt); + if (!isCine || ((mgr->flg_npar & 2))) + { + mgr->UpdateAndRender(dt); + } } } } @@ -152,6 +146,35 @@ NPARMgmt* NPAR_FindParty(en_nparptyp parType) return mgmt; } +#if 0 +// Matches, but appears to be using some kinda weird secret overload for xMemAlloc?? Find out wtf this is. +void* xMemAlloc(U32 heapID, U32 size, S32 align, void* data, S32 dataSize); + +void NPARMgmt::Init(en_nparptyp parType, void** userData, NPARXtraData* xtraData) +{ + S32 amt = g_npar_info[parType].num_maxParticles; + NPARInfo* info = &g_npar_info[parType]; + + void* mem = xMemAlloc(gActiveHeap, amt * 0x50, 0x10, xtraData, parType << 4); + memset(mem, 0, amt * 0x50); + typ_npar = parType; + flg_npar = info->flg_npar; + par_buf = (NPARData*)mem; + cnt_active = 0; + num_max = info->num_maxParticles; + UserDataSet(userData); + XtraDataSet(xtraData); + if (info->nam_texture == NULL) + { + txtr = NULL; + } + else + { + txtr = NPCC_FindRWTexture( info->nam_texture ); + } +} +#endif + void NPARMgmt::Clear() { typ_npar = NPAR_TYP_UNKNOWN; @@ -244,7 +267,7 @@ void NPAR_TubeSpiralMagic(RwRGBA* color, int unused, F32 pam) // Lots of different dates if (g_isSpecialDay & 0b100000001) { - S32 trun = _1558_10_0 * pam; + S32 trun = 10.0f * pam; if (trun < 0) { trun = 0; @@ -260,12 +283,12 @@ void NPAR_TubeSpiralMagic(RwRGBA* color, int unused, F32 pam) // July 4th (Independence Day) if (g_isSpecialDay & 0b000000010) { - if (pam < _1559_0_2857143) + if (pam < (2.0f / 7.0f)) { *color = colr_julyred; return; } - if (pam < _1560_0_5714286) + if (pam < (4.0f / 7.0f)) { *color = colr_julywhite; return; @@ -291,23 +314,23 @@ void NPAR_TubeSpiralMagic(RwRGBA* color, int unused, F32 pam) // Also 4th of July? Unused if (g_isSpecialDay & 0b000010000) { - if (pam < _1561_0_125) + if (pam < 0.125f) { *color = colr_maroon; return; } - if (pam < _918_0_25) + if (pam < 0.25f) { *color = colr_julyred; return; } - if (pam < _1018_0_375) + if (pam < 0.375f) { *color = colr_julywhite; return; } - if (pam < _909_0_5) + if (pam < 0.5f) { *color = colr_julyblue; return; @@ -326,22 +349,22 @@ void NPAR_TubeSpiralMagic(RwRGBA* color, int unused, F32 pam) // June 6th if (g_isSpecialDay & 0b001000000) { - if (pam < _918_0_25) + if (pam < 0.25f) { *color = colr_red; return; } - if (pam < _1018_0_375) + if (pam < 0.375f) { *color = colr_orange; return; } - if (pam < _909_0_5) + if (pam < 0.5f) { *color = colr_green; return; } - if (pam < _1562_0_625) + if (pam < 0.625f) { *color = colr_blue; return; @@ -360,12 +383,12 @@ void NPAR_TubeSpiralMagic(RwRGBA* color, int unused, F32 pam) F32 ARCH3(F32 param_1) { - return _907_1_0 - BOWL3(param_1); + return 1.0f - BOWL3(param_1); } F32 BOWL3(F32 param_1) { - return QUB((F32)_1022_2_0 * (F32)iabs(param_1 - _909_0_5)); + return QUB((F32)2.0f * (F32)iabs(param_1 - 0.5f)); } F32 QUB(F32 param_1) @@ -375,7 +398,7 @@ F32 QUB(F32 param_1) F32 ARCH(F32 param_1) { - return _907_1_0 - BOWL(param_1); + return 1.0f - BOWL(param_1); } void NPARMgmt::Done() @@ -402,3 +425,583 @@ void NPARMgmt::UserDataSet(void** param_1) { user_data = param_1; } + +void NPARParmVisSplash::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = xurand() * 0.5f + 0.5f; + F32 samecalc = tym_lifespan * fac_rand; + + par->fac_abuse = fac_rand; + par->tmr_remain = samecalc; + par->tym_exist = samecalc; + + par->pos = *pos; + par->vel = *vel; + + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + + par->color = colr_base; + + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = 0.0f; + par->uv_br[0] = 1.0f; + par->uv_br[1] = 1.0f; + + par->flg_popts |= 2; + par->nparmode = pmod; +} + +void NPARParmDogBreath::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = xurand() * 0.5f + 0.5f; + F32 samecalc = tym_lifespan * fac_rand; + + par->fac_abuse = fac_rand; + par->tmr_remain = samecalc; + par->tym_exist = samecalc; + + par->pos = *pos; + par->vel = *vel; + + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + + par->color = colr_base; + + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = 0.0f; + par->uv_br[0] = 1.0f; + par->uv_br[1] = 1.0f; + + par->nparmode = pmod; +} + +NPARParmFahrwerkz g_parm_fahrwerkz[4]; + +void NPAR_EmitFireworks(en_nparmode pmod, const xVec3* pos, const xVec3* vel) +{ + NPARData *pNVar1; + NPARMgmt *mgmt = NPAR_FindParty(NPAR_TYP_FIREWORKS); + if ((mgmt != NULL) && (pNVar1 = mgmt->NextAvail(), pNVar1 != NULL)) + { + g_parm_fahrwerkz[pmod].ConfigPar(pNVar1, pmod, pos, vel); + } +} + +void NPAR_EmitFWExhaust(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitFireworks(NPAR_MODE_FWEXHAUST, pos, vel); +} + +NPARParmVisSplash g_parm_vissplash[4]; + +void NPAR_EmitVisSplash(en_nparmode pmod, const xVec3* vel, const xVec3* pos) +{ + NPARData* par; + NPARMgmt* mgmt = NPAR_FindParty(NPAR_TYP_VISSPLASH); + if ((mgmt != NULL) && (par = mgmt->NextAvail(), par != NULL)) + { + g_parm_vissplash[pmod].ConfigPar(par, pmod, vel, pos); + } +} + +NPARParmOilBub g_parm_oilbub[4]; + +void NPAR_EmitOilBubble(en_nparmode pmod, const xVec3* pos, const xVec3* vel) +{ + NPARData* par; + NPARMgmt* mgmt = NPAR_FindParty(NPAR_TYP_OILBUB); + if ((mgmt != NULL) && (par = mgmt->NextAvail(), par != NULL)) + { + g_parm_oilbub[pmod].ConfigPar(par, pmod, pos, vel); + } +} + +NPARParmTubeSpiral g_parm_tubespiral[4]; + +// Equivalent: weird unnecessary use of mulli to index into g_parm_tubespiral. +void NPAR_EmitTubeSpiral(const xVec3* pos, const xVec3* vel, F32 dt) +{ + NPARData* par; + NPARMgmt* mgmt = NPAR_FindParty(NPAR_TYP_TUBESPIRAL); + if ((mgmt != NULL) && (par = mgmt->NextAvail(), par != NULL)) + { + g_parm_tubespiral[1].ConfigPar(par, NPAR_MODE_SPIRALNORM, pos, vel, dt); + } +} + +NPARParmTubeConfetti g_parm_tubeconfetti[2]; + +void NPAR_EmitTubeConfetti(const xVec3* pos, const xVec3* vel) +{ + NPARData* par; + NPARMgmt* mgmt = NPAR_FindParty(NPAR_TYP_TUBECONFETTI); + if ((mgmt != NULL) && (par = mgmt->NextAvail(), par != NULL)) + { + g_parm_tubeconfetti[0].ConfigPar(par, NPAR_MODE_STD, pos, vel); + } +} + +void NPAR_EmitTubeSparklies(const xVec3* pos, const xVec3* vel) +{ + NPARData* par; + NPARMgmt* mgmt = NPAR_FindParty(NPAR_TYP_TUBECONFETTI); + if ((mgmt != NULL) && (par = mgmt->NextAvail(), par != NULL)) + { + g_parm_tubeconfetti[1].ConfigPar(par, NPAR_MODE_FETTI_SPARKLIES, pos, vel); + } +} + +// Equivalent: operands of single fmuls instruction swapped. +void NPARParmTubeConfetti::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = 0.5f * xurand() + 0.5f; + + par->fac_abuse = fac_rand; + par->tmr_remain = tym_lifespan * fac_rand; + par->tym_exist = tym_lifespan * fac_rand; + par->pos = *pos; + par->vel = *vel; + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + par->color = colr_base; + + if (pmod == 0) + { + par->color.red = xurand() * 95.0f + 160.0f; + par->color.green = xurand() * 95.0f + 160.0f; + par->color.blue = xurand() * 95.0f + 160.0f; + par->color.alpha = colr_base.alpha; + + par->flg_popts |= 4; + } + else + { + par->color = colr_base; + } + + F32 justTheRand = fac_rand; + + F32 du = 1.0f / num_uvcell[0]; + F32 dv = 1.0f / num_uvcell[1]; + + if (pmod == 0) + { + F32 samecalc = 2.0f * (justTheRand - 0.5f ); + par->uv_tl[0] = ((int)(samecalc * num_uvcell[1])) * du; // Multiplication operands swapped + par->uv_tl[1] = (row_uvstart + (int)(samecalc * num_uvcell[0])) * dv; + par->uv_br[0] = par->uv_tl[0] + du; + par->uv_br[1] = par->uv_tl[1] + dv; + + par->flg_popts |= 2; + } + else + { + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = row_uvstart * dv; + par->uv_br[0] = du; + par->uv_br[1] = dv; + + par->flg_popts &= ~2; + } + + par->nparmode = pmod; +} + +// Equivalent: operands of single fmuls instruction swapped. +void NPARParmFahrwerkz::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = 0.5f * xurand() + 0.5f; + + par->fac_abuse = fac_rand; + par->tmr_remain = tym_lifespan * fac_rand; + par->tym_exist = tym_lifespan * fac_rand; + par->pos = *pos; + par->vel = *vel; + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + par->color = colr_base; + + F32 justTheRand = fac_rand; + + F32 du = 1.0f / num_uvcell[0]; + F32 dv = 1.0f / num_uvcell[1]; + + if (pmod == 0) + { + F32 samecalc = 2.0f * (justTheRand - 0.5f ); + par->uv_tl[0] = ((int)(samecalc * num_uvcell[1])) * du; // Multiplication operands swapped + par->uv_tl[1] = (row_uvstart + (int)(samecalc * num_uvcell[0])) * dv; + par->uv_br[0] = par->uv_tl[0] + du; + par->uv_br[1] = par->uv_tl[1] + dv; + + par->flg_popts |= 2; + } + else + { + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = row_uvstart * dv; + par->uv_br[0] = du; + par->uv_br[1] = dv; + + par->flg_popts &= ~2; + } + + par->nparmode = pmod; +} + +// Equivalent: operands of single fmuls instruction swapped. +void NPARParmTarTarGunk::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = 0.5f * xurand() + 0.5f; + + par->fac_abuse = fac_rand; + par->tmr_remain = tym_lifespan * fac_rand; + par->tym_exist = tym_lifespan * fac_rand; + par->pos = *pos; + par->vel = *vel; + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + par->color = colr_base; + + F32 justTheRand = fac_rand; + + F32 du = 1.0f / num_uvcell[0]; + F32 dv = 1.0f / num_uvcell[1]; + + if (pmod == 0) + { + F32 samecalc = 2.0f * (justTheRand - 0.5f ); + par->uv_tl[0] = ((int)(samecalc * num_uvcell[1])) * du; // Multiplication operands swapped + par->uv_tl[1] = (row_uvstart + (int)(samecalc * num_uvcell[0])) * dv; + par->uv_br[0] = par->uv_tl[0] + du; + par->uv_br[1] = par->uv_tl[1] + dv; + + par->flg_popts |= 2; + } + else + { + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = row_uvstart * dv; + par->uv_br[0] = du; + par->uv_br[1] = dv; + + par->flg_popts &= ~2; + } + + par->nparmode = pmod; +} + +// Equivalent: operands of single fmuls instruction swapped. +void NPARParmSleepyZeez::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = 0.5f * xurand() + 0.5f; + + par->fac_abuse = fac_rand; + par->tmr_remain = tym_lifespan * fac_rand; + par->tym_exist = tym_lifespan * fac_rand; + par->pos = *pos; + par->vel = *vel; + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + par->color = colr_base; + + F32 justTheRand = fac_rand; + + F32 du = 1.0f / num_uvcell[0]; + F32 dv = 1.0f / num_uvcell[1]; + + if (pmod == 0) + { + F32 samecalc = 2.0f * (justTheRand - 0.5f ); + par->uv_tl[0] = ((int)(samecalc * num_uvcell[1])) * du; // Multiplication operands swapped + par->uv_tl[1] = (row_uvstart + (int)(samecalc * num_uvcell[0])) * dv; + par->uv_br[0] = par->uv_tl[0] + du; + par->uv_br[1] = par->uv_tl[1] + dv; + + par->flg_popts |= 2; + } + else + { + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = row_uvstart * dv; + par->uv_br[0] = du; + par->uv_br[1] = dv; + + par->flg_popts &= ~2; + } + + par->nparmode = pmod; +} + +void NPARParmChuckSplash::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = xurand() * 0.5f + 0.5f; + F32 samecalc = tym_lifespan * fac_rand; + + par->fac_abuse = fac_rand; + par->tmr_remain = samecalc; + par->tym_exist = samecalc; + + par->pos = *pos; + par->vel = *vel; + + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + + par->color = colr_base; + + if (pmod == NPAR_MODE_STD) + { + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = 0.0f; + par->uv_br[0] = 1.0f; + par->uv_br[1] = 1.0f; + par->flg_popts |= 2; + } + else if ((pmod == NPAR_MODE_ALT_C) ||(pmod == NPAR_MODE_ALT_A) ||(pmod == NPAR_MODE_ALT_B)) + { + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = 0.0f; + par->uv_br[0] = 1.0f; + par->uv_br[1] = 1.0f; + par->flg_popts |= 2; + } + else if (pmod == NPAR_MODE_ALT_D) + { + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = 0.0f; + par->uv_br[0] = 1.0f; + par->uv_br[1] = 1.0f; + par->flg_popts |= 2; + } + else + { + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = 0.0f; + par->uv_br[0] = 1.0f; + par->uv_br[1] = 1.0f; + par->flg_popts |= 2; + } + + par->nparmode = pmod; +} + +NPARParmChuckSplash g_parm_chucksplash[5]; + +//todo +void NPAR_EmitDroplets(en_nparmode pmod, const xVec3* pos, const xVec3* vel) +{ + NPARData *pNVar1; + NPARMgmt *mgmt = (NPARMgmt *)NPAR_FindParty(NPAR_TYP_CHUCKSPLASH); + if ((mgmt != NULL) && (pNVar1 = mgmt->NextAvail(), pNVar1 != NULL)) + { + g_parm_chucksplash[pmod].ConfigPar(pNVar1, pmod, pos, vel); + } +} + +void NPAR_EmitOilShieldPop(const xVec3* pos) +{ + NPAR_EmitOilBubble(NPAR_MODE_STD, pos, NULL); +} + +void NPAR_EmitOilTrailz(const xVec3* pos) +{ + NPAR_EmitOilBubble(NPAR_MODE_ALT_A, pos, NULL); +} + +void NPAR_EmitOilVapors(const xVec3* pos) +{ + NPAR_EmitOilBubble(NPAR_MODE_ALT_B, pos, NULL); +} + +void NPAR_EmitOilSplash(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitOilBubble(NPAR_MODE_ALT_C, pos, vel); +} + +NPARParmTarTarGunk g_parm_tartargunk[6]; + +void NPAR_EmitTarTarGunk(en_nparmode pmod, const xVec3* pos, const xVec3* vel) +{ + NPARData *pNVar1; + NPARMgmt *mgmt = (NPARMgmt *)NPAR_FindParty(NPAR_TYP_TARTARGUNK); + if ((mgmt != NULL) && (pNVar1 = mgmt->NextAvail(), pNVar1 != NULL)) + { + g_parm_tartargunk[pmod].ConfigPar(pNVar1, pmod, pos, vel); + } +} + +void NPAR_EmitGloveDust(const xVec3* pos, const xVec3* vel) +{ + NPARData *pNVar1; + NPARMgmt *mgmt = (NPARMgmt *)NPAR_FindParty(NPAR_TYP_GLOVEDUST); + if ((mgmt != NULL) && (pNVar1 = mgmt->NextAvail(), pNVar1 != NULL)) + { + g_parm_tartargunk[0].ConfigPar(pNVar1, NPAR_MODE_STD, pos, vel); + } +} + +void NPAR_EmitSleepyZeez(const xVec3* pos, const xVec3* vel) +{ + NPARData *pNVar1; + NPARMgmt *mgmt = (NPARMgmt *)NPAR_FindParty(NPAR_TYP_SLEEPYZEEZ); + if ((mgmt != NULL) && (pNVar1 = mgmt->NextAvail(), pNVar1 != NULL)) + { + g_parm_tartargunk[0].ConfigPar(pNVar1, NPAR_MODE_STD, pos, vel); + } +} + +void NPAR_EmitTarTarNozzle(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitTarTarGunk(NPAR_MODE_ALT_A, pos, vel); +} + +void NPAR_EmitTarTarTrail(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitTarTarGunk(NPAR_MODE_ALT_B, pos, vel); +} + +void NPAR_EmitTarTarSplash(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitTarTarGunk(NPAR_MODE_ALT_C, pos, vel); +} + +void NPAR_EmitTarTarSpoil(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitTarTarGunk(NPAR_MODE_ALT_D, pos, vel); +} + +void NPAR_EmitTarTarSmoke(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitTarTarGunk(NPAR_MODE_ALT_E, pos, vel); +} + +void NPAR_EmitVSSpray(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitVisSplash(NPAR_MODE_STD, pos, vel); +} + +NPARParmDogBreath g_parm_dogbreath[3]; + +void NPAR_EmitDoggyBreath(en_nparmode pmod, const xVec3* pos, const xVec3* vel) +{ + NPARData *pNVar1; + NPARMgmt *mgmt = (NPARMgmt *)NPAR_FindParty(NPAR_TYP_DOGBREATH); + if ((mgmt != NULL) && (pNVar1 = mgmt->NextAvail(), pNVar1 != NULL)) + { + g_parm_dogbreath[pmod].ConfigPar(pNVar1,pmod,pos,vel); + } +} + +void NPAR_EmitDoggyWisps(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitDoggyBreath(NPAR_MODE_ALT_A, pos, vel); +} + +void NPAR_EmitDoggyAttack(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitDoggyBreath(NPAR_MODE_ALT_B, pos, vel); +} + +void NPARParmGloveDust::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = xurand() * 0.5f + 0.5f; + F32 samecalc = tym_lifespan * fac_rand; + + par->fac_abuse = fac_rand; + par->tmr_remain = samecalc; + par->tym_exist = samecalc; + + par->pos = *pos; + par->vel = *vel; + + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + + par->color = colr_base; + + par->uv_tl[0] = 0.0f; + par->uv_tl[1] = 0.0f; + par->uv_br[0] = 1.0f; + par->uv_br[1] = 1.0f; + + par->nparmode = pmod; +} + +void NPARParmTubeSpiral::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel, F32 dt) const +{ + par->fac_abuse = (xurand() * 0.5f + 0.5f); + par->tmr_remain = dt; + par->tym_exist = dt; + par->pos = *pos; + par->vel = *vel; + par->xy_size[0] = siz_base[0]; + par->xy_size[1] = siz_base[0]; + par->color = colr_base; + par->uv_tl[0] = 0.0; + par->uv_tl[1] = 0.0; + par->uv_br[0] = 1.0; + par->uv_br[1] = 1.0; + par->nparmode = pmod; +} + +// Equivalent: weird unnecessary use of mulli to index into g_parm_tubespiral. +void NPAR_EmitTubeSpiralCin(const xVec3* pos, const xVec3* vel, float dt) +{ + NPARData* par; + NPARMgmt* mgmt = NPAR_FindParty(NPAR_TYP_TUBESPIRAL); + if ((mgmt != NULL) && (par = mgmt->NextAvail(), par != NULL)) + { + g_parm_tubespiral[3].ConfigPar(par, NPAR_MODE_SPIRALCINE, pos, vel, dt); + } +} + +void NPARParmOilBub::ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const +{ + F32 fac_rand = (xurand() * 0.5f + 0.5f); + F32 samecalc = tym_lifespan * fac_rand; + par->fac_abuse = fac_rand; + par->tmr_remain = samecalc; + par->tym_exist = samecalc; + par->pos = *pos; + par->vel = (vel != NULL) ? *vel : g_O3; + F32 uVar2 = siz_base[0]; + par->xy_size[0] = uVar2; + par->xy_size[1] = uVar2; + par->color = colr_base; + par->uv_tl[0] = 0.0; + par->uv_tl[1] = 0.0; + par->uv_br[0] = 1.0; + par->uv_br[1] = 1.0; + par->nparmode = pmod; +} + +void NPAR_EmitH2ODrips(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitDroplets(NPAR_MODE_DRIP, pos, vel); +} + +void NPAR_EmitH2ODrops(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitDroplets(NPAR_MODE_DROP, pos, vel); +} + +void NPAR_EmitH2OSpray(const xVec3* pos, const xVec3* vel) +{ + NPAR_EmitDroplets(NPAR_MODE_SPLASH, pos, vel); +} + +void NPAR_EmitH2OTrail(const xVec3* pos) +{ + NPAR_EmitDroplets(NPAR_MODE_TRAIL, pos, (xVec3 *)&g_O3); +} + +static void NPCC_ShadowCacheReset() +{ + for (int i = 0; i < sizeof(g_shadCachesInUseFlags) / sizeof(S8); i++) + { + g_shadCachesInUseFlags[i] = 0; + } +} \ No newline at end of file diff --git a/src/SB/Game/zNPCSupplement.h b/src/SB/Game/zNPCSupplement.h index 0530486a8..efb1a8eb9 100644 --- a/src/SB/Game/zNPCSupplement.h +++ b/src/SB/Game/zNPCSupplement.h @@ -43,6 +43,37 @@ enum en_npcstreak NPC_STRK_FORCE = 0x7fffffff }; +enum en_nparmode { + NPAR_MODE_STD = 0, + NPAR_MODE_ALT_A = 1, + NPAR_MODE_ALT_B = 2, + NPAR_MODE_ALT_C = 3, + NPAR_MODE_ALT_D = 4, + NPAR_MODE_ALT_E = 5, + NPAR_MODE_SPIRALNORM = 1, + NPAR_MODE_SPIRALCALT = 2, + NPAR_MODE_SPIRALCINE = 3, + NPAR_MODE_OIL_TRAIL = 1, + NPAR_MODE_OIL_VAPOR = 2, + NPAR_MODE_OIL_SPLASH = 3, + NPAR_MODE_FETTI_SPARKLIES = 1, + NPAR_MODE_DRIP = 1, + NPAR_MODE_DROP = 2, + NPAR_MODE_SPLASH = 3, + NPAR_MODE_TRAIL = 4, + NPAR_MODE_TTNOZZLE = 1, + NPAR_MODE_TTTRAIL = 2, + NPAR_MODE_TTSPLASH = 3, + NPAR_MODE_TTSPOIL = 4, + NPAR_MODE_TTSMOKE = 5, + NPAR_MODE_DOGGYWISP = 1, + NPAR_MODE_DOGGYATTACK = 2, + NPAR_MODE_FWEXHAUST = 1, + NPAR_MODE_FWSTARBURST = 2, + NPAR_MODE_FWGLITTER = 3, + NPAR_MODE_NOMORE = 4, +}; + struct NPARData { xVec3 pos; @@ -66,6 +97,137 @@ struct NPARXtraData { }; +class NPARParmVisSplash { + // total size: 0x20 +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + F32 siz_base[2]; // offset 0x8, size 0x8 + xVec3 acc_base; // offset 0x10, size 0xC + S32 pct_keep; // offset 0x1C, size 0x4 + + void ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const; +}; + +class NPARParmTarTarGunk { + // total size: 0x28 +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + F32 siz_base[2]; // offset 0x8, size 0x8 + xVec3 acc_base; // offset 0x10, size 0xC + F32 uv_scroll[2]; // offset 0x1C, size 0x8 + U8 row_uvstart; // offset 0x24, size 0x1 + U8 num_uvcell[2]; // offset 0x25, size 0x2 + U8 pct_keep; // offset 0x27, size 0x1 + + void ConfigPar(NPARData*, en_nparmode, const xVec3*, const xVec3*) const; +}; + +class NPARParmFahrwerkz { + // total size: 0x28 +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + F32 siz_base[2]; // offset 0x8, size 0x8 + xVec3 acc_base; // offset 0x10, size 0xC + F32 uv_scroll[2]; // offset 0x1C, size 0x8 + U8 row_uvstart; // offset 0x24, size 0x1 + U8 num_uvcell[2]; // offset 0x25, size 0x2 + U8 pct_keep; // offset 0x27, size 0x1 + + void ConfigPar(NPARData*, en_nparmode, const xVec3*, const xVec3*) const; +}; + +class NPARParmSleepyZeez { + // total size: 0x28 +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + F32 siz_base[2]; // offset 0x8, size 0x8 + xVec3 acc_base; // offset 0x10, size 0xC + F32 uv_scroll[2]; // offset 0x1C, size 0x8 + U8 row_uvstart; // offset 0x24, size 0x1 + U8 num_uvcell[2]; // offset 0x25, size 0x2 + U8 pct_keep; // offset 0x27, size 0x1 + + void ConfigPar(NPARData*, en_nparmode, const xVec3*, const xVec3*) const; +}; + +class NPARParmDogBreath { + // total size: 0x20 +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + F32 siz_base[2]; // offset 0x8, size 0x8 + xVec3 acc_base; // offset 0x10, size 0xC + U8 pct_keep; // offset 0x1C, size 0x1 + U8 unused[3]; // offset 0x1D, size 0x3 + + void ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const; +}; + +class NPARParmGloveDust { + // total size: 0x1C +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + F32 siz_base[2]; // offset 0x8, size 0x8 + xVec3 acc_base; // offset 0x10, size 0xC + + void ConfigPar(NPARData* par, en_nparmode pmod, const xVec3* pos, const xVec3* vel) const; +}; + +class NPARParmOilBub +{ + // total size: 0x1C +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + xVec3 acc_oilBubble; // offset 0x8, size 0xC + F32 siz_base[2]; // offset 0x14, size 0x8 + + void ConfigPar(NPARData*, en_nparmode, const xVec3*, const xVec3*) const; +}; + +class NPARParmTubeConfetti +{ + // total size: 0x28 +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + F32 siz_base[2]; // offset 0x8, size 0x8 + xVec3 acc_base; // offset 0x10, size 0xC + F32 uv_scroll[2]; // offset 0x1C, size 0x8 + U8 row_uvstart; // offset 0x24, size 0x1 + U8 num_uvcell[2]; // offset 0x25, size 0x2 + U8 pct_keep; // offset 0x27, size 0x1 + + void ConfigPar(NPARData*, en_nparmode, const xVec3*, const xVec3*) const; +}; + +class NPARParmTubeSpiral +{ + // total size: 0xC +public: + RwRGBA colr_base; // offset 0x0, size 0x4 + F32 siz_base[2]; // offset 0x4, size 0x8 + + void ConfigPar(NPARData*, en_nparmode, const xVec3*, const xVec3*, F32 dt) const; +}; + +class NPARParmChuckSplash { + // total size: 0x20 +public: + F32 tym_lifespan; // offset 0x0, size 0x4 + RwRGBA colr_base; // offset 0x4, size 0x4 + F32 siz_base[2]; // offset 0x8, size 0x8 + xVec3 acc_base; // offset 0x10, size 0xC + S32 pct_keep; // offset 0x1C, size 0x4 + + void ConfigPar(NPARData*, en_nparmode, const xVec3*, const xVec3*) const; +}; + struct NPARMgmt { en_nparptyp typ_npar; @@ -76,6 +238,7 @@ struct NPARMgmt RwTexture* txtr; NPARXtraData* xtra_data; void** user_data; + void KillAll(); void Init(en_nparptyp parType, void** userData, NPARXtraData* xtraData); void Clear(); @@ -85,6 +248,7 @@ struct NPARMgmt void UpdateAndRender(F32 param_1); void XtraDataSet(NPARXtraData* param_1); void UserDataSet(void** user_data); + NPARData* NextAvail(); }; struct NPARInfo @@ -119,8 +283,9 @@ void NPAR_SceneFinish(); void NPAR_EmitTarTarTrail(const xVec3*, const xVec3*); NPARMgmt* NPAR_PartySetup(en_nparptyp parType, void** userData, NPARXtraData* xtraData); void NPAR_SceneReset(); -void NPCC_ShadowCacheReset(); +static void NPCC_ShadowCacheReset(); void NPAR_Timestep(F32 dt); +void NPAR_EmitDroplets(en_nparmode, const xVec3*, const xVec3*); void NPCC_MakeStreakInfo(en_npcstreak styp, StreakInfo* info); U32 xFXStreakStart(StreakInfo* styp); U32 NPCC_StreakCreate(en_npcstreak styp); diff --git a/src/SB/Game/zNPCSupport.cpp b/src/SB/Game/zNPCSupport.cpp index da6ee848d..0c04cd95e 100644 --- a/src/SB/Game/zNPCSupport.cpp +++ b/src/SB/Game/zNPCSupport.cpp @@ -1,16 +1,24 @@ #include "zNPCSupport.h" #include +#include +#include +#include "zGlobals.h" #include "zNPCHazard.h" #include "zNPCGlyph.h" #include "zNPCSupplement.h" #include "xMathInlines.h" +#include "xMath3.h" +#include "xUtil.h" +#include "xBound.h" NPCWidget g_npc_widgets[1] = {}; -static U32 g_hash_uiwidgets[1]; -static char* g_strz_uiwidgets[1] = {}; +static U32 g_hash_uiwidgets[1] = { 0 }; +static char* g_strz_uiwidgets[1] = { "MNU4 NPCTALK" }; +S32 g_pc_playerInvisible; +static Firework g_fireworks[32]; void NPCSupport_Startup() { @@ -18,7 +26,6 @@ void NPCSupport_Startup() zNPCGlyph_Startup(); NPCWidget_Startup(); NPCSupplement_Startup(); - return; } void NPCSupport_Shutdown() @@ -29,14 +36,14 @@ void NPCSupport_Shutdown() NPCSupplement_Shutdown(); } -bool NPCSupport_ScenePrepare() +void NPCSupport_ScenePrepare() { zNPCHazard_ScenePrepare(); zNPCGlyph_ScenePrepare(); NPCWidget_ScenePrepare(); NPCSupplement_ScenePrepare(); Firework_ScenePrepare(); - return NPCC_ForceTalkOk(); + NPCC_ForceTalkOk(); } void NPCSupport_SceneFinish() @@ -46,7 +53,6 @@ void NPCSupport_SceneFinish() NPCWidget_SceneFinish(); NPCSupplement_SceneFinish(); Firework_SceneFinish(); - return; } void NPCSupport_ScenePostInit() @@ -56,7 +62,6 @@ void NPCSupport_ScenePostInit() NPCWidget_ScenePostInit(); NPCSupplement_ScenePostInit(); zNPC_SNDInit(); - return; } void NPCSupport_SceneReset() @@ -66,7 +71,6 @@ void NPCSupport_SceneReset() NPCWidget_SceneReset(); NPCSupplement_SceneReset(); Firework_SceneReset(0); - return; } void NPCSupport_Timestep(F32 dt) @@ -104,17 +108,107 @@ void NPCWidget::Reset() { } +U32 NPCWidget::On(const zNPCCommon* npc, int theman) +{ + if ((!theman && !NPCIsTheLocker(npc)) && (((S32)IsLocked()) || (!Lock(npc)))) + { + return 0; + } + if (IsVisible()) + { + return 1; + } + else + { + zEntEvent(base_widge, 0x5e); + zEntEvent(base_widge, 0x03); + return 1; + } + + return 1; +} + +S32 NPCWidget::Unlock(const zNPCCommon* npc) +{ + if (npc_ownerlock == NULL) + { + return 1; + } + if (npc != npc_ownerlock) + { + return 0; + } + npc_ownerlock = NULL; + return 1; +} + +S32 NPCWidget::NPCIsTheLocker(const zNPCCommon* npc) +{ + if ((S32)IsLocked() == 0) + { + return 0; + } + else + { + return npc == npc_ownerlock ? 1 : 0; + } +} + +S32 NPCWidget::IsVisible() +{ + if (base_widge == NULL) + { + return 0; + } + else if (base_widge->baseType != 0x21) + { + return 0; + } + else + { + return xEntIsVisible((xEnt*)base_widge); + } +} + +S32 NPCWidget::Lock(const zNPCCommon* npc) +{ + if ((npc_ownerlock != NULL) && (npc != npc_ownerlock)) + { + return 0; + } + npc_ownerlock = (zNPCCommon*)npc; + return 1; +} + void NPCWidget_ScenePostInit() { + g_npc_widgets->Init(NPC_WIDGE_TALK); } -void NPCWidget_Find(en_NPC_UI_WIDGETS) +NPCWidget* NPCWidget_Find(en_NPC_UI_WIDGETS which) { - zSceneFindObject(g_hash_uiwidgets[1]); + return &g_npc_widgets[(int)which]; } -void NPCWidget::Init(en_NPC_UI_WIDGETS) +void NPCWidget::Init(en_NPC_UI_WIDGETS which) { + base_widge = zSceneFindObject(g_hash_uiwidgets[idxID = which]); +} + +void NPCTarget::TargetSet(xEnt* ent, int b) +{ + ent_target = ent; + if ((ent != NULL) && (b != 0)) + { + typ_target = NPC_TGT_PLYR; + return; + } + if (ent != NULL) + { + typ_target = NPC_TGT_ENT; + return; + } + typ_target = NPC_TGT_NONE; } void NPCTarget::TargetClear() @@ -125,6 +219,34 @@ void NPCTarget::TargetClear() void NPCBlinker::Reset() { + tmr_uvcell = -1.0f; + idx_uvcell = 0; +} + +void NPCBlinker::Update(F32 dt, F32 ratio, F32 tym_slow, F32 tym_fast) +{ + if (tmr_uvcell < 0.0f) + { + idx_uvcell++; + if (3 < idx_uvcell) + { + idx_uvcell = 0; + } + tmr_uvcell = LERP(SQ(ratio), tym_slow, tym_fast); + } + tmr_uvcell = MAX(-1.0f, tmr_uvcell - dt); +} + +void NPCBlinker::IndexToUVCoord(S32 param_1, F32* param_2, F32* param_3) +{ + S32 shift = ((U32)param_1 >> 31); + S32 uVar1 = ((param_1 & 1) ^ shift) - shift; + + param_2[0] = uVar1 * 0.5f; + param_2[1] = ((param_1 - uVar1) / 2) * 0.5f; + + param_3[0] = param_2[0] + 0.5f; + param_3[1] = param_2[1] + 0.5f; } void Firework_Release(Firework* firework) @@ -148,17 +270,75 @@ void Firework::Cleanup() { } -void Firework_SceneReset(int) +void NPAR_EmitFWExhaust(xVec3* pos, xVec3* vel); + +void Firework::Detonate() +{ + xUtil_yesno(0.25f); +} + +void NPCC_ang_toXZDir(F32 angle, xVec3* dir) +{ + dir->x = isin(angle); + dir->y = 0.0f; + dir->z = icos(angle); +} + +void NPCC_dir_toXZAng(const xVec3* vec) { + xatan2(vec->x, vec->z); +} + +void NPCC_aimMiss(xVec3* dir_aim, xVec3* pos_src, xVec3* pos_tgt, F32 dst_miss, xVec3* pos_miss) +{ + NPCC_aimVary(dir_aim, pos_src, pos_tgt, dst_miss, 8, pos_miss); +} + +void Firework_SceneReset(int param_1) +{ + Firework* fw; + for (int i = 0; i < (int)(sizeof(g_fireworks) / sizeof(Firework)); i++) + { + fw = &g_fireworks[i]; + if ((param_1 != 0) && (fw->fwstate != 0)) + { + Firework_Release(fw); + } + fw->fwstate = 0; + fw++; + } } void Firework_Timestep(F32 dt) { + for (int i = 0; i < 32; i++) + { + if (g_fireworks[i].fwstate != FW_STAT_UNUSED) + { + if ((g_fireworks[i].fwstate != FW_STAT_READY) && (g_fireworks[i].flg_firework & 4)) + { + if (g_fireworks[i].fwstate == FW_STAT_DONE) + { + Firework_Release(&g_fireworks[i]); + } + else + { + g_fireworks[i].Update(dt); + g_fireworks[i].flg_firework &= ~2; + } + } + } + } +} + +S32 NPCC_LampStatus() +{ + return g_pc_playerInvisible == 0 ? true : false; } bool NPCC_ForceTalkOk() { - return false; + return globals.player.g.DisableForceConversation == 0 ? 1 : 0; } RwRaster* NPCC_FindRWRaster(const char* txtrname) @@ -171,9 +351,14 @@ RwRaster* NPCC_FindRWRaster(const char* txtrname) return NULL; } -RwTexture* NPCC_FindRWTexture(const char*) +RwTexture* NPCC_FindRWTexture(U32 hashid) { - return NULL; + return (RwTexture*)xSTFindAsset(hashid, NULL); +} + +RwTexture* NPCC_FindRWTexture(const char* txtrname) +{ + return (RwTexture*)xSTFindAsset(xStrHash(txtrname), NULL); } RwRaster* NPCC_FindRWRaster(RwTexture* txtr) @@ -189,6 +374,205 @@ void zNPC_SNDInit() { } +U32 NPCC_LineHitsBound(xVec3* param_1, xVec3* param_2, xBound* param_3, xCollis* param_4) +{ + xRay3 ray; + xVec3 vec; + xCollis local_colrec; + xCollis* colrec = &local_colrec; + F32 len; + + if (param_4 != NULL) + { + colrec = (xCollis *)param_4; + } + xVec3Sub(&vec, param_2, param_1); + len = xVec3Length(&vec); + if (len < 0.001f) + { + len = 0.001f; + } + xVec3Copy(&ray.origin, param_1); + xVec3SMul(&ray.dir, &vec, (1.0f / len)); + + ray.max_t = len; + ray.min_t = 0.1f; + ray.flags = 3072; + + xRayHitsBound(&ray, param_3, colrec); + return colrec->flags & 1; +} + +S32 NPCC_bnd_ofBase(xBase* tgt, xBound* bnd) +{ + S32 retval = 1; + + switch(tgt->baseType) + { + case eBaseTypeCamera: + case eBaseTypeDoor: + case eBaseTypeVolume: + case eBaseTypeEGenerator: + retval = 0; + break; + case eBaseTypePlayer: + case eBaseTypePickup: + case eBaseTypePlatform: + case eBaseTypeStatic: + case eBaseTypeDynamic: + case eBaseTypeBubble: + case eBaseTypePendulum: + case eBaseTypeHangable: + case eBaseTypeButton: + case eBaseTypeProjectile: + case eBaseTypeDestructObj: + case eBaseTypeNPC: + case eBaseTypeBoulder: + *bnd = *(xBound*)((int)tgt + 0x64); + break; + default: + retval = 0; + break; + case eBaseTypeCruiseBubble: + break; + } + return retval; +} + +S32 NPCC_pos_ofBase(xBase* tgt, xVec3* pos) +{ + xVec3 *pxVar1; + S32 retval = 1; + + switch(tgt->baseType) + { + case eBaseTypeCamera: + xVec3Copy(pos, &globals.camera.mat.pos); + break; + case eBaseTypeCruiseBubble: + retval = 0; + break; + case eBaseTypePlayer: + case eBaseTypePickup: + case eBaseTypePlatform: + case eBaseTypeStatic: + case eBaseTypeDynamic: + case eBaseTypeBubble: + case eBaseTypePendulum: + case eBaseTypeHangable: + case eBaseTypeButton: + case eBaseTypeProjectile: + case eBaseTypeDestructObj: + case eBaseTypeNPC: + case eBaseTypeBoulder: + xVec3Copy(pos, xEntGetPos((xEnt *)tgt)); + break; + case eBaseTypeDoor: + case eBaseTypeVolume: + case eBaseTypeEGenerator: + retval = 0; + break; + default: + retval = 0; + break; + } + return retval; +} + +void NPCTarget::PosGet(xVec3* pos) +{ + switch (typ_target) + { + case NPC_TGT_NONE: + break; + case NPC_TGT_PLYR: + case NPC_TGT_ENT: + case NPC_TGT_BASE: + NPCC_pos_ofBase(bas_target, pos); + break; + case NPC_TGT_POS: + xVec3Copy(pos, &pos_target); + break; + case NPC_TGT_MVPT: + xVec3Copy(pos, zMovePointGetPos(nav_target)); + break; + } +} + +void NPCC_xBoundAway(xBound* bnd) +{ + if (bnd->type == XBOUND_TYPE_SPHERE) + { + bnd->box.center.y -= 1000000.0f; + } + else if (bnd->type == XBOUND_TYPE_BOX) + { + bnd->box.center.y -= 1000000.0f; + } +} + +void NPCC_xBoundBack(xBound* bnd) +{ + if (bnd->type == XBOUND_TYPE_SPHERE) + { + bnd->box.center.y += 1000000.0f; + } + else if (bnd->type == XBOUND_TYPE_BOX) + { + bnd->box.center.y += 1000000.0f; + } +} + +void NPCC_DstSq(const xVec3*, const xVec3*, xVec3*); + +void NPCC_DstSqPlyrToPos(const xVec3* pos) +{ + NPCC_DstSq(pos, xEntGetPos(&globals.player.ent), NULL); +} + +F32 NPCC_ds2_toCam(const xVec3* pos_from, xVec3* delta) +{ + xVec3 delt = {}; + xVec3Sub(&delt, &globals.camera.mat.pos, pos_from); + F32 retval = xVec3Length2(&delt); + if (delta != (xVec3 *)0) + { + xVec3Copy(delta, &delt); + } + return retval; +} + +void NPCC_Bounce(xVec3* vec_input, xVec3* vec_anti, F32 elastic) +{ + if (vec_input->x * vec_anti->x < 0.0f) + { + vec_input->x *= -1.0f; + } + + if (vec_input->y * vec_anti->y < 0.0f) + { + vec_input->y *= -1.0f; + } + + if (vec_input->z * vec_anti->z < 0.0f) + { + vec_input->z *= -1.0f; + } + + xVec3SMulBy(vec_input, elastic); +} + +void NPCC_rotHPB(xMat3x3* mat, F32 heading, F32 pitch, F32 bank) +{ + xMat3x3 mat_rot = {}; + + xMat3x3RotZ(mat, bank); + xMat3x3RotX(&mat_rot, -pitch); + xMat3x3Mul(mat, mat, &mat_rot); + xMat3x3RotY(&mat_rot, heading); + xMat3x3Mul(mat, mat, &mat_rot); +} + F32 NPCC_TmrCycle(float* tmr, float dt, float interval) { F32 parameterized; @@ -208,3 +592,18 @@ F32 NPCC_TmrCycle(float* tmr, float dt, float interval) return parameterized; } + +void NPCC_MakePerp(xVec3* dir_perp, const xVec3* dir_axis) +{ + dir_perp->x = dir_axis->y - dir_axis->z; + dir_perp->y = dir_axis->z - dir_axis->x; + dir_perp->z = dir_axis->x - dir_axis->y; + + xVec3Normalize(dir_perp, dir_perp); +} + +void NPCC_MakeArbPlane(const xVec3* dir_norm, xVec3* at, xVec3* rt) +{ + NPCC_MakePerp(at, dir_norm); + xVec3Cross(rt, at, dir_norm); +} \ No newline at end of file diff --git a/src/SB/Game/zNPCSupport.h b/src/SB/Game/zNPCSupport.h index 8dfaa1909..96b6761b9 100644 --- a/src/SB/Game/zNPCSupport.h +++ b/src/SB/Game/zNPCSupport.h @@ -27,7 +27,9 @@ enum _tageNPCSnd enum en_NPC_UI_WIDGETS { - NPC_UI_WIDGETS_unk // Come back after more data is put in + NPC_WIDGE_TALK = 0, + NPC_WIDGE_NOMORE = 1, + NPC_WIDGE_FORCE = 2, }; enum en_fwstate @@ -65,6 +67,9 @@ struct NPCTarget zNPCCommon* npc_owner; void TargetClear(); + void PosGet(xVec3* pos); + void TargetSet(xEnt* ent, int b); + S32 IsDead(); }; struct NPCBlinker @@ -73,6 +78,8 @@ struct NPCBlinker S32 idx_uvcell; void Reset(); + void IndexToUVCoord(int param_1, float* param_2, float* param_3); + void Update(F32 dt, F32 ratio, F32 tym_slow, F32 tym_fast); }; struct NPCWidget @@ -81,16 +88,22 @@ struct NPCWidget xBase* base_widge; zNPCCommon* npc_ownerlock; - U32 NPCIsTheLocker(zNPCCommon* npc_lock); - U32 IsVisible(); + S32 NPCIsTheLocker(const zNPCCommon* npc_lock); + U32 IsLocked(); + S32 IsVisible(); U32 Off(zNPCCommon* npc, U32 theman); - U32 On(zNPCCommon* npc, U32 theman); + U32 On(const zNPCCommon* npc, S32 theman); void Reset(); void Init(en_NPC_UI_WIDGETS); + S32 Lock(const zNPCCommon*); + S32 Unlock(const zNPCCommon*); }; struct Firework { + static F32 acc_thrust; + static F32 acc_gravity; + struct { en_fwstate fwstate : 8; @@ -105,6 +118,7 @@ struct Firework void FlyFlyFly(F32 dt); void Update(F32 dt); void Cleanup(); + void Detonate(); }; bool NPCC_ForceTalkOk(); @@ -115,7 +129,7 @@ void NPCWidget_SceneFinish(); void NPCWidget_SceneReset(); void NPCWidget_ScenePostInit(); void NPCSupport_Startup(); -bool NPCSupport_ScenePrepare(); +void NPCSupport_ScenePrepare(); void NPCSupport_SceneFinish(); void NPCSupport_Timestep(F32 dt); void NPCSupport_SceneReset(); @@ -138,6 +152,7 @@ xVec3* NPCC_faceDir(xEnt* ent); void NPCC_ang_toXZDir(F32 angle, xVec3* dir); F32 NPCC_aimVary(xVec3* dir_aim, xVec3* pos_src, xVec3* pos_tgt, F32 dst_vary, S32 flg_vary, xVec3* pos_aimPoint); +void NPCC_aimMiss(xVec3*, xVec3*, xVec3*, float, xVec3*); F32 NPCC_ds2_toCam(const xVec3* pos_from, xVec3* delta); void zNPC_SNDStop(_tageNPCSnd snd); void zNPC_SNDPlay3D(_tageNPCSnd snd, xEnt*); diff --git a/src/SB/Game/zNPCTypeAmbient.h b/src/SB/Game/zNPCTypeAmbient.h index 0a2bf955f..5d402e2d0 100644 --- a/src/SB/Game/zNPCTypeAmbient.h +++ b/src/SB/Game/zNPCTypeAmbient.h @@ -47,10 +47,12 @@ struct zNPCJelly : zNPCAmbient void PlayWithAlpha(F32 unk); void PlayWithAnimSpd(); void PumpFaster(); + xVec3* JellyBoneWorldPos(xVec3* pos, S32 idx_request) const; void PlayWithLightnin(); void SetAlpha(F32 alpha); U32 AnimPick(S32 animID, en_NPC_GOAL_SPOT gspot, xGoal* goal); + void ActLikeOctopus(); }; struct zNPCNeptune : zNPCAmbient diff --git a/src/SB/Game/zNPCTypeBossPlankton.cpp b/src/SB/Game/zNPCTypeBossPlankton.cpp index ba6885a84..65d30295a 100644 --- a/src/SB/Game/zNPCTypeBossPlankton.cpp +++ b/src/SB/Game/zNPCTypeBossPlankton.cpp @@ -30,6 +30,15 @@ namespace return 0; } + F32 get_player_loc() + { + return 0; + } + + void play_sound(int, const xVec3*, float) + { + } + } // namespace xAnimTable* ZNPC_AnimTable_BossPlankton() @@ -387,6 +396,75 @@ S32 zNPCGoalBPlanktonMove::Process(en_trantype*, F32, void*, xScene*) return 0; } +xFactoryInst* zNPCGoalBPlanktonBomb::create(S32 who, RyzMemGrow* grow, void* info) +{ + return 0; // To-Do +} + +S32 zNPCGoalBPlanktonStun::Enter(float dt, void* updCtxt) +{ + owner.reappear(); + owner.delay = 0.0f; + owner.flag.follow = owner.FOLLOW_NONE; + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBPlanktonStun::Exit(float dt, void* updCtxt) +{ + owner.give_control(); + owner.flag.follow = owner.FOLLOW_PLAYER; + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalBPlanktonDizzy::Enter(float dt, void* updCtxt) +{ + owner.give_control(); + owner.delay = 0.0f; + owner.flag.follow = owner.FOLLOW_NONE; + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBPlanktonBeam::Enter(float dt, void* updCtxt) +{ + xParEmitter parE; + xParEmitter& pEmit = parE; // this is one of the codes of all time + owner.reappear(); + owner.delay = 0.0f; + emitted = 0.0f; + owner.flag.follow = owner.FOLLOW_NONE; + owner.enable_emitter(pEmit); + void play_sound(S32, const xVec3*, F32); // dunno how to get this to call properly + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBPlanktonBomb::Enter(float dt, void* updCtxt) +{ + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBPlanktonHunt::Enter(float dt, void* updCtxt) +{ + owner.reappear(); + get_player_loc(); + owner.flag.attacking = true; + owner.delay = 0.0f; + owner.reset_speed(); + owner.refresh_orbit(); + owner.follow_camera(); + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBPlanktonHunt::Exit(float dt, void* updCtxt) +{ + owner.refresh_orbit(); + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalBPlanktonBomb::Exit(float dt, void* updCtxt) +{ + return xGoal::Exit(dt, updCtxt); +} + S32 zNPCGoalBPlanktonTaunt::Process(en_trantype*, F32, void*, xScene*) { return 0; diff --git a/src/SB/Game/zNPCTypeBossPlankton.h b/src/SB/Game/zNPCTypeBossPlankton.h index 1d4c62553..be7ec5e9a 100644 --- a/src/SB/Game/zNPCTypeBossPlankton.h +++ b/src/SB/Game/zNPCTypeBossPlankton.h @@ -9,6 +9,7 @@ #include "xLaserBolt.h" #include "xTimer.h" #include "zNPCGoals.h" +#include "xParEmitter.h" struct zNPCNewsFish; @@ -124,15 +125,23 @@ struct zNPCBPlankton : zNPCBoss void update_dialog(float); void init_beam(); void vanish(); + void reappear(); U32 crony_attacking() const; S32 player_left_territory(); void say(int, int, bool); void aim_gun(xAnimPlay*, xQuat*, xVec3*, int); void here_boy(); + void follow_camera(); + void reset_speed(); + void refresh_orbit(); S32 IsAlive(); + void give_control(); U8 ColPenFlags() const; U8 ColChkFlags() const; U8 ColChkByFlags() const; + + // Not yet organized + void enable_emitter(xParEmitter&) const; }; struct zNPCGoalBPlanktonIdle : zNPCGoalCommon @@ -178,6 +187,9 @@ struct zNPCGoalBPlanktonHunt : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + + S32 Enter(float, void*); + S32 Exit(float, void*); }; struct zNPCGoalBPlanktonTaunt : zNPCGoalCommon @@ -201,6 +213,9 @@ struct zNPCGoalBPlanktonStun : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Enter(float, void*); + S32 Exit(float, void*); + S32 Process(en_trantype*, float, void*, xScene*); }; struct zNPCGoalBPlanktonFall : zNPCGoalCommon @@ -215,6 +230,8 @@ struct zNPCGoalBPlanktonDizzy : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Enter(float, void*); + S32 Exit(float, void*); }; struct zNPCGoalBPlanktonBeam : zNPCGoalCommon @@ -232,6 +249,7 @@ struct zNPCGoalBPlanktonBeam : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Enter(float, void*); }; struct zNPCGoalBPlanktonWall : zNPCGoalCommon @@ -255,6 +273,8 @@ struct zNPCGoalBPlanktonBomb : zNPCGoalCommon zNPCBPlankton& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); + S32 Enter(float, void*); + S32 Exit(float, void*); S32 Process(en_trantype*, float, void*, xScene*); }; diff --git a/src/SB/Game/zNPCTypeBossSandy.cpp b/src/SB/Game/zNPCTypeBossSandy.cpp index c1a50ac90..c7f031241 100644 --- a/src/SB/Game/zNPCTypeBossSandy.cpp +++ b/src/SB/Game/zNPCTypeBossSandy.cpp @@ -5,12 +5,17 @@ #include "xEvent.h" #include "xCamera.h" #include "xMath3.h" +#include "xDebug.h" #include "zEnt.h" #include "zFX.h" #include "zGlobals.h" #include "zNPCSndTable.h" #include "zNPCTypeBossSandy.h" +#include "xMarkerAsset.h" +#include "zCamera.h" +#include "zGrid.h" +#include "zAssetTypes.h" extern const char bossSandyStrings[]; @@ -43,104 +48,83 @@ extern const char bossSandyStrings[]; #define NoHeadReplace01 27 #define NoHeadHit01 28 -extern F32 __830; // 0.0 0 -extern F32 __831; // 1.0 3f800000 -extern F32 __842; // 0.20000000298023224 3e4ccccd -extern F32 _843; // 3.3333332538604736 40555555 -extern F32 _864; // 0.25 3e800000 -extern F32 _1029; // 6.2831854820251465 40c90fdb -extern F32 _1030; // 0.0625 3d800000 -extern F32 _1031; // 255.0 437f0000 -extern F32 _1032; // 0.5 3f000000 -extern F32 _1033; // -1.0 bf800000 -extern F32 _1034; // 20.0 41a00000 -extern F32 _1035; // 10.0 41200000 -extern F32 _1036; // 1000000000.0 4e6e6b28 -extern F32 _1037; // 2.25 40100000 -extern F32 _1039; // 176.0 43300000 -extern F32 _1061_1; // 6.0 40c00000 -extern F32 _1062_1; // 1.2999999523162842 3fa66666 -extern F32 _1063; // 2.0 40000000 -extern F32 _1064; // 3.0 40400000 -extern F32 _1065; // 8.199999809265137 41033333 -extern F32 _1066; // 4.0 40800000 -extern F32 _1067; // 4.5 40900000 -extern F32 _1068; // 0.15000000596046448 3e19999a -extern F32 _1069; // -0.4000000059604645 becccccd -extern F32 _1070; // 9.699999809265137 411b3333 -extern F32 _1071; // 7.0 40e00000 -extern F32 _1072; // 5.0 40a00000 -extern F32 _1188_1; // -0.30000001192092896 be99999a -extern F32 _1189; // 1.25 3fa00000 -extern F32 _1190; // 0.035999998450279236 3d1374bc -extern F32 _1191; // 0.10999999940395355 3de147ae -extern F32 _1192_1; // 0.10000000149011612 3dcccccd -extern F32 _1193; // -10.0 c1200000 -extern F32 _1194; // 6.041999816894531 40c15810 -extern F32 _1195; // 0.125 3e000000 -extern F32 _1196; // 100.0 42c80000 -extern F32 _1209; // 9.999999747378752e-06 3727c5ac -extern F32 _1378; // 478.0 43ef0000 -extern F32 _1379; // 0.6000000238418579 3f19999a -extern F32 _1380; // 0.8999999761581421 3f666666 -extern F32 _1381; // 1.100000023841858 3f8ccccd -extern F32 _1462; // 9.0 41100000 -extern F32 _1463; // 0.30000001192092896 3e99999a -extern F32 _1464; // 0.699999988079071 3f333333 -extern F32 _1465; // 3.1415927410125732 40490fdb -extern F32 _1466; // 0.75 3f400000 -extern F32 _1521; // 0.800000011920929 3f4ccccd -extern F32 _1522; // -0.800000011920929 bf4ccccd -extern F32 _1523; // -2.0 c0000000 -extern F32 _1524; // 66.0 42840000 -extern F32 _1525; // -2500.0 c51c4000 -extern F32 _1526_0; // -1.5 bfc00000 -extern F32 _1527; // 13.0 41500000 -extern F32 _1528; // 3.5 40600000 -extern F32 _1529; // -2.5 c0200000 -extern F32 _1530; // 25.0 41c80000 -extern F32 _1531; // 15.0 41700000 -extern F32 _1666; // 0.4000000059604645 3ecccccd -extern F32 _1667; // -3.1415927410125732 c0490fdb -extern F32 _1935; // 60.0 42700000 -extern F32 _1936; // 0.9900000095367432 3f7d70a4 -extern F32 _1937; // 0.009999999776482582 3c23d70a -extern F32 _1938; // 2.950000047683716 403ccccd -extern F32 _1939; // 15.5 41780000 -extern F32 _1940; // 1.5 3fc00000 -extern F32 _1941; // 40.0 42200000 -extern F32 _1942; // 0.8100000023841858 3f4f5c29 -extern F32 _2154; // 30.0 41f00000 -extern F32 _2155; // -9.999999747378752e-06 b727c5ac -extern F32 _2156; // 2.309999942779541 4013d70a -extern F32 _2173; // 12.0 41400000 -extern F32 _2236; // 0.7070000171661377 3f34fdf4 -extern F32 _2237; // 2.5 40200000 -extern F32 _2264; // 1.7000000476837158 3fd9999a -extern F32 _2265; // 0.7699999809265137 3f451eb8 -extern F32 _2376; // 0.9800000190734863 3f7ae148 -extern F32 _2377; // 0.019999999552965164 3ca3d70a -extern F32 _2517; // 1.1549999713897705 3f93d70a -extern F32 _2518; // 80.0 42a00000 -extern F32 _2519; // 31.0 41f80000 -extern F32 _2520; // 42.0 42280000 -extern F32 _2525; // 0.6499999761581421 3f266666 -extern F32 _2582; // -3.0 c0400000 -extern F32 _2633; // 5.25 40a80000 -extern F32 _2741; // 0.0010000000474974513 3a83126f -extern F32 _2742; // 4.71238899230957 4096cbe4 -extern F32 _2818; // 1.75 3fe00000 -extern F32 _2903; // 0.05000000074505806 3d4ccccd -extern F32 _2904; // -0.05000000074505806 bd4ccccd +static F32 sSinTable[16]; +static SandyLimbSpring sLeftArmSpring; +static SandyLimbSpring sRightArmSpring; +static SandyLimbSpring sLeftLegSpring; +static SandyLimbSpring sRightLegSpring; +static xVec3 sCamSubTargetFixed; +static U32 sNFSoundValue[30]; +static BossDamageEffectRecord BDErecord[4]; + +static U8 sOthersHaventBeenAdded; +static U8 sPCWasBubbleBouncing; +static F32 sRadiusOfRing; +static F32 sElbowDropTimer; +static F32 sChaseTimer; +static F32 sNumAttacks; +static F32 sDidClothesline; +static F32 sElbowDropThreshold; +static zNPCBSandy* sSandyPtr; +static xVec3* sCamSubTarget; +static F32 sCurrYaw; +static F32 sCurrHeight; +static F32 sCurrRadius; +static F32 sCurrPitch; +static U32 sCurrNFSound; + +static U8 sUseBossCam = TRUE; +static U8 sWasUsingBossCam = TRUE; +static F32 sPCHeightDiff = -1.0f; +static F32 sHeadPopOffFactor = -1.0f; +static S32 sLeftFootBones[2] = { 0x2B, 0x2C }; +static S32 sRightFootBones[2] = { 0x30, 0x31 }; + +static S32 sBone[13] = { + 0x3, 0x5, 0x12, 0x14, 0x19, 0x1B, 0x22, 0x24, 0x26, 0x29, 0x2B, 0x2E, 0x30 +}; +static S32 sLeftHandBones[4] = { 0x14, 0x15, 0x16, 0x17 }; +static S32 sRightHandBones[4] = { 0x1B, 0x1C, 0x1D, 0x1E }; +static F32 sBoundRadius[13] = { 1.4f, 1.3f, -1.0f, 0.6f, -1.0f, 0.6f, 0.6f, + 0.69999999f, 0.8f, -1.0f, 0.89999999f, -1.0f, 0.89999999f }; +static xVec3 sBoneOffset[13] = { {}, + { 0.0f, 1.1f, 0.0f }, + {}, + { 0.3f, 0.0f, 0.0f }, + {}, + { -0.3f, 0.0f, 0.0f }, + { 0.0f, 0.2f, 0.0f }, + { 0.0f, 0.2f, 0.0f }, + {}, + {}, + { 0.0f, -0.6f, 0.3f }, + {}, + { 0.0f, -0.6f, 0.3f } }; +static char* sNFSoundLabel[30] = { + "FAB1006", "FAB1007", "FAB1008", "FAB1009", "FAB1010", "FAB1011", "FAB1012", "FAB1013", + "FAB1014", "FAB1015", "FAB1016", "FAB1017", "FAB1018", "FAB1018", "FAB1018", "FAB1018", + "FAB1018", "FAB1018", "FAB1019", "FAB1020", "FAB1021", "FAB1022", "FAB1023", "FAB1024", + "FAB1025", "FAB1026", "FAB1027", "FAB1028", "FAB1029", "FAB1030" +}; + +static const tweak_callback newsfish_cb = {}; +static const tweak_callback shockwave_cb = {}; extern zGlobals globals; -extern zNPCBSandy* sSandyPtr; -extern U32 sCurrNFSound; - extern NPCSndTrax g_sndTrax_BossSandy[1]; -extern BossDamageEffectRecord BDErecord[4]; +static S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 noHeadCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 elbowDropCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 leapCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 chaseCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 meleeCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 sitCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 getUpCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 runToRopeCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 clotheslineCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); void on_change_newsfish(const tweak_info& tweak) { @@ -154,8 +138,8 @@ void on_change_shockwave(const tweak_info& tweak) xVec3Copy((xVec3*)(&sSandyPtr->shockwaveEmitter->tasset->pos), (xVec3*)(&sSandyPtr->model->Mat->pos)); - sSandyPtr->shockwaveEmitter->tasset->pos.y = __830; - sSandyPtr->shockRadius = __831; + sSandyPtr->shockwaveEmitter->tasset->pos.y = 0.0f; + sSandyPtr->shockRadius = 1.0f; } xAnimTable* ZNPC_AnimTable_BossSandy() @@ -196,54 +180,61 @@ xAnimTable* ZNPC_AnimTable_BossSandy() //Missing like 2 logic lines or something, too tired to figure it out xAnimTable* table = xAnimTableNew("zNPCBSandy", NULL, 0); - xAnimTableNewState(table, g_strz_bossanim[Unknown], 0x10, 0x40, __831, NULL, NULL, __830, NULL, - NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Idle02], 0x10, 0x40, __831, NULL, NULL, __830, NULL, + xAnimTableNewState(table, g_strz_bossanim[Unknown], 0x10, 0x40, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Taunt01], 0x10, 0, __831, NULL, NULL, __830, NULL, + xAnimTableNewState(table, g_strz_bossanim[Idle02], 0x10, 0x40, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Run01], 0x10, 0, __831, NULL, NULL, __830, NULL, NULL, + xAnimTableNewState(table, g_strz_bossanim[Taunt01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Walk01], 0x10, 0, __831, NULL, NULL, __830, NULL, - NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Dizzy01], 0x10, 0, __831, NULL, NULL, __830, NULL, - NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[ElbowDrop01], 0x10, 0, __831, NULL, NULL, __830, NULL, - NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Leap01], 0x10, 0, __831, NULL, NULL, __830, NULL, - NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Leap02], 0x10, 0, __831, NULL, NULL, __830, NULL, - NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Leap03], 0x10, 0, __831, NULL, NULL, __830, NULL, - NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Leap04], 0x10, 0, __831, NULL, NULL, __830, NULL, + xAnimTableNewState(table, g_strz_bossanim[Run01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[Walk01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[Dizzy01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[ElbowDrop01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Sit01], 0x10, 0, __831, NULL, NULL, __830, NULL, NULL, + xAnimTableNewState(table, g_strz_bossanim[Leap01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[Leap02], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[Leap03], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[Hit02], 0x10, 0, __831, NULL, NULL, __830, NULL, NULL, + xAnimTableNewState(table, g_strz_bossanim[Leap04], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[SitShock01], 0x10, 0, __831, NULL, NULL, __830, NULL, + xAnimTableNewState(table, g_strz_bossanim[Sit01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[Hit02], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[SitShock01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[CLBegin01], 0x10, 0, __831, NULL, NULL, __830, NULL, + xAnimTableNewState(table, g_strz_bossanim[CLBegin01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[CLLoop01], 0x10, 0, __831, NULL, NULL, __830, NULL, + xAnimTableNewState(table, g_strz_bossanim[CLLoop01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[CLEnd01], 0x10, 0, __831, NULL, NULL, __830, NULL, + xAnimTableNewState(table, g_strz_bossanim[CLEnd01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[NoHeadIdle01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[NoHeadIdle01], 0x10, 0, __831, NULL, NULL, __830, - NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[NoHeadWaving01], 0x10, 0, __831, NULL, NULL, __830, + xAnimTableNewState(table, g_strz_bossanim[NoHeadWaving01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[NoHeadGetUp01], 0x10, 0, __831, NULL, NULL, __830, - NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[NoHeadShotUp01], 0x10, 0, __831, NULL, NULL, __830, - NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[NoHeadShock01], 0x10, 0, __831, NULL, NULL, __830, + xAnimTableNewState(table, g_strz_bossanim[NoHeadGetUp01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, + NULL, xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[NoHeadShotUp01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, g_strz_bossanim[NoHeadReplace01], 0x10, 0, __831, NULL, NULL, __830, + xAnimTableNewState(table, g_strz_bossanim[NoHeadShock01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, + NULL, xAnimDefaultBeforeEnter, NULL, NULL); + xAnimTableNewState(table, g_strz_bossanim[NoHeadReplace01], 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - NPCC_BuildStandardAnimTran(table, g_strz_bossanim, ourAnims, 1, __842); + NPCC_BuildStandardAnimTran(table, g_strz_bossanim, ourAnims, 1, 0.2f); + + xAnimTransition* tList = table->TransitionList; + while (tList != NULL) + { + tList->BlendRecip = 3.3333333f; + tList = tList->Next; + } return table; } @@ -279,25 +270,159 @@ xAnimTable* ZNPC_AnimTable_BossSandyHead() table = xAnimTableNew(str_SandyBossHead, NULL, 0); - xAnimTableNewState(table, str_Idle01, 0x10, 0, __831, NULL, NULL, __830, NULL, NULL, + xAnimTableNewState(table, str_Idle01, 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, str_Carried01, 0x10, 0, __831, NULL, NULL, __830, NULL, NULL, + xAnimTableNewState(table, str_Carried01, 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewState(table, str_Shocked01, 0x10, 0, __831, NULL, NULL, __830, NULL, NULL, + xAnimTableNewState(table, str_Shocked01, 0x10, 0, 1.0f, NULL, NULL, 0.0f, NULL, NULL, xAnimDefaultBeforeEnter, NULL, NULL); - xAnimTableNewTransition(table, str_Idle01, str_Carried01, HeadIsCarried, NULL, 0, 0, __830, - __830, 0, 0, _864, NULL); - xAnimTableNewTransition(table, str_Carried01, str_Idle01, HeadNotCarried, NULL, 0, 0, __830, - __830, 0, 0, _864, NULL); - xAnimTableNewTransition(table, str_Idle01, str_Shocked01, HeadIsShocked, NULL, 0, 0, __830, - __830, 0, 0, _864, NULL); - xAnimTableNewTransition(table, str_Shocked01, str_Idle01, HeadNotShocked, NULL, 0, 0, __830, - __830, 0, 0, _864, NULL); + xAnimTableNewTransition(table, str_Idle01, str_Carried01, HeadIsCarried, NULL, 0, 0, 0.0f, 0.0f, + 0, 0, 0.25f, NULL); + xAnimTableNewTransition(table, str_Carried01, str_Idle01, HeadNotCarried, NULL, 0, 0, 0.0f, + 0.0f, 0, 0, 0.25f, NULL); + xAnimTableNewTransition(table, str_Idle01, str_Shocked01, HeadIsShocked, NULL, 0, 0, 0.0f, 0.0f, + 0, 0, 0.25f, NULL); + xAnimTableNewTransition(table, str_Shocked01, str_Idle01, HeadNotShocked, NULL, 0, 0, 0.0f, + 0.0f, 0, 0, 0.25f, NULL); return table; } +void zNPCBSandy::Init(xEntAsset* asset) +{ + S32 i; + xEnt* ent; + char objName[32]; + xMarkerAsset* laserMarker; + U32 colorPicker; + RwRGBA* _col; + // RwRGBA* _col; + // RwRGBA* _col; + // RwRGBA* _col; + + zNPCCommon::Init(asset); + sSandyPtr = this; + + round = 1; + firstTimeR1Csn = 1; + boundFlags = (U32*)xMemAlloc(gActiveHeap, 13 * sizeof(U32), 0x0); + boundList = (xEnt**)xMemAlloc(gActiveHeap, 13 * sizeof(xEnt*), 0x0); + + for (i = 0; i < 13; i++) + { + } +} + +void zNPCBSandy::Setup() +{ + S32 i; + char objName[32]; + + newsfish = (zNPCNewsFish*)zSceneFindObject(xStrHash("NPC_NEWSCASTER")); + newsfish->TalkOnScreen(1); + + strcpy(objName, "HEALTH_00"); + for (i = 0; i < 3; i++) + { + objName[8] = '1' + (char)i; + underwear[i] = (zEntPickup*)zSceneFindObject(xStrHash(objName)); + } + + // Configure and initialize bossCam + bossCam.cfg.zone_rest.distance = 6.0f; + bossCam.cfg.zone_rest.height = 1.3f; + bossCam.cfg.zone_rest.height_focus = 2.0f; + + bossCam.cfg.zone_above.distance = 3.0f; + bossCam.cfg.zone_above.height = 8.2f; + bossCam.cfg.zone_above.height_focus = 4.0f; + + bossCam.cfg.zone_below.distance = 4.5f; + bossCam.cfg.zone_below.height = 0.15f; + bossCam.cfg.zone_below.height_focus = 2.0f; + + bossCam.cfg.move_speed = 10.0f; + bossCam.cfg.turn_speed = 10.0f; + bossCam.cfg.stick_speed = 10.0f; + bossCam.cfg.stick_yaw_vel = 10.0f; + bossCam.cfg.max_yaw_vel = 10.0f; + bossCam.cfg.margin_angle = -0.4f; + + bossCam.init(); + bossCam.add_tweaks("NPC|zNPCBSandy|Boss Cam|"); + + // Configure and initialize specialBossCam + specialBossCam.cfg.zone_rest.distance = 9.7f; + specialBossCam.cfg.zone_rest.height = 4.0f; + specialBossCam.cfg.zone_rest.height_focus = 4.0f; + + specialBossCam.cfg.zone_above.distance = 10.0f; + specialBossCam.cfg.zone_above.height = 7.0f; + specialBossCam.cfg.zone_above.height_focus = 0.15f; + + specialBossCam.cfg.zone_below.distance = 10.0f; + specialBossCam.cfg.zone_below.height = 0.5f; + specialBossCam.cfg.zone_below.height_focus = 5.0f; + + specialBossCam.cfg.move_speed = 10.0f; + specialBossCam.cfg.turn_speed = 10.0f; + specialBossCam.cfg.stick_speed = 10.0f; + specialBossCam.cfg.stick_yaw_vel = 10.0f; + specialBossCam.cfg.max_yaw_vel = 10.0f; + specialBossCam.cfg.margin_angle = -0.4f; + + specialBossCam.init(); + specialBossCam.add_tweaks("NPC|zNPCBSandy|Mat Smash Cam|"); + + zNPCCommon::Setup(); +} + +void zNPCBSandy::SelfSetup() +{ + xBehaveMgr* bmgr = xBehaveMgr_GetSelf(); + psy_instinct = bmgr->Subscribe(this, 0); + + xPsyche* psy = psy_instinct; + psy->BrainBegin(); + + xGoal* goal = psy->AddGoal('NGB1', NULL); + goal->SetCallbacks(idleCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB2', NULL); + goal->SetCallbacks(tauntCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB3', NULL); + goal->SetCallbacks(chaseCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB4', NULL); + goal->SetCallbacks(meleeCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB5', NULL); + goal->SetCallbacks(noHeadCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB6', NULL); + goal->SetCallbacks(elbowDropCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB7', NULL); + goal->SetCallbacks(leapCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB8', NULL); + goal->SetCallbacks(sitCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB9', NULL); + goal->SetCallbacks(getUpCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB:', NULL); + goal->SetCallbacks(runToRopeCB, NULL, NULL, NULL); + + goal = psy->AddGoal('NGB;', NULL); + goal->SetCallbacks(clotheslineCB, NULL, NULL, NULL); + + psy->BrainEnd(); + psy->SetSafety('NGB1'); +} + void zNPCBSandy::ParseINI() { zNPCCommon::ParseINI(); @@ -308,6 +433,119 @@ void zNPCBSandy::ParseINI() NPCS_SndTablePrepare(g_sndTrax_BossSandy); } +U32 zNPCBSandy::AnimPick(S32 gid, en_NPC_GOAL_SPOT param_2, xGoal* rawgoal) +{ + S32 index = -1; + U32 animID = 0; + zNPCGoalBossSandyClothesline* cl; + + switch (gid) + { + case 'NGB1': + index = 1; + break; + case 'NGB2': + index = 3; + break; + case 'NGB3': + index = 5; + break; + case 'NGB4': + index = 6; + break; + case 'NGB5': + zNPCGoalBossSandyNoHead* noHeadGoal = (zNPCGoalBossSandyNoHead*)rawgoal; + U32 anid = noHeadGoal->stage; + if (anid == 0) + { + if (round == 2) + { + index = 23; + } + else + { + index = 24; + } + } + else if (anid == 1) + { + if (round == 2) + { + index = 21; + } + else + { + index = 22; + } + } + else if (anid == 2) + { + index = 25; + } + else if (anid == 3) + { + index = 21; + } + else if (anid == 4) + { + index = 26; + } + else if (anid == 5) + { + index = 27; + } + break; + case 'NGB6': + index = 11; + break; + case 'NGB7': + index = 12; + break; + case 'NGB8': + zNPCGoalBossSandySit* sitGoal = (zNPCGoalBossSandySit*)rawgoal; + if ((sitGoal->sitFlags & 2) != 0x0) + { + index = 17; + } + else + { + index = 16; + } + break; + case 'NGB:': + index = 4; + break; + case 'NGB;': + cl = (zNPCGoalBossSandyClothesline*)rawgoal; + if (cl->stage == 0) + { + index = 18; + } + else if (cl->stage == 1 && cl->playedAnimEarly == FALSE) + { + index = 19; + } + else + { + index = 20; + } + break; + case 'NGB9': + index = 9; + break; + default: + index = 1; + break; + } + + if (index > -1) + { + animID = g_hash_bossanim[index]; + } + + return animID; +} + void zNPCBSandy_BossDamageEffect_Init() { for (S32 i = 0; i < 4; i++) @@ -316,6 +554,76 @@ void zNPCBSandy_BossDamageEffect_Init() } } +static void UpdateSandyBossCam(zNPCBSandy* sandy, F32 dt) +{ + S32 needToCallStart = 0; + xVec3 tempTarget; + + if ((zCameraIsTrackingDisabled() & 0x8) == 0) + { + needToCallStart = 1; + } + + zCameraDisableTracking(CO_BOSS); + + if (needToCallStart) + { + sandy->bossCam.start(globals.camera); + } + + if (sandy->bossFlags & 0x40) + { + if ((sandy->bossFlags & 0x2000) == 0) + { + sandy->specialBossCam.start(globals.camera); + } + + tempTarget.x = globals.player.ent.model->Mat->pos.x; + tempTarget.y = 0.0f; + tempTarget.z = globals.player.ent.model->Mat->pos.z; + sandy->specialBossCam.set_targets(tempTarget, (xVec3&)sCamSubTarget, 2.0f); + + if ((sandy->bossFlags & 0x4000)) + { + sandy->specialBossCam.update(10.0f); + sandy->bossFlags &= ~0x4000; + } + else + { + sandy->specialBossCam.update(dt); + } + } + else + { + if (sandy->bossFlags & 0x2000) + { + sandy->bossCam.start(globals.camera); + } + + sandy->bossCam.set_targets(*((xVec3*)&globals.player.ent.model->Mat->pos), + (xVec3&)sCamSubTarget, 10.0f); + + if (sandy->bossFlags & 0x4000) + { + sandy->bossCam.update(10.0f); + sandy->bossFlags &= ~0x4000; + } + else + { + sandy->bossCam.update(dt); + } + } + + if (sandy->bossFlags & 0x40) + { + sandy->bossFlags |= 0x2000; + } + else + { + sandy->bossFlags &= ~0x2000; + } +} + static void GetBonePos(xVec3* result, xMat4x3* matArray, S32 index, xVec3* offset) { xMat4x3 tmpMat; @@ -347,7 +655,7 @@ void zNPCBSandy::hiddenByCutscene() { this->underwear[i]->state = (this->underwear[i]->state & 0xffffffc0) | 1; zEntEvent(this->underwear[i], eEventCollision_Visible_On); - this->underwear[i]->timer = __830; // 0.0 + this->underwear[i]->timer = 0.0f; // 0.0 } switch (this->round) @@ -410,6 +718,54 @@ void zNPCBSandy::Damage(en_NPC_DAMAGE_TYPE damtype, xBase*, const xVec3*) } } +void zNPCBSandy_AddBoundEntsToGrid(zScene* scn) +{ + S32 i; + S32 isLimb; + xEnt* ent; + + if (sOthersHaventBeenAdded) + { + sOthersHaventBeenAdded = 0; + + for (i = 0; i < 13; i++) + { + ent = sSandyPtr->boundList[i]; + if (i == 2 || i == 4 || i == 9 || i == 11) + { + isLimb = TRUE; + } + else + { + isLimb = FALSE; + } + + if (isLimb || xGridEntIsTooBig(&colls_grid, ent) != FALSE) + { + xGridAdd(&colls_oso_grid, ent); + + if (isLimb || xGridEntIsTooBig(&colls_oso_grid, ent) != FALSE) + { + ent->gridb.oversize = 0x2; + } + else + { + ent->gridb.oversize = 0x1; + } + } + else + { + xGridAdd(&colls_grid, ent); + ent->gridb.oversize = 0x0; + } + } + } + else + { + sSandyPtr = NULL; + } +} + void zNPCBSandy_GameIsPaused(zScene*) { if (sSandyPtr) @@ -422,7 +778,7 @@ void zNPCBSandy_GameIsPaused(zScene*) } } -S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*) +static S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*) { zNPCGoalBossSandyIdle* idle = (zNPCGoalBossSandyIdle*)rawgoal; zNPCBSandy* sandy = (zNPCBSandy*)idle->psyche->clt_owner; @@ -447,13 +803,13 @@ S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*) xVec3Sub(&tempVector, (xVec3*)&globals.player.ent.model->Mat->pos, (xVec3*)&sandy->model->Mat->pos); - tempVector.y = __830; // 0.0 + tempVector.y = 0.0f; // 0.0 F32 length = xVec3Length2(&tempVector); - if (idle->timeInGoal > _1463) // 0.3 + if (idle->timeInGoal > 0.30000001192092896f) // 0.3 { - if (length > _2173) // 12.0 + if (length > 12.0f) // 12.0 { *trantype = GOAL_TRAN_SET; nextgoal = 'NGB3'; @@ -468,14 +824,14 @@ S32 idleCB(xGoal* rawgoal, void*, en_trantype* trantype, F32, void*) return nextgoal; } -S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +static S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) { zNPCGoalBossSandyTaunt* taunt = (zNPCGoalBossSandyTaunt*)rawgoal; zNPCBSandy* sandy = (zNPCBSandy*)taunt->psyche->clt_owner; S32 nextgoal = 0; xVec3 tempVector; - if (taunt->timeInGoal > _1463) // 0.3 + if (taunt->timeInGoal > 0.30000001192092896f) // 0.3 { if (sandy->bossFlags & 0x400) { @@ -487,18 +843,18 @@ S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) xVec3Sub(&tempVector, (xVec3*)&globals.player.ent.model->Mat->pos, (xVec3*)&sandy->model->Mat->pos); - tempVector.y = __830; // 0.0 + tempVector.y = 0.0f; // 0.0 F32 length = xVec3Length2(&tempVector); - if (sandy->AnimTimeRemain(NULL) < _1381 * dt) // 1.1 + if (sandy->AnimTimeRemain(NULL) < 1.100000023841858f * dt) // 1.1 { if (globals.player.ControlOff) { *trantype = GOAL_TRAN_SET; nextgoal = 'NGB1'; } - else if (length > _2173) // 12.0 + else if (length > 12.0f) // 12.0 { *trantype = GOAL_TRAN_SET; nextgoal = 'NGB3'; @@ -513,7 +869,10 @@ S32 tauntCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } -S32 noHeadCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +static S32 chaseCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); +static S32 meleeCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*); + +static S32 noHeadCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) { zNPCGoalBossSandyNoHead* noHead = (zNPCGoalBossSandyNoHead*)rawgoal; zNPCBSandy* sandy = (zNPCBSandy*)noHead->psyche->clt_owner; @@ -521,7 +880,7 @@ S32 noHeadCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) if (noHead->stage == 4 || noHead->stage == 5) { - if (sandy->AnimTimeRemain(NULL) < _2264 * dt) // 1.7 + if (sandy->AnimTimeRemain(NULL) < 1.7000000476837158f * dt) // 1.7 { *trantype = GOAL_TRAN_SET; nextgoal = 'NGB1'; @@ -531,14 +890,14 @@ S32 noHeadCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } -S32 elbowDropCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +static S32 elbowDropCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) { zNPCGoalBossSandyElbowDrop* edrop = (zNPCGoalBossSandyElbowDrop*)rawgoal; zNPCBSandy* sandy = (zNPCBSandy*)edrop->psyche->clt_owner; S32 nextgoal = 0; xVec3 tempVector; - if (edrop->timeInGoal > _1463) // 0.3 + if (edrop->timeInGoal > 0.30000001192092896f) // 0.3 { if (sandy->bossFlags & 0x400) { @@ -550,11 +909,11 @@ S32 elbowDropCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) xVec3Sub(&tempVector, (xVec3*)&globals.player.ent.model->Mat->pos, (xVec3*)&sandy->model->Mat->pos); - tempVector.y = __830; // 0.0 + tempVector.y = 0.0f; // 0.0 F32 length = xVec3Length2(&tempVector); - if (sandy->AnimTimeRemain(NULL) < _2264 * dt) // 1.7 + if (sandy->AnimTimeRemain(NULL) < 1.7000000476837158f * dt) // 1.7 { if (globals.player.ControlOff) { @@ -567,7 +926,7 @@ S32 elbowDropCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) *trantype = GOAL_TRAN_SET; nextgoal = 'NGB2'; } - else if (length < _2173) // 12.0 + else if (length < 12.0f) // 12.0 { *trantype = GOAL_TRAN_SET; nextgoal = 'NGB4'; @@ -582,7 +941,7 @@ S32 elbowDropCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } -S32 leapCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +static S32 leapCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) { zNPCGoalBossSandyLeap* leap = (zNPCGoalBossSandyLeap*)rawgoal; zNPCBSandy* sandy = (zNPCBSandy*)leap->psyche->clt_owner; @@ -590,7 +949,7 @@ S32 leapCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) if (leap->stage == 3) { - if (sandy->AnimTimeRemain(NULL) < _2264 * dt) // 1.7 + if (sandy->AnimTimeRemain(NULL) < 1.7000000476837158f * dt) // 1.7 { if (sandy->bossFlags & 2) { @@ -608,6 +967,495 @@ S32 leapCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) return nextgoal; } +static S32 sitCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossSandySit* sit = (zNPCGoalBossSandySit*)rawgoal; + zNPCBSandy* sandy = (zNPCBSandy*)sit->psyche->clt_owner; + S32 nextgoal = 0; + + if (sandy->round == 3 && sHeadPopOffFactor > 0.0f) + { + xSndPlay3D(xStrHash("B101_SC_headoff1"), 2.31f, 0.0f, 0x0, 0x0, sandy, 30.0f, SND_CAT_GAME, + 0.0f); + *trantype = GOAL_TRAN_SET; + nextgoal = 'NGB5'; + } + else if (sit->sitFlags & 0x1) + { + if (sit->timeInGoal > sit->totalTime) + { + if (sandy->round == 1) + { + nextgoal = 'NGB9'; + *trantype = GOAL_TRAN_SET; + } + else + { + nextgoal = 'NGB5'; + *trantype = GOAL_TRAN_SET; + } + } + } + else if (sit->timeInGoal > 5.0f) + { + nextgoal = 'NGB9'; + *trantype = GOAL_TRAN_SET; + } + + return nextgoal; +} + +static S32 getUpCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossSandyRunToRope* runGoal = (zNPCGoalBossSandyRunToRope*)rawgoal; + zNPCBSandy* sandy = (zNPCBSandy*)runGoal->psyche->clt_owner; + S32 nextgoal = 0; + xVec3 pcFuturePos; + F32 futureDist; + + xVec3Sub(&pcFuturePos, (xVec3*)&globals.player.ent.model->Mat->pos, + (xVec3*)&sandy->model->Mat->pos); + + pcFuturePos.y = 0.0f; + futureDist = xVec3Length2(&pcFuturePos); + + if (sandy->AnimTimeRemain(NULL) < 1.7f * dt) + { + if ((sandy->round == 1 && !(sandy->hitPoints > 6)) || + (sandy->round == 2 && !(sandy->hitPoints > 3)) || + (sandy->round == 3 && !(sandy->hitPoints > 0)) || (globals.player.ControlOff)) + { + nextgoal = 'NGB1'; + *trantype = GOAL_TRAN_SET; + } + else if (sandy->bossFlags & 0x2) + { + sandy->bossFlags &= ~0x2; + nextgoal = 'NGB2'; + *trantype = GOAL_TRAN_SET; + } + else if (futureDist < 12.0f) + { + nextgoal = 'NGB4'; + *trantype = GOAL_TRAN_SET; + } + else + { + nextgoal = 'NGB3'; + *trantype = GOAL_TRAN_SET; + } + } + + return nextgoal; +} + +static S32 runToRopeCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossSandyRunToRope* runGoal = (zNPCGoalBossSandyRunToRope*)rawgoal; + zNPCBSandy* sandy = (zNPCBSandy*)runGoal->psyche->clt_owner; + S32 nextgoal = 0; + F32 projection; + xVec3 newPos; + + xVec3Sub(&newPos, &sandy->bouncePoint[sandy->fromRope], (xVec3*)&sandy->model->Mat->pos); + + newPos.y = 0.0f; + projection = xVec3Dot(&newPos, &sandy->ropeNormal[sandy->fromRope]); + + if (globals.player.ControlOff != FALSE) + { + nextgoal = 'NGB1'; + *trantype = GOAL_TRAN_SET; + } + else if (projection > 0.0f) + { + nextgoal = 'NGB;'; + *trantype = GOAL_TRAN_SET; + sandy->boundFlags[10] &= ~0x10; + sandy->boundFlags[12] &= ~0x10; + } + + return nextgoal; +} + +static S32 clotheslineCB(xGoal* rawgoal, void*, en_trantype* trantype, F32 dt, void*) +{ + zNPCGoalBossSandyClothesline* cl = (zNPCGoalBossSandyClothesline*)rawgoal; + zNPCBSandy* sandy = (zNPCBSandy*)cl->psyche->clt_owner; + S32 nextgoal = 0; + + if (cl->stage == 2 && sandy->AnimTimeRemain(NULL) < 1.7f * dt) + { + sandy->boundFlags[10] &= ~0x10; + sandy->boundFlags[12] &= ~0x10; + + if (globals.player.ControlOff) + { + nextgoal = 'NGB1'; + *trantype = GOAL_TRAN_SET; + } + else if (sandy->bossFlags & 0x2) + { + sandy->bossFlags &= ~0x2; + nextgoal = 'NGB2'; + *trantype = GOAL_TRAN_SET; + } + else + { + nextgoal = 'NGB3'; + *trantype = GOAL_TRAN_SET; + } + } + + return nextgoal; +} + +S32 zNPCGoalBossSandyIdle::Enter(F32 dt, void* updCtxt) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + timeInGoal = 0.0f; + sandy->bossFlags |= 0x20; + + xVec3Init(&sandy->frame->vel, 0.0f, 0.0f, 0.0f); + + sandy->boundFlags[10] |= 0x10; + sandy->boundFlags[12] |= 0x10; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBossSandyIdle::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + timeInGoal += dt; + + xVec3 newAt; + xVec3Sub(&newAt, (xVec3*)&globals.player.ent.model->Mat->pos, (xVec3*)&sandy->model->Mat->pos); + + newAt.y = 0.0f; + + xVec3Normalize(&newAt, &newAt); + xVec3SMul((xVec3*)&sandy->frame->mat.at, (xVec3*)&sandy->model->Mat->at, 0.98f); + + xVec3AddScaled((xVec3*)&sandy->frame->mat.at, &newAt, 0.02f); + + sandy->frame->mat.at.y = 0.0f; + xVec3Normalize(&sandy->frame->mat.at, &sandy->frame->mat.at); + xVec3Cross(&sandy->frame->mat.right, &sandy->frame->mat.up, &sandy->frame->mat.at); + + sandy->frame->mat.pos.y = 0.0f; + xVec3Dot(&newAt, (xVec3*)&sandy->model->Mat->right); + + F32 lerp = 1.0f; + lerp -= 0.02f; + sandy->model->Anim->Single->BilinearLerp[0] = lerp; + sandy->model->Anim->Single->Blend->BilinearLerp[0] = lerp; + + return xGoal::Process(trantype, dt, updCtxt, xscn); +} + +S32 zNPCGoalBossSandyIdle::Exit(F32 dt, void* updCtxt) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + sandy->bossFlags &= ~0x20; + sandy->boundFlags[10] &= ~0x10; + sandy->boundFlags[12] &= ~0x10; + + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalBossSandyTaunt::Enter(F32 dt, void* updCtxt) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + timeInGoal = 0.0f; + + xVec3Init(&sandy->frame->vel, 0.0f, 0.0f, 0.0f); + xSndPlay3D(xStrHash("B101_SC_taunt"), 0.77f, 0.0f, 0x0, 0x0, sandy, 30.0f, SND_CAT_GAME, 0.6f); + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBossSandyTaunt::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + timeInGoal += dt; + + xVec3 newAt; + xVec3Sub(&newAt, (xVec3*)&globals.player.ent.model->Mat->pos, (xVec3*)&sandy->model->Mat->pos); + + newAt.y = 0.0f; + + xVec3Normalize(&newAt, &newAt); + xVec3SMul((xVec3*)&sandy->frame->mat.at, (xVec3*)&sandy->model->Mat->at, 0.98f); + + xVec3AddScaled((xVec3*)&sandy->frame->mat.at, &newAt, 0.02f); + + sandy->frame->mat.at.y = 0.0f; + xVec3Normalize(&sandy->frame->mat.at, &sandy->frame->mat.at); + xVec3Cross(&sandy->frame->mat.right, &sandy->frame->mat.up, &sandy->frame->mat.at); + + sandy->frame->mat.pos.y = 0.0f; + + return zNPCGoalCommon::Process(trantype, dt, updCtxt, xscn); +} + +S32 zNPCGoalBossSandyChase::Enter(F32 dt, void* updCtxt) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + sandy->bossFlags |= 0x20; + timeInGoal = 0.0f; + + sandy->boundFlags[10] |= 0x10; + sandy->boundFlags[12] |= 0x10; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBossSandyChase::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + sChaseTimer += dt; + timeInGoal += dt; + + xVec3 newAt; + xVec3Sub(&newAt, (xVec3*)&globals.player.ent.model->Mat->pos, (xVec3*)&sandy->model->Mat->pos); + + newAt.y = 0.0f; + + xVec3Normalize(&newAt, &newAt); + xVec3SMul((xVec3*)&sandy->frame->mat.at, (xVec3*)&sandy->model->Mat->at, 0.98f); + + xVec3AddScaled((xVec3*)&sandy->frame->mat.at, &newAt, 0.02f); + + sandy->frame->mat.at.y = 0.0f; + xVec3Normalize(&sandy->frame->mat.at, &sandy->frame->mat.at); + xVec3Cross(&sandy->frame->mat.right, &sandy->frame->mat.up, &sandy->frame->mat.at); + + sandy->frame->mat.pos.y = 0.0f; + xVec3SMul(&sandy->frame->vel, &sandy->frame->mat.at, sandy->cfg_npc->spd_moveMax); + + return zNPCGoalCommon::Process(trantype, dt, updCtxt, xscn); +} + +S32 zNPCGoalBossSandyChase::Exit(F32 dt, void* updCtxt) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + sandy->bossFlags &= ~0x20; + sandy->boundFlags[10] &= ~0x10; + sandy->boundFlags[12] &= ~0x10; + + return zNPCGoalCommon::Exit(dt, updCtxt); +} + +S32 zNPCGoalBossSandyMelee::Enter(F32 dt, void* updCtxt) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + timeInGoal = 0.0f; + sandy->bossFlags &= ~0x2; + + xVec3Init(&sandy->frame->vel, 0.0f, 0.0f, 0.0f); + + sandy->boundList[2]->penby = 0x0; + sandy->boundList[3]->penby = 0x0; + sandy->boundList[4]->penby = 0x0; + sandy->boundList[5]->penby = 0x0; + sandy->boundList[6]->penby = 0x0; + sandy->boundList[7]->penby = 0x0; + sandy->boundList[8]->penby = 0x0; + + xSndPlay3D(xStrHash("B101_SC_chop"), 0.77f, 0.0f, 0x0, 0x0, sandy, 30.0f, SND_CAT_GAME, 0.6f); + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBossSandyMelee::Exit(F32 dt, void* updCtxt) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + sandy->boundList[2]->penby = 0x10; + sandy->boundList[3]->penby = 0x10; + sandy->boundList[4]->penby = 0x10; + sandy->boundList[5]->penby = 0x10; + sandy->boundList[6]->penby = 0x10; + sandy->boundList[7]->penby = 0x10; + sandy->boundList[8]->penby = 0x10; + + return zNPCGoalCommon::Exit(dt, updCtxt); +} + +S32 zNPCGoalBossSandyMelee::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + timeInGoal += dt; + + if (timeInGoal > 0.1f && timeInGoal < 0.75f) + { + xVec3 newAt; + xVec3Sub(&newAt, (xVec3*)&globals.player.ent.model->Mat->pos, + (xVec3*)&sandy->model->Mat->pos); + + newAt.y = 0.0f; + xVec3Normalize(&newAt, &newAt); + xVec3SMul((xVec3*)&sandy->frame->mat.at, (xVec3*)&sandy->model->Mat->at, 0.9f); + + xVec3AddScaled((xVec3*)&sandy->frame->mat.at, &newAt, 0.1f); + + sandy->frame->mat.at.y = 0.0f; + xVec3Normalize(&sandy->frame->mat.at, &sandy->frame->mat.at); + xVec3Cross(&sandy->frame->mat.right, &sandy->frame->mat.up, &sandy->frame->mat.at); + } + + sandy->boundFlags[2] |= 0x1; + sandy->boundFlags[3] |= 0x1; + sandy->boundFlags[4] |= 0x1; + sandy->boundFlags[5] |= 0x1; + sandy->boundFlags[6] |= 0x1; + sandy->boundFlags[7] |= 0x1; + sandy->boundFlags[8] |= 0x1; + + sandy->bossFlags |= 0x1; + + return zNPCGoalCommon::Process(trantype, dt, updCtxt, xscn); +} + +S32 zNPCGoalBossSandyNoHead::Enter(F32 dt, void* updCtxt) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + + sandy->bossFlags &= ~0x100; + timeInGoal = 0.0f; + + xVec3Init(&sandy->frame->vel, 0.0f, 0.0f, 0.0f); + + if (sandy->round == 2) + { + sandy->headBoulder->collis_chk = 0x26; + sandy->headBoulder->collis_pen = 0x0; + } + + stage = 0; + secsSincePatWasCarryingHead = 1.0f; + + return zNPCGoalCommon::Enter(dt, updCtxt); +} + +S32 zNPCGoalBossSandyNoHead::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn) +{ + zNPCBSandy* sandy = (zNPCBSandy*)psyche->clt_owner; + U32 numHints; + xVec3 newAt; + float lerpFactor; + xMat4x3 boneMat; + xQuat q; + + timeInGoal += dt; + if (globals.player.carry.grabbed == sandy->headBoulder) + { + secsSincePatWasCarryingHead = 0.0f; + } + else + { + secsSincePatWasCarryingHead += dt; + } + + if (stage == 0) + { + if (sandy->AnimTimeRemain(NULL) < 1.7f * dt) + { + stage = 1; + DoAutoAnim(NPC_GSPOT_START, FALSE); + timeInGoal = 0.0f; + + if (sandy->round == 3) + { + sandy->boundFlags[10] |= 0x10; + sandy->boundFlags[12] |= 0x10; + } + + if ((sandy->nfFlags & 0x4) == 0 && (sandy->round == 2 || sandy->round == 3)) + { + if (((sandy->nfFlags >> 3) & 3) < 3 || (xrand() & 0x300) == 0) + { + numHints = 2; + if (((sandy->nfFlags >> 3) & 3) < 3) + { + numHints = (sandy->nfFlags >> 3) & 3; + } + + if (sandy->round == 2) + { + sandy->newsfish->SpeakStart(sNFSoundValue[numHints + 12], 0, 0xFFFFFFFF); + } + else + { + sandy->newsfish->SpeakStart(sNFSoundValue[numHints + 21], 0, 0xFFFFFFFF); + } + + sandy->nfFlags &= ~0x18; + sandy->nfFlags |= (numHints + 1) * 8; + } + } + } + + if (sandy->round == 2) + { + if (secsSincePatWasCarryingHead > 0.5f) + { + sCamSubTarget = &sandy->headBoulder->localCenter; + } + else + { + sCamSubTarget = &sandy->bouncePoint[0]; + } + } + } + else if (stage == 1) + { + if (sandy->round == 2) + { + } + else if (secsSincePatWasCarryingHead <= 15.0f) + { + if (((sandy->boundFlags[0] + 4) & 4) == 0) + { + sandy->bossFlags |= 0x80; + } + else + { + } + } + else + { + stage = 4; + sandy->boundFlags[10] &= 0x100; + sandy->boundFlags[12] &= 0x100; + + xSndPlay3D(xStrHash("B101_SC_headback"), 1.155f, 0.0f, 0x0, 0x0, sandy, 30.0f, + SND_CAT_GAME, 0.8f); + DoAutoAnim(NPC_GSPOT_START, FALSE); + timeInGoal = 0.0f; + sandy->bossFlags &= ~0x80; + } + } + else if (stage == 2) + { + } + else if (stage == 3) + { + } + + return zNPCGoalCommon::Process(trantype, dt, updCtxt, xscn); +} + void xBinaryCamera::add_tweaks(char const*) { } diff --git a/src/SB/Game/zNPCTypeBossSandy.h b/src/SB/Game/zNPCTypeBossSandy.h index 178bb7a47..cbd5280fb 100644 --- a/src/SB/Game/zNPCTypeBossSandy.h +++ b/src/SB/Game/zNPCTypeBossSandy.h @@ -186,6 +186,10 @@ struct zNPCGoalBossSandyIdle : zNPCGoalCommon zNPCGoalBossSandyIdle(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 Exit(F32 dt, void* updCtxt); }; struct zNPCGoalBossSandyTaunt : zNPCGoalCommon @@ -195,6 +199,9 @@ struct zNPCGoalBossSandyTaunt : zNPCGoalCommon zNPCGoalBossSandyTaunt(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); }; struct zNPCGoalBossSandyChase : zNPCGoalCommon @@ -204,6 +211,10 @@ struct zNPCGoalBossSandyChase : zNPCGoalCommon zNPCGoalBossSandyChase(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 Exit(F32 dt, void* updCtxt); }; struct zNPCGoalBossSandyMelee : zNPCGoalCommon @@ -213,6 +224,10 @@ struct zNPCGoalBossSandyMelee : zNPCGoalCommon zNPCGoalBossSandyMelee(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); }; struct zNPCGoalBossSandyNoHead : zNPCGoalCommon @@ -224,6 +239,9 @@ struct zNPCGoalBossSandyNoHead : zNPCGoalCommon zNPCGoalBossSandyNoHead(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); }; struct zNPCGoalBossSandyElbowDrop : zNPCGoalCommon @@ -234,6 +252,10 @@ struct zNPCGoalBossSandyElbowDrop : zNPCGoalCommon zNPCGoalBossSandyElbowDrop(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 Exit(F32 dt, void* updCtxt); }; struct zNPCGoalBossSandyLeap : zNPCGoalCommon @@ -249,6 +271,9 @@ struct zNPCGoalBossSandyLeap : zNPCGoalCommon { } + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 Exit(F32 dt, void* updCtxt); S32 Name(); }; @@ -261,6 +286,10 @@ struct zNPCGoalBossSandySit : zNPCGoalCommon zNPCGoalBossSandySit(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 Exit(F32 dt, void* updCtxt); }; struct zNPCGoalBossSandyGetUp : zNPCGoalCommon @@ -270,6 +299,9 @@ struct zNPCGoalBossSandyGetUp : zNPCGoalCommon zNPCGoalBossSandyGetUp(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); }; struct zNPCGoalBossSandyRunToRope : zNPCGoalCommon @@ -279,6 +311,10 @@ struct zNPCGoalBossSandyRunToRope : zNPCGoalCommon zNPCGoalBossSandyRunToRope(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); + virtual S32 Exit(F32 dt, void* updCtxt); }; struct zNPCGoalBossSandyClothesline : zNPCGoalCommon @@ -292,6 +328,18 @@ struct zNPCGoalBossSandyClothesline : zNPCGoalCommon zNPCGoalBossSandyClothesline(S32 goalID) : zNPCGoalCommon(goalID) { } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* scene); +}; + +struct SandyLimbSpring +{ + F32 node1; + F32 vel1; + F32 node2; + F32 vel2; + xBound* bound; }; void zNPCBSandy_AddBoundEntsToGrid(zScene*); diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 773b5f3fa..463202dac 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -418,6 +418,7 @@ struct zNPCCommon : xNPCBasic //Size of zNPCCommon: 0x2A0 bool IsMountableType(en_ZBASETYPE type); void MvptReset(zMovePoint* nav_goto); S32 MvptCycle(); + S32 HaveLOSToPos(xVec3*, float, xScene*, xBase*, xCollis*); void ModelScaleSet(F32 x, F32 y, F32 z); void ModelScaleSet(F32 unk); void ModelScaleSet(const xVec3* vec); @@ -448,6 +449,7 @@ struct zNPCCommon : xNPCBasic //Size of zNPCCommon: 0x2A0 int (*)(xGoal*, void*, en_trantype*, float, void*), int (*)(xGoal*, void*, en_trantype*, float, void*), int (*)(xGoal*, void*, en_trantype*, float, void*)); + zMovePoint* FirstAssigned(); // defined from zNPCGoalRobo.cpp xVec3* Center(); diff --git a/src/SB/Game/zNPCTypeDutchman.cpp b/src/SB/Game/zNPCTypeDutchman.cpp index 2bed6e12a..36b5563c0 100644 --- a/src/SB/Game/zNPCTypeDutchman.cpp +++ b/src/SB/Game/zNPCTypeDutchman.cpp @@ -371,20 +371,39 @@ S32 zNPCGoalDutchmanIdle::Exit(F32 dt, void* updCtxt) S32 zNPCGoalDutchmanIdle::Process(en_trantype* trantype, float dt, void* updCtxt, xScene* xscn) { owner.goal_delay(); - if (owner.delay < owner.delay) + if (owner.delay == owner.delay) { - xGoal::Process(trantype, dt, updCtxt, xscn); + owner.delay = 1; + + owner.next_goal(); } else { - trantype = 0; - owner.next_goal(); + xGoal::Process(trantype, dt, updCtxt, xscn); } return 0; //return xGoal::Process(trantype, dt, updCtxt, xscn); } +xFactoryInst* zNPCGoalDutchmanDisappear::create(S32 who, RyzMemGrow* grow, void* info) +{ + zNPCGoalDutchmanDisappear* tempVar; + tempVar = new (who, grow) zNPCGoalDutchmanDisappear(who, (zNPCDutchman&)*info); + // tempVar = new (who, grow) RyzMemGrow(grow); + if (tempVar != NULL) + { + //tempVar = zNPCGoalDutchmanDisappear(0, (zNPCDutchman&)*info); + // tempVar = new (who, grow) zNPCGoalDutchmanDisappear(who, (zNPCDutchman&)*info); + + //goal = new (who, growCtxt) xGoalEmpty(who); + } + // if () + // { + // } + return 0; +} + S32 zNPCGoalDutchmanDisappear::Exit(F32 dt, void* updCtxt) { return xGoal::Exit(dt, updCtxt); @@ -433,7 +452,7 @@ S32 zNPCGoalDutchmanFlame::Exit(F32 dt, void* updCtxt) return xGoal::Exit(dt, updCtxt); } -S32 zNPCGoalDutchmanCaught::Exit(float dt, void* updCtxt) +S32 zNPCGoalDutchmanCaught::Exit(F32 dt, void* updCtxt) { return xGoal::Exit(dt, updCtxt); } @@ -444,6 +463,24 @@ S32 zNPCGoalDutchmanDeath::Enter(F32 dt, void* updCtxt) return zNPCGoalCommon::Enter(dt, updCtxt); } +S32 zNPCGoalDutchmanDeath::Exit(F32 dt, void* updCtxt) +{ + // Not sure how this is supposed to be called? + // dwarf dats shows: xVec3& up = dt; + owner.move.dest.assign(dt, 0.0f, 1.0f); + return xGoal::Exit(dt, updCtxt); +} + +S32 zNPCGoalDutchmanDeath::Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn) +{ + if (owner.delay >= 2.0f) + { + owner.decompose(); + owner.vanish(); + } + return xGoal::Process(trantype, dt, updCtxt, xscn); +} + U8 zNPCDutchman::PhysicsFlags() const { return 3; diff --git a/src/SB/Game/zNPCTypeDutchman.h b/src/SB/Game/zNPCTypeDutchman.h index d74ee7308..1c1f42f59 100644 --- a/src/SB/Game/zNPCTypeDutchman.h +++ b/src/SB/Game/zNPCTypeDutchman.h @@ -166,6 +166,7 @@ struct zNPCDutchman : zNPCSubBoss void LassoNotify(en_LASSO_EVENT); S32 LassoSetup(); void update_round(); + void decompose(); void next_goal(); void goal_delay(); void start_eye_glow(); @@ -204,8 +205,12 @@ struct zNPCGoalDutchmanIdle : zNPCGoalCommon struct zNPCGoalDutchmanDisappear : zNPCGoalCommon { zNPCDutchman& owner; - S32 Exit(float, void*); + zNPCGoalDutchmanDisappear(S32 goalID, zNPCDutchman& npc) : zNPCGoalCommon(goalID), owner(npc) + { + } + + S32 Exit(float, void*); static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); }; @@ -324,6 +329,8 @@ struct zNPCGoalDutchmanDeath : zNPCGoalCommon F32 min_y; F32 max_y; S32 Enter(F32 dt, void* updCtxt); + S32 Exit(F32 dt, void* updCtxt); + S32 Process(en_trantype* trantype, F32 dt, void* updCtxt, xScene* xscn); zNPCDutchman& owner; static xFactoryInst* create(S32 who, RyzMemGrow* grow, void* info); diff --git a/src/SB/Game/zNPCTypeVillager.cpp b/src/SB/Game/zNPCTypeVillager.cpp index 47b5a9cb5..16104d65b 100644 --- a/src/SB/Game/zNPCTypeVillager.cpp +++ b/src/SB/Game/zNPCTypeVillager.cpp @@ -21,7 +21,7 @@ extern char* g_strz_platanim[2]; extern U32 g_hash_platanim[2]; extern zParEmitter* g_pemit_aqualeak; extern xParEmitterCustomSettings g_parf_aqualeak; -extern xVec3 g_O3; +extern const xVec3 g_O3; // Taken from zNPCTypeVillager.s // Defining these here makes the stringBase0 offsets match in the later functions. diff --git a/src/SB/Game/zNPCTypeVillager.h b/src/SB/Game/zNPCTypeVillager.h index 2c1b95dc7..b3e1b522e 100644 --- a/src/SB/Game/zNPCTypeVillager.h +++ b/src/SB/Game/zNPCTypeVillager.h @@ -225,12 +225,12 @@ void ZNPC_Villager_Startup(); void ZNPC_Villager_Shutdown(); xFactoryInst* ZNPC_Create_Villager(S32 who, RyzMemGrow* growCtxt, void*); void ZNPC_Destroy_Villager(xFactoryInst* inst); -NPCSndTrax g_sndTrax_Villager; S32 zParamGetFloatList(xModelAssetParam* parmdata, U32 pdatsize, const char* str32, S32 found, F32* non_choices, F32 len_mvptspline); void zNPCVillager_SceneFinish(); void zNPCVillager_SceneTimestep(xScene* xscn, F32 dt); +extern NPCSndTrax g_sndTrax_Villager; extern NPCSndTrax g_sndTrax_VillagerMale; extern NPCSndTrax g_sndTrax_VillagerFemale; extern NPCSndTrax g_sndTrax_VillagerElder; diff --git a/src/SB/Game/zTalkBox.cpp b/src/SB/Game/zTalkBox.cpp index f39f00241..dc984e90e 100644 --- a/src/SB/Game/zTalkBox.cpp +++ b/src/SB/Game/zTalkBox.cpp @@ -1,3 +1,19 @@ #include "zTalkBox.h" #include + +namespace +{ + struct SharedTalkboxState + { + void* padding[2]; // FIXME: variables not verified + ztalkbox* active; + }; + + SharedTalkboxState ztalkbox_shared; +} + +ztalkbox* ztalkbox::get_active() +{ + return ztalkbox_shared.active; +} diff --git a/src/SB/Game/zTalkBox.h b/src/SB/Game/zTalkBox.h index 776ecb790..b7ae4c526 100644 --- a/src/SB/Game/zTalkBox.h +++ b/src/SB/Game/zTalkBox.h @@ -84,7 +84,10 @@ struct ztalkbox : xBase static void update_all(xScene& s, F32 dt); static void render_all(); static void reset_all(); + static void clear_layout(); static void permit(U32 add_flags, U32 remove_flags); + static ztalkbox* get_active(); + void start_talk(U32 textID, callback*, zNPCCommon*); // FIXME: params not verified void stop_talk();