Create Wander in Grass Movement Type - Pawkkie/Team-Aquas-Asset-Repo GitHub Wiki

Tutorial was written using pokeemerald-expansion v1.9.X.


This creates a movement type that will only allow object events to 'wander' on grass tiles within a given range, perfect for overworld encounters.

wanderingrass

Note: This feature only prevents an object event wandering onto non-grass metatiles. Placing an object with this movement type will cause behaviour similar to MOVEMENT_TYPE_LOOK_AROUND if there is not a grass metatile for it to wander onto next to it. Examples are provided at the end of this tutorial.

Defining a new movement

In include/constants/event_object_movement.h, add a new movement type, remembering to change the total movement count.

  #define MOVEMENT_TYPE_FOLLOW_PLAYER                    0x51
- #define NUM_MOVEMENT_TYPES                             0x52
+ #define MOVEMENT_TYPE_WANDER_IN_GRASS                  0x52
+ #define NUM_MOVEMENT_TYPES                             0x53

Then, head to somewhere in include/event_object_movement.h and add in these two declarations. Feel free to add them in individually with the movement type and movement step declarations respectively.

+ void MovementType_WanderInGrass(struct Sprite *);
+ u8 MovementType_WanderInGrass_Step4(struct ObjectEvent *, struct Sprite *);

Adding the movement

In src/event_object_movement.c, add these three lines to the end of their respective arrays.

  static void (*const sMovementTypeCallbacks[])(struct Sprite *) =
  {
  … … …
+ [MOVEMENT_TYPE_WANDER_IN_GRASS] = MovementType_WanderInGrass,
  };
  static const bool8 sMovementTypeHasRange[NUM_MOVEMENT_TYPES] = {
  … … …
+ [MOVEMENT_TYPE_WANDER_IN_GRASS] = TRUE,
  };
  const u8 gInitialMovementTypeFacingDirections[] = {
  … … …
+ [MOVEMENT_TYPE_WANDER_IN_GRASS] = DIR_SOUTH,
  };

Then, still in src/event_object_movement.c, add the movement function itself.

+ movement_type_def(MovementType_WanderInGrass, gMovementTypeFuncs_WanderInGrass)
+
+ bool8 MovementType_WanderInGrass_Step4(struct ObjectEvent *objectEvent, struct Sprite *sprite)
+ {
+     u8 directions[4];
+     u8 chosenDirection;
+
+     memcpy(directions, gStandardDirections, sizeof directions);
+     chosenDirection = directions[Random() & 3];
+     SetObjectEventDirection(objectEvent, chosenDirection);
+     sprite->sTypeFuncId = 5;
+     if (!MetatileBehavior_IsPokeGrass(MapGridGetMetatileBehaviorAt(objectEvent->currentCoords.x + gDirectionToVectors[chosenDirection].x, objectEvent->currentCoords.y + gDirectionToVectors[chosenDirection].y))
+         || GetCollisionInDirection(objectEvent, chosenDirection))
+         sprite->sTypeFuncId = 1;
+
+     return TRUE;
+ }

And then finally in src/data/object_events/movement_type_func_tables.h create the movement table by adding in the following.

+ u8 (*const gMovementTypeFuncs_WanderInGrass[])(struct ObjectEvent *, struct Sprite *) = {
+     MovementType_WanderAround_Step0,
+     MovementType_WanderAround_Step1,
+     MovementType_WanderAround_Step2,
+     MovementType_Wander_Step3,
+     MovementType_WanderInGrass_Step4,
+     MovementType_WanderAround_Step5,
+     MovementType_WanderAround_Step6,
+ };

Note: Multiple movement steps were condensed into MovementType_Wander_Step3 in pokeemerald-expansion v1.9.2. If you do not yet have these changes, replace it with MovementType_WanderAround_Step3.

Results

And it's as easy as that. Simply set an objects movement type to MOVEMENT_TYPE_WANDER_IN_GRASS, set it's maximum movement range, and enjoy restricting object events to only wandering into grass!

wanderingrass wanderingrass_beside wanderingrass_away