blob: 2da9190112201aa54392121bcfb79ec848131ec3 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
/**
* @file tilePuzzleManager.c
* @ingroup Managers
*
* @brief Tile puzzles (step on all blue tiles exactly once).
*
* The Manager's field 0xe is used for the remaining number of tiles to be changed.
* field 0xf is used for the total number of tiles to be changed.
*/
#include "manager/tilePuzzleManager.h"
#include "asm.h"
#include "flags.h"
#include "sound.h"
#include "tiles.h"
#include "room.h"
#include "player.h"
enum { INIT, IN_PROGRESS, FAILED, SUCCEEDED };
void TilePuzzleManager_Main(TilePuzzleManager* this) {
u32 i, j, tmp, tmp2;
switch (super->action) {
default:
break;
case INIT:
super->action = IN_PROGRESS;
super->subtimer = super->timer;
this->own_tile = (((this->x >> 4) & 0x3fU) | ((this->y >> 4) & 0x3fU) << 6);
this->player_previous_tile = this->player_current_tile = COORD_TO_TILE((&gPlayerEntity.base));
break;
case 1:
this->player_current_tile = COORD_TO_TILE((&gPlayerEntity.base));
if (this->player_current_tile != this->player_previous_tile) {
this->player_previous_tile = this->player_current_tile;
switch (GetTileTypeAtTilePos(this->player_current_tile, super->type2)) {
case TILE_TYPE_791:
// stepped on a red tile again
super->action = FAILED;
SoundReq(SFX_MENU_ERROR);
break;
case TILE_TYPE_792:
// stepped on a blue tile
// turn the tile into a red tile
sub_0807B7D8(TILE_TYPE_791, this->player_current_tile, super->type2);
SoundReq(SFX_6B);
// decrease the number of remaining tiles and check if we're done
if (--super->timer == 0) {
super->action = SUCCEEDED;
// set up delay for setting the flag/playing the success sfx
super->timer = 64;
}
break;
}
}
// fall through, can be reset in-progress
case FAILED:
if (!this->flag_reset)
return; // can't be reset
if (!CheckFlags(this->flag_reset))
return; // wait for the flag telling it to reset
ClearFlag(this->flag_reset); // make sure the puzzle can be reset again later
super->action = IN_PROGRESS;
super->timer = super->subtimer;
for (i = 0; i < this->height; i++) {
tmp = this->own_tile + (i << 6);
for (j = 0; j < this->width; j++) {
RestorePrevTileEntity(tmp + j, super->type2);
}
}
break;
case SUCCEEDED:
if (super->timer == 0)
return;
tmp2 = --super->timer;
if (tmp2) {
if (tmp2 == 0x20) {
SetFlag(this->flag_succeeded);
}
} else {
SoundReq(SFX_SECRET);
}
}
}
|