215 lines
No EOL
6.2 KiB
C
215 lines
No EOL
6.2 KiB
C
/* Super Mario Sunshine Chaos Edition */
|
|
/* by miluaces */
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdarg.h>
|
|
#include <math.h>
|
|
#include "sms.h"
|
|
|
|
//This version is different from the released version:
|
|
/* 4 effects can occur at the same time
|
|
* Boring effects removed
|
|
* Fixed some crashes
|
|
* A few optimizations for space because of 229 byte limit
|
|
*/
|
|
|
|
//Static variables don't take up code space
|
|
static int timer[4] __attribute__((section(".sdata"))); //Effect timers
|
|
static int currentEffect[4] __attribute__((section(".sdata"))); //Current effects
|
|
static int val[4] __attribute__((section(".sdata"))); //Effect values
|
|
static int oval[4] __attribute__((section(".sdata"))); //Effect reset values
|
|
static Vector lastposition __attribute__((section(".sdata"))); //Stage start position
|
|
static MarioActor* mario __attribute__((section(".sdata"))); //Mario
|
|
|
|
//Runs every frame
|
|
int OnUpdate(MarDirector* director) {
|
|
int (*GameUpdate)(MarDirector* director) = GetObjectFunction(director, Director_GameUpdate);
|
|
|
|
//If a cutscene is running or anything else is wrong, don't do effects (saves alot of crashes)
|
|
if (director != *gpMarDirector || mario == NULL || (mario->status & STATE_CUTSCENE))
|
|
goto EndUpdate;
|
|
|
|
//Kill switch
|
|
if (ControllerOne->buttons & PRESS_DD)
|
|
**gpMarioFlag = MARIOFLAG_GAMEOVER;
|
|
|
|
//Four effects at once
|
|
for (int i = 0; i < 4; i++){
|
|
//If timer passed then generate another effect
|
|
if (timer[i] == 0){
|
|
currentEffect[i] = rand() / 1639; //Random effect (between 0 and 19), division takes less space than modulus
|
|
timer[i] = (rand() / 36) + 450; //Random time (between 15s - 45s)
|
|
val[i] = rand() / 32; //Random effect modifier (between 0 and 1023)
|
|
oval[i] = 0; //Reset effect memory
|
|
}
|
|
|
|
HitActor* other;
|
|
switch (currentEffect[i]){
|
|
case 0:
|
|
//Teleport Mario randomly
|
|
if (rand() <= 500)
|
|
mario->position.x += (float)(val[i] - 500);
|
|
//Only teleport in one direction :(
|
|
break;
|
|
case 1:
|
|
//Gravity reduce
|
|
**gpMarioSpeedY += 1.0f;
|
|
break;
|
|
//Removed annoying camera
|
|
case 4:
|
|
//Maybe remove
|
|
timer[i] = 1;
|
|
|
|
//Test if items can be spawned
|
|
if (*gpItemManager == NULL)
|
|
break;
|
|
|
|
//Create coin
|
|
other = MakeObjAppear(*gpItemManager, OBJ_COIN);
|
|
((ItemActor*)other)->position.x = mario->position.x;
|
|
((ItemActor*)other)->position.y = mario->position.y + 200.0f;
|
|
((ItemActor*)other)->position.z = mario->position.z;
|
|
((ItemActor*)other)->velocity.y = 20.0f;
|
|
((ItemActor*)other)->flags = ((ItemActor*)other)->flags & ~ITEMFLAG_STATIC;
|
|
break;
|
|
case 5:
|
|
//Randomize flags
|
|
//Saved so they can be restored
|
|
if (oval[i] == 0){
|
|
oval[i] = **gpMarioFlag;
|
|
val[i] = (rand() & 0x0FFF) | (rand() << 12);
|
|
val[i] = val[i] | 0x00000001;
|
|
val[i] = val[i] & 0x0013B085;
|
|
}
|
|
**gpMarioFlag = val[i];
|
|
if (timer[i] == 1)
|
|
**gpMarioFlag = oval[i];
|
|
break;
|
|
case 6:
|
|
//Teleport to beginning of stage
|
|
mario->position = lastposition;
|
|
timer[i] = 1;
|
|
break;
|
|
case 7:
|
|
//Random noises
|
|
//Todo: find bounds
|
|
Mario_StartVoice(mario, rand());
|
|
break;
|
|
case 8:
|
|
//Random jump
|
|
//if (rand() <= 1500){
|
|
MarioDoJump(mario);
|
|
// **gpMarioSpeedY = (float)val[i] / 200.0f;
|
|
//}
|
|
break;
|
|
case 9:
|
|
//Hurt mario slowly
|
|
//Todo: no flinch
|
|
if (oval[i] == 0)
|
|
{
|
|
SendMsgToMario(mario, MARIOMSG_HURT);
|
|
oval[i] = 350;
|
|
}
|
|
oval[i]--;
|
|
break;
|
|
//Removed sun changed side
|
|
//Removed sweat and electrify
|
|
case 12:
|
|
//Y textures (taken from gecko code by )
|
|
*(float*)0x803db224 = val[i] / 20.47f;
|
|
if (timer[i] == 1)
|
|
*(float*)0x803db224 = 1.0f;
|
|
break;
|
|
case 13:
|
|
//Launch mario
|
|
MarioDoThrow(mario);
|
|
**gpMarioSpeedY = 200.0f;
|
|
timer[i] = 1;
|
|
break;
|
|
case 14:
|
|
//Jump = launch
|
|
if (mario->status & STATE_AIRBORN)
|
|
MarioDoThrow(mario);
|
|
break;
|
|
case 15:
|
|
//Tremble mario to oblivion
|
|
StartTrembleEffect(GetMarioTrembleEffect(mario), 5.0f, 2.0f, 1.02f, timer[i]);
|
|
timer[i] = 1;
|
|
break;
|
|
case 16:
|
|
//Mario super speed
|
|
SetMarioVelocity(mario, (float)val[i]);
|
|
break;
|
|
}
|
|
timer[i]--;
|
|
}
|
|
|
|
EndUpdate:
|
|
//Run the replaced branch
|
|
return GameUpdate(director);
|
|
}
|
|
|
|
//Called at the start of every scene
|
|
void OnSetup(MarDirector* director)
|
|
{
|
|
//Run replaced branch
|
|
MarDirector_SetupObjects(director);
|
|
|
|
//Save mario's position and reset variables
|
|
mario = GetMarioHitActor();
|
|
lastposition = mario->position;
|
|
|
|
//Fix bad textures, takes less space to just set to 1.0 without if statement
|
|
*(float*)0x803db224 = 1.0f;
|
|
|
|
//Clear effects
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
currentEffect[i] = 0xFF;
|
|
timer[i] = 60;
|
|
}
|
|
}
|
|
|
|
//Called every time water touches the floor
|
|
void OnWaterHitsGround(PollutionManager* pollution, float x, float y, float z, float r)
|
|
{
|
|
//If pollution effect is running, place pollution instead of cleaning it
|
|
if (currentEffect[0] == 17 || currentEffect[1] == 17)
|
|
StampPollution(pollution, 2, x, y, z, r);
|
|
else
|
|
CleanPollution(pollution, x, y, z, r);
|
|
}
|
|
|
|
//Called every time an object touches mario
|
|
void OnObjectTouchMario(HitActor* this, HitActor* other)
|
|
{
|
|
//If effect is running don't run TouchPlayer()
|
|
if (currentEffect[0] == 18 || currentEffect[1] == 18)
|
|
return;
|
|
|
|
//Run replaced branch
|
|
HitActor* (*TouchPlayer)(void* t, void* o) = GetObjectFunction(this, HitActor_TouchPlayer);
|
|
TouchPlayer((void*)this, (void*)other);
|
|
}
|
|
|
|
//Called for each NPC every frame
|
|
void OnAllNPCsUpdate(HitActor* this, int a1, void* drama, void* graphics, int obj)
|
|
{
|
|
Vector dif;
|
|
if (currentEffect[0] == 19 || currentEffect[1] == 19)
|
|
{
|
|
//Get difference between mario and NPC using built in functions to save precious instruction space
|
|
dif = mario->position;
|
|
Vector_Subtract(&dif, &(this->position));
|
|
Vector_Normalize(&dif, &dif);
|
|
Vector_Scale(&dif, 2.0f);
|
|
|
|
//Add to NPC position
|
|
Vector_Add(&(this->position), &dif, &(this->position));
|
|
}
|
|
|
|
//Run replaced branch
|
|
Drama_PrepareUpdate(this, a1, drama, graphics, obj);
|
|
} |