Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/game/behaviors/activated_bf_plat.inc.c
7861 views
1
/**
2
* Behavior for bhvActivatedBackAndForthPlatform.
3
* There are only 2 of these in the game; the BitFS gray elevator
4
* and the BitS arrow platform.
5
* Note: The filename is abbreviated to avoid compiler seg fault on long paths
6
*/
7
8
/**
9
* Table of activated back-and-forth platform collision models.
10
* The second entry is unused. It corresponds to the mesh platform
11
* at the beginning of BitFS. In the game, it's a bhvPlatformOnTrack,
12
* which allows for more complex movement; its path is mostly a straight line
13
* except for where it dips into the lava. It seems the programmers
14
* had it as a bhvActivatedBackAndForthPlatform initially, which moves
15
* in a straight line, and wanted it to dip into the lava to make Mario have to
16
* move off of it. To do this, they changed it to a bhvPlatformOnTrack, but
17
* forgot to remove its entry in this table.
18
*/
19
static void const *sActivatedBackAndForthPlatformCollisionModels[] = {
20
/* ACTIVATED_BF_PLAT_TYPE_BITS_ARROW_PLAT */ bits_seg7_collision_0701AD54,
21
/* ACTIVATED_BF_PLAT_TYPE_BITFS_MESH_PLAT */ bitfs_seg7_collision_070157E0,
22
/* ACTIVATED_BF_PLAT_TYPE_BITFS_ELEVATOR */ bitfs_seg7_collision_07015124
23
};
24
25
/**
26
* Activated back-and-forth platform initialization function.
27
*/
28
void bhv_activated_back_and_forth_platform_init(void) {
29
// Equivalent to the first behavior param byte & 3 (last 2 bits of the byte).
30
s32 platformType = ((u16)(o->oBehParams >> 16) & 0x0300) >> 8;
31
32
// The BitS arrow platform should flip 180º (0x8000 angle units), but
33
// there is no reason for the other platforms to flip.
34
if (platformType != ACTIVATED_BF_PLAT_TYPE_BITS_ARROW_PLAT) {
35
o->oActivatedBackAndForthPlatformFlipRotation = 0;
36
} else {
37
o->oActivatedBackAndForthPlatformFlipRotation = 0x8000;
38
}
39
40
o->collisionData =
41
segmented_to_virtual(sActivatedBackAndForthPlatformCollisionModels[platformType]);
42
43
// Max distance the platform should move.
44
// Equivalent to 50 * (oBehParams2ndByte & 0x7F), i.e. 50 * (oBehParams2ndByte % 128).
45
// The maximum possible value of this is 50 * 127 = 6350.
46
// It's 50 * 97 = 4850 in BitS and 50 * 31 = 1550 in BitFS.
47
o->oActivatedBackAndForthPlatformMaxOffset = 50.0f * ((u16)(o->oBehParams >> 16) & 0x007F);
48
49
if (platformType == ACTIVATED_BF_PLAT_TYPE_BITFS_ELEVATOR) {
50
o->oActivatedBackAndForthPlatformMaxOffset -= 12.0f;
51
}
52
53
// Truthy/falsy value that determines the direction of movement.
54
// Equivalent to oBehParams2ndByte & 0x80, i.e. the most significant bit of oBehParams2ndByte.
55
o->oActivatedBackAndForthPlatformVertical = (u16)(o->oBehParams >> 16) & 0x0080;
56
57
o->oActivatedBackAndForthPlatformStartYaw = o->oFaceAngleYaw;
58
}
59
60
/**
61
* Activated back-and-forth platform update function.
62
*/
63
void bhv_activated_back_and_forth_platform_update(void) {
64
UNUSED s32 unused[3];
65
66
// oVelY is used for vertical platforms' movement and also for
67
// horizontal platforms' dipping up/down when Mario gets on/off them
68
if (gMarioObject->platform == o) {
69
o->oVelY = -6.0f;
70
} else {
71
o->oVelY = 6.0f;
72
}
73
74
// If the platform's velocity is set...
75
if (o->oActivatedBackAndForthPlatformVel != 0.0f) {
76
// ...wait until the countdown is 0 before moving.
77
// Since there's a 1 frame "lag" after the countdown is set to 20,
78
// and one more frame of "lag" after it finally reaches 0 here,
79
// Mario actually has to wait 22 frames before the platform starts moving.
80
if (o->oActivatedBackAndForthPlatformCountdown != 0) {
81
o->oActivatedBackAndForthPlatformCountdown -= 1;
82
} else {
83
// After the wait period is over, we start moving, by adding the velocity
84
// to the positional offset.
85
o->oActivatedBackAndForthPlatformOffset += o->oActivatedBackAndForthPlatformVel;
86
87
// clamp_f32 returns whether the value needed to be clamped.
88
// So if the offset got out of bounds (i.e. platform has reached an end of its path),
89
// or Mario is over 3000 units away, the platform will reset the wait timer and flip around.
90
if (clamp_f32(&o->oActivatedBackAndForthPlatformOffset, 0.0f,
91
o->oActivatedBackAndForthPlatformMaxOffset)
92
||
93
// The platform will not reset if Mario goes far away and it's travelling backwards
94
(o->oActivatedBackAndForthPlatformVel > 0.0f && o->oDistanceToMario > 3000.0f)) {
95
// Reset the wait timer
96
o->oActivatedBackAndForthPlatformCountdown = 20;
97
98
// oVelY is only negative if Mario is on the platform,
99
// so if Mario is on the platform or the platform is going forwards when it resets,
100
// the platform will reverse directions. Otherwise, it will stop.
101
// This means that if Mario touches the platform initially, then gets off,
102
// it will do a full round trip then stop (assuming Mario stays within 3000 units).
103
if (o->oVelY < 0.0f || o->oActivatedBackAndForthPlatformVel > 0.0f) {
104
o->oActivatedBackAndForthPlatformVel = -o->oActivatedBackAndForthPlatformVel;
105
} else {
106
o->oActivatedBackAndForthPlatformVel = 0.0f;
107
}
108
109
// Make the platform face the opposite way if it should.
110
// This is for the BitS arrow platform, which has an indicated direction.
111
o->oFaceAngleYaw += o->oActivatedBackAndForthPlatformFlipRotation;
112
}
113
}
114
} else {
115
// oVelY is only negative if Mario is on the platform
116
if (o->oVelY < 0.0f) {
117
o->oActivatedBackAndForthPlatformVel = 10.0f;
118
}
119
120
// Set waiting countdown to 20 frames
121
o->oActivatedBackAndForthPlatformCountdown = 20;
122
}
123
124
// Save the object's current position to a safe location.
125
obj_perform_position_op(POS_OP_SAVE_POSITION);
126
127
// Update the object's position.
128
// If the platform moves vertically...
129
if (o->oActivatedBackAndForthPlatformVertical != FALSE) {
130
// ...set its position to its original position + the offset.
131
o->oPosY = o->oHomeY + o->oActivatedBackAndForthPlatformOffset;
132
} else {
133
// Otherwise, dip down 20 units if Mario gets on the horizontal platform, and undo if he gets
134
// off.
135
o->oPosY += o->oVelY;
136
clamp_f32(&o->oPosY, o->oHomeY - 20.0f, o->oHomeY);
137
138
// Update the position using the object's home (original position), facing angle, and offset.
139
// This has to be done manually when the platform is vertical because only the yaw is used
140
// by this function; it doesn't update the Y position.
141
obj_set_dist_from_home(-o->oActivatedBackAndForthPlatformOffset);
142
}
143
144
// Compute the object's velocity using the old saved position.
145
obj_perform_position_op(POS_OP_COMPUTE_VELOCITY);
146
}
147
148