How To Make A New Move - Pawkkie/Team-Aquas-Asset-Repo GitHub Wiki

By PCG.

Note: As of 2024/02/05 at the latest, this is outdated for pokeemerald-expansion v1.8.0 and above. Click here for an updated tutorial.

This tutorial will show you how to make a new move.

jetsreamsingles

This tutorial will not feature creating new effects.

Defining your move

All moves are defined in include/constants/moves.h Your moves.h file should have something like this.

#define MOVE_PSYBLADE 827
#define MOVE_HYDRO_STEAM 828

#define MOVES_COUNT_GEN9 829

Now, you want to your define your new move right below the last move, and increment MOVES_COUNT_GEN9.

#define MOVE_PSYBLADE 827
#define MOVE_HYDRO_STEAM 828
+#define MOVE_JETSREAM 829

-#define MOVES_COUNT_GEN9 829
+#define MOVES_COUNT_GEN9 830

Move name

Moves are given their names in src/data/text/move_names.h

Now, you can place it anywhere, but for the sake order, lets place it right under MOVE_HYDRO_STEAM.

[MOVE_HYDRO_STEAM] = _("Hydro Steam"),
-};
+[MOVE_JETSTREAM] = ("Jetstream"),
+};

If you are using pokeemerald Expansion, you need to paste the same line again under the other definition of [MOVE_HYDRO_STEAM] = _("Hydro Steam") because of expanded move names, but its not a necessity.

Move description

Moves are given their description in src/data/text/move_descriptions.h.

static const u8 sHydroSteamDescription[] = _(
    "This move's power increases\n"
    "under harsh sunlight.");

+ static const u8 sJetstreamDescription[] = _(
+    "Shoots a stream of air.\n"
+    "High critical-hit ratio.");


const u8 gNotDoneYetDescription[] = _(
    "This move can't be used. Its\n"
    "effect is in development.");

Move data

Now, you have to give data to your new move which you just defined.

There are two types of data for moves.

Battle data and Contest data.

Battle data

Battle data for moves is stored in src/data/battle_moves.h.

Let's define our move's data right under MOVE_HYDRO_STEAM

    [MOVE_HYDRO_STEAM] =
    {
        .effect = EFFECT_HYDRO_STEAM,
        .power = 80,
        .type = TYPE_WATER,
        .accuracy = 100,
        .pp = 15,
        .secondaryEffectChance = 0,
        .target = MOVE_TARGET_SELECTED,
        .priority = 0,
        .split = SPLIT_SPECIAL,
        .zMoveEffect = Z_EFFECT_NONE,
    },

+   [MOVE_JETSTREAM] =
+   {
+       .effect = EFFECT_HIT,
+       .power = 90,
+       .type = TYPE_FLYING,
+       .accuracy = 100,
+       .pp = 16,
+       .secondaryEffectChance = 0,
+       .target = MOVE_TARGET_SELECTED,
+       .priority = 0,
+       .split = SPLIT_SPECIAL,
+       .zMoveEffect = Z_EFFECT_NONE,
+       .highCritRatio = TRUE,
+   },
+

You can also give additional effects to the move, such as higher crit rate, banned by instruct and metronome, priority, etc.. Over here, I've given the move a higher crit rate.

Contest data

Contest data for moves is stored src/data/contest_moves.h

Now, if you don't care about contests at all, you can just do this.

[MOVE_HYDRO_STEAM] = {0}, // TODO
+[MOVE_JETSTREAM] = {0},

But, if you do care for contests, you can give your move some data.

[MOVE_JETSTREAM] =
    {
        .effect = CONTEST_EFFECT_HIGHLY_APPEALING,
        .contestCategory = CONTEST_CATEGORY_BEAUTY,
        .comboStarterId = 0,
        .comboMoves = {0},
    },

You can also add .comboMoves such as COMBO_STARTER_PECK or COMBO_STARTER_POUND and many more, check include/constants/contest.h.

Move animations

Oh boy! Oh boy! Oh boy!

Move animations are a little complicated, and out of this tutorial's scope.

But let's see the basics.

This is the first time I've attempted anims too, so lets keep it small and simple.

If you know about animations, please don't hesistate to update this part of the tutorial.

You need to define your move animation right below the move you defined it under at the start. Definitions for animations go in data/battle_anim_scripts.s.

.4byte Move_HYDRO_STEAM
+.4byte Move_JETSTREAM

Now let's create the animation.

Move_JETSTREAM::
        loadspritegfx ANIM_TAG_AIR_WAVE_2
	loadspritegfx ANIM_TAG_AIR_WAVE_2
	loadspritegfx ANIM_TAG_EXPLOSION_2
	call SetSkyBg
	monbg ANIM_DEF_PARTNER
	splitbgprio ANIM_TARGET
	setalpha 12, 8
	call AirProjectile
	call AirProjectile
	call AirProjectile
	call AirProjectile
	createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 10, 1
	call SonicBoomHit
	waitforvisualfinish
	clearmonbg ANIM_DEF_PARTNER
	call UnsetSkyBg
	blendoff
	end

AirProjectile:
	playsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER
	createsprite gAirWaveCrescentSpriteTemplate, ANIM_ATTACKER, 2, 14, -12, 0, -12, 15, 0, 0
	createsprite gAirWaveCrescentSpriteTemplate, ANIM_ATTACKER, 2, 26, 8, 12, 8, 15, 0, 0
	delay 3
	createsprite gSpriteTemplate_SpiritBreakExplode, ANIM_TARGET, 3, 0x40, 0x40, 0x16, 0x16
	delay 4
	return

Here, we load the sprite graphics of ANIM_TAG_AIR_WAVE_2, and ANIM_TAG_EXPLOSION_2.

The background has been set to SetSkyBg.

We are creating a new anim script for the main anim called AirProjectile.

AirProjectile uses gAirWaveCrescentSpriteTemplate which needs ANIM_TAG_AIR_WAVE_2, and gSpriteTemplate_SpiritBreakExplode which needs ANIM_TAG_EXPLOSION_2.

ANIM_ATTACKER means the user who uses the attack.

ANIM_TARGET is the target to whom the attack is being used at.

delay is the wait time.

return goes back to the script that calls it.

We then create a visual of the target shaking after getting hit, and I called the Sonic Boom effect SonicBoomHit, which needs ANIM_TAG_AIR_WAVE.

After the visual, we use waitforvisualfinish which is self-explanatory.

To remove the sky background, we call UnsetSkyBg.

End the script with end.