/* Super Mario Sunshine Chaos Edition */ /* by miluaces */ #include #include #include #include #include #include "inc/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 225 line limit */ int timer[4]; //Effect timers int currentEffect[4]; //Current effects int val[4]; //Effect values int oval[4]; //Effect reset values Vector lastposition; //Stage start position MarioActor* mario; //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); }