Path: blob/master/SonicMania/Objects/Global/Competition.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Competition Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectCompetition *Competition;1011void Competition_Update(void)12{13RSDK_THIS(Competition);1415StateMachine_Run(self->state);16}1718void Competition_LateUpdate(void) {}1920void Competition_StaticUpdate(void) {}2122void Competition_Draw(void)23{24RSDK_THIS(Competition);2526#if MANIA_USE_PLUS27if (RSDK_GET_ENTITY(SceneInfo->currentScreenID, Player)->classID == Player->classID) {28#endif29if (!self->playerFinished[SceneInfo->currentScreenID]) {30Vector2 drawPos;31drawPos.x = TO_FIXED(ScreenInfo[SceneInfo->currentScreenID].center.x - 4);32drawPos.y = TO_FIXED(26);33self->animator.frameID = self->timer / 10;34RSDK.DrawSprite(&self->animator, &drawPos, true);3536drawPos.x += TO_FIXED(8);37self->animator.frameID = self->timer % 10;38RSDK.DrawSprite(&self->animator, &drawPos, true);39}40#if MANIA_USE_PLUS41}42#endif43}4445void Competition_Create(void *data)46{47RSDK_THIS(Competition);4849if (!SceneInfo->inEditor) {50self->isPermanent = true;51self->active = ACTIVE_NORMAL;52self->visible = true;53self->drawGroup = Zone->hudDrawGroup - 1;5455self->seconds = SceneInfo->seconds;56if (SceneInfo->minutes == 9) {57self->timer = 0;5859if (60 - SceneInfo->seconds > 0)60self->timer = 60 - SceneInfo->seconds;6162if (!SceneInfo->milliseconds)63SceneInfo->milliseconds = 1;64}65else {66self->timer = 60;67}6869self->state = Competition_State_Manager;70RSDK.SetSpriteAnimation(Competition->aniFrames, 1, &self->animator, true, 0);71}72}7374void Competition_StageLoad(void)75{76Competition->sessionManager = NULL;7778Competition->aniFrames = RSDK.LoadSpriteAnimation("Global/HUD.bin", SCOPE_STAGE);79}8081void Competition_State_Manager(void)82{83RSDK_THIS(Competition);8485#if MANIA_USE_PLUS86if (self->timer <= 0) {87Zone->gotTimeOver = true;88SceneInfo->timeEnabled = false;89for (int32 p = 0; p < Player->playerCount; ++p) {90EntityPlayer *player = RSDK_GET_ENTITY(p, Player);91if (player->classID == Player->classID && player->state == Player_State_Death)92player->visible = true;93}94self->state = StateMachine_None;95}96else {97if (self->seconds != SceneInfo->seconds) {98self->seconds = SceneInfo->seconds;99100self->timer--;101if (self->timer == 12) {102Music_PlayJingle(TRACK_DROWNING);103}104else if (!self->timer) {105Zone->gotTimeOver = true;106SceneInfo->timeEnabled = false;107for (int32 p = 0; p < Player->playerCount; ++p) {108if (!self->playerFinished[p]) {109EntityPlayer *player = RSDK_GET_ENTITY(p, Player);110if (player->classID == Player->classID)111player->deathType = PLAYER_DEATH_DIE_USESFX;112}113}114}115}116}117#else118if (self->timer > 0) {119if (self->seconds != SceneInfo->seconds) {120self->seconds = SceneInfo->seconds;121122self->timer--;123if (!self->timer) {124Zone->gotTimeOver = true;125for (int32 p = 0; p < Player->playerCount; ++p) {126if (!self->playerFinished[p]) {127EntityPlayer *player = RSDK_GET_ENTITY(p, Player);128player->deathType = PLAYER_DEATH_DIE_USESFX;129self->state = StateMachine_None;130}131}132}133}134}135#endif136}137138#if MANIA_USE_PLUS139void Competition_ResetOptions(void)140{141EntityCompetitionSession *session = CompetitionSession_GetSession();142session->inMatch = false;143session->matchID = 0;144session->matchCount = 0;145session->stageIndex = 0;146147for (int32 i = 0; i < COMPETITION_STAGE_COUNT; ++i) {148session->completedStages[i] = false;149session->matchWinner[i] = 0;150}151152for (int32 p = 0; p < PLAYER_COUNT; ++p) {153session->finishState[p] = FINISHTYPE_NOTFINISHED;154session->playerID[p] = ID_NONE;155session->time[p].minutes = 0;156session->time[p].seconds = 0;157session->time[p].milliseconds = 0;158session->rings[p] = 0;159session->score[p] = 0;160session->items[p] = 0;161session->totalRings[p] = 0;162session->wins[p] = 0;163session->lives[p] = 0;164}165}166167void Competition_ClearMatchData(void)168{169EntityCompetitionSession *session = CompetitionSession_GetSession();170171session->matchWinner[session->matchID] = 0;172173for (int32 p = 0; p < PLAYER_COUNT; ++p) {174session->finishState[p] = FINISHTYPE_NOTFINISHED;175session->time[p].minutes = 0;176session->time[p].seconds = 0;177session->time[p].milliseconds = 0;178session->rings[p] = 0;179session->score[p] = 0;180session->items[p] = 0;181session->totalRings[p] = 0;182}183}184185void Competition_DeriveWinner(int32 playerID, uint8 finishType)186{187EntityCompetitionSession *session = CompetitionSession_GetSession();188session->finishState[playerID] = finishType;189190if (finishType == FINISHTYPE_GAMEOVER) {191session->totalRings[playerID] = 0;192session->items[playerID] = 0;193session->rings[playerID] = 0;194session->score[playerID] = 0;195session->time[playerID].minutes = 9;196session->time[playerID].seconds = 59;197session->time[playerID].milliseconds = 59;198}199200int32 deathCount = 0;201bool32 allPlayersFinished = true;202for (int32 p = 0; p < session->playerCount; ++p) {203if (!session->lives[p] || session->finishState[p] == FINISHTYPE_GAMEOVER)204++deathCount;205}206207if (deathCount < session->playerCount - 1) {208for (int32 p = 0; p < session->playerCount; ++p) allPlayersFinished = allPlayersFinished && (!session->lives[p] || session->finishState[p]);209}210211if (allPlayersFinished) {212if (!session->matchWinner[session->matchID]) {213uint32 winnerTime = 0xFFFFFFFF;214int32 winnerRings = 0;215int32 winnerScore = 0;216int32 winnerItems = 0;217int32 winnerTotalRings = 0;218219uint32 times[PLAYER_COUNT];220for (int32 p = 0; p < session->playerCount; ++p) {221int32 mins = session->time[p].minutes;222int32 secs = session->time[p].seconds;223int32 ms = session->time[p].milliseconds;224uint32 time = ms + 100 * (secs + 60 * mins);225times[p] = time;226227if (session->rings[p] > winnerRings)228winnerRings = session->rings[p];229230if (session->totalRings[p] > winnerTotalRings)231winnerTotalRings = session->totalRings[p];232233if (session->score[p] > winnerScore)234winnerScore = session->score[p];235236if (session->items[p] > winnerItems)237winnerItems = session->items[p];238239if (time < winnerTime)240winnerTime = time;241}242243int32 scores[PLAYER_COUNT];244memset(scores, 0, PLAYER_COUNT * sizeof(int32));245246int32 winner = 0;247for (int32 p = 0; p < session->playerCount; ++p) {248if (session->finishState[p] == FINISHTYPE_PASSEDSIGNPOST) {249int32 score = 0;250if (session->rings[p] == winnerRings)251score++;252253if (session->totalRings[p] == winnerTotalRings)254++score;255256if (session->score[p] == winnerScore)257++score;258259if (times[p] == winnerTime)260++score;261262if (session->items[p] == winnerItems)263++score;264265LogHelpers_Print("player %d => score %d", p, score);266267scores[p] = score;268if (score > winner)269winner = score;270}271}272273for (int32 p = 0; p < session->playerCount; ++p) {274bool32 isWinner = session->lives[p] > 0 && session->finishState[p] != FINISHTYPE_GAMEOVER && scores[p] == winner;275if (isWinner) {276Competition_WinMatchFor(p);277}278}279}280}281}282283void Competition_WinMatchFor(int32 playerID)284{285EntityCompetitionSession *session = CompetitionSession_GetSession();286287++session->wins[playerID];288session->matchWinner[session->matchID] |= 1 << playerID;289}290#endif291292#if GAME_INCLUDE_EDITOR293void Competition_EditorDraw(void) {}294295void Competition_EditorLoad(void) {}296#endif297298void Competition_Serialize(void) {}299300301