diff --git a/src/fp/practice/trainer.c b/src/fp/practice/trainer.c index 2aa4f152..39c7c4cd 100644 --- a/src/fp/practice/trainer.c +++ b/src/fp/practice/trainer.c @@ -1,6 +1,7 @@ #include "trainer.h" #include "fp.h" #include "menu/menu.h" +#include "sys/input.h" #include "sys/resource.h" #include "sys/settings.h" #include @@ -179,6 +180,17 @@ static s32 enableClippyTrainerProc(struct MenuItem *item, enum MenuCallbackReaso return 0; } +static s32 enableQJumpTrainerProc(struct MenuItem *item, enum MenuCallbackReason reason, void *data) { + if (reason == MENU_CALLBACK_SWITCH_ON) { + settings->trainerBits.qJumpEnabled = 1; + } else if (reason == MENU_CALLBACK_SWITCH_OFF) { + settings->trainerBits.qJumpEnabled = 0; + } else if (reason == MENU_CALLBACK_THINK) { + menuCheckboxSet(item, settings->trainerBits.qJumpEnabled); + } + return 0; +} + static s32 byteOptionmodProc(struct MenuItem *item, enum MenuCallbackReason reason, void *data) { u8 *p = data; if (reason == MENU_CALLBACK_THINK_INACTIVE) { @@ -386,6 +398,29 @@ static void updateBowserBlockTrainer(void) { } } +static void updateQuickJumpTrainer(void) { + static bool qAPressed; + static u8 qJumpCounter; + + if (settings->trainerBits.qJumpEnabled && pm_gGameStatus.isBattle && pm_gActionCommandStatus.actionCommandID == 1) { + // only increment counter if mario is crouching + if (pm_gBattleStatus.playerActor->partsTable->curAnimation == 0x10006) { + if (inputPressed() & BUTTON_A) { + qAPressed = TRUE; + } + qJumpCounter++; + } else if (qJumpCounter != 0) { + if (qJumpCounter > 2 && qJumpCounter < 8) { + fpLog("%d frame%s late", qJumpCounter - 3, qJumpCounter == 1 ? "" : "s"); + } else if (qJumpCounter == 8 && qAPressed) { + fpLog(">= 5 frames late"); + } + qJumpCounter = 0; + qAPressed = FALSE; + } + } +} + static void updateLzsTrainer(void) { if (settings->trainerBits.lzsEnabled) { // detect if loading zone is stored @@ -602,6 +637,7 @@ void trainerUpdate(void) { updateLzsTrainer(); updateBlockTrainer(); updateClippyTrainer(); + updateQuickJumpTrainer(); } void createTrainerMenu(struct Menu *menu) { @@ -644,6 +680,9 @@ void createTrainerMenu(struct Menu *menu) { menuAddStatic(menu, 0, y, "clippy", 0xC0C0C0); struct MenuItem *lastOption = menuAddCheckbox(menu, xOffset, y++, enableClippyTrainerProc, NULL); + + menuAddStatic(menu, 0, y, "quick jumps", 0xC0C0C0); + menuAddCheckbox(menu, xOffset, y++, enableQJumpTrainerProc, NULL); #if PM64_VERSION == JP menuAddStatic(menu, 0, y, "ice staircase skip", 0xC0C0C0); menuAddSubmenuIcon(menu, xOffset, y++, &issMenu, wrench, 0, 0, 1.0f); diff --git a/src/pm64.h b/src/pm64.h index e0608a09..8e5f7e74 100644 --- a/src/pm64.h +++ b/src/pm64.h @@ -524,6 +524,46 @@ typedef struct { /* 0x4C */ f32 distance; } pm_ActorMovement; // size = 0x50; +typedef struct ActorPart { + /* 0x00 */ s32 flags; + /* 0x04 */ s32 targetFlags; /* initialized to 0 */ + /* 0x08 */ void *staticData; + /* 0x0C */ struct ActorPart *nextPart; + /* 0x10 */ void *movement; + /* 0x14 */ Vec3s partOffset; + /* 0x1A */ Vec3s visualOffset; + /* 0x20 */ Vec3f partOffsetFloat; + /* 0x2C */ Vec3f absolutePos; + /* 0x38 */ Vec3f rot; + /* 0x44 */ Vec3s rotPivotOffset; + /* 0x4A */ char unk_4A[2]; + /* 0x4C */ Vec3f scale; + /* 0x58 */ Vec3f curPos; + /* 0x64 */ f32 yaw; + /* 0x68 */ s16 palAnimPosOffset[2]; // used by some palette animations to slightly adjust the screen position + /* 0x6C */ s16 targetOffset[2]; + /* 0x70 */ s16 targetPriorityOffset; + /* 0x72 */ Vec2bu size; + /* 0x74 */ s8 verticalStretch; + /* 0x75 */ Vec2b projectileTargetOffset; + /* 0x77 */ char unk_77[1]; + /* 0x78 */ u32 *defenseTable; + /* 0x7C */ s32 eventFlags; + /* 0x80 */ s32 elementalImmunities; // bits from Elements, i.e., ELEMENT_FIRE | ELEMENT_QUAKE + /* 0x84 */ s32 spriteInstanceID; + /* 0x88 */ u32 curAnimation; + /* 0x8C */ s32 animNotifyValue; + /* 0x90 */ f32 animationRate; + /* 0x94 */ u32 *idleAnimations; + /* 0x98 */ s16 opacity; + /* 0x9A */ char unk_9A[2]; + /* 0x9C */ s32 shadowIndex; + /* 0xA0 */ f32 shadowScale; + /* 0xA4 */ s32 partTypeData[6]; + /* 0xBC */ s16 actorTypeData2b[2]; + /* 0xC0 */ void *decorationTable; +} pm_ActorPart; // size = 0xC4 + typedef struct { /* 0x000 */ s32 flags; /* 0x004 */ s32 flags2; @@ -582,7 +622,7 @@ typedef struct { /* 0x1F1 */ s8 turnPriority; /* 0x1F2 */ s8 enemyIndex; /* actorID = this | 200 */ /* 0x1F3 */ s8 numParts; - /* 0x1F4 */ void *partsTable; // ActorPart + /* 0x1F4 */ pm_ActorPart *partsTable; /* 0x1F8 */ s16 lastDamageTaken; /* 0x1FA */ s16 hpChangeCounter; /* 0x1FC */ u16 damageCounter; diff --git a/src/sys/settings.h b/src/sys/settings.h index c38f31bc..8bf124a8 100644 --- a/src/sys/settings.h +++ b/src/sys/settings.h @@ -49,6 +49,7 @@ struct TrainerBits { u32 lzsEnabled : 1; u32 acEnabled : 1; u32 clippyEnabled : 1; + u32 qJumpEnabled : 1; }; struct SettingsData {