Alchemy
Loading...
Searching...
No Matches

markers.c

Go to the documentation of this file.
1/// @file
2/// The map's markers: chests and Psynergy stones.
3/// Part of object.c, the field object, compiled only through it.
4
6
7/// Sets an actor's y and terrainHeight to the map's height at its x and z.
8/// Called by Field_PlaceMapMarkers for each marker it places.
9void ObjectMotion_SnapToTerrain(void *object) {
10 struct ObjectRuntime *actor = object;
12
13 terrainHeight = Map_GetTerrainHeightFar(0, actor->x, actor->z);
14 actor->y = terrainHeight;
16}
17
18/// The start of the map's work.
19struct MarkerMap {
20 u8 unk00[0x10];
21 u8 *markers; ///< (column, row, id) triples, ended by 255, 255
22};
23
24/// Places an actor at each of the map's markers (ids 100 to 239) that the
25/// scene has an event for, up to ten: a chest (actor 20) for a chest event,
26/// shown open once its flag is set and gone once its mimic was beaten, and a
27/// Psynergy stone (actor 28) for a search event giving one, until it is taken.
28/// A marker with no such event takes no slot. Called by Field_RunScene on
29/// scene load; clears and fills work->markers.
31 u32 id;
32 struct MarkerMap *map = gMapWork[0];
33#ifdef UBFIX
34 struct FieldWork *work = (struct FieldWork *)gEventWork;
35#else
36 // UB: the event cell is a separate global, beyond gMapWork's one pointer.
37 // Reading gEventWork plainly grows 0x254 to 0x25c bytes in English.
38 struct FieldWork *work = gMapWork[HEAP_SLOT_EVENT - 8];
39#endif
40 s32 markerCount = 0;
41 u8 *list = map->markers;
42 struct MarkerSlot *slot = work->markers;
43 const struct SceneEvent *event;
44 struct ScriptObjectRuntime *markerActor;
45 u32 column;
46 u32 row;
47
48 Dma_Fill32(0, slot, sizeof(struct MarkerSlot) * MARKER_MAX);
49 // A map without a marker list places nothing.
50 if (list == NULL)
51 return;
52
53 column = *list++;
54 row = *list++;
55 while (column != 255 || row != 255) {
56 id = *list++;
57 if (id >= 100 && id <= 239) {
58 // The first event with this trigger that places something wins; the
59 // event's value says what the search gives (bits 31..20: 0x2 coins,
60 // 0x3 a Psynergy stone, 0x5 a mimic, as Field_SearchTile reads them).
61 event = gOverlayArea.events();
62 for (; event->control != -1; event++) {
63 if (event->trigger != id)
64 continue;
65 // 19 is SEARCH(SEARCH_CHEST).
66 if ((event->control & 0x1ff) == 19) {
67 // A chest, at the centre of its cell (cells are 16 pixels, and
68 // positions 16.16).
69 markerActor = (struct ScriptObjectRuntime *)Object_CreateFar(
70 20, (column << 20) + 0x80000, 0, (row << 20) + 0x80000);
71 if (markerActor == NULL)
72 continue;
73 ObjectMotion_SnapToTerrain(markerActor);
75 (struct DispatchObject *)markerActor, 0);
76 // An opened chest shows open (animation 2); an opened mimic's chest
77 // is not placed at all.
78 if (GameFlag_TestFar(event->condition)) {
79 if ((event->value & 0xfff00000) == 0x500000) {
80 ObjectDispatch_ReleaseFar((struct DispatchObject *)markerActor);
81 continue;
82 }
84 }
85 ObjectDispatch_StartIdleFar((struct DispatchObject *)markerActor);
86 markerActor->homeX = markerActor->x / 0x10000;
87 markerActor->homeZ = markerActor->z / 0x10000;
88 markerActor->unk23 = 1;
89 markerActor->flags59 = 1;
90 slot->id = event->trigger;
91 slot->object = (struct ObjectRuntime *)markerActor;
92 slot->column = markerActor->x / 0x100000;
93 slot->row = markerActor->z / 0x100000;
94 slot++;
95 markerCount++;
96 if (markerCount >= MARKER_MAX)
97 return;
98 } else if ((event->control & 0x1ff) == EVENT_SEARCH) {
99 // A Psynergy stone not yet taken.
100 if ((event->value & 0xfff00000) != 0x300000)
101 continue;
102 if (GameFlag_TestFar(event->condition))
103 continue;
104 markerActor = (struct ScriptObjectRuntime *)Object_CreateFar(
105 28, (column << 20) + 0x80000, 0, (row << 20) + 0x80000);
106 if (markerActor == NULL)
107 continue;
108 ObjectMotion_SnapToTerrain(markerActor);
110 (struct DispatchObject *)markerActor, 0);
111 ObjectDispatch_StartIdleFar((struct DispatchObject *)markerActor);
112 ObjectDispatch_SelectAnimationFar(markerActor, 1);
113 markerActor->homeX = markerActor->x / 0x10000;
114 markerActor->homeZ = markerActor->z / 0x10000;
115 markerActor->flags59 = 1;
116 markerActor->unk23 = 1;
117 slot->object = (struct ObjectRuntime *)markerActor;
118 slot->id = event->trigger;
119 slot->column = markerActor->x / 0x100000;
120 slot->row = markerActor->z / 0x100000;
121 slot++;
122 markerCount++;
123 if (markerCount >= MARKER_MAX)
124 return;
125 } else {
126 continue;
127 }
128 break;
129 }
130 }
131 column = *list++;
132 row = *list++;
133 }
134}
135
136/// Returns the marker slot (0 to 9) whose event trigger is id, or -1. Called
137/// by the Marker_ functions below.
139 s32 slotIndex;
140 s32 matchingSlot;
141 struct MarkerSlot *slot;
142
143 slot = ((struct FieldWork *)gEventWork)->markers;
144 matchingSlot = -1;
145 for (slotIndex = 0; slotIndex <= 9; slotIndex++, slot++) {
146 if (slot->id == id) {
147 matchingSlot = slotIndex;
148 break;
149 }
150 }
151 return matchingSlot;
152}
153
155
156/// Gives the actor of marker id animation, plays sound and waits 12 frames.
157static __inline__ void SetMarkerAnimationAndPlaySound(s32 id, s32 animation,
158 s32 sound) {
159 s32 slotIndex;
160 struct MarkerSlot *marker;
161 struct ObjectRuntime *object;
162
163 slotIndex = Marker_FindSlot(id);
164 if (slotIndex != -1) {
165 marker = &((struct FieldWork *)gEventWork)->markers[slotIndex];
166 object = marker->object;
167 if (object != NULL)
168 ObjectDispatch_SelectAnimationFar(object, animation);
170 WaitFrames(12);
171 }
172}
173
174/// Closes the chest of marker id again (its item could not be carried), with
175/// SE_125. Called by Field_SearchTile.
178}
179
180/// Makes the chest of marker id jump up as a mimic: after 18 frames it takes
181/// animation 7, plays SE_146 and gets an upward velocityY of 8 << 16.
182/// Called by Field_SearchTile before the mimic's battle.
184 s32 slotIndex;
185 struct MarkerSlot *marker;
186 struct ObjectRuntime *object;
187
188 slotIndex = Marker_FindSlot(id);
189 if (slotIndex != -1) {
190 marker = &((struct FieldWork *)gEventWork)->markers[slotIndex];
191 object = marker->object;
192 WaitFrames(18);
193 if (object != NULL)
196 if (object != NULL) {
197 object->velocityY = 8 << 16;
199 }
200 }
201}
202
203/// Opens the chest of marker id (animation 4) with SE_124, and waits 12
204/// frames. Called by Field_SearchTile when a chest is searched.
206
207/// Shows the chest of marker id open (animation 2), with no sound. Called by
208/// Field_SearchTile once a chest's contents are taken.
210 s32 slotIndex;
211 struct MarkerSlot *marker;
212 struct ObjectRuntime *object;
213
214 slotIndex = Marker_FindSlot(id);
215 if (slotIndex != -1) {
216 marker = &((struct FieldWork *)gEventWork)->markers[slotIndex];
217 object = marker->object;
218 if (object != NULL)
220 }
221}
222
223/// Returns the actor of marker id, or NULL when no slot has it. Called by
224/// Field_SearchTile, and by the world map markers (field_fx.c) to skip a
225/// marker already placed.
227 s32 slotIndex = Marker_FindSlot(id);
228 struct MarkerSlot *marker;
229
230 if (slotIndex == -1)
231 return NULL;
232 marker = &((struct FieldWork *)gEventWork)->markers[slotIndex];
233 return marker->object;
234}
235
236/// Hides the actor of marker id by clearing its animationKind. Called by
237/// Field_SearchTile once a Psynergy stone is taken.
238void Marker_Hide(s32 id) {
239 s32 slotIndex;
240 struct MarkerSlot *marker;
241 struct ObjectRuntime *object;
242
243 slotIndex = Marker_FindSlot(id);
244 if (slotIndex != -1) {
245 marker = &((struct FieldWork *)gEventWork)->markers[slotIndex];
246 object = marker->object;
247 if (object != NULL)
248 object->animationKind = 0;
249 }
250}
251
252/// Moves the actor of marker id to (x, z) on the ground; -1 keeps the centre
253/// of its cell on that axis. Positions are 16.16. Scene overlays call it as
254/// Engine_MapObjectSetPosition.
256 s32 slotIndex;
257 s32 terrainHeight;
258 s32 objectX;
259 s32 objectZ;
260 struct MarkerSlot *marker;
261 struct ObjectRuntime *object;
262
263 objectZ = z;
264 objectX = x;
265 slotIndex = Marker_FindSlot(id);
266 if (slotIndex != -1) {
267 marker = &((struct FieldWork *)gEventWork)->markers[slotIndex];
268 object = marker->object;
269 if (object != NULL) {
270 if (objectX == -1)
271 objectX = (marker->column << 20) + 0x80000;
272 if (objectZ == -1)
273 objectZ = (marker->row << 20) + 0x80000;
274 object->x = objectX;
275 object->z = objectZ;
276 terrainHeight = Map_GetTerrainHeightFar(0, objectX, objectZ);
277 object->terrainHeight = terrainHeight;
278 object->y = terrainHeight;
279 }
280 }
281}
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
Definition dma.h:30
struct ObjectRuntime * Object_CreateFar(s32 id, s32 x, s32 y, s32 z)
Far call to FieldObject_Create.
void ObjectDispatch_ReleaseFar(struct DispatchObject *obj)
s32 Map_GetTerrainHeightFar(s32 layer, s32 x, s32 y)
void ObjectDispatch_SetSingleChildFlagsFar(struct DispatchObject *obj, u32 flags)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void ObjectDispatch_StartIdleFar(struct DispatchObject *obj)
s32 GameFlag_TestFar(s32 flag)
void AudioCommand_PlayFar(s32 id)
struct SceneEntries gOverlayArea
@ EVENT_SEARCH
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
void * gMapWork[]
@ HEAP_SLOT_EVENT
Definition heap_state.h:40
void Field_PlaceMapMarkers(void)
Places an actor at each of the map's markers (ids 100 to 239) that the scene has an event for,...
Definition markers.c:30
void Marker_SetActorPosition(s32 id, s32 x, s32 z)
Moves the actor of marker id to (x, z) on the ground; -1 keeps the centre of its cell on that axis.
Definition markers.c:255
s32 Marker_FindSlot(s32 id)
Returns the marker slot (0 to 9) whose event trigger is id, or -1.
Definition markers.c:138
struct ObjectRuntime * Marker_GetActor(s32 id)
Returns the actor of marker id, or NULL when no slot has it.
Definition markers.c:226
UNUSED void EffectRuntime_ReservedNoOp(void)
Definition markers.c:154
void ObjectMotion_SnapToTerrain(void *object)
Sets an actor's y and terrainHeight to the map's height at its x and z.
Definition markers.c:9
void Marker_CloseChest(s32 id)
Closes the chest of marker id again (its item could not be carried), with SE_125.
Definition markers.c:176
void Marker_ShowOpened(s32 id)
Shows the chest of marker id open (animation 2), with no sound.
Definition markers.c:209
static __inline__ void SetMarkerAnimationAndPlaySound(s32 id, s32 animation, s32 sound)
Gives the actor of marker id animation, plays sound and waits 12 frames.
Definition markers.c:157
void Marker_OpenChest(s32 id)
Opens the chest of marker id (animation 4) with SE_124, and waits 12 frames.
Definition markers.c:205
void Marker_LaunchMimic(s32 id)
Makes the chest of marker id jump up as a mimic: after 18 frames it takes animation 7,...
Definition markers.c:183
void Marker_Hide(s32 id)
Hides the actor of marker id by clearing its animationKind.
Definition markers.c:238
What every part of object.c shares: its includes and the macros and types more than one part uses.
#define SE_146
Definition songs.h:139
#define SE_125
Definition songs.h:118
#define SE_124
Definition songs.h:117
struct EventWork * gEventWork
#define NULL
Definition bilibin.h:6
A field object as the object dispatcher's far calls take it.
Full event work allocated by Field_RunScene (heap slot 27).
struct MarkerSlot markers[10]
the map's markers (MARKER_MAX)
The start of the map's work.
Definition markers.c:19
u8 * markers
(column, row, id) triples, ended by 255, 255
Definition markers.c:21
u8 unk00[0x10]
Definition markers.c:20
A map marker placed as an actor: a chest or a Psynergy stone.
u8 id
the trigger of its scene event
struct ObjectRuntime * object
u8 column
its 16-pixel cell
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
s32 terrainHeight
16.16 fixed-point pixels
s32 z
16.16 fixed-point pixels
s32 x
16.16 fixed-point pixels
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.
const struct SceneEvent *(*) events(void)
A scene event: its kind and detail, the trigger it answers, its condition and its value (a message or...
s16 condition
-1 always, a flag | 0x1000 set, else the flag clear
s16 trigger
What the event answers: an actor id, a tile's collision code, a marker id or a raised value.
u32 value
A message below 0x10000, else an event function; for an exit, the exit kind its scene's exit table ma...
u32 control
The kind and its detail, read by Scene_FindEvent and the item, Psynergy and search lookups; -1 ends t...
A field object as its object script commands see it: the script and its place, position,...
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
#define MARKER_MAX
Definition object.h:76