27#define SCRIPT_LABEL_KEY_MASK 0xbfffffff
35 interpreter->
wait = interpreter->
script[commandCursor + 1] - 1;
66 if (callback(interpreter) != 0)
68 if (interpreter->
cursor == initialCursor)
80 s16 *waitCounter = &interpreter->
wait;
92 if (*scriptWords++ == labelKey) {
106 const s32 *arguments;
112 arguments = &interpreter->
script[interpreter->
cursor + 1];
113 repeatLimit = *arguments++;
114 jumpKey = *arguments;
119 nextCount = *repeatCount + 1;
120 *repeatCount = nextCount;
121 if ((
u8)nextCount < (
s16)repeatLimit) {
134 interpreter, interpreter->
script[interpreter->
cursor + 1]);
142 u32 labelKey = script[commandCursor + 1];
156 u32 labelKey = script[commandCursor + 1];
173 interpreter->
cursor = (result = 0);
187#define SCRIPT_DEFINE_FLAG_COMMAND(name, change) \
188 s32 name(struct ScriptInterpreter *interpreter) { \
191 flagId = interpreter->script[interpreter->cursor + 1]; \
192 interpreter->conditionResult = GameFlag_TestFar(flagId); \
194 interpreter->cursor += 2; \
205 s32 previousFlagValue;
207 flagId = interpreter->script[interpreter->cursor + 1];
209 interpreter->conditionResult = previousFlagValue;
211 if ((previousFlagValue << 0x18) == 0x01000000) {
216 interpreter->cursor += 2;
261 objectIndex++, candidate++,
collisionFlags +=
sizeof(*candidate)) {
265 &candidate->
x, ((
struct FieldActor *)candidate)->radius - 2,
266 values, ((
struct FieldActor *)
object)->radius - 2) >= 0)
285 objectIndex++, candidate++,
collisionFlags +=
sizeof(*candidate)) {
289 &candidate->
x, ((
struct FieldActor *)candidate)->radius - 2,
290 values, ((
struct FieldActor *)
object)->radius - 2) >= 0)
304 const s32 *coordinates;
306 coordinates = interpreter->
script + interpreter->
cursor;
314 interpreter->cursor += 4;
335 s32 *arguments = (
s32 *)(commandBytes + 4);
336 s32 deltaX = *arguments++;
337 s32 deltaY = *arguments++;
338 s32 deltaZ = *arguments;
341 object->
y + deltaY, object->
z + deltaZ);
342 object->scriptCursor += 4;
356 ArcTan2((target->
z - object->
z), (target->
x - object->
x));
357 object->scriptCursor++;
371 object->scriptCursor++;
386 localOffset[0] = localOffset[1] = localOffset[2] = 0;
389 object->
x + localOffset[0], object->
y + localOffset[1],
390 object->
z + localOffset[2]);
391 object->scriptCursor += 3;
427 if (leader ==
NULL) {
428 cameraObject->
flags = 0;
429 cameraObject->
step++;
437 cameraObject->
flags = 0;
453 if (cameraObject->
action != 0) {
458 dx = (x - cameraObject->
x) / 0x10000;
462 dy = (y - cameraObject->
y) / 0x10000;
463 dz = (z - cameraObject->
z) / 0x10000;
464 distance =
Iwram_Sqrt(dx * dx + dz * dz) << 16;
465 dx = x - cameraObject->
x;
466 dy = y - cameraObject->
y;
467 dz = z - cameraObject->
z;
472 if ((moveStep = distance / 8) > cameraObject->
speedLimit)
479 if (distance > moveStep) {
483 cameraObject->
x += dx;
484 cameraObject->
z += dz;
489 cameraObject->
y += dy;
492 cameraObject->
step++;
515 s32 remainingDistance;
525 deltaXPixels = dx >> 0x10;
526 deltaZPixels = dz >> 0x10;
531 distancePixels =
_call_via_r3((deltaXPixels * deltaXPixels) +
532 (deltaZPixels * deltaZPixels),
537 moveX = scaledDeltaX * remainingDistance / distancePixels;
538 moveZ = dz * remainingDistance / distancePixels;
542 object->step = (
object->step + 1);
564 s32 homeRadiusSquared;
577 minimumDistance = *operands++;
578 distanceRange = *operands++;
579 homeRadiusSquared = *operands / 0x10000;
581 homeRadiusSquared = homeRadiusSquared * homeRadiusSquared;
591 (
s32 *)&candidatePosition) != 0 ||
593 &candidatePosition) != 0)
598 SET_POSITION(&probePosition, object->x, object->y, object->z);
606 SET_POSITION(&probePosition, object->x, object->y, object->z);
611 &probePosition) != 0)
617 SET_POSITION(&probePosition, object->x, object->y, object->z);
629 dx = candidatePosition.x / 0x10000 -
object->homeX;
630 dz = candidatePosition.z / 0x10000 -
object->homeZ;
632 if (dx * dx + dz * dz > homeRadiusSquared)
638 object->turnedBack = 1;
642 candidatePosition.
y, candidatePosition.
z);
643 object->scriptCursor += 4;
663 s32 homeRadiusSquared;
672 minimumDistance = *operands++;
673 distanceRange = *operands++;
674 homeRadiusSquared = *operands / 0x10000;
675 angle =
object->scriptValue;
676 homeRadiusSquared *= homeRadiusSquared;
678 dx =
object->x / 0x10000 -
object->homeX;
679 dz =
object->z / 0x10000 -
object->homeZ;
680 if (dx * dx + dz * dz <= homeRadiusSquared) {
694 (
s32 *)&candidatePosition) != 0)
696 SET_POSITION(&candidatePosition, object->x, object->y, object->z);
699 &candidatePosition) != 0)
701 probePosition.
x =
object->x;
702 probePosition.
y =
object->y;
704 probePosition.
z =
object->z;
709 SET_POSITION(&probePosition, object->x, object->y, object->z);
716 SET_POSITION(&probePosition, object->x, object->y, object->z);
723 SET_POSITION(&probePosition, object->x, object->y, object->z);
729 SET_POSITION(&probePosition, object->x, object->y, object->z);
735 dx = candidatePosition.x / 0x10000 -
object->homeX;
736 dz = candidatePosition.z / 0x10000 -
object->homeZ;
737 if (dx * dx + dz * dz > homeRadiusSquared)
739 object->flags59 |= 2;
741 candidatePosition.y, candidatePosition.z);
760 (
s32 *)&candidatePosition) != 0)
762 SET_POSITION(&candidatePosition, object->x, object->y, object->z);
765 &candidatePosition) != 0)
767 object->flags59 &= ~2;
769 candidatePosition.y, candidatePosition.z);
772 object->scriptCursor += 4;
784#define SCRIPT_DEFINE_OPERAND_WORD(name, field) \
785 void name(struct ScriptOperands *operands, s32 operation, s32 value) { \
786 if (operation == SCRIPT_OPERAND_SET) { \
787 operands->field = value; \
790 if (operation == SCRIPT_OPERAND_ADD) { \
791 operands->field += value; \
794 operands->conditionResult = operands->field == value; \
798#define SCRIPT_DEFINE_OPERAND_ADDRESS(name, field) \
799 void name(struct ScriptOperands *operands, s32 operation, s32 value) { \
800 if (operation == SCRIPT_OPERAND_SET) { \
801 operands->field = value; \
804 if (operation == SCRIPT_OPERAND_ADD) { \
805 operands->field += value * 4; \
808 operands->conditionResult = operands->field == value; \
812#define SCRIPT_DEFINE_OPERAND_NARROW(name, field, type) \
813 void name(struct ScriptOperands *operands, s32 operation, s32 value) { \
814 if (operation == SCRIPT_OPERAND_SET) { \
815 operands->field = value; \
816 } else if (operation == SCRIPT_OPERAND_ADD) { \
817 operands->field += value; \
819 operands->conditionResult = operands->field == (type)value; \
832 operands->cursor = value;
834 operands->cursor = ((
s16)operands->cursor + value);
836 operands->conditionResult = (
s16)operands->cursor == (
s16)value;
849 state->radius = value;
853 state->radius = (state->radius + value);
856 state->conditionResult = state->radius == (
s16)value;
898 work->conditionResult = (
s16)work->wait == (
s16)value;
914 s16 commandCursor = operands->cursor;
915 const s32 *arguments =
916 (
const s32 *)operands->scriptAddress + commandCursor + 1;
920 handler(operands, operation, arguments[1]);
921 operands->cursor += 3;
946#undef SCRIPT_DEFINE_FLAG_COMMAND
947#undef SCRIPT_DEFINE_OPERAND_WORD
948#undef SCRIPT_DEFINE_OPERAND_ADDRESS
949#undef SCRIPT_DEFINE_OPERAND_NARROW
950#undef SCRIPT_LABEL_KEY_MASK
const s32 gScript_MainScript[1]
The idle script an object returns to when its own one ends: a lone SC_END, which reloads it.
s32 GameFlag_TestFar(s32 flag)
s32 GameFlag_SetBitFar(s32 flag)
void GameFlag_ClearBitFar(s32 flag)
void AudioCommand_PlayFar(s32 id)
void ObjectDispatch_Release(struct DispatchObject *object)
Releases an object's sprites and zeroes it, freeing it.
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.
#define Q16_ONE
One in the engine's signed 16.16 fixed-point format.
static s32 Iwram_RatioMulQ14(s32 divisor, s32 value)
All calls go through this layer.
static s32 Iwram_Sqrt(s32 value)
#define Iwram_MulQ16(left, right)
#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.
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,...
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
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 Object_IsTargetUnset(struct ObjectRuntime *object)
Returns 1 when the object has no movement target: none of its target coordinates set,...
void Object_SetPositionAndResetMotion(struct ObjectRuntime *object, s32 x, s32 y, s32 z)
Places the object at (x, y, z), in 16.16 pixels, clears its movement target and stops it.
const OperandFunc gScript_OperandHandlerTable[41]
The handler for each work value number (enum ScriptWork).
void(*) OperandFunc(struct ScriptOperands *state, s32 operation, s32 value)
A work value's handler: by operation (enum ScriptOperandOperation in script_commands....
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(*) ScriptCommand(struct ScriptInterpreter *)
void Script_SetOrCompareWord68(struct ScriptOperands *operands, s32 operation, s32 value)
@ SCRIPT_WANDER_SIDE_ANGLE
one quarter of a turn
@ CAMERA_FOLLOW_SNAP_DISTANCE
@ SCRIPT_BLOCKED_MOVE_FRAMES
@ SCRIPT_WANDER_PROBE_DISTANCE
@ CAMERA_FOLLOW_FINE_DISTANCE
@ CAMERA_FOLLOW_HEIGHT_SNAP
@ SCRIPT_LABEL_SEARCH_WORDS
@ SCRIPT_APPROACH_DISTANCE
@ SCRIPT_WANDER_DIAGONAL_ANGLE
one eighth of a turn
void Script_SetOrCompareUnsignedHalfword(struct ScriptOperands *operands, s32 operation, s32 value)
static __inline__ s32 Script_ApplyPositionCommand(struct ScriptInterpreter *interpreter, void(*applyPosition)(struct ObjectRuntime *object, s32 x, s32 y, s32 z))
Reads three coordinate words and applies the selected positioning operation.
s32 Object_ApproachLinkedObject(struct ScriptInterpreter *interpreter)
SC_APPROACH_LINK: follows the linked object at its speed.
s32 Script_RepeatOrJump(struct ScriptInterpreter *interpreter)
SC_LOOP(n, to): jumps to label to until it has done so n - 1 times, then moves on; with n = SC_FOREVE...
void Script_SetOrCompareVerticalMotion(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_ApplyRelativePosition(struct ScriptInterpreter *interpreter)
SC_MOVE_BY(x, y, z): sends the object towards its position plus (x, y, z).
#define SCRIPT_DEFINE_OPERAND_NARROW(name, field, type)
The same for an 8- or 16-bit value: a compare narrows value to its type.
s32 Script_StoreAngleToLinkedObject(struct ScriptInterpreter *interpreter)
SC_FACE_LINK: stores the angle from the object to its linked object in scriptValue,...
s32 Script_SetFlagAndTest(struct ScriptInterpreter *interpreter)
SC_FLAG_ON(f) and SC_FLAG_OFF(f): test game flag f, then set or clear it.
s32 Script_JumpToLabel(struct ScriptInterpreter *interpreter)
SC_JUMP(to): jumps to label to.
s32 Script_Wait(struct ScriptInterpreter *interpreter)
SC_WAIT(n): waits n frames; this frame counts as the first.
s32 Script_ClearFlagAndTest(struct ScriptInterpreter *interpreter)
void Script_SetOrCompareGravity(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_PlaySound(struct ScriptInterpreter *interpreter)
SC_SE(n): sends sound command n (a sound effect).
s32 Camera_FollowLeaderInBounds(struct ScriptInterpreter *interpreter)
SC_CAMERA: keeps the camera object on its leader (linkedObject), clamped so the view stays on the map...
void Script_SetOrCompareRadius(struct ScriptOperands *state, s32 operation, s32 value)
Work value SW_RADIUS: sets, adds to or compares the object's radius.
struct ScriptObjectEntry * ScriptObject_FindOverlappingEntry(struct ScriptObjectEntry *object, s32 *values)
Returns the first solid object that an object at position values would overlap, as ScriptObject_Check...
s32 Script_ApplyOperandSet(struct ScriptInterpreter *interpreter)
SC_SET(w, v): sets work value w to v.
void Script_SetOrCompareSpeedLimit(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareSignedHalfword66(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrComparePaused(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_JumpIfTrue(struct ScriptInterpreter *interpreter)
SC_IF(to): jumps to label to when the last test was true.
void Script_SetOrCompareRepeatCount(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_ApplyOperandAdd(struct ScriptInterpreter *interpreter)
SC_ADD(w, v): adds v to work value w.
s32 Script_ToggleFlagAndTest(struct ScriptInterpreter *interpreter)
SC_FLAG_REV(f): tests game flag f, then flips it.
s32 Script_InvokeCallback(struct ScriptInterpreter *interpreter)
SC_CALL(fn): calls fn with the object.
s32 Script_ApplyLocalOffsetPosition(struct ScriptInterpreter *interpreter)
SC_MOVE_LOCAL(a, b): sends the object towards its position plus an offset that is never filled in; th...
s32 Script_Nop(struct ScriptInterpreter *interpreter)
SC_NOP(v): does nothing with its operand.
void Script_SetOrCompareCollisionFlags(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareComparisonResult(struct ScriptOperands *operands, s32 operation, s32 value)
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),...
s32 Script_FreeObject(struct ScriptInterpreter *interpreter)
SC_FREE: releases the object through ObjectDispatch_Release, which releases its sprites and zeroes it...
void Script_SetOrCompareCursor(struct ScriptOperands *operands, s32 operation, s32 value)
Work value SW_CURSOR: sets, adds to or compares the script cursor.
s32 _call_via_r3(s32, s32, s32, s32)
void Script_SetOrCompareByte63(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_End(struct ScriptInterpreter *interpreter)
SC_END: hands the object back to the idle script, gScript_MainScript, whose lone SC_END runs again ea...
#define SCRIPT_DEFINE_OPERAND_WORD(name, field)
Defines the handler for a 32-bit work value: set it, add to it, or compare it (into conditionResult).
s32 Script_ApplyAbsolutePosition(struct ScriptInterpreter *interpreter)
SC_MOVE(x, y, z): sends the object towards (x, y, z).
void Script_SetOrCompareScaleX(struct ScriptOperands *operands, s32 operation, s32 value)
#define SCRIPT_DEFINE_FLAG_COMMAND(name, change)
Defines a flag command: stores the flag's current value in conditionResult, then changes the flag wit...
s32 ScriptObject_WanderNearHome(struct ScriptInterpreter *interpreter)
SC_WANDER_HOME(base, range, limit): wanders as SC_WANDER does, testing more ground around the point,...
void Script_SetOrCompareAddress50(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareVelocityX(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareArrivalAxis(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareTargetY(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareZ(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_WaitForArrival(struct ScriptInterpreter *interpreter)
SC_SYNC: waits until the object arrives at its target, or until a solid object has blocked it for 60 ...
s32 Object_Wander(struct ScriptInterpreter *interpreter)
SC_WANDER(base, range, limit): walks to a random point base to base + range away, within 90 degrees e...
void Script_SetOrCompareSnapToTarget(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareX(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareScaleY(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_TestFlag(struct ScriptInterpreter *interpreter)
SC_FLAG_CHECK(f): tests game flag f.
#define SCRIPT_LABEL_KEY_MASK
SC_LABEL and SC_TO differ only in bit 30; a jump searches for the label.
void Script_SetOrCompareY(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareTargetX(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareHalfword5e(struct ScriptOperands *work, s32 operation, s32 value)
Work value SW_WAIT: sets, adds to or compares the wait counter.
s32 Script_ApplyOperandCompare(struct ScriptInterpreter *interpreter)
SC_CMP(w, v): tests whether work value w equals v.
void Script_SetOrCompareByte54(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareWord4c(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareMotionFlags(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareSignedHalfword64(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_SetPositionAndResetMotion(struct ScriptInterpreter *interpreter)
SC_POS(x, y, z): places the object at (x, y, z) and stops it.
s32 Script_SetAnimation(struct ScriptInterpreter *interpreter)
SC_ARG(v): switches the object's sprites to animation v.
void Script_SetOrCompareVelocityY(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_ApplyLinkedObjectPosition(struct ScriptInterpreter *interpreter)
SC_MOVE_LINK: sends the object towards its linked object.
void Script_SetOrCompareByte62(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_FindLabel(struct ScriptInterpreter *interpreter, u32 labelKey)
Returns the cursor just past the script's label key (SC_LABEL or SC_TO, matched without the bit that ...
void Script_SetOrCompareTerrainHeight(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareVelocityZ(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareTargetZ(struct ScriptOperands *operands, s32 operation, s32 value)
static __inline__ s32 Script_ApplyOperandCommand(struct ScriptOperands *operands, s32 operation)
Reads the two words after the command (a work value number and a value) and passes operation to that ...
void Script_SetOrCompareAcceleration(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareSteeringFlags(struct ScriptOperands *operands, s32 operation, s32 value)
void Script_SetOrCompareAddress(struct ScriptOperands *operands, s32 operation, s32 value)
The work value handlers, one for each entry of enum ScriptWork (see gScript_OperandHandlerTable in op...
#define SCRIPT_DEFINE_OPERAND_ADDRESS(name, field)
The same for an address: an add steps by value words (value * 4 bytes).
void Script_SetOrCompareUpdateAddress(struct ScriptOperands *operands, s32 operation, s32 value)
s32 Script_JumpIfFalse(struct ScriptInterpreter *interpreter)
SC_IFNOT(to): jumps to label to when the last test was false.
A field object as the object dispatcher's far calls take it.
A field actor: a person or thing on the field with a position, motion toward a target,...
s32 z
16.16 fixed-point pixels
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
s32 targetZ
16.16 fixed-point pixels; 0x80000000 when unset
s32 targetY
16.16 fixed-point pixels; 0x80000000 when unset
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....
s32 targetX
16.16 fixed-point pixels; 0x80000000 when unset
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
u8 flags
FieldActor.motionFlags: 3 when created, 4 for a placed actor above the ground; zero is free flight in...
s32 x
16.16 fixed-point pixels
s16 step
the script cursor, in words
s32 speedLimit
16.16 fixed-point pixels per frame
s32 y
16.16 fixed-point pixels
struct ObjectRuntime * linkedObject
The object its action script follows or faces.
s16 action
The parameter its action script reads (a follow distance or an angle), or the player's frames to its ...
The prefix that command handlers read from a field object's 0x70-byte slot.
u8 repeatCount
SC_LOOP's count of jumps so far.
s16 cursor
the word index of the next command in script
u8 conditionResult
the last flag test, read by SC_IF and SC_IFNOT
const s32 * script
the running script; SC_END sets gScript_MainScript
s16 wait
Frames left of SC_WAIT (n - 1 when it starts); the update loops count it down, and Script_FindLabel c...
u8 refused
Frames in a row a solid object has refused the object's move (ScriptMotionObject.refused); SC_SYNC st...
A field object as the script commands' overlap checks see it.
A field object as its object script commands see it: the script and its place, position,...
struct ScriptObjectRuntime * linkedObject
The object SC_FACE_LINK and SC_MOVE_LINK aim at.
s32 x
16.16 fixed-point pixels
s32 y
16.16 fixed-point pixels
const s32 * script
null when the object is free
s32 z
16.16 fixed-point pixels
u16 scriptValue
The object's facing, 1/65536 turns: the heading SC_WANDER and SC_WANDER_HOME wander around,...
The whole 0x70-byte slot as SC_SET, SC_ADD and SC_CMP see it: each field is one work value (enum Scri...
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)...
struct ScriptMotionObject * gObjectSlots