Alchemy
Loading...
Searching...
No Matches

climbing.c

Go to the documentation of this file.
1/// @file
2/// Jumping and climbing on the field.
3/// Part of psynergy_effects.c, compiled only through it.
4
6
7// The map's cells (128 to a row), and the same cells seen one row south and
8// one row north: TILE_CELLS_SOUTH[i] is the cell below TILE_CELLS[i].
9#define TILE_CELLS ((struct MapCell *)Ram_MapCellBuffer)
10#define TILE_CELLS_SOUTH ((struct MapCell *)(Ram_MapCellBuffer + 0x200))
11#define TILE_CELLS_NORTH ((struct MapCell *)(Ram_MapCellBuffer - 0x200))
12
13/// Makes the leader jump two tiles forward, over the tile in front, when the
14/// map allows it (Map_CheckObjectStep). On a platform object (sprite 207 or
15/// 205) the platform plays its animation 7 and the leader bobs down 2 pixels
16/// and back. Each jump adds two tiles to work->walkingDistance, as walking
17/// them would, and the leader keeps jumping while it lands on another jump
18/// spot (collision 0xf9). Returns 0 after a jump, -1 when the leader cannot
19/// jump.
20///
21/// Called by Field_RunPushTileEvent when the leader has pushed against a jump
22/// spot (0xf9 or 0xfe) for more than 12 frames, and by the gap jumps of Goma
23/// Cave's pillar and Kolima Forest's bend, which import it. Moves the leader,
24/// and takes the field over between FieldEvent_Begin and FieldEvent_End.
26 // A chained jump repeats both the gap and landing probes, including their
27 // failure returns, before taking control of the field again.
28 struct ObjectRuntime *leader =
30 s32 result = -1;
31 s32 angle = (leader->angle + 0x2000) & 0xc000; // to the nearest quarter
32 u8 *flags = &leader->flags;
33 u8 saved = *flags;
34 struct FieldWork *work = (struct FieldWork *)gEventWork;
35 s32 spriteFlags = 1;
36 struct FieldPosition position;
37 struct FieldPosition *pos;
38 struct ObjectRuntime *platform;
39
40 pos = &position;
41again:
42 // The middle of the tile in front, then of the tile beyond.
43 SET_POSITION(pos, (leader->x & 0xfff00000) + 0x80000, leader->y,
44 (leader->z & 0xfff00000) + 0x80000);
45 Vector_AddPolarOffset(0x100000, angle, pos);
46 if (Map_CheckObjectStepFar(leader, pos) == 1)
47 return -1;
48 SET_POSITION(pos, (leader->x & 0xfff00000) + 0x80000, leader->y,
49 (leader->z & 0xfff00000) + 0x80000);
50 Vector_AddPolarOffset(0x200000, angle, pos);
51 if (Map_CheckObjectStepFar(leader, pos) == 0) {
52 // Suspend terrain following while airborne. Restore the original motion
53 // and sprite flags after landing, before returning field control.
54 if (leader->animationKind == 1)
55 spriteFlags = ((struct AnimationObject *)leader->animation)->flags;
58 WaitFrames(6);
61 leader->speedLimit = 0x30000;
62 leader->acceleration = 0x20000;
63 leader->velocityY = 0x40000;
64 *flags &= 0x7e;
66 spriteFlags & 0xfe);
69 ((union FieldCoordinate *)&pos->x)->part.pixel,
70 ((union FieldCoordinate *)&pos->z)->part.pixel);
73 spriteFlags);
74
75 // A platform underfoot dips 2 pixels with the leader and comes back up.
76 if ((platform = Object_FindNearestFacingTarget(leader, 207)) != NULL ||
77 (platform = Object_FindNearestFacingTarget(leader, 205)) != NULL) {
79 leader->y -= 0x10000;
80 leader->terrainHeight -= 0x10000;
81 WaitFrames(2);
82 leader->y -= 0x10000;
83 leader->terrainHeight -= 0x10000;
84 WaitFrames(10);
85 leader->y += 0x10000;
86 leader->terrainHeight += 0x10000;
87 WaitFrames(4);
88 leader->y += 0x10000;
89 leader->terrainHeight += 0x10000;
90 } else {
91 WaitFrames(6);
92 }
93 *flags = saved;
95 if (work != NULL)
96 work->walkingDistance +=
97 Iwram_MulQ16(work->walkingDistanceScale, 0x200000);
98 // Landed on another jump spot: stand, then jump again.
99 if (GetMapCellCollisionFar(leader->terrainId, pos->x, pos->z) == 0xf9) {
101 WaitFrames(6);
102 goto again;
103 }
104 result = 0;
105 }
106 return result;
107}
108
109/// Climbing down (the player presses down at a climbable wall). On the ground,
110/// when the cell south of the leader's is the same climbable cell, the leader
111/// turns round, grabs the wall and climbs down onto it (climbing pose 13).
112/// While climbing, the leader lets go and drops to the ground. Returns 0, or -1
113/// when there is nothing to climb or the way is blocked.
114///
115/// Called by Field_RunPushTileEvent for a climbing spot (0xfd) with Down held,
116/// and imported by the scenes with ladders and climbable walls (Babi's
117/// Lighthouse, Crossbone Isle, Tolbi's ship and others). Sets
118/// gGameState.movementMode: 1 while the leader is on the wall, 0 off it.
120 struct ObjectRuntime *object =
122 s32 gridX =
123 8 + ((((union FieldCoordinate *)&object->x)->part.pixel) & 0xfff0);
124 s32 gridZ =
125 8 + ((((union FieldCoordinate *)&object->z)->part.pixel) & 0xfff0);
126 s32 result;
127
129
130 if (gGameState.movementMode == 0) {
131 s32 index = gridX / 16 + (gridZ / 16) * 128;
132
133 // A wall goes down only where the cell below is the same climbing code.
134 if (TILE_CELLS[index].collisionCode ==
135 TILE_CELLS_SOUTH[index].collisionCode) {
136 /* FAKEMATCH(dead): a six-word probe, though only its first three words
137 * are the position, which keeps the native 24-byte frame; as one
138 * struct FieldPosition, 4 of 163 instructions differ in tbs-en. */
139 s32 vector[6];
140 struct FieldPosition *position = (struct FieldPosition *)vector;
141
142 // Nothing may stand on the wall 16 pixels below.
143 SET_POSITION(position, object->x, object->y - 0x100000, object->z);
144 result =
146 if (result != 0)
147 goto failure;
148
149 // Step to the middle of the tile, face north and climb down a tile.
151 object->speedLimit = 0x10000;
154 object->actionFlags = 1;
155 object->flags = 0;
158 Object_SetMoveTargetFar(object, gridX << 16, object->y - 0x100000,
159 (gridZ << 16) + 0x100000);
162 } else {
163 goto failure;
164 }
165 } else {
166 // Let go of the wall and fall.
168 object->flags = 3;
169 object->velocityY = 0x40000;
170 object->terrainHeight = object->y;
174 object->actionFlags = 1;
175 object->angle = 0xc000;
176 }
177
179 return 0;
180
181failure:
183 return -1;
184}
185
186/// Climbing up (the player presses up at a climbable wall). On the ground, when
187/// the cell north of the leader's is the same climbable cell, the leader jumps
188/// onto the wall and holds on (climbing pose 12). While climbing, the leader
189/// climbs over the top onto the ground. Returns 0, or -1 when there is nothing
190/// to climb or the way is blocked.
191///
192/// Called by Field_RunPushTileEvent for a climbing spot (0xfd) with Up held,
193/// and imported by the scenes with ladders and climbable walls (Babi's
194/// Lighthouse, Colosso, Crossbone Isle and others). Sets
195/// gGameState.movementMode as Field_ClimbDown does.
197 struct ObjectRuntime *object =
199 s16 spriteFlags = 1;
200 s32 gridX =
201 8 + ((((union FieldCoordinate *)&object->x)->part.pixel) & 0xfff0);
202 s32 gridZ =
203 8 + ((((union FieldCoordinate *)&object->z)->part.pixel) & 0xfff0);
204 s32 result;
205
207
208 if (object->animationKind == 1)
209 spriteFlags = ((struct AnimationObject *)object->animation)->flags;
210
211 if (gGameState.movementMode == 0) {
212 s32 index = gridX / 16 + (gridZ / 16) * 128;
213
214 if (TILE_CELLS[index].collisionCode ==
215 TILE_CELLS_NORTH[index].collisionCode) {
216 /* FAKEMATCH(dead): a six-word probe, though only its first three words
217 * are the position, which keeps the native 24-byte frame; as one
218 * struct FieldPosition, 4 of 183 instructions differ in tbs-en. */
219 s32 vector[6];
220 struct FieldPosition *position = (struct FieldPosition *)vector;
221
222 SET_POSITION(position, object->x, object->y, object->z);
223 result =
225 if (result != 0)
226 goto failure;
227
228 // Step to the middle of the tile, crouch, jump and grab the wall.
229 object->actionFlags = 0;
232 WaitFrames(4);
234 object->velocityY = 0x40000;
235 WaitFrames(4);
236 object->flags = 0;
237 spriteFlags &= 0xfe;
239 spriteFlags);
240 object->speedLimit = 0x10000;
241 object->velocityY = 0;
243 WaitFrames(4);
245 object->actionFlags = 1;
246 WaitFrames(8);
247 } else {
248 goto failure;
249 }
250 } else {
251 // Climb over the top: up 8 pixels and a tile north.
252 object->flags = 0;
254 Object_SetMoveTargetFar(object, gridX << 16, object->y + 0x80000,
255 (gridZ << 16) - 0x100000);
257 object->flags = 3;
258 spriteFlags |= 1;
259 object->terrainHeight = object->y;
261 spriteFlags);
264 object->actionFlags = 1;
265 }
266
268 return 0;
269
270failure:
272 return -1;
273}
274
275#undef TILE_CELLS
276#undef TILE_CELLS_SOUTH
277#undef TILE_CELLS_NORTH
void ObjectMotion_CommitCurrentPositionAndActivate(u32 objectId)
The event command "wait for actor": waits (at most 600 frames) for the actor to arrive and stands it ...
void Object_RefreshSelectorById(u32 objectId)
Waits, at most 300 frames, for an actor's script to reach its end (command 0x10).
void ObjectMotion_ArmCallback(s32 objectId, s32 angle, s32 wait)
The event command "actor face direction": the actor turns toward angle (0x10000 a full turn; ObjectMo...
void ObjectMotion_SetPositionAndCommit(u32 objectId, s32 x, s32 z)
The event command "move actor and wait": as ObjectMotion_ResetAndSetPosition, then waits (at most 600...
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
struct ObjectRuntime * Object_FindNearestFacingTarget(struct ObjectRuntime *self, s32 sprite)
Finds the nearest animated object to self within 40 pixels and 48 pixels of height,...
#define TILE_CELLS
Definition climbing.c:9
#define TILE_CELLS_SOUTH
Definition climbing.c:10
s32 Field_ClimbUp(void)
Climbing up (the player presses up at a climbable wall).
Definition climbing.c:196
#define TILE_CELLS_NORTH
Definition climbing.c:11
s32 Field_ClimbDown(void)
Climbing down (the player presses down at a climbable wall).
Definition climbing.c:119
s32 Field_TryJumpForward(void)
Makes the leader jump two tiles forward, over the tile in front, when the map allows it (Map_CheckObj...
Definition climbing.c:25
void ObjectDispatch_SetSingleChildFlagsFar(struct DispatchObject *obj, u32 flags)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void Object_SetMoveTargetFar(struct ObjectRuntime *object, s32 x, s32 y, s32 z)
s32 Map_CheckObjectStepFar(struct ObjectRuntime *object, struct FieldPosition *position)
s32 GetMapCellCollisionFar(s32 layer, s32 x, s32 y)
s32 CheckMapPositionCellOccupiedFar(struct WorldPosition *position)
void AudioCommand_PlayFar(s32 id)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
struct GameState gGameState
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
#define SET_POSITION(p, px, py, pz)
Sets the position or the velocity of a particle, a piece of debris or an object in one statement.
Definition macros.h:16
void Vector_AddPolarOffset(s32 radius, s32 angle, void *position)
Moves the point position by radius in direction angle on the ground plane: x by the cosine,...
Definition math.c:23
void FieldEvent_End(void)
Ends an event: stops the debug fast-forward callback, gives the camera back to the leader and refresh...
Definition events.c:120
void FieldEvent_WaitFrames(s32 frames)
The event command "wait": waits the requested frames, unless debug fast forward (Event_UpdateDebugSki...
Definition events.c:55
void FieldEvent_Begin(void)
The event command "begin event": closes any timed notice, stops the leader, resets the message and ti...
Definition events.c:91
What every part of psynergy_effects.c shares: its includes and the macros and types more than one par...
#define SE_JUMP
An actor jumps: ObjectMotion_Launch plays the high jump above 5 pixels a frame.
Definition songs.h:147
struct EventWork * gEventWork
#define NULL
Definition bilibin.h:6
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
Definition animspr.h:128
A field object as the object dispatcher's far calls take it.
A position on the field.
s32 z
16.16 fixed-point pixels
Full event work allocated by Field_RunScene (heap slot 27).
s32 walkingDistanceScale
scales movement for PP and status updates
s32 walkingDistance
accumulated 16.16 distance awaiting an update
u8 movementMode
1 while the leader is climbing, 0 otherwise
Definition game_state.h:57
s32 selectedActor
the leader: its unit and its actor
Definition game_state.h:59
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
u16 angle
1/65536 turns
s32 velocityY
16.16 fixed-point pixels per frame
s32 z
16.16 fixed-point pixels
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
u8 flags
FieldActor.motionFlags: 3 when created, 4 for a placed actor above the ground; zero is free flight in...
void * animation
its sprite, or its list of four, by animationKind
s32 x
16.16 fixed-point pixels
s32 speedLimit
16.16 fixed-point pixels per frame
s32 y
16.16 fixed-point pixels
u8 animationKind
Low four bits: 0 no sprite, 1 one sprite, 2 a group of up to four.
A position on the world map, as its walkability check reads it.
Definition map.h:74
signed int s32
Definition types.h:14
signed short s16
Definition types.h:12
unsigned char u8
Definition types.h:11
A field coordinate, read whole or as its fraction and its whole pixels.