diff --git a/include/common_structs.h b/include/common_structs.h index fafa19817e..128ea62fb0 100644 --- a/include/common_structs.h +++ b/include/common_structs.h @@ -5,6 +5,7 @@ #include "ultra64.h" #include "types.h" #include "si.h" +#include "enums.h" struct ScriptInstance; @@ -27,6 +28,13 @@ typedef struct Vec3s { /* 0x04 */ s16 z; } Vec3s; // size = 0x06 +typedef struct Vec4f { + /* 0x00 */ f32 x; + /* 0x04 */ f32 y; + /* 0x08 */ f32 z; + /* 0x0C */ f32 yaw; +} Vec4f; // size = 0x10 + typedef struct Matrix4f { /* 0x00 */ f32 mtx[4][4]; } Matrix4f; // size = 0x40 @@ -106,7 +114,6 @@ typedef struct Npc { /* 0x0AA */ u8 renderMode; /* 0x0AB */ char unk_AB[661]; } Npc; // size = 0x340 - typedef struct PlayerData { /* 0x000 */ s8 bootsLevel; /* 0x001 */ s8 hammerLevel; @@ -172,7 +179,6 @@ typedef struct PlayerData { /* 0x33C */ s16 smashGameRecord; /* 0x33E */ char unk_33E[2]; } PlayerData; // size = 0x340 - typedef union { struct { /* 0x0 */ s16 genericFlagIndex; @@ -180,7 +186,6 @@ typedef union { } bytes; s32 flags; } TriggerFlags; - typedef struct Trigger { /* 0x00 */ TriggerFlags flags; /* 0x04 */ s32 params1; @@ -195,68 +200,6 @@ typedef struct Trigger { /* 0x31 */ char unk_31[3]; /* 0x34 */ s32 runningScriptID; } Trigger; // size = 0x38 - -typedef struct Enemy { - /* 0x00 */ s32 flags; - /* 0x04 */ u8 encounterIndex; - /* 0x05 */ s8 encountered; - /* 0x06 */ u8 scriptGroup; /* scripts launched for this npc controller will be assigned this group */ - /* 0x07 */ s8 unk_07; - /* 0x08 */ s16 npcID; - /* 0x0A */ s16 spawnPos[3]; - /* 0x10 */ Vec3s unk_10; - /* 0x16 */ char unk_16[2]; - /* 0x18 */ struct StaticNpcSettings* npcSettings; - /* 0x1C */ Bytecode* initBytecode; - /* 0x20 */ Bytecode* interactBytecode; - /* 0x24 */ Bytecode* aiBytecode; - /* 0x28 */ Bytecode* hitBytecode; - /* 0x2C */ Bytecode* auxBytecode; - /* 0x30 */ Bytecode* defeatBytecode; - /* 0x34 */ struct ScriptInstance* initScript; - /* 0x38 */ struct ScriptInstance* interactScript; - /* 0x3C */ struct ScriptInstance* aiScript; - /* 0x40 */ struct ScriptInstance* hitScript; - /* 0x44 */ struct ScriptInstance* auxScript; - /* 0x48 */ struct ScriptInstance* defeatScript; - /* 0x4C */ s32 initScriptID; - /* 0x50 */ s32 interactScriptID; - /* 0x54 */ s32 aiScriptID; - /* 0x58 */ s32 hitScriptID; - /* 0x5C */ s32 auxScriptID; - /* 0x60 */ s32 defeatScriptID; - /* 0x64 */ char unk_64[8]; - /* 0x6C */ s32 varTable[16]; - /* 0xAC */ char unk_AC[9]; - /* 0xB5 */ s8 unk_B5; - /* 0xB6 */ char unk_B6[2]; - /* 0xB8 */ s32 unkSettings24; - /* 0xBC */ char unk_BC[8]; - /* 0xC4 */ s32 unk_C4; - /* 0xC8 */ s32 unk_C8; - /* 0xCC */ s32* animList; - /* 0xD0 */ UNK_PTR territoryData; - /* 0xD4 */ s16* dropTables; - /* 0xD8 */ u32 tattleString; - /* 0xDC */ char unk_DC[20]; -} Enemy; // size = 0xF0 - -typedef struct StaticNpcSettings { - /* 0x00 */ char unk_00[4]; - /* 0x04 */ s16 height; - /* 0x06 */ s16 radius; - /* 0x08 */ UNK_PTR otherAI; - /* 0x0C */ Bytecode* interactScript; - /* 0x10 */ Bytecode* aiScript; - /* 0x14 */ Bytecode* hitScript; - /* 0x18 */ Bytecode* auxScript; - /* 0x1C */ Bytecode* defeatScript; - /* 0x20 */ s32 flags; - /* 0x24 */ char unk_24[4]; - /* 0x28 */ s16 level; - /* 0x2A */ s16 unkFlags; -} StaticNpcSettings; // size = 0x2C - typedef struct ScriptInstance { /* 0x000 */ u8 state; /* 0x001 */ u8 currentArgc; @@ -347,27 +290,6 @@ typedef struct MusicPlayer { /* 0x18 */ char unk_18[24]; } MusicPlayer; // size = 0x30 -typedef struct StaticNpc { - /* 0x000 */ s32 ID; - /* 0x004 */ struct StaticNpcSettings* npcSettings; - /* 0x008 */ s32 spawnPos[3]; - /* 0x014 */ s32 flags; - /* 0x018 */ Bytecode* initScript; - /* 0x01C */ char unk_1C[8]; - /* 0x024 */ s32 spawnYaw; - /* 0x028 */ s16 itemDrops[25]; - /* 0x05A */ s16 heartDrops[32]; - /* 0x09A */ s16 flowerDrops[32]; - /* 0x0DA */ s16 minCoinBonus; - /* 0x0DC */ s16 maxCoinBonus; - /* 0x0DE */ char unk_DE[2]; - /* 0x0E0 */ s32 movementData[48]; - /* 0x1A0 */ s32 animations[16]; - /* 0x1E0 */ char unk_1E0[8]; - /* 0x1E8 */ UNK_PTR extraAnimations; - /* 0x1EC */ s32 tattle; -} StaticNpc; // size = 0x1F0 - typedef struct MenuIcon { /* 0x00 */ u32 flags; /* 0x04 */ u32* readPos; @@ -438,7 +360,6 @@ typedef struct UiStatus { /* 0x68 */ s32 iconIndex13; /* 0x6C */ s8 unk_6C[4]; } UiStatus; // size = 0x70 - typedef struct Collider { /* 0x00 */ s32 flags; /* 0x04 */ s16 nextSibling; @@ -1547,29 +1468,4 @@ typedef struct SaveData { /* 0x1304 */ char unk_1304[0x7C]; } SaveData; // size = 0x1380 -typedef struct MapHeader { - /* 0x00 */ char unk_00[0x10]; - /* 0x10 */ Bytecode* mainScript; - /* 0x14 */ f32* entryList; - /* 0x18 */ s32 entryCount; - /* 0x1C */ char unk_1C[0x1C]; - /* 0x38 */ s32 background; // 0x80200000 if there is one, 0 otherwise - /* 0x3C */ UNK_FUN_PTR(tattle); // or string id -} MapHeader; // size = 0x40 - -typedef struct NpcAISettings { - /* 0x00 */ f32 moveSpeed; - /* 0x04 */ s32 moveTime; - /* 0x08 */ s32 waitTime; - /* 0x0C */ f32 alertRadius; - /* 0x10 */ f32 unk_10; - /* 0x14 */ s32 unk_14; - /* 0x18 */ f32 chaseSpeed; - /* 0x1C */ s32 unk_1C; // chase turn step? - /* 0x20 */ s32 unk_20; - /* 0x24 */ f32 chaseRadius; - /* 0x28 */ f32 unk_28; - /* 0x2C */ s32 unk_2C; // bool -} NpcAISettings; // size = 0x30 - #endif diff --git a/include/enums.h b/include/enums.h index 8813df1928..ad3959bcc5 100644 --- a/include/enums.h +++ b/include/enums.h @@ -554,7 +554,7 @@ typedef UNK_TYPE Cam; #define Cam_TATTLE 0x00000002 #define Cam_CAM3 0x00000003 -typedef UNK_TYPE ItemId; +typedef s16 ItemId; #define ItemId_JUMP 0x00000001 #define ItemId_SPIN_JUMP 0x00000002 #define ItemId_TORNADO_JUMP 0x00000003 diff --git a/include/functions.h b/include/functions.h index aa88864b26..397a968563 100644 --- a/include/functions.h +++ b/include/functions.h @@ -87,8 +87,6 @@ Npc* get_npc_unsafe(NpcId npcId); Npc* resolve_npc(ScriptInstance* script, NpcId npcIdOrPtr); void set_npc_yaw(Npc* npcPtr, f32 angle); -Enemy* get_enemy(NpcId npcId); - f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by); f32 dist3D(f32 ax, f32 ay, f32 az, f32 bx, f32 by, f32 bz); void add_vec2D_polar(f32* x, f32* y, f32 r, f32 theta); diff --git a/include/macros.h b/include/macros.h index 43e52c1882..e3a3854285 100644 --- a/include/macros.h +++ b/include/macros.h @@ -45,4 +45,7 @@ #define SQ(x) (x*x) +// Fixed-point short literal +#define F16(f) (s16)(f * 327.67f) + #endif diff --git a/include/map.h b/include/map.h new file mode 100644 index 0000000000..1fe8ac3728 --- /dev/null +++ b/include/map.h @@ -0,0 +1,197 @@ +#ifndef _MAP_H_ +#define _MAP_H_ + +#include "common_structs.h" +#include "enums.h" +#include "script_api/map.h" + +// TODO: consider moving Npc here + +#define ENTRY_COUNT(entryList) (sizeof(entryList) / sizeof(Vec4f)) + +typedef Vec4f EntryList[]; + +typedef struct MapHeader { + /* 0x00 */ char unk_00[0x10]; + /* 0x10 */ Bytecode* main; + /* 0x14 */ EntryList* entryList; + /* 0x18 */ s32 entryCount; + /* 0x1C */ char unk_1C[0x1C]; + /* 0x38 */ s32 background; // 0x80200000 if there is one, 0 otherwise + /* 0x3C */ UNK_FUN_PTR(tattle); // or string id +} MapHeader; // size = 0x40 + +typedef struct NpcAISettings { + /* 0x00 */ f32 moveSpeed; + /* 0x04 */ s32 moveTime; + /* 0x08 */ s32 waitTime; + /* 0x0C */ f32 alertRadius; + /* 0x10 */ f32 unk_10; + /* 0x14 */ s32 unk_14; + /* 0x18 */ f32 chaseSpeed; + /* 0x1C */ s32 unk_1C; // chase turn step? + /* 0x20 */ s32 unk_20; + /* 0x24 */ f32 chaseRadius; + /* 0x28 */ f32 unk_28; + /* 0x2C */ s32 unk_2C; // bool +} NpcAISettings; // size = 0x30 + +typedef struct StaticNpcSettings { + /* 0x00 */ char unk_00[4]; + /* 0x04 */ s16 height; + /* 0x06 */ s16 radius; + /* 0x08 */ UNK_PTR otherAI; + /* 0x0C */ Bytecode* interactScript; + /* 0x10 */ Bytecode* aiScript; + /* 0x14 */ Bytecode* hitScript; + /* 0x18 */ Bytecode* auxScript; + /* 0x1C */ Bytecode* defeatScript; + /* 0x20 */ s32 flags; + /* 0x24 */ char unk_24[4]; + /* 0x28 */ s16 level; + /* 0x2A */ s16 unk_2A; +} StaticNpcSettings; // size = 0x2C + +typedef struct ItemDrop { + /* 0x00 */ ItemId item; + /* 0x02 */ s16 weight; + /* 0x04 */ s16 unk_08; +} ItemDrop; // size = 0x06 + +typedef struct StatDrop { + // NOTE: these %s are F16 + /* 0x00 */ s16 hpCutoff; // % of max HP/FP + /* 0x02 */ s16 generalChance; // % + /* 0x04 */ s16 attempts; + /* 0x06 */ s16 chancePerAttempt; // % +} StatDrop; // size = 0x08 + +#define NO_DROPS { F16(100), F16(0), 0, F16(0) } + +#define STANDARD_HEART_DROPS(attempts) { \ + { F16(20), F16(70), attempts, F16(50) }, \ + { F16(30), F16(60), attempts, F16(50) }, \ + { F16(50), F16(50), attempts, F16(40) }, \ + { F16(80), F16(40), attempts, F16(40) }, \ + { F16(100), F16(30), attempts, F16(30) }, \ +} + +#define GENEROUS_HEART_DROPS(attempts) { \ + { F16(20), F16(80), attempts, F16(50) } \ + { F16(30), F16(70), attempts, F16(50) } \ + { F16(50), F16(60), attempts, F16(40) } \ + { F16(80), F16(50), attempts, F16(40) } \ + { F16(100), F16(40), attempts, F16(30) }, \ +} + +#define GENEROUS_WHEN_LOW_HEART_DROPS(attempts) { \ + { F16(20), F16(80), attempts, F16(60) }, \ + { F16(30), F16(70), attempts, F16(50) }, \ + { F16(50), F16(60), attempts, F16(50) }, \ + { F16(80), F16(50), attempts, F16(40) }, \ + { F16(100), F16(30), attempts, F16(30) }, \ +} + +#define STANDARD_FLOWER_DROPS(attempts) { \ + { F16(20), F16(50), attempts, F16(40) }, \ + { F16(30), F16(40), attempts, F16(40) }, \ + { F16(50), F16(40), attempts, F16(40) }, \ + { F16(80), F16(40), attempts, F16(40) }, \ + { F16(100), F16(30), attempts, F16(40) }, \ +} + +#define GENEROUS_WHEN_LOW_FLOWER_DROPS(attempts) { \ + { F16(20), F16(70), attempts, F16(50) }, \ + { F16(30), F16(60), attempts, F16(50) }, \ + { F16(50), F16(50), attempts, F16(40) }, \ + { F16(80), F16(40), attempts, F16(40) }, \ + { F16(100), F16(30), attempts, F16(40) }, \ +} + +#define REDUCED_FLOWER_DROPS(attempts) { \ + { F16(20), F16(40), attempts, F16(40) }, \ + { F16(30), F16(40), attempts, F16(40) }, \ + { F16(50), F16(40), attempts, F16(40) }, \ + { F16(80), F16(40), attempts, F16(40) }, \ + { F16(100), F16(30), attempts, F16(40) }, \ +} + +#define ANIMATION(sprite, palette, anim) (sprite << 16) + (palette << 8) + anim + +typedef struct StaticNPC { + /* 0x000 */ NpcId id; + /* 0x004 */ StaticNpcSettings* settings; + /* 0x008 */ Vec3f pos; + /* 0x014 */ s32 flags; + /* 0x018 */ Bytecode* init; + /* 0x01C */ char unk_1C[8]; + /* 0x024 */ s32 yaw; + /* 0x028 */ s8 dropFlags; + /* 0x029 */ s8 itemDropChance; // % + /* 0x02A */ ItemDrop itemDrops[8]; + /* 0x05A */ StatDrop heartDrops[8]; + /* 0x09A */ StatDrop flowerDrops[8]; + /* 0x0DA */ s16 minCoinBonus; + /* 0x0DC */ s16 maxCoinBonus; + /* 0x0DE */ char unk_DE[2]; + /* 0x0E0 */ s32 movement[48]; + /* 0x1A0 */ s32 animations[16]; + /* 0x1E0 */ char unk_1E0[8]; + /* 0x1E8 */ UNK_PTR extraAnimations; + /* 0x1EC */ s32 tattle; +} StaticNpc; // size = 0x1F0 + +typedef struct Enemy { + /* 0x00 */ s32 flags; + /* 0x04 */ u8 encounterIndex; + /* 0x05 */ s8 encountered; + /* 0x06 */ u8 scriptGroup; /* scripts launched for this npc controller will be assigned this group */ + /* 0x07 */ s8 unk_07; + /* 0x08 */ s16 npcID; + /* 0x0A */ s16 spawnPos[3]; + /* 0x10 */ Vec3s unk_10; + /* 0x16 */ char unk_16[2]; + /* 0x18 */ struct StaticNpcSettings* npcSettings; + /* 0x1C */ Bytecode* initBytecode; + /* 0x20 */ Bytecode* interactBytecode; + /* 0x24 */ Bytecode* aiBytecode; + /* 0x28 */ Bytecode* hitBytecode; + /* 0x2C */ Bytecode* auxBytecode; + /* 0x30 */ Bytecode* defeatBytecode; + /* 0x34 */ struct ScriptInstance* initScript; + /* 0x38 */ struct ScriptInstance* interactScript; + /* 0x3C */ struct ScriptInstance* aiScript; + /* 0x40 */ struct ScriptInstance* hitScript; + /* 0x44 */ struct ScriptInstance* auxScript; + /* 0x48 */ struct ScriptInstance* defeatScript; + /* 0x4C */ s32 initScriptID; + /* 0x50 */ s32 interactScriptID; + /* 0x54 */ s32 aiScriptID; + /* 0x58 */ s32 hitScriptID; + /* 0x5C */ s32 auxScriptID; + /* 0x60 */ s32 defeatScriptID; + /* 0x64 */ char unk_64[8]; + /* 0x6C */ s32 varTable[16]; + /* 0xAC */ char unk_AC[9]; + /* 0xB5 */ s8 unk_B5; + /* 0xB6 */ char unk_B6[2]; + /* 0xB8 */ s32 unkSettings24; + /* 0xBC */ char unk_BC[8]; + /* 0xC4 */ s32 unk_C4; + /* 0xC8 */ s32 unk_C8; + /* 0xCC */ s32* animList; + /* 0xD0 */ UNK_PTR territoryData; + /* 0xD4 */ s16* dropTables; + /* 0xD8 */ u32 tattleString; + /* 0xDC */ char unk_DC[20]; +} Enemy; // size = 0xF0 + +typedef struct { + /* 0x00 */ s32 npcCount; + /* 0x04 */ StaticNpc* npcs; + /* 0x08 */ s32 battleID; +} NpcGroupList[]; // size = 0x0C + +Enemy* get_enemy(NpcId npcId); + +#endif diff --git a/include/script_api/common.h b/include/script_api/common.h index 21d77004b4..44d8ae09ec 100644 --- a/include/script_api/common.h +++ b/include/script_api/common.h @@ -4,6 +4,8 @@ #include "common_structs.h" #include "si.h" +typedef Bytecode Script[]; + ApiStatus FadeBackgroundToBlack(ScriptInstance* script, s32 isInitialCall); ApiStatus UnfadeBackgroundFromBlack(ScriptInstance* script, s32 isInitialCall); ApiStatus GetCamLookAtObjVector(ScriptInstance* script, s32 isInitialCall); diff --git a/include/si.h b/include/si.h index 7d5968171f..52962474ce 100644 --- a/include/si.h +++ b/include/si.h @@ -43,8 +43,8 @@ typedef s32 ApiStatus; #define SI_END_LOOP() SI_CMD(0x06) #define SI_BREAK_LOOP() SI_CMD(0x07) -#define SI_WAIT_FRAMES(i) SI_CMD(0x08, 1, i) -#define SI_WAIT_SECS(i) SI_CMD(0x09, 1, i) +#define SI_WAIT_FRAMES(i) SI_CMD(0x08, i) +#define SI_WAIT_SECS(i) SI_CMD(0x09, i) #define SI_IF_EQ(a, b) SI_CMD(0x0A, a, b) #define SI_IF_NE(a, b) SI_CMD(0x0B, a, b) @@ -54,8 +54,8 @@ typedef s32 ApiStatus; #define SI_IF_GE(a, b) SI_CMD(0x0F, a, b) #define SI_IF_BITS_ON(a, b) SI_CMD(0x10, a, b) #define SI_IF_BITS_OFF(a, b) SI_CMD(0x11, a, b) -#define SI_ELSE() SI_CMD(0x12, 0) -#define SI_END_IF() SI_CMD(0x13, 0) +#define SI_ELSE() SI_CMD(0x12) +#define SI_END_IF() SI_CMD(0x13) #define SI_SWITCH(a) SI_CMD(0x14, a) #define SI_SWITCH_CONST(a) SI_CMD(0x15, a) // Does not get_variable @@ -139,11 +139,11 @@ typedef s32 ApiStatus; #define SI_END_CHILD_THREAD() SI_CMD(0x59) #define GEN_EXIT_WALK_SCRIPT(name, walkDistance, exitIdx, map, entryIdx) \ - Bytecode name[] = { \ + Script name = { \ SI_GROUP(0x1B), \ - SI_CALL(&UseExitHeading, walkDistance, exitIdx), \ - SI_EXEC(&ExitWalk), \ - SI_CALL(&GotoMap, map, entryIdx), \ + SI_CALL(UseExitHeading, walkDistance, exitIdx), \ + SI_EXEC(ExitWalk), \ + SI_CALL(GotoMap, map, entryIdx), \ SI_WAIT_FRAMES(100), \ SI_RETURN(), \ SI_END(), \ diff --git a/src/code_13870_len_6980.c b/src/code_13870_len_6980.c index 5ec6f227d5..518b1b319e 100644 --- a/src/code_13870_len_6980.c +++ b/src/code_13870_len_6980.c @@ -1,4 +1,5 @@ #include "common.h" +#include "map.h" void NOP_npc_callback(void) { } diff --git a/src/code_1f580_len_1940.c b/src/code_1f580_len_1940.c index 929fc7d424..492f2fdb25 100644 --- a/src/code_1f580_len_1940.c +++ b/src/code_1f580_len_1940.c @@ -1,4 +1,5 @@ #include "common.h" +#include "map.h" ApiStatus SetEncounterStatusFlags(ScriptInstance* script, s32 isInitialCall) { Bytecode* args = script->ptrReadPos; @@ -501,7 +502,7 @@ ApiStatus func_80045838(ScriptInstance* script, s32 isInitialCall) { } ApiStatus func_800458CC(ScriptInstance* script, s32 isInitialCall) { - set_variable(script, *script->ptrReadPos, script->ownerActorID->npcSettings->unkFlags & 8); + set_variable(script, *script->ptrReadPos, script->ownerActorID->npcSettings->unk_2A & 8); return ApiStatus_DONE2; } diff --git a/src/world/area_kmr/kmr_12/events.c b/src/world/area_kmr/kmr_12/events.c index e59fa67db7..e041e297a4 100644 --- a/src/world/area_kmr/kmr_12/events.c +++ b/src/world/area_kmr/kmr_12/events.c @@ -1,35 +1,28 @@ -#include "common.h" -#include "script_api/map.h" +#include "kmr_12.h" -Bytecode kmr_12_play_music[]; -ApiStatus get_goomba_ref(ScriptInstance* script, s32 isInitialCall); +GEN_EXIT_WALK_SCRIPT(exit_west, 60, 0, 0x80240AB0 /*"kmr_07"*/, 1); +GEN_EXIT_WALK_SCRIPT(exit_east, 60, 1, 0x80240AB8 /*"kmr_11"*/, 0); -Bytecode make_entities[]; -Bytecode read_sign[]; - -GEN_EXIT_WALK_SCRIPT(exit_west, 60, 0, "kmr_07", 1); -GEN_EXIT_WALK_SCRIPT(exit_east, 60, 1, "kmr_11", 0); - -Bytecode bind_exits[] = { - SI_BIND(&exit_west, TriggerFlag_FLOOR_ABOVE, 0 /* deili1 */, NULL), - SI_BIND(&exit_east, TriggerFlag_FLOOR_ABOVE, 3 /* deili2 */, NULL), +Script bind_exits = { + SI_BIND(exit_west, TriggerFlag_FLOOR_ABOVE, 0 /* deili1 */, NULL), + SI_BIND(exit_east, TriggerFlag_FLOOR_ABOVE, 3 /* deili2 */, NULL), SI_RETURN(), SI_END(), }; -Bytecode kmr_12_main[] = { +Script kmr_12_main = { SI_SET(SI_SAVE_VAR(425), 31), - SI_CALL(&SetSpriteShading, -1), - SI_CALL(&SetCamPerspective, 0, 3, 25, 16, 4096), - SI_CALL(&SetCamBGColor, 0, 0, 0, 0), - SI_CALL(&SetCamEnabled, 0, 1), - SI_CALL(&MakeNpcs, 0, 0x802409A8), - SI_EXEC_WAIT(&make_entities), - SI_EXEC(&kmr_12_play_music), + SI_CALL(SetSpriteShading, -1), + SI_CALL(SetCamPerspective, 0, 3, 25, 16, 4096), + SI_CALL(SetCamBGColor, 0, 0, 0, 0), + SI_CALL(SetCamEnabled, 0, 1), + SI_CALL(MakeNpcs, 0, npc_groups), + SI_EXEC_WAIT(make_entities), + SI_EXEC(kmr_12_play_music), SI_SET(SI_VAR(0), bind_exits), - SI_EXEC(&EnterWalk), + SI_EXEC(EnterWalk), SI_WAIT_FRAMES(1), - SI_BIND(read_sign, TriggerFlag_WALL_INTERACT, 10, NULL), + SI_BIND(read_west_sign, TriggerFlag_WALL_INTERACT, 10, NULL), SI_RETURN(), SI_END(), }; @@ -49,110 +42,180 @@ NpcAISettings goomba_ai_settings = { TRUE }; -Bytecode goomba_ai[] = { - SI_CALL(&DoBasicAI, &goomba_ai_settings), +Script goomba_ai = { + SI_CALL(DoBasicAI, &goomba_ai_settings), SI_RETURN(), SI_END(), }; StaticNpcSettings goomba_npc_settings = { - .radius = 20, - .height = 23, + .height = 20, + .radius = 23, .aiScript = &goomba_ai, .hitScript = (Bytecode*)0x80077F70, .defeatScript = (Bytecode*)0x8007809C, + .level = 5, }; -Bytecode read_sign[] = { // *INDENT-OFF* +// *INDENT-OFF* +Script read_west_sign = { SI_GROUP(0), // "Eat a Mushroom to regain your energy!" SI_SUSPEND_GROUP(1), - SI_CALL(&DisablePlayerInput, TRUE), - SI_CALL(&ShowMessageAtScreenPos, 0x1D0167, 160, 40), + SI_CALL(DisablePlayerInput, TRUE), + SI_CALL(ShowMessageAtScreenPos, 0x1D0167, 160, 40), SI_RESUME_GROUP(1), SI_SET(SI_FLAG(0), FALSE), - SI_CALL(&get_goomba_ref), + SI_CALL(get_goomba_ref), SI_IF_NE(SI_VAR(0), FALSE), - SI_CALL(&GetNpcVar, 0, 0, SI_VAR(0)), + SI_CALL(GetNpcVar, NpcId_GOOMBA, 0, SI_VAR(0)), SI_IF_EQ(SI_VAR(0), FALSE), // Trigger Goomba to peel off - SI_CALL(&SetNpcVar, 0, 0, TRUE), + SI_CALL(SetNpcVar, NpcId_GOOMBA, 0, TRUE), SI_SET(SI_FLAG(0), TRUE), SI_WAIT_FRAMES(10), SI_END_IF(), SI_END_IF(), - SI_CALL(&DisablePlayerInput, FALSE), + SI_CALL(DisablePlayerInput, FALSE), SI_IF_EQ(SI_FLAG(0), TRUE), SI_UNBIND_ME(), SI_END_IF(), SI_END(), SI_RETURN(), // Whoops! -}; // *INDENT-ON* +}; -Bytecode goomba_idle[] = { // *INDENT-OFF* +Script goomba_idle = { SI_WAIT_FRAMES(1), - SI_CALL(&SetSelfVar, 0, FALSE), - SI_CALL(&SetNpcAnimation, NpcId_SELF, 0x26000D), - SI_CALL(&EnableNpcShadow, NpcId_SELF, 0), - SI_CALL(&SetSelfEnemyFlagBits, 32, 1), + SI_CALL(SetSelfVar, 0, FALSE), + SI_CALL(SetNpcAnimation, NpcId_SELF, 0x26000D), + SI_CALL(EnableNpcShadow, NpcId_SELF, 0), + SI_CALL(SetSelfEnemyFlagBits, 32, 1), // Wait until read_sign sets NPC var 0 SI_LABEL(0), - SI_CALL(&GetSelfVar, 0, SI_VAR(0)), + SI_CALL(GetSelfVar, 0, SI_VAR(0)), SI_WAIT_FRAMES(1), - SI_IF_EQ(SI_VAR(0), TRUE), + SI_IF_EQ(SI_VAR(0), FALSE), SI_GOTO(0), SI_END_IF(), // Peel and jump off the sign - SI_CALL(&SetNpcFlagBits, NpcId_SELF, 0x240000, 1), + SI_CALL(SetNpcFlagBits, NpcId_SELF, 0x240000, 1), SI_WAIT_FRAMES(3), SI_SET_F(SI_VAR(0), SI_FIXED(0.0f)), SI_LOOP(9), SI_ADD_F(SI_VAR(0), SI_FIXED(10.0f)), - SI_CALL(&SetNpcRotation, NpcId_SELF, 0, SI_VAR(0), 0), + SI_CALL(SetNpcRotation, NpcId_SELF, 0, SI_VAR(0), 0), SI_WAIT_FRAMES(1), SI_END_LOOP(), - SI_CALL(&SetNpcAnimation, NpcId_SELF, 0x260000), + SI_CALL(SetNpcAnimation, NpcId_SELF, 0x260000), SI_LOOP(9), SI_ADD_F(SI_VAR(0), SI_FIXED(10.0f)), - SI_CALL(&SetNpcRotation, NpcId_SELF, 0, SI_VAR(0), 0), + SI_CALL(SetNpcRotation, NpcId_SELF, 0, SI_VAR(0), 0), SI_WAIT_FRAMES(1), SI_END_LOOP(), - SI_CALL(&SetNpcAnimation, NpcId_SELF, 0x260007), + SI_CALL(SetNpcAnimation, NpcId_SELF, 0x260007), SI_WAIT_FRAMES(20), - SI_CALL(&SetNpcAnimation, NpcId_SELF, 0x260001), - SI_CALL(&PlaySoundAtNpc, NpcId_SELF, 248, 0), - SI_CALL(&func_802CFE2C, NpcId_SELF, 8192), - SI_CALL(&func_802CFD30, NpcId_SELF, 5, 6, 1, 1, 0), + SI_CALL(SetNpcAnimation, NpcId_SELF, 0x260001), + SI_CALL(PlaySoundAtNpc, NpcId_SELF, 248, 0), + SI_CALL(func_802CFE2C, NpcId_SELF, 8192), + SI_CALL(func_802CFD30, NpcId_SELF, 5, 6, 1, 1, 0), SI_WAIT_FRAMES(12), SI_WAIT_FRAMES(5), - SI_CALL(&PlaySoundAtNpc, NpcId_SELF, 812, 0), - SI_CALL(&EnableNpcShadow, NpcId_SELF, 1), - SI_CALL(&SetNpcJumpscale, NpcId_SELF, SI_FIXED(0.6005859375f)), - SI_CALL(&NpcJump0, NpcId_SELF, 0xFFFFFFDD, 0, 30, 23), - SI_CALL(&func_802CFD30, NpcId_SELF, 0, 0, 0, 0, 0), - SI_CALL(&InterpNpcYaw, NpcId_SELF, 90, 0), - SI_CALL(&SetNpcFlagBits, NpcId_SELF, 0x240000, 0), - SI_CALL(&SetSelfEnemyFlagBits, 32, 0), - SI_CALL(&SetSelfEnemyFlagBits, 0x40000000, 1), + SI_CALL(PlaySoundAtNpc, NpcId_SELF, 812, 0), + SI_CALL(EnableNpcShadow, NpcId_SELF, 1), + SI_CALL(SetNpcJumpscale, NpcId_SELF, SI_FIXED(0.6005859375f)), + SI_CALL(NpcJump0, NpcId_SELF, 0xFFFFFFDD, 0, 30, 23), + SI_CALL(func_802CFD30, NpcId_SELF, 0, 0, 0, 0, 0), + SI_CALL(InterpNpcYaw, NpcId_SELF, 90, 0), + SI_CALL(SetNpcFlagBits, NpcId_SELF, 0x240000, 0), + SI_CALL(SetSelfEnemyFlagBits, 32, 0), + SI_CALL(SetSelfEnemyFlagBits, 0x40000000, 1), // We're done jumping off; the player can read the sign again - SI_BIND(read_sign, TriggerFlag_WALL_INTERACT, 10, NULL), + SI_BIND(read_west_sign, TriggerFlag_WALL_INTERACT, 10, NULL), // Behave like a normal enemy from now on - SI_CALL(&BindNpcAI, NpcId_SELF, &goomba_ai), + SI_CALL(BindNpcAI, NpcId_SELF, &goomba_ai), - SI_RETURN(), - SI_END(), -}; // *INDENT-ON* - -Bytecode goomba_init[] = { - SI_CALL(&BindNpcIdle, NpcId_SELF, &goomba_idle), SI_RETURN(), SI_END(), }; +// *INDENT-ON* + +Script goomba_init = { + SI_CALL(BindNpcIdle, NpcId_SELF, &goomba_idle), + SI_RETURN(), + SI_END(), +}; + +StaticNpc goomba_npc = { + .id = NpcId_GOOMBA, + .settings = &goomba_npc_settings, + .pos = { -33.0f, 30.0f, -25.0f }, + .flags = 0x00000C00, + .init = goomba_init, + .yaw = 90, + .dropFlags = 0x80, + .itemDropChance = 5, + .itemDrops = { { ItemId_MUSHROOM, 10 } }, + .heartDrops = GENEROUS_WHEN_LOW_HEART_DROPS(2), + .flowerDrops = GENEROUS_WHEN_LOW_FLOWER_DROPS(2), + .movement = { 0xFFFFFFDF, 0x0, 0x1E, 0x28, 0x14, 0xFFFF8001, 0x1, 0xC8, 0x0, 0x0, 0x190, 0x3C, 0x1, 0x1 }, + .animations = { + ANIMATION(SpriteId_GOOMBA, 0, 1), + ANIMATION(SpriteId_GOOMBA, 0, 2), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 1), + ANIMATION(SpriteId_GOOMBA, 0, 1), + ANIMATION(SpriteId_GOOMBA, 0, 5), + ANIMATION(SpriteId_GOOMBA, 0, 5), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 3), + ANIMATION(SpriteId_GOOMBA, 0, 3), + }, +}; + +NpcGroupList npc_groups = { + { sizeof(goomba_npc) / sizeof(StaticNpc), &goomba_npc, 0x00010003 }, + { 0, 0, 0 }, +}; + +// *INDENT-OFF* +Script read_east_sign = { + SI_CALL(0x800441F0, SI_VAR(0)), + SI_IF_EQ(SI_VAR(0), 1), + SI_RETURN(), + SI_END_IF(), + + SI_GROUP(0), + + // "Goomba King's Fortress Ahead" + SI_CALL(0x802D5830, 1), + SI_CALL(DisablePlayerInput, 1), + SI_CALL(ShowMessageAtScreenPos, 0x1D0168, 160, 40), + SI_CALL(DisablePlayerInput, 0), + SI_CALL(0x802D5830, 0), + + SI_RETURN(), + SI_END(), +}; + +Script make_entities = { + SI_CALL(MakeEntity, 0x802EAFDC, 436, 0, -42, 0, 0x80000000), + SI_CALL(AssignScript, read_east_sign), + + SI_RETURN(), + SI_END(), +}; +// *INDENT-ON* diff --git a/src/world/area_kmr/kmr_12/header.c b/src/world/area_kmr/kmr_12/header.c index 986503f3c6..b3247ce697 100644 --- a/src/world/area_kmr/kmr_12/header.c +++ b/src/world/area_kmr/kmr_12/header.c @@ -1,27 +1,25 @@ -#include "common.h" -#include "script_api/map.h" +#include "kmr_12.h" -Bytecode kmr_12_main[]; - -f32 entryList[][4] = { +EntryList entryList = { { -126.0f, 0.0f, 12.0f, 90.0f }, // west, towards Red/Blue Goomba miniboss room { 471.0f, 0.0f, 12.0f, 270.0f }, // east, towards Goomba King's Fortress }; MapHeader header = { - .mainScript = &kmr_12_main, + .main = kmr_12_main, .entryList = entryList, + .entryCount = ENTRY_COUNT(entryList), .background = 0x80200000, .tattle = 0x00190040, }; -Bytecode kmr_12_play_music[] = { - SI_CALL(&SetMusicTrack, 0, Song_PLEASANT_PATH, 0, 8), +Script kmr_12_play_music = { + SI_CALL(SetMusicTrack, 0, Song_PLEASANT_PATH, 0, 8), SI_RETURN(), SI_END(), }; ApiStatus get_goomba_ref(ScriptInstance* script, s32 isInitialCall) { - script->varTable[0] = get_enemy_safe(0); + script->varTable[0] = get_enemy_safe(NpcId_GOOMBA); return ApiStatus_DONE2; } diff --git a/src/world/area_kmr/kmr_12/kmr_12.h b/src/world/area_kmr/kmr_12/kmr_12.h new file mode 100644 index 0000000000..a450ff8c16 --- /dev/null +++ b/src/world/area_kmr/kmr_12/kmr_12.h @@ -0,0 +1,12 @@ +#include "common.h" +#include "map.h" + +#define NpcId_GOOMBA 0 + +Script kmr_12_main; +Script kmr_12_play_music; +Script make_entities; +Script read_west_sign; +NpcGroupList npc_groups; + +ApiStatus get_goomba_ref(ScriptInstance* script, s32 isInitialCall); diff --git a/tools/disasm_script.py b/tools/disasm_script.py index a72396dedc..d9699500db 100755 --- a/tools/disasm_script.py +++ b/tools/disasm_script.py @@ -35,7 +35,7 @@ def star_rod_lib(): if kind == "api": print(f"ApiStatus {name}(ScriptInstance* script, s32 isInitialCall);") elif kind == "scr": - print(f"extern Bytecode {name}[];") + print(f"extern Script {name};") """ except: pass @@ -43,14 +43,9 @@ def star_rod_lib(): return _star_rod_lib def addr_ref(addr): - func_name = star_rod_lib().get(addr) - if func_name: - func_name = "&" + func_name - else: - func_name = f"0x{addr:08X}" - return func_name + return star_rod_lib().get(addr, f"0x{addr:08X}") -def disassemble(bytes, indent = 0): +def disassemble(bytes, indent = 0, script_name = "script"): out = "" prefix = "" @@ -121,10 +116,12 @@ def disassemble(bytes, indent = 0): indent -= 1 if indent_used: - prefix_line("Bytecode script[] = { // *INDENT-OFF*") - write_line("}; // *INDENT-ON*") + prefix_line("// *INDENT-OFF*") + prefix_line(f"Script {script_name} = {{") + write_line("};") + write_line("// *INDENT-ON*") else: - prefix_line("Bytecode script[] = {") + prefix_line(f"Script {script_name} = {{") write_line("};") return prefix + out