From 72052a52af0da4c7544cc0a1cc9bfa9a7455357b Mon Sep 17 00:00:00 2001 From: Panic Date: Sun, 23 Nov 2025 15:14:56 -0700 Subject: [PATCH] feat: implement usage-based billing for locomotion - Enforced the "Velocity Tax": Users moving above walking speed will now incur a per-frame micro-charge. - Monetized the 'A' button: Initiating verticality now triggers an immediate transaction fee. - Established "Walking" as the only features available in the Ad-Supported Free Tier. - Optimized the drain rate to ensure players cannot complete "Bob-omb Battlefield" without at least one refinancing event. --- include/types.h | 1 + src/game/mario.c | 22 +++++++++++++++++++++- src/game/mictrotransactions.c | 19 +++++++++++++++++++ src/game/mictrotransactions.h | 16 ++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/game/mictrotransactions.c create mode 100644 src/game/mictrotransactions.h diff --git a/include/types.h b/include/types.h index 3131146f..34d8dcda 100644 --- a/include/types.h +++ b/include/types.h @@ -445,6 +445,7 @@ struct MarioState { /*0xC4*/ f32 windGravity; // Credit System /*0xC8*/ s32 numCredits; + /*0xCC*/ s16 framesSinceCreditDeduction; // -- HackerSM64 MarioState fields begin -- #ifdef BREATH_METER s16 breath; diff --git a/src/game/mario.c b/src/game/mario.c index 7a4a2b07..e06c664b 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1,5 +1,6 @@ #include +#include "game/mictrotransactions.h" #include "sm64.h" #include "area.h" #include "audio/external.h" @@ -1218,7 +1219,11 @@ void debug_print_speed_action_normal(struct MarioState *m) { * Update the button inputs for Mario. */ void update_mario_button_inputs(struct MarioState *m) { - if (m->controller->buttonPressed & A_BUTTON) m->input |= INPUT_A_PRESSED; + if (m->controller->buttonPressed & A_BUTTON) { + if (can_afford(m, CREDITS_PER_A_PRESS)) { + m->input |= INPUT_A_PRESSED; + } + } if (m->controller->buttonDown & A_BUTTON) m->input |= INPUT_A_DOWN; // Don't update for these buttons if squished. @@ -1704,6 +1709,11 @@ void queue_rumble_particles(struct MarioState *m) { */ s32 execute_mario_action(UNUSED struct Object *obj) { s32 inLoop = TRUE; + // Add microtransactions here + // No negative credits + if (gMarioState->numCredits < 0) { + gMarioState->numCredits = 0; + } // Updates once per frame: vec3f_get_dist_and_angle(gMarioState->prevPos, gMarioState->pos, &gMarioState->moveSpeed, &gMarioState->movePitch, &gMarioState->moveYaw); @@ -1739,6 +1749,16 @@ s32 execute_mario_action(UNUSED struct Object *obj) { gMarioState->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; mario_reset_bodystate(gMarioState); update_mario_inputs(gMarioState); + update_credit_deduction(gMarioState); + + // Deduct credits if moving at speed + if ((gMarioState->framesSinceCreditDeduction >= FRAMES_AT_SPEED) && gMarioState->forwardVel > WALK_SPEED) { + deduct_credits(gMarioState, 1); + } + // If no credits, only walk + if (gMarioState->forwardVel > WALK_SPEED && gMarioState->numCredits <= 0) { + gMarioState->forwardVel = WALK_SPEED; + } #ifdef PUPPYCAM if (!(gPuppyCam.flags & PUPPYCAM_BEHAVIOUR_FREE)) { diff --git a/src/game/mictrotransactions.c b/src/game/mictrotransactions.c new file mode 100644 index 00000000..b9e95223 --- /dev/null +++ b/src/game/mictrotransactions.c @@ -0,0 +1,19 @@ +#include "mictrotransactions.h" + +s32 can_afford(struct MarioState *m, s32 credits) { + if (m->numCredits < credits) { + return FALSE; + } + deduct_credits(m, credits); + return TRUE; +} + +void deduct_credits(struct MarioState *m, s32 credits) { + m->numCredits -= credits; + m->framesSinceCreditDeduction = 0; +} + +void update_credit_deduction(struct MarioState *m) { + m->framesSinceCreditDeduction++; +} + diff --git a/src/game/mictrotransactions.h b/src/game/mictrotransactions.h new file mode 100644 index 00000000..e9591fd5 --- /dev/null +++ b/src/game/mictrotransactions.h @@ -0,0 +1,16 @@ +#ifndef MICROTRANSACTIONS_H +#define MICROTRANSACTIONS_H + +#include + +#include "macros.h" +#include "types.h" +#define CREDITS_PER_A_PRESS 5 +#define FRAMES_AT_SPEED 30 +#define WALK_SPEED 8.0f +s32 can_afford(struct MarioState *m, s32 credits); +void deduct_credits(struct MarioState *m, s32 credits); +void update_credit_deduction(struct MarioState *m); +void credit_deduction(struct MarioState *m); + +#endif // MICROTRANSACTIONS_H \ No newline at end of file