12#define FIELD_SHORTCUT_KEYS gKeysPressed
13#define WORLD_MAP_PROBE_RADIUS 0x70000
15#define FIELD_SHORTCUT_KEYS gKeysHeld
16#define WORLD_MAP_PROBE_RADIUS 0x80000
45 u32 assignmentKind = encodedAssignment >> 14;
46 u32 requestId = 0x3FFF & encodedAssignment;
51 }
else if (fieldWork->
mode == 3) {
58 switch (assignmentKind) {
82 if (fieldWork ==
NULL)
106 s32 *secondPosition,
s32 radiusB) {
111 const s32 *firstCoordinate = &firstPoint->
x;
112 const s32 *secondCoordinate = &secondPoint->
x;
113 s32 dx = (*firstCoordinate++ - *secondCoordinate++) >> 16;
114 s32 dy = (*firstCoordinate++ - *secondCoordinate++) >> 16;
115 s32 dz = (*firstCoordinate - *secondCoordinate) >> 16;
116 s32 radius = radiusA + radiusB;
122 if (!(dx > 0x400000) && !(dz > 0x400000) &&
123 dx * dx + dy * dy + dz * dz < radius * radius)
145 s16 angleOffsets[22];
150 s32 movementAnimation;
166 for (blockIndex = 0; blockIndex < 512; blockIndex++) {
170 if (freeBlocks - 136 < 0)
181 delayKeyMask =
KEY_L;
185 delayIterations = delayKeyMask;
188 if (delayIterations != 0)
190 delayIterations = 95;
193 if (delayIterations >= 0)
195 delayIterations = 63;
198 if (delayIterations >= 0)
200 delayIterations = 63;
203 if (delayIterations >= 0)
210 object->speedLimit = 0x18000;
211 object->acceleration = 0x4000;
212 movementAnimation = 5;
214 object->speedLimit = 0x10000;
215 object->acceleration = 0x4000;
216 movementAnimation = 2;
219 object->speedLimit = 0x40000;
220 object->acceleration = 0x10000;
221 movementAnimation = 5;
234 position.
x =
object->x;
235 position.
y =
object->y;
236 position.
z =
object->z;
242 testPosition.
x =
object->x;
243 testPosition.
y =
object->y;
244 testPosition.
z =
object->z;
247 testPosition.
x =
object->x;
248 testPosition.
y =
object->y;
249 testPosition.
z =
object->z;
252 testPosition.
x =
object->x;
253 testPosition.
y =
object->y;
254 testPosition.
z =
object->z;
257 testPosition.
x =
object->x;
258 testPosition.
y =
object->y;
259 testPosition.
z =
object->z;
275 angleOffsets[headingCount++] = direction + 0x1000;
276 angleOffsets[headingCount++] = direction - 0x1000;
277 angleOffsets[headingCount++] = direction + 0x2000;
278 angleOffsets[headingCount++] = direction - 0x2000;
279 angleOffsets[headingCount++] = direction + 0x3000;
280 angleOffsets[headingCount++] = direction - 0x3000;
281 for (angleIndex = 0; angleIndex < headingCount; angleIndex++) {
282 heading = angleOffsets[angleIndex];
283 position.
x =
object->x;
284 position.
y =
object->y;
285 position.
z =
object->z;
289 testPosition.
x =
object->x;
290 testPosition.
y =
object->y;
291 testPosition.
z =
object->z;
295 testPosition.
x =
object->x;
296 testPosition.
y =
object->y;
297 testPosition.
z =
object->z;
301 testPosition.
x =
object->x;
302 testPosition.
y =
object->y;
303 testPosition.
z =
object->z;
307 testPosition.
x =
object->x;
308 testPosition.
y =
object->y;
309 testPosition.
z =
object->z;
315 position.
x =
object->x;
316 position.
y =
object->y;
317 position.
z =
object->z;
324 contact.
x =
object->x;
325 contact.
y =
object->y;
326 contact.
z =
object->z;
329 for (angleIndex = 63; angleIndex >= 0; angleIndex -= 1, pushedObject++) {
332 radius =
object->radius - 2;
333 if (pushedObject->
script == 0)
337 if (pushedObject ==
object)
340 pushedObject->
radius - 2) < 0)
348 ArcTan2(pushedObject->
z - object->
z, pushedObject->
x - object->
x);
349 testPosition.
x = pushedObject->
x;
350 testPosition.
y = pushedObject->
y;
351 testPosition.
z = pushedObject->
z;
356 (
s32 *)&testPosition)) {
357 testPosition.x = pushedObject->x;
358 testPosition.y = pushedObject->y;
359 testPosition.z = pushedObject->z;
362 testPosition.x = pushedObject->x;
363 testPosition.y = pushedObject->y;
364 testPosition.z = pushedObject->z;
369 testPosition.x = pushedObject->x;
370 testPosition.y = pushedObject->y;
371 testPosition.z = pushedObject->z;
391 if (collision == 0 && pushed != 0) {
392 object->speedLimit = 0x4000;
393 object->acceleration = 0x2000;
407 }
else if (collision != 0) {
421 if (collision != 0) {
425 object->velocityX = 0;
426 object->velocityZ = 0;
431 difference = (
s16)difference;
432 if (difference > 0x1000)
434 if (difference < -0x1000)
435 difference = -0x1000;
436 object->angle += difference;
439 object->footprintSide = 2;
446 object->velocityX = 0;
447 object->velocityZ = 0;
459 object->
action == 0 && collision == 0) {
470 effect->priorityFlags = 2;
471 effect->flags = collision;
472 if (animation != 0) {
474 animation->
flags = collision;
475 animation->
rotation = footprintAngle + 0x4000;
480 object->footprintSide = collision;
483 effect->angle = 0x8000;
484 if (movementAnimation == 5)
488 object->footprintSide ^= 1;
511 s16 angleOffsets[28];
515 s16 angleOffsets[22];
521 s32 movementAnimation;
524 s32 terrainCollision;
533 movementAnimation = 2;
542 object->speedLimit = 0x10000;
543 object->acceleration = 0x14000;
544 movementAnimation = 5;
546 object->speedLimit = 0x8000;
547 object->acceleration = 0x4000;
550 object->speedLimit = 0x40000;
554 if (direction == 0xffff) {
558 position.
x =
object->x;
559 position.
y =
object->y;
560 position.
z =
object->z;
570 testPosition.
x =
object->x;
571 testPosition.
y =
object->y;
572 testPosition.
z =
object->z;
577 testPosition.
x =
object->x;
578 testPosition.
y =
object->y;
579 testPosition.z =
object->z;
584 testPosition.
x =
object->x;
585 testPosition.
y =
object->y;
586 testPosition.z =
object->z;
591 testPosition.
x =
object->x;
592 testPosition.
y =
object->y;
593 testPosition.z =
object->z;
604 angleOffsets[
count++] = direction + 0x1000;
605 angleOffsets[
count++] = direction - 0x1000;
606 angleOffsets[
count++] = direction + 0x2000;
607 angleOffsets[
count++] = direction - 0x2000;
608 angleOffsets[
count++] = direction + 0x3000;
609 angleOffsets[
count++] = direction - 0x3000;
610 angleOffsets[
count++] = direction + 0x4000;
611 angleOffsets[
count++] = direction - 0x4000;
612 for (angleIndex = 0; angleIndex <
count; angleIndex++) {
613 direction = angleOffsets[angleIndex];
614 position.
x =
object->x;
615 position.
y =
object->y;
616 position.z =
object->z;
621 testPosition.
x =
object->x;
622 testPosition.
y =
object->y;
623 testPosition.
z =
object->z;
629 testPosition.
x =
object->x;
630 testPosition.
y =
object->y;
631 testPosition.z =
object->z;
637 testPosition.
x =
object->x;
638 testPosition.
y =
object->y;
639 testPosition.z =
object->z;
645 testPosition.
x =
object->x;
646 testPosition.
y =
object->y;
647 testPosition.z =
object->z;
653 angle = (
s16)direction;
659 leftPosition.
x =
object->x;
660 leftPosition.
y =
object->y;
661 leftPosition.
z =
object->z;
664 rightPosition.
x =
object->x;
665 rightPosition.
y =
object->y;
666 rightPosition.
z =
object->z;
675 angleOffsets[
count++] = direction + 0x1000;
676 angleOffsets[
count++] = direction - 0x1000;
677 angleOffsets[
count++] = direction + 0x2000;
678 angleOffsets[
count++] = direction - 0x2000;
679 angleOffsets[
count++] = direction + 0x3000;
680 angleOffsets[
count++] = direction - 0x3000;
681 for (angleIndex = 0; angleIndex <
count; angleIndex++) {
682 direction = angleOffsets[angleIndex];
683 position.
x =
object->x;
684 position.
y =
object->y;
685 position.z =
object->z;
687 leftPosition.
x =
object->x;
688 leftPosition.
y =
object->y;
689 leftPosition.z =
object->z;
692 rightPosition.
x =
object->x;
693 rightPosition.
y =
object->y;
694 rightPosition.z =
object->z;
704 angle = (
s16)direction;
715 if ((collision & 3) != 0)
725 if (collision != 0) {
729 object->velocityX = 0;
730 object->velocityZ = 0;
731 if ((collision & 3) != 0) {
733 difference = (
s16)(direction - object->
angle);
734 if (difference > 0x1000)
736 if (difference < -0x1000)
737 difference = -0x1000;
738 object->angle += difference;
741 object->footprintSide = 2;
746 object->velocityX = collision;
747 object->velocityZ = collision;
759 yawStep = (
s16)(targetCameraYaw - perspective->
yaw) / 8;
762 if (yawStep < -0x200)
764 if (yawStep > -16 && yawStep < 16)
765 yawStep = targetCameraYaw - perspective->
yaw;
766 perspective->
yaw += yawStep;
769 playerSprite =
object->animation;
771 if (terrainCollision == 9) {
773 playerSprite->
flags = 0;
776 playerSprite->
flags = 1;
780 if (terrainCollision == 6 && object->
action == 0 && collision == 0) {
786 ripple->flags = collision;
787 ripple->terrainId = 1;
788 if (rippleSprite != 0) {
790 rippleSprite->
flags = collision;
832 struct MapCell *destinationCell;
839 object->speedLimit = 0x8000;
840 object->acceleration = 0x4000;
843 if (angle == 0xffff) {
849 if ((angle & 0xf000) != 0) {
851 if ((angle & 0xf000) != 0x8000)
861 position.
x +=
object->x;
864 object->angle = 0xc000;
866 object->angle = 0x4000;
867 position.
y =
object->y - position.
z;
868 position.
z =
object->z;
873 (position.
z / 0x100000) * 128];
876 (position.
z / 0x100000) * 128];
886 position.z - 0x100000);
887 if (terrainHeight - object->
y < 0x100000)
892 if (terrainHeight - object->
y > -0x80000) {
900 if (collisionFlags & 3)
906 if (collisionFlags != 0) {
918#undef FIELD_SHORTCUT_KEYS
919#undef WORLD_MAP_PROBE_RADIUS
s32 AnimationObjects_SelectAnimation(struct AnimationObject *sprite, s32 animation)
Starts animation flags & 0x7f on every layer of a sprite (bit 7 keeps each layer's place and timer),...
const s32 gWorldMap_KeyYaws[16]
The world map camera's turn rate for each state of the direction pad, read by Object_MoveOnWorldMap.
const s32 gWorldMap_FootprintActions[6]
Two scripts for the world map's footprint and dust effects: wait 120 or 30 frames,...
const u16 gWorldMap_KeyHeadings[16]
The heading for each state of the direction pad (bits 4-7 of the keys); 0xffff means no direction is ...
struct BattleUnit * UnitGetFar(u32 owner)
s32 GameFlag_TestFar(s32 flag)
void AudioCommand_PlayFar(s32 id)
struct ObjectRuntime * FieldObject_Create(s32 encodedSprite, s32 x, s32 y, s32 z)
Creates a field object at (x, y, z), in 16.16 pixels, or returns 0 when none is free.
void ObjectDispatch_Initialize(struct DispatchObject *object, const s32 *script)
Gives an object a script and starts it from the top.
void ObjectDispatch_SelectAnimation(void *rawObject, s32 value)
Switches all of an object's sprites to animation value.
What every part of the field object shares: its includes and the few names more than one part uses.
#define TARGET_UNSET
A movement target coordinate that is not set.
u8 gDebugMode
Debug builds: Start+Select pauses the frame loop.
struct GameState gGameState
#define Iwram_MulQ16(left, right)
volatile u32 gKeysHeld
Keys down now.
volatile u32 gKeysPressed
Keys that went down this frame.
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
#define SET_VELOCITY(p, vx, vy, vz)
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,...
s32 ArcTan2(s32 x, s32 y)
Returns the angle of the vector (x, y), in 1/65536 turns, measured from the y axis: 0 along +y,...
s32 FixedSqrt(s32 value)
Square root of a 16.16 fixed-point value, in 16.16.
void Object_SetMoveTarget(struct ObjectRuntime *object, s32 x, s32 y, s32 z)
Sends an object towards (x, y, z), in 16.16 pixels.
s32 Runtime_CheckRadiusOverlap(s32 *firstPosition, s32 radiusA, s32 *secondPosition, s32 radiusB)
Returns 0 when two spheres overlap: at positions a and b (16.16 pixels) with radii radiusA and radius...
s32 Object_MoveByKeys(struct ScriptInterpreter *interpreter)
SC_KEYS: moves an object 8 pixels at a time by the direction pad, with up and down changing its heigh...
s32 Field_CheckConfiguredKeysAndCount(struct ScriptInterpreter *interpreter)
SC_KEY_COUNT: checks the configured keys (Field_CheckConfiguredKeys).
#define FIELD_SHORTCUT_KEYS
s32 Object_MoveOnWorldMap(struct ScriptInterpreter *interpreter)
SC_WORLD: moves the player on the world map by the direction pad, as SC_PLAYER does on the field,...
s32 FieldObject_UpdatePlayerControl(struct ScriptInterpreter *interpreter)
SC_PLAYER: moves the player on the field by the direction pad: walking or running,...
#define WORLD_MAP_PROBE_RADIUS
UNUSED void ObjectDispatch_SetUpdateValue(void *rawObject, s32 value)
Stores value as a word at the object's unk6c.
static __inline__ void Field_StoreHalfword(s16 *address, s32 value)
Stores value in a halfword of the event work.
u32 Field_RequestShortcut(u32 encodedAssignment)
Handles a shortcut key's assignment: its top two bits choose what it requests (0 Psynergy,...
s32 Field_CheckConfiguredKeys(void)
Checks the keys the player has configured: Select, A and Start set their flag in the event work and r...
#define Ram_MapCellBuffer
s32 ScriptObject_CheckOverlap(struct ScriptObjectEntry *object, s32 *values)
Returns -1 when an object at position values would overlap a solid object (bit 0 of collisionFlags),...
struct EventWork * gEventWork
u8 priority
drawing order 0 to 3 among the layers; above 3 not drawn
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
struct AnimationSpritePart image
u16 rotation
1/65536 turns
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
struct AnimationEntry * entries[4]
its layers; empty ones null
u8 count
layers in use, up to the last one present
u16 priority
2 when created
s16 hp
current HP, 0 when downed
A field object as the object dispatcher's far calls take it.
s16 blockedSteps
frames the leader has pushed against something
s32 z
16.16 fixed-point pixels
Full event work allocated by Field_RunScene (heap slot 27).
s16 event
A raised event for Scene_RunRaisedEvent, or -1 when characters fell to poison or hazard damage,...
s16 command
a field Psynergy to use, as owner << 10 | Psynergy
s16 start
the Start button: open the pause menu
s16 menu
open the main menu
s16 mode
MODE_WORLD_MAP (3) on the world map.
s16 examine
the A button: examine what is ahead
s16 item
an item to use, packed as Field_UseItem reads it
u16 firstShortcut
The shortcuts' assignments.
u16 selectKeys
the menu; KEY_SELECT
u16 secondShortcutKeys
secondShortcut; KEY_R
s32 selectedActor
the leader: its unit and its actor
u16 aKeys
The buttons for each field command, as KEY_ masks; read with gKeysPressed except dashKeys,...
u16 firstShortcutKeys
firstShortcut; KEY_L
One cell of a map layer: its metatile and flags, its collision code and an attribute indexing the col...
u8 collisionCode
The step code: 1 to 239 scene events, 240 and 241 encounter ground, 250 hazard, 252 to 254 for Field_...
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
s32 velocityZ
16.16 fixed-point pixels per frame
s32 terrainHeight
16.16 fixed-point pixels
s32 velocityX
16.16 fixed-point pixels per frame
u16 radius
collision radius in pixels
u8 movementState
nonzero skips its script and motion (paused)
s16 footprintSide
the side of the player's next footprint (2 after a stop)
s32 z
16.16 fixed-point pixels
u8 collisionFlags
FieldActor.collisionFlags: bit 0 solid, bit 1 the player pushes it, bits 2 to 4 for talk and Psynergy...
s32 * script
the object script it runs; null when the object is free
void * animation
its sprite, or its list of four, by animationKind
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.
s16 action
The parameter its action script reads (a follow distance or an angle), or the player's frames to its ...
u8 terrainId
the map layer its ground height is read from
u8 unk6c[0x04]
The update hook (FieldActor.update), which the unused ObjectDispatch_SetUpdateValue sets as a word.
The world map's perspective view: the followed position, screen shake, view position,...
The prefix that command handlers read from a field object's 0x70-byte slot.
A field object as the script commands' overlap checks see it.
A position on the world map, as its walkability check reads it.
s32 x
16.16 fixed-point pixels
s32 y
16.16 fixed-point pixels
s32 Map_CheckObjectStep(struct ObjectRuntime *object, struct FieldPosition *position)
Returns whether an object can step to position: 2 when the cell there is a wall (collision code 0xff)...
s32 CheckWorldMapWalkable(s32 unused, struct WorldPosition *position)
Returns 0 when the world map at position can be walked on (collision 5 to 12), else -1.
s32 GetWorldMapCollision(struct WorldPosition *position)
Returns the world map's collision value (1-15) at position: from the upper collision layer where it h...
s32 CheckMapPositionCellOccupied(struct WorldPosition *position)
Returns 0 when the cell under position (its x, and y less its height) in layer 2 is a wall (collision...
s32 Map_GetTerrainHeight(s32 layer, s32 x, s32 y)
Returns the ground height of a layer at (x, y) in 16.16 pixels: the height function of the cell's ter...
struct ScriptMotionObject * gObjectSlots
u8 gResourceBlockOwners[VRAM_BLOCK_COUNT]