#include "state.h" static void _state_set(State* self, StateType type); static void _state_level_tick(State* self, LevelType type); static void _state_level_tick(State* self, LevelType type) { level_tick(&self->states.level); if (self->states.level.isPaused) { if (control_released(self->ecs->control, CONTROL_RETRY)) _state_set(self, self->type); if (control_released(self->ecs->control, CONTROL_ESCAPE)) { level_unpause(&self->states.level); _state_set(self, STATE_TITLE); } } if (self->states.level.isFinished) { if (self->states.level.medal > LEVEL_MEDAL_NONE) self->levelData[type].status = LEVEL_STATUS_LOCKED + self->states.level.medal; self->levelData[type].time = self->states.level.timeToMedal; self->levelData[type].score = self->states.level.score; if (self->states.level.isComplete && type < LEVEL_FIVE) { if (self->levelData[type + 1].status == LEVEL_STATUS_LOCKED) self->levelData[type + 1].status = LEVEL_STATUS_UNLOCKED; } if (type == LEVEL_FIVE && self->states.level.isComplete) _state_set(self, STATE_CUTSCENE_FINAL); else _state_set(self, STATE_TITLE); } } static void _state_set(State* self, StateType type) { state_free(self); self->type = type; for (s32 i = 0; i < RENDERER_BUFFER_COUNT; i++) postprocessing_init(&self->ecs->postprocessing[i], OPAQUE, TRANSPARENT); switch (self->type) { case STATE_TITLE: title_init(&self->states.title, self->ecs, (LevelData*)self->levelData, LEVEL_COUNT); break; case STATE_CUTSCENE_ONE: cutscene_init(&self->states.cutscene, self->ecs, CUTSCENE_ONE); break; case STATE_CUTSCENE_TWO: cutscene_init(&self->states.cutscene, self->ecs, CUTSCENE_TWO); break; case STATE_CUTSCENE_THREE: cutscene_init(&self->states.cutscene, self->ecs, CUTSCENE_THREE); break; case STATE_CUTSCENE_FOUR: cutscene_init(&self->states.cutscene, self->ecs, CUTSCENE_FOUR); break; case STATE_CUTSCENE_FIVE: cutscene_init(&self->states.cutscene, self->ecs, CUTSCENE_FIVE); break; case STATE_CUTSCENE_FINAL: cutscene_init(&self->states.cutscene, self->ecs, CUTSCENE_FINAL); break; case STATE_ENDING: ending_init(&self->states.ending, self->ecs, ENDING_ONE); break; case STATE_ENDING_TWO: ending_init(&self->states.ending, self->ecs, ENDING_TWO); break; case STATE_ENDING_THREE: ending_init(&self->states.ending, self->ecs, ENDING_THREE); break; case STATE_LEVEL_ONE: level_init(&self->states.level, self->ecs, LEVEL_SETTINGS[LEVEL_ONE], LEVEL_ONE); break; case STATE_LEVEL_TWO: level_init(&self->states.level, self->ecs, LEVEL_SETTINGS[LEVEL_TWO], LEVEL_TWO); break; case STATE_LEVEL_THREE: level_init(&self->states.level, self->ecs, LEVEL_SETTINGS[LEVEL_THREE], LEVEL_THREE); break; case STATE_LEVEL_FOUR: level_init(&self->states.level, self->ecs, LEVEL_SETTINGS[LEVEL_FOUR], LEVEL_FOUR); break; case STATE_LEVEL_FIVE: level_init(&self->states.level, self->ecs, LEVEL_SETTINGS[LEVEL_FIVE], LEVEL_FIVE); break; default: break; } } void state_init(State* self, ECS* ecs, StateType type) { memset(self, '\0', sizeof(State)); self->ecs = ecs; memcpy(self->levelData, LEVEL_DATA_DEFAULT, sizeof(LEVEL_DATA_DEFAULT)); _state_set(self, type); } void state_free(State* self) { switch (self->type) { case STATE_TITLE: title_free(&self->states.title); break; case STATE_LEVEL_ONE: case STATE_LEVEL_TWO: case STATE_LEVEL_THREE: case STATE_LEVEL_FOUR: case STATE_LEVEL_FIVE: level_free(&self->states.level); break; case STATE_CUTSCENE_ONE: case STATE_CUTSCENE_TWO: case STATE_CUTSCENE_THREE: case STATE_CUTSCENE_FOUR: case STATE_CUTSCENE_FIVE: case STATE_CUTSCENE_FINAL: cutscene_free(&self->states.cutscene); break; case STATE_ENDING: case STATE_ENDING_TWO: case STATE_ENDING_THREE: ending_free(&self->states.ending); default: break; } ecs_clear(self->ecs); } void state_change(State* self, StateType type) { self->setType = type; } void state_tick(State* self) { u32 endingPoints; endingPoints = 0; if (self->isChanging) { self->isChanging = false; state_free(self); memset(&self->states, '\0', sizeof(self->states)); _state_set(self, self->setType); return; } switch (self->type) { case STATE_LEVEL_ONE: _state_level_tick(self, LEVEL_ONE); break; case STATE_LEVEL_TWO: _state_level_tick(self, LEVEL_TWO); break; case STATE_LEVEL_THREE: _state_level_tick(self, LEVEL_THREE); break; case STATE_LEVEL_FOUR: _state_level_tick(self, LEVEL_FOUR); break; case STATE_LEVEL_FIVE: _state_level_tick(self, LEVEL_FIVE); break; case STATE_TITLE: title_tick(&self->states.title); if (self->states.title.isLevelSelected) _state_set(self, STATE_CUTSCENE_ONE + self->states.title.levelSelected); /* if (control_released(self->ecs->control, CONTROL_CHEAT)) { memcpy(self->levelData, LEVEL_DATA_CHEAT, sizeof(LEVEL_DATA_CHEAT)); sound_play(&self->ecs->resources->sounds[SOUND_CHEAT]); _state_set(self, STATE_TITLE); } */ break; case STATE_CUTSCENE_ONE: cutscene_tick(&self->states.cutscene); if (self->states.cutscene.isFinished) _state_set(self, STATE_LEVEL_ONE); break; case STATE_CUTSCENE_TWO: cutscene_tick(&self->states.cutscene); if (self->states.cutscene.isFinished) _state_set(self, STATE_LEVEL_TWO); break; case STATE_CUTSCENE_THREE: cutscene_tick(&self->states.cutscene); if (self->states.cutscene.isFinished) _state_set(self, STATE_LEVEL_THREE); break; case STATE_CUTSCENE_FOUR: cutscene_tick(&self->states.cutscene); if (self->states.cutscene.isFinished) _state_set(self, STATE_LEVEL_FOUR); break; case STATE_CUTSCENE_FIVE: cutscene_tick(&self->states.cutscene); if (self->states.cutscene.isFinished) _state_set(self, STATE_LEVEL_FIVE); break; case STATE_CUTSCENE_FINAL: cutscene_tick(&self->states.cutscene); if (self->states.cutscene.isFinished) { for (s32 i = 0; i < LEVEL_COUNT; i++) endingPoints += self->levelData[i].status; if (endingPoints >= LEVEL_STATUS_GOLD * LEVEL_COUNT) _state_set(self, STATE_ENDING_THREE); else if (endingPoints >= (LEVEL_STATUS_SILVER * LEVEL_COUNT)) _state_set(self, STATE_ENDING_TWO); else _state_set(self, STATE_ENDING); } break; case STATE_ENDING: case STATE_ENDING_TWO: case STATE_ENDING_THREE: ending_tick(&self->states.ending); if (self->states.ending.isFinished) _state_set(self, STATE_TITLE); break; default: break; } }