Simple Modifications Directory Page 11

Started by Avara December 30th, 2018 2:48 PM
  • 77871 views
  • 271 replies
Seen 2 Days Ago
Posted 2 Weeks Ago
9 posts
155 Days
Implement a metatile behavior for Feebas encounters (Emerald)

A very simple little tweak.

https://github.com/surskitty/pokeemerald/commit/fea41dbc7a8620782b1c1a67f60db6aaddca46c1

You can then use Porymap to edit Route 119, make a new tile with the behavior MB_FEEBAS, and use that tile to set that as the location for Feebas.

In ORAS, Feebas are found under the bridge next to the Weather Institute during the daytime, and by the rock in the water at the southern end of Route 119 during the night.

git remote add surskitty https://github.com/surskitty/pokeemerald
git cherry-pick fea41dbc7a8620782b1c1a67f60db6aaddca46c1
Seen 12 Hours Ago
Posted 2 Weeks Ago
97 posts
3.6 Years
Display Mugshots/Other Images In The Overworld (Emerald / Firered)

This modification allows you to load images onto BG0 from a script. It can only show one 16-color image at a time.


1. Installation
Spoiler:

1. Create mugshot.c in the src folder and copy the following code to it:
Spoiler:
#include "global.h"
#include "blit.h"
#include "window.h"
#include "menu.h"
#include "palette.h"
#include "event_data.h"
#include "constants/mugshots.h"

#define MUGSHOT_PALETTE_NUM 13

struct Mugshot{
    u8 x;
    u8 y;
    u8 width;
    u8 height;
    const u32* image;
    const u16* palette;
};

void DrawMugshot(void); //VAR_0x8000 = mugshot id
void DrawMugshotAtPos(void); //VAR_0x8000 = mugshot id, VAR_0x8001 = x, VAR_0x8002 = y
void ClearMugshot(void);


static const struct Mugshot sMugshots[] = {
    //ADD YOUR MUGSHOTS HERE
};


//WindowId + 1, 0 if window is not open
static EWRAM_DATA u8 sMugshotWindow = 0;

void ClearMugshot(void){
    if(sMugshotWindow != 0){
        ClearStdWindowAndFrameToTransparent(sMugshotWindow - 1, 0);
        CopyWindowToVram(sMugshotWindow - 1, 3);
        RemoveWindow(sMugshotWindow - 1);
        sMugshotWindow = 0;
    }
}

static void DrawMugshotCore(const struct Mugshot* const mugshot, int x, int y){
    struct WindowTemplate t;
    u16 windowId;
    
    if(sMugshotWindow != 0){
        ClearMugshot();
    }
    
    #if GAME_VERSION==VERSION_EMERALD
    SetWindowTemplateFields(&t, 0, x, y, mugshot->width/8, mugshot->height/8, MUGSHOT_PALETTE_NUM, 0x40);
    #else
    t = SetWindowTemplateFields(0, x, y, mugshot->width/8, mugshot->height/8, MUGSHOT_PALETTE_NUM, 0x40);
    #endif
    windowId = AddWindow(&t);
    sMugshotWindow = windowId + 1;
    
    LoadPalette(mugshot->palette, 16 * MUGSHOT_PALETTE_NUM, 32);
    CopyToWindowPixelBuffer(windowId, (const void*)mugshot->image, 0, 0);
    PutWindowRectTilemap(windowId, 0, 0, mugshot->width/8, mugshot->height/8);
    CopyWindowToVram(windowId, 3);
}

void DrawMugshot(void){
    const struct Mugshot* const mugshot = sMugshots + VarGet(VAR_0x8000);
    DrawMugshotCore(mugshot, mugshot->x, mugshot->y);
}

void DrawMugshotAtPos(void){
    DrawMugshotCore(sMugshots + VarGet(VAR_0x8000), VarGet(VAR_0x8001), VarGet(VAR_0x8002));
}


2. Create mugshots.h in include/constants/ and copy the following to it:
Spoiler:
#ifndef GUARD_CONSTANTS_MUGSHOTS_H
#define GUARD_CONSTANTS_MUGSHOTS_H

//Add your mugshot constants here

#endif


3. Open ld_script.txt and add .text and .rodata for mugshot.o:
Add this somewhere among the other src files' text sections (for example here):
src/mugshot.o(.text);
Add this somewhere among the other src files' rodata sections (for example here):
src/mugshot.o(.rodata);
4. Open sym_ewram.txt and add this to the end:
.include "src/mugshot.o"
5. Open data/event_scripts.s and add this after the includes at the top of the file:
#include "constants/mugshots.h"


2. Adding new mugshots
Spoiler:

Your mugshot images need to be 16-color indexed PNGs. Their width and height must be multiples of 8.

(OPTIONAL). Make a new folder called "mugshots" in the graphics folder for your images, you could also just place them in some other folder.

1. Add a constant for each image in include/constants/mugshots.h, each with a number one higher than the last:
#ifndef GUARD_CONSTANTS_MUGSHOT_H
#define GUARD_CONSTANTS_MUGSHOT_H

//Add your mugshot constants here
#define MUGSHOT_BLAINE 0
#define MUGSHOT_MAZE 1

#endif

2. Load the image's tiles and palette in src/mugshot.c, above the definition of sMugshots
static const u32 sMugshotImg_Blaine[] = INCBIN_U32("graphics/mugshots/blaine.4bpp.lz");
static const u16 sMugshotPal_Blaine[] = INCBIN_U16("graphics/mugshots/blaine.gbapal");

static const u32 sMugshotImg_Maze[] = INCBIN_U32("graphics/mugshots/maze.4bpp.lz");
static const u16 sMugshotPal_Maze[] = INCBIN_U16("graphics/mugshots/maze.gbapal");
The path in the incbin is the path to your image except "png" is replaced with "4bpp.lz" for the tiles and "gbapal" for the palette.


3. Create mugshot templates in sMugshots in src/mugshot.c using the images and palettes from the last step and the constants from the first step
static const struct Mugshot sMugshots[] = {
    //ADD YOUR MUGSHOTS HERE
    [MUGSHOT_BLAINE] = {.x = 16, .y = 5, .width = 80, .height = 72, .image = sMugshotImg_Blaine, .palette = sMugshotPal_Blaine},
    [MUGSHOT_MAZE] = {.x = 6, .y = 1, .width = 144, .height = 96, .image = sMugshotImg_Maze, .palette = sMugshotPal_Maze},
};
Note that x & y are tile coordinates, so the mugshot will be drawn at (8*x, 8*y).


3. Using mugshots in a script
Spoiler:

There are 3 new functions, which you can call with the callnative command:
DrawMugshot: draws mugshot that's id is in VAR_0x8000
DrawMugshotAtPos: draws mugshot that's id is in VAR_0x8000, at coordinates stored in VAR_0x8001 and VAR_0x8002
ClearMugshot: clears drawn mugshot

If a mugshot is drawn while one is already on the screen, the previous one is automatically cleared.

Example script:
setvar VAR_0x8000, MUGSHOT_BLAINE
callnative DrawMugshot
msgbox SomeText, MSGBOX_NPC
callnative ClearMugshot
end

SomeText:
.string "hi.$"
Seen 4 Hours Ago
Posted 2 Weeks Ago
1,382 posts
7.2 Years
void DrawMugshot();
void DrawMugshotAtPos();
void ClearMugshot();
Hiya, I guess you're a C++ programmer. Unlike C++ where empty parens mean "no parameters", in C what you've written is prototypes that can take any arguments at all (think something like how
...
is used by
printf
). You'd want to write, e.g.
void DrawMugshot(void);
. (It's not going to break anything if you don't, but it's pretty bad style and can mask errors when you get it wrong in header files!)

Lunos

Random Uruguayan User

Male
Montevideo (Uruguay)
Seen 10 Hours Ago
Posted 2 Days Ago
2,767 posts
12.7 Years
Locktarget Overworld scripting command (Em)
About an hour ago, SBird in Pret's Discord server brought up how the
lock
scripting command locks the movement of all the event objects on screen instead of just locking the event object that the Player is interacting with.
I decided to take a stab at it since it sounded like a fairly easy thing to address.

The changes can be checked in this commit:
https://github.com/LOuroboros/pokeemerald/commit/05f57351a0cf8a97134d7ef5067d4e68aab5bb1c

To quickly incorporate it into a project, you just have to track my repository via
git remote
and pull the branch where I did the modifications using
git pull
, like so:
git remote add lunos https://github.com/LOuroboros/pokeemerald
git pull lunos locktarget
Note: Depending on the feature branches you use in your project, you may need to adjust some of these values.
For example, if you added other new scripting commands to your project you'll need to change the internal ID of
locktarget
from 0xe3 to something else.


Pic:


And that's pretty much it.

Lunos

Random Uruguayan User

Male
Montevideo (Uruguay)
Seen 10 Hours Ago
Posted 2 Days Ago
2,767 posts
12.7 Years
Making Pokémon with Poison Heal be unaffected by poison in the overworld (Em)
Note: Poison Heal is an ability introduced in Gen. 4 and it's naturally not present in Pokemon Emerald by default.
This is mainly an optional thing you can add to projects that make use of DizzyEgg's battle_engine.


Earlier, Meister_anon from this forums' Discord server asked some tips because they wanted to make Pokémon with the Poison Heal ability not be affected by poison in the overworld, an effect that should have been implemented in the official games since its introduction, imo.
I decided to take a stab at it since it sounded like a fairly easy thing to do.

There are no commits this time. I won't make a branch because it's so utterly simple it doesn't warrant making one.
All you need to do is to go to the
DoPoisonFieldEffect
function in
src/field_poison.c
, and add the following check to the first
if
statement inside the
for
loop:
&& GetMonAbility(&gPlayerParty[i]) != ABILITY_POISON_HEAL
Don't forget to throw in a
#include "constants/abilities.h"
at the end of the header files list at the top of the file.
src/field_poison.c
can't recognize species abilities by default.

Video:


And that's pretty much it.
Seen 4 Hours Ago
Posted 22 Hours Ago
751 posts
170 Days
Excluding pokemon with Ability POISON_HEAL from overworld poison damage.

I started it, but most credit goes to Lunos, for the fix.

This works for all decomps far as I can tell, I've checked poke-emerald and poke-firered
this change goes in the field_poison.c file

Screenshot (1276).png
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Buffel Saft

Male
Seen 18 Hours Ago
Posted 18 Hours Ago
1,038 posts
7.8 Years
Remove the need to water berries on rainy Routes (Emerald)

Ever watered berry trees in the thunderstorm on Route 119 and thought "this makes no sense"?

This little tweak will make any berry trees on specified routes give out their maximum number of berries all the time, as if the weather watered them for you!

Go to src\berry.c and find the function named
CalcBerryYieldInternal
.
Add this code below the existing variable declarations:
u16 currentMap = ((gSaveBlock1Ptr->location.mapGroup) << 8 | gSaveBlock1Ptr->location.mapNum);

if (currentMap == MAP_ROUTE119 || currentMap == MAP_ROUTE120 || currentMap == MAP_ROUTE123)
        return max;
The maps used here are just examples, so you can change them to whatever you want. Also, this won't affect trees that have already grown - you'll need to plant new ones to see the effect.
Seen 12 Hours Ago
Posted 2 Weeks Ago
97 posts
3.6 Years
Prevent Map Fade With A Flag (Emerald)

This modification allows you to stop the screen from fading after loading a map - useful for cutscenes.



Spoiler:

1. Open include/constants/flags.h and rename one of the unused flags to FLAG_SYS_PREVENT_MAP_FADE
2. Open src/field_screen_effect.c and find the function WarpFadeInScreen, add the following if statements before the FadeScreen calls.
void WarpFadeInScreen(void)
{
    u8 previousMapType = GetLastUsedWarpMapType();
    switch (GetMapPairFadeFromType(previousMapType, GetCurrentMapType()))
    {
    case 0:
        FillPalBufferBlack();
        if(!FlagGet(FLAG_SYS_PREVENT_MAP_FADE))
            FadeScreen(FADE_FROM_BLACK, 0);
        break;
    case 1:
        FillPalBufferWhite();
        if(!FlagGet(FLAG_SYS_PREVENT_MAP_FADE))
            FadeScreen(FADE_FROM_WHITE, 0);
    }
}
Now just set the flag and the screen will stay black/white after a map loads. You can use the fadescreen command to fade the palette manually.

Here are the scripts used in the example GIF (note that the ON_TRANSITION script runs before the fading would start):
LittlerootTown_BrendansHouse_2F_MapScripts::
    map_script MAP_SCRIPT_ON_TRANSITION, LittlerootTown_BrendansHouse_2F_OnTransition
    map_script MAP_SCRIPT_ON_FRAME_TABLE, LittlerootTown_BrendansHouse_2F_OnFrame
    .byte 0

LittlerootTown_BrendansHouse_2F_OnFrame:
    map_script_2 VAR_TEMP_0, 0, LittlerootTown_BrendansHouse_2F_Lights
    .2byte 0

LittlerootTown_BrendansHouse_2F_OnTransition:
    setflag FLAG_SYS_PREVENT_MAP_FADE
    end

LittlerootTown_BrendansHouse_2F_Lights:
    msgbox Text_LittlerootTown_BrendansHouse_2F_Lights, MSGBOX_NPC
    fadescreen FADE_FROM_BLACK
    clearflag FLAG_SYS_PREVENT_MAP_FADE
    setvar VAR_TEMP_0, 1
    end

Text_LittlerootTown_BrendansHouse_2F_Lights:
    .string "...\p"
    .string "I can't see anything.\l"
    .string "Let's turn on the lights.$"
Seen 12 Hours Ago
Posted 2 Weeks Ago
97 posts
3.6 Years
I noticed that despite being updated recently, the starting post is missing quite a few older modifications.
Here is a list of them:
Spoiler:
Change the limbo slots' hardcoded Unown cry
Removing Badge Checks for HMs
"Move Pokémon" as first PSS option [EM]
Full National Dex [EM]
Gen. 8 Synchronize [EM]
Set Trainer's Levels Dynamically POKEEMERALD
Set Wild Pokémon's Levels Dynamically POKEEEMERALD
Remove Pokemon Data Encryption [Pokeemerald]
Move Item [EM]
(POKEEMERALD) Set a Trainer's Pokémon's abilities
Make eggs hatch at level 1 instead of 5
Allow specifying multi-choice options in scripts (Pokeemerald)
Always inherit nature when holding an Everstone
Destiny Knot IV Inheritance Implementation
[Pokeemerald] Saveblock Cleansing
Change the title screen music [EM]
Fixing Battle Factory opponent IV Glitch
Preserve Trainer Party Order
Headbutt tree for Pokeemerald
[Pokeemerald] Rock Climb
[PokeEmerald] Grindrunning For Easier Diagonal Movement
[Pokeemerald] Give Custom Mon
Pokemerald: Change bag sound with the ones from FR
[Pokeemerald] Repeated Field Medicine Use
Make reusable TMs unsellable
Obtain exp. points per catch [EM/FR]
[Emerald] Move camera to a coordinates and return camera to the player specials
Use variables with setmonmove
Flying Taxis
[PokeEmerald] Improving Switching AI
[PokeEmerald] Improving Switching AI #2
[Pokeemerald] Delete save file
[Pokeemerald] Make text speed-up like holding the A/B buttons automatically
[Pokeemerald] Make text autoscroll
[PokeEmerald] Improving the Pace of Battles
[Pokeemerald] Hidden Power type in summary screen
Make the game read the dynamic type of Hidden Power in battles (Em)
[Pokeemerald] Have the game display Hidden Power's true base power (for pre - Gen VI power calculations)
[Pokéemerald] - Register pokémon you battle at the Battle Frontier in the Pokédex
[Pokeemerald] Improved scrolling options menu with instant text, HP and EXP bar speeds and a metric unit option!
[Pokeemerald] Changing encounter groups with map scripts
[Pokefirered] Bag Sort Ported
[Pokefirered] Snow Weather fix ported
[Pokefirered] Auto-Run Ported
[pokefirered] Skip Controls Intro, First Battle Tutorial, Viridian Old Man, Flashbacks
[pokefirered] Remove redundant move grammar tables
[Pokefirered] Money Limit Ported
Adding the Fairy Type (Em)
[Pokeemerald] Auto-read signposts
Uniquely Shuffle Arrays
[Pokéfirered] Remove FRLG item use animation screen
Custom Battle Music Via Scripting (Emerald / Firered)
Implement a metatile behavior for Feebas encounters (Emerald)
[Pokeemerald]Spawn an invisible Player
Seen 4 Hours Ago
Posted 22 Hours Ago
751 posts
170 Days
Greetings everyone, I've got a pretty desirable fix I think, with credit and thanks to Buffel Saft, for helping me understand the function, I was able to figure a simple way of adding fairy type to hidden power.

It's just a simple C trick but this should work for firered and leaf green. Emerald doesn't seem to have mystery type so unfortunately this wouldn't work for it.

in pokefirered there's a line of code that essentially says, if hidden power type is greater or equal to type mystery add 1. (this is to remove mystery type from pool of possible results.

if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
  gBattleStruct->dynamicMoveType++;
the ++ is the plus 1.

now from messing around with effect spore I learned a trick of replacing an effect by setting it equal to another field. And that's what I did to get fairy in.
I replaced the above with this...

if (gBattleStruct->dynamicMoveType == TYPE_MYSTERY)
  gBattleStruct->dynamicMoveType = TYPE_FAIRY;
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Lunos

Random Uruguayan User

Male
Montevideo (Uruguay)
Seen 10 Hours Ago
Posted 2 Days Ago
2,767 posts
12.7 Years
Greetings everyone, I've got a pretty desirable fix I think, with credit and thanks to Buffel Saft, for helping me understand the function, I was able to figure a simple way of adding fairy type to hidden power.

It's just a simple C trick but this should work for firered and leaf green. Emerald doesn't seem to have mystery type so unfortunately this wouldn't work for it.

in pokefirered there's a line of code that essentially says, if hidden power type is greater or equal to type mystery add 1. (this is to remove mystery type from pool of possible results.

if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
  gBattleStruct->dynamicMoveType++;
the ++ is the plus 1.

now from messing around with effect spore I learned a trick of replacing an effect by setting it equal to another field. And that's what I did to get fairy in.
I replaced the above with this...

if (gBattleStruct->dynamicMoveType == TYPE_MYSTERY)
  gBattleStruct->dynamicMoveType = TYPE_FAIRY;
Emerald does have the Mystery Type. Every game up to HeartGold and SoulSilver have it, in fact, as it was removed in Black and White (1).
It's highly likely your modification will work on a clean copy of Pokeemerald normally, assuming Hidden Power's type can be set to Type Mystery normally.
Seen 4 Hours Ago
Posted 2 Weeks Ago
1,382 posts
7.2 Years
if (gBattleStruct->dynamicMoveType == TYPE_MYSTERY)
  gBattleStruct->dynamicMoveType = TYPE_FAIRY;
I might be mistaken, but won't this basically replace Hidden Power Dark with Fairy?

My thinking is that before the numbers worked like this:
 i | i + 1
 9 | TYPE_FIRE (10)
10 | TYPE_WATER (11)
11 | TYPE_GRASS (12)
12 | TYPE_ELECTRIC (13)
13 | TYPE_PSYCHIC (14)
14 | TYPE_ICE (15)
15 | TYPE_DRAGON (16)
16 | TYPE_DARK (17)
But now that you've replaced ++ (i.e. + 1) with turning
TYPE_MYSTERY
(8) into
TYPE_FAIRY
(18) you get this:
 i | i == 8 ? 18 : i
 9 | TYPE_FAIRY (18)
10 | TYPE_FIRE (10)
11 | TYPE_WATER (11)
12 | TYPE_GRASS (12)
13 | TYPE_ELECTRIC (13)
14 | TYPE_PSYCHIC (14)
15 | TYPE_ICE (15)
16 | TYPE_DRAGON (16)
I think you both need to generate a number that's 1 bigger and remap
TYPE_MYSTERY
to
TYPE_FAIRY
to have all the types. This might actually be working on your thread? I saw you and Buffel Saft made some changes to how
dynamicMoveType
was calculated.
Seen 4 Hours Ago
Posted 22 Hours Ago
751 posts
170 Days
I might be mistaken, but won't this basically replace Hidden Power Dark with Fairy?

But now that you've replaced ++ (i.e. + 1) with turning
TYPE_MYSTERY
(8) into
TYPE_FAIRY
(18) you get this:
 i | i == 8 ? 18 : i
 9 | TYPE_FAIRY (18)
10 | TYPE_FIRE (10)
11 | TYPE_WATER (11)
12 | TYPE_GRASS (12)
13 | TYPE_ELECTRIC (13)
14 | TYPE_PSYCHIC (14)
15 | TYPE_ICE (15)
16 | TYPE_DRAGON (16)
I think you both need to generate a number that's 1 bigger and remap
TYPE_MYSTERY
to
TYPE_FAIRY
to have all the types. This might actually be working on your thread? I saw you and Buffel Saft made some changes to how
dynamicMoveType
was calculated.
possibly, I'm sending you a message from my thread now. but if it means anything type mystery is actually 0x9, not 0x8.


edit:
looked through things, mgriffin is right, there's one other change that needs to be made for this to work correctly.

This is the original.
gBattleStruct->dynamicMoveType = (15 * typeBits) / 63 + 1;
if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY)
++gBattleStruct->dynamicMoveType;
This is what it needs to be changed to.
gBattleStruct->dynamicMoveType = (16 * typeBits) / 63 + 1;
if (gBattleStruct->dynamicMoveType == TYPE_MYSTERY)
gBattleStruct->dynamicMoveType = TYPE_FAIRY;
Pretty confident about that, if you want to go over the explanations yourself you can check out my thread on the topic Here.

also making this change *may* affect the odds/conditions for certain types appearing I can't confirm that as its theory and I'm not good with bitwise anyway.

And a last note to cover all the bases , while the theory for this is sound, I haven't been able to test yet, so I don't recommend using the trick to try to add any more than
1 type.

Because of the way types have to be added, I am unsure if increasing the number would cause you to run afoul of the non-battle types.
There could be simple ways around that, if you're knowledgeable/savvy but I just didn't feel comfortable leaving people without that warning.
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

Seen 2 Days Ago
Posted 2 Weeks Ago
9 posts
155 Days
Curve low-leveled wild Pokemon (PokeEmerald)

The level-scaling logic I used is in `src/pokemon.c` in GetPartyMonCurvedLevel(). You will probably want to edit it; the logic I have here was to demonstrate it works, not designed around game balance.

Locations that can have pokemon with a very wide range of levels will continue to do so; the level ranges are moved up so that the maximum level for wild pokemon is now either the max level in the encounter table, or (2 * curvedLevel + max)/3, whichever is higher. This weights the levels closer to the curve than the original, while maintaining a distinction between low-level areas and high-level ones.

https://github.com/surskitty/pokeemerald/commit/192bc233a0ef7523289a0314946e9b0af23aac83

git remote add surskitty https://github.com/surskitty/pokeemerald
git cherry-pick 192bc233a0ef7523289a0314946e9b0af23aac83
ETA: Vital Spirit et al weren't functioning correctly. That's fixed now. Adjusted level scaling logic for slightly better scaling.

Lunos

Random Uruguayan User

Male
Montevideo (Uruguay)
Seen 10 Hours Ago
Posted 2 Days Ago
2,767 posts
12.7 Years
Wonder Trade (Em)
I've been working on this for the past 8 days or so, and after so many small issues that I solved thanks to the help of the gang at ROM Hacking Hideout, I think it's finally good to go.
This is a Pokeemerald port of Deokishisu's Wonder Trade system for Pokeruby, modified to suit my personal tastes and made compatible with the Pokeemerald-expansion.
Everything is pretty easy to modify as there's a handful of comments here and there, and the code in itself is easy to read too, so y'all can edit the whole thing as you see fit.

To incorporate this into a project automatically, you'll have to track my repository via
git remote
and pull my wonder_trade branch using
git pull
.
In other words:
git remote add lunos https://github.com/LOuroboros/pokeemerald
git pull lunos wonder_trade
Video:


I tried to test it as thoroughly as I could, but I wouldn't be surprised if for whatever reason invalid species or items could be generated.
I appreciate any and all tests.

Bugs:
-Pokémon who can Mega Evolve or who can evolve into a species that can Mega Evolve, can't carry Y Mega Stones. Yes, this only applies to the Charmander Line, but still. (Fixed!)

And that's pretty much it.
Seen 2 Days Ago
Posted 2 Weeks Ago
9 posts
155 Days
Improved Editing Trainer Parties [EM]

Provides control over most aspects of NPC trainers and homogenizes party types. Based off part of Syreldar's hack. Thanks to UltimaSoul for helping me get it to work.

How to use:

git remote add surskitty https://github.com/surskitty/pokeemerald
git pull surskitty trainer_control
src/data/trainer_parties.h will need all structs changed to TrainerMon and src/data/trainers.h needs to have .TrainerMon instead of .NoItemDefaultMoves et al. Those are both already applied to vanilla, but if you've done substantial edits, keep your versions and then do the find-replace to change structs and .party type.

More detailed usage notes are over here.
This has recently had some refactoring to save space and fix bugs.

I also have made a simpler version that's more space-efficient and does not involve manually selecting IVs and EVs. Instead, you set .build, .hiddenPower, and .difficulty to get an effort and IV setup that does roughly what you want. It's more limited but I'm personally finding it much better suited to my needs.

.build can be TRAINER_MON_DEFENSES, TRAINER_MON_SPEED_PHYS, TRAINER_MON_SPEED_SPEC, TRAINER_MON_HP_DEF, TRAINER_MON_HP_SPDEF, TRAINER_MON_PHYS, TRAINER_MON_SPEC, and determines EV allocation. Both of the speed options raise the corresponding attack stat. A default build at high difficulty allocates effort points evenly.
.difficulty TRAINER_EASIEST, TRAINER_EASY, TRAINER_MEDIUM only decide amount of IVs; TRAINER_MEDIUM is maxed. TRAINER_HARD, TRAINER_HARDER, and TRAINER_HARDEST allocate EVs and have maxed IVs. TRAINER_MAX is not player legal and assigns 255 EVs to each stat.
.hiddenPower takes TYPE_ constants. TYPE_NORMAL is default and gives either worst, best, or average IVs, depending on difficulty. The IV spreads used can be found in include/pokemon_iv_spreads.h .

git remote add surskitty https://github.com/surskitty/pokeemerald
git pull surskitty trainer_control_v2

Lunos

Random Uruguayan User

Male
Montevideo (Uruguay)
Seen 10 Hours Ago
Posted 2 Days Ago
2,767 posts
12.7 Years
Evolution moves (FR)
I ported UltimaSoul and Sagiri/Zeturic's implementation of the evolution moves mechanic which I brought here sometime ago to Pokefirered because I was bored.

The changes can be checked in this commit:
https://github.com/LOuroboros/pokefirered/commit/c5c27fe5838e10af7bdd9d85cf5f3cd4dc08aba7

To quickly incorporate it into a project, you just have to track my repository via
git remote
and pull the branch where I did the modifications using
git pull
, like so:
git remote add lunos https://github.com/LOuroboros/pokefirered
git pull lunos evo_moves
Pic:


And that's pretty much it.

Robinlukke

Badass Blastoise

Male
Seen 1 Day Ago
Posted 2 Weeks Ago
44 posts
10.7 Years
[pokeemerald] Feed any number of pokéblocks

All changes are made at src/use_pokeblock.c:

From the following code, delete what is in RED:

Spoiler:
static void UsePokeblockMenu(void)
{
    bool8 loading;

    switch (sInfo->mainState)
    {
    case STATE_HANDLE_INPUT:
        if (JOY_HELD(DPAD_UP))
        {
            PlaySE(SE_SELECT);
            UpdateSelection(TRUE);
            DestroyConditionSparkleSprites(sMenu->sparkles);
            sInfo->mainState = STATE_UPDATE_SELECTION;
        }
        else if (JOY_HELD(DPAD_DOWN))
        {
            PlaySE(SE_SELECT);
            UpdateSelection(FALSE);
            DestroyConditionSparkleSprites(sMenu->sparkles);
            sInfo->mainState = STATE_UPDATE_SELECTION;
        }
        else if (JOY_NEW(B_BUTTON))
        {
            PlaySE(SE_SELECT);
            sInfo->mainState = STATE_CLOSE;
        }
        else if (JOY_NEW(A_BUTTON))
        {
            PlaySE(SE_SELECT);

            // If last item, selected Cancel. Otherwise selected mon
            if (sMenu->info.curSelection == sMenu->info.numSelections - 1)
                sInfo->mainState = STATE_CLOSE;
            else
                sInfo->mainState = STATE_CONFIRM_SELECTION;
        }
        break;
    case STATE_UPDATE_SELECTION:
        loading = sMenu->info.loadNewSelection();
        if (!loading)
            sInfo->mainState = STATE_HANDLE_INPUT;
        break;
    case STATE_2:
        break;
    case STATE_CLOSE:
        SetUsePokeblockCallback(CloseUsePokeblockMenu);
        break;
    case STATE_4:
        break;
    case STATE_CONFIRM_SELECTION:
        AskUsePokeblock();
        sInfo->mainState++;
        break;
    case STATE_HANDLE_CONFIRMATION:
        switch (HandleAskUsePokeblockInput())
        {
        case 1: // NO
        case MENU_B_PRESSED:
            sInfo->mainState = STATE_HANDLE_INPUT;
            break;
        case 0: // YES
            if (IsSheenMaxed())
            {
                PrintWontEatAnymore();
                sInfo->mainState = STATE_WAIT_MSG;
            }
            else
            {
                SetUsePokeblockCallback(FeedPokeblockToMon);
            }
            break;
        }
        break;
    case STATE_WAIT_MSG:
        if (JOY_NEW(A_BUTTON | B_BUTTON))
        {
            EraseMenuWindow();
            sInfo->mainState = STATE_HANDLE_INPUT;
        }
        break;
    }
}
static void AddPokeblockToConditions(struct Pokeblock *pokeblock, struct Pokemon *mon)
{
    u16 i;
    s16 cstat;
    u8 data;

    if (GetMonData(mon, MON_DATA_SHEEN) != 255)
    {
        CalculatePokeblockEffectiveness(pokeblock, mon);
        for (i = 0; i < FLAVOR_COUNT; i++)
        {
            data = GetMonData(mon, sMonDataConditions[i]);
            cstat = data +  sInfo->pokeblockStatBoosts[i];
            if (cstat < 0)
                cstat = 0;
            if (cstat > 255)
                cstat = 255;
            data = cstat;
            SetMonData(mon, sMonDataConditions[i], &data);
        }

        cstat = (u8)(GetMonData(mon, MON_DATA_SHEEN)) + pokeblock->feel;
        if (cstat > 255)
            cstat = 255;

        data = cstat;
        SetMonData(mon, MON_DATA_SHEEN, &data);
    }
}
3DS Friend Code: 0920-1704-7407
Friend Safari:

Seen 4 Hours Ago
Posted 22 Hours Ago
751 posts
170 Days
probably not something many would want to use, but if you want to remove all instances of critical hits, you can do so with 1 change.

https://github.com/pret/pokefirered/blob/master/src/battle_script_commands.c#L1219

this is from pokefirered but the same change can be made in other decomps,

in the critcalc function make sure gCritMultiplier is set to 1 for both cases.

That one change prevents crits altogether, that includes bypassing the damage increase, the crit stat bypass, & avoiding the crit message popup.

Since all of those things, check for if the multiplier is equal to 2.
The A-non Team



Trevenant
Lv. 100 @ 306
Points: 70
Challenge: Souls of the Damned
Legendary: TBA

Chandelure
Lv. 100 @ 213
Points: 100
Challenge: N/A
Legendary: Entei

Rapidash
Lv. 100 @ 497
Points: 70
Challenge: N/A
Legendary: Entei

Flareon
Lv. 100 @ 708
Points: 70
Challenge: TBA
Legendary: TBA

Budew
Lv. 100 @ 794
Points: 100
Challenge: TBA
Legendary: TBA

takyon

Villain

Seen 1 Hour Ago
Posted 4 Days Ago
13 posts
3.4 Years

Move Item [EM]


Spoiler:

Adds a
MOVE
option to the
ITEM
menu which allows you to move held items directly between Pokémon in your party, instead of having to use the bag as a middle man.

I've had this up in my pokeemerald fork for a while, but I never got around to writing it up here. Since I originally made it, the relevant functions got actual names in pokeemerald, so I'm taking this as an opportunity to update it and post it here.

There's going to be multiple changes required across multiple files, so I'm going to try to keep them in a logical order that minimizes jumping between files. Also, at the end of each step, pokeemerald will still be in a compilable state if done properly.

In the code blocks throughout this post, new lines of code are highlighted with the color green. Red highlights denote deleted lines of code. If a line of code isn't highlighted either color, it is only included for context.

Adding the strings



In
include/strings.h
, add the following to the end of the file:

Spoiler:
extern const u8 gMenuText_Move[];
extern const u8 gText_MoveItemWhere[];
extern const u8 gText_XsYAnd[];
extern const u8 gText_XsYWereSwapped[];

#endif // GUARD_STRINGS_H


In
src/strings.c
, add the following to the end of the file:

Spoiler:

const u8 gMenuText_Move[] = _("MOVE");
const u8 gText_MoveItemWhere[] = _("Move item to where?");
const u8 gText_XsYAnd[] = _("{STR_VAR_1}'s\n{STR_VAR_2} and\l");
const u8 gText_XsYWereSwapped[] = _("{STR_VAR_1}'s\l{STR_VAR_2} were swapped!{PAUSE_UNTIL_PRESS}");


Adding the code



You'll need to add a forward declaration for
CursorCb_MoveItem
in
src/party_menu.c
, like so:

Spoiler:
static void CursorCb_Summary(u8);
static void CursorCb_Switch(u8);
static void CursorCb_Cancel1(u8);
static void CursorCb_Item(u8);
static void CursorCb_Give(u8);
static void CursorCb_TakeItem(u8);
static void CursorCb_MoveItem(u8);
static void CursorCb_Mail(u8);
static void CursorCb_Read(u8);
static void CursorCb_TakeMail(u8);
static void CursorCb_Cancel2(u8);
static void CursorCb_SendMon(u8);
static void CursorCb_Enter(u8);
static void CursorCb_NoEntry(u8);
static void CursorCb_Store(u8);
static void CursorCb_Register(u8);
static void CursorCb_Trade1(u8);
static void CursorCb_Trade2(u8);
static void CursorCb_Toss(u8);
static void CursorCb_FieldMove(u8);


At the end of
src/party_menu.c
, add the following:

Spoiler:

void CursorCb_MoveItemCallback(u8 taskId)
{
    u16 item1, item2;
    u8 buffer[100];

    if (gPaletteFade.active || sub_81221EC())
        return;

    switch (PartyMenuButtonHandler(&gPartyMenu.slotId2))
    {
    case 2:     // User hit B or A while on Cancel
        HandleChooseMonCancel(taskId, &gPartyMenu.slotId2);
        break;
    case 1:     // User hit A on a Pokemon
        // Pokemon can't give away items to eggs or themselves
        if (GetMonData(&gPlayerParty[gPartyMenu.slotId2], MON_DATA_IS_EGG)
            || gPartyMenu.slotId == gPartyMenu.slotId2)
        {
            PlaySE(SE_HAZURE);
            return;
        }

        PlaySE(SE_SELECT);
        gPartyMenu.action = PARTY_ACTION_CHOOSE_MON;

        // look up held items
        item1 = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM);
        item2 = GetMonData(&gPlayerParty[gPartyMenu.slotId2], MON_DATA_HELD_ITEM);

        // swap the held items
        SetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM, &item2);
        SetMonData(&gPlayerParty[gPartyMenu.slotId2], MON_DATA_HELD_ITEM, &item1);

        // update the held item icons
        UpdatePartyMonHeldItemSprite(
            &gPlayerParty[gPartyMenu.slotId],
            &sPartyMenuBoxes[gPartyMenu.slotId]
        );

        UpdatePartyMonHeldItemSprite(
            &gPlayerParty[gPartyMenu.slotId2],
            &sPartyMenuBoxes[gPartyMenu.slotId2]
        );

        // create the string describing the move
        if (item2 == ITEM_NONE)
        {
            GetMonNickname(&gPlayerParty[gPartyMenu.slotId2], gStringVar1);
            CopyItemName(item1, gStringVar2);
            StringExpandPlaceholders(gStringVar4, gText_PkmnWasGivenItem);
        }
        else
        {
            GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
            CopyItemName(item1, gStringVar2);
            StringExpandPlaceholders(buffer, gText_XsYAnd);

            StringAppend(buffer, gText_XsYWereSwapped);
            GetMonNickname(&gPlayerParty[gPartyMenu.slotId2], gStringVar1);
            CopyItemName(item2, gStringVar2);
            StringExpandPlaceholders(gStringVar4, buffer);
        }

        // display the string
        DisplayPartyMenuMessage(gStringVar4, TRUE);

        // update colors of selected boxes
        AnimatePartySlot(gPartyMenu.slotId2, 0);
        AnimatePartySlot(gPartyMenu.slotId, 1);

        // return to the main party menu
        schedule_bg_copy_tilemap_to_vram(2);
        gTasks[taskId].func = Task_UpdateHeldItemSprite;
        break;
    }
}

void CursorCb_MoveItem(u8 taskId)
{
    struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];

    PlaySE(SE_SELECT);

    // delete old windows
    PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
    PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);

    if (GetMonData(mon, MON_DATA_HELD_ITEM) != ITEM_NONE)
    {
        gPartyMenu.action = PARTY_ACTION_SWITCH;

        // show "Move item to where" in bottom left
        DisplayPartyMenuStdMessage(PARTY_MSG_MOVE_ITEM_WHERE);
        // update color of first selected box
        AnimatePartySlot(gPartyMenu.slotId, 1);

        // set up callback
        gPartyMenu.slotId2 = gPartyMenu.slotId;
        gTasks[taskId].func = CursorCb_MoveItemCallback;
    }
    else
    {
        // create and display string about lack of hold item
        GetMonNickname(mon, gStringVar1);
        StringExpandPlaceholders(gStringVar4, gText_PkmnNotHolding);
        DisplayPartyMenuMessage(gStringVar4, TRUE);

        // return to the main party menu
        schedule_bg_copy_tilemap_to_vram(2);
        gTasks[taskId].func = Task_UpdateHeldItemSprite;
    }
}


Open
include/constants/party_menu.h
, and look for
#define
s of the form
PARTY_MSG_WHATEVER
. We need to add a
#define
for
PARTY_MSG_MOVE_ITEM_WHERE
like so:

Spoiler:
#define PARTY_MSG_CHOOSE_MON                0
#define PARTY_MSG_CHOOSE_MON_OR_CANCEL      1
#define PARTY_MSG_CHOOSE_MON_AND_CONFIRM    2
#define PARTY_MSG_MOVE_TO_WHERE             3 
#define PARTY_MSG_TEACH_WHICH_MON           4
#define PARTY_MSG_USE_ON_WHICH_MON          5
#define PARTY_MSG_GIVE_TO_WHICH_MON         6
#define PARTY_MSG_NOTHING_TO_CUT            7
#define PARTY_MSG_CANT_SURF_HERE            8
#define PARTY_MSG_ALREADY_SURFING           9
#define PARTY_MSG_CURRENT_TOO_FAST          10
#define PARTY_MSG_ENJOY_CYCLING             11
#define PARTY_MSG_ALREADY_IN_USE            12
#define PARTY_MSG_CANT_USE_HERE             13
#define PARTY_MSG_NO_MON_FOR_BATTLE         14
#define PARTY_MSG_CHOOSE_MON_2              15
#define PARTY_MSG_NOT_ENOUGH_HP             16
#define PARTY_MSG_X_MONS_ARE_NEEDED         17
#define PARTY_MSG_MONS_CANT_BE_SAME         18
#define PARTY_MSG_NO_SAME_HOLD_ITEMS        19
#define PARTY_MSG_UNUSED                    20
#define PARTY_MSG_DO_WHAT_WITH_MON          21
#define PARTY_MSG_RESTORE_WHICH_MOVE        22
#define PARTY_MSG_BOOST_PP_WHICH_MOVE       23
#define PARTY_MSG_DO_WHAT_WITH_ITEM         24
#define PARTY_MSG_DO_WHAT_WITH_MAIL         25
#define PARTY_MSG_ALREADY_HOLDING_ONE       26
#define PARTY_MSG_MOVE_ITEM_WHERE           27
#define PARTY_MSG_NONE                      127


Updating relevant data



Everything from here on will be in
src/data/party_menu.h
.

Look for an unnamed
enum
with values such as
MENU_SUMMARY
. Add
MENU_MOVE_ITEM
to the
enum
's list of values, like so:

Spoiler:
enum
{
    MENU_SUMMARY,
    MENU_SWITCH,
    MENU_CANCEL1,
    MENU_ITEM,
    MENU_GIVE,
    MENU_TAKE_ITEM,
    MENU_MOVE_ITEM,
    MENU_MAIL,
    MENU_TAKE_MAIL,
    MENU_READ,
    MENU_CANCEL2,
    MENU_SHIFT,
    MENU_SEND_OUT,
    MENU_ENTER,
    MENU_NO_ENTRY,
    MENU_STORE,
    MENU_REGISTER,
    MENU_TRADE1,
    MENU_TRADE2,
    MENU_TOSS,
    MENU_FIELD_MOVES,
};


Now, we need to add an entry to the
sCursorOptions
array. Add an entry for
MENU_MOVE_ITEM
like so:

Spoiler:
struct
{
    const u8 *text;
    TaskFunc func;
} static const sCursorOptions[] =
{
    [MENU_SUMMARY] = {gText_Summary5, CursorCb_Summary},
    [MENU_SWITCH] = {gText_Switch2, CursorCb_Switch},
    [MENU_CANCEL1] = {gText_Cancel2, CursorCb_Cancel1},
    [MENU_ITEM] = {gText_Item, CursorCb_Item},
    [MENU_GIVE] = {gMenuText_Give, CursorCb_Give},
    [MENU_TAKE_ITEM] = {gText_Take, CursorCb_TakeItem},
    [MENU_MOVE_ITEM] = {gMenuText_Move, CursorCb_MoveItem},
    [MENU_MAIL] = {gText_Mail, CursorCb_Mail},
    [MENU_TAKE_MAIL] = {gText_Take2, CursorCb_TakeMail},
    [MENU_READ] = {gText_Read2, CursorCb_Read},
    [MENU_CANCEL2] = {gText_Cancel2, CursorCb_Cancel2},
    [MENU_SHIFT] = {gText_Shift, CursorCb_SendMon},
    [MENU_SEND_OUT] = {gText_SendOut, CursorCb_SendMon},
    [MENU_ENTER] = {gText_Enter, CursorCb_Enter},
    [MENU_NO_ENTRY] = {gText_NoEntry, CursorCb_NoEntry},
    [MENU_STORE] = {gText_Store, CursorCb_Store},
    [MENU_REGISTER] = {gText_Register, CursorCb_Register},
    [MENU_TRADE1] = {gText_Trade4, CursorCb_Trade1},
    [MENU_TRADE2] = {gText_Trade4, CursorCb_Trade2},
    [MENU_TOSS] = {gMenuText_Toss, CursorCb_Toss},
    [MENU_FIELD_MOVES + FIELD_MOVE_CUT] = {gMoveNames[MOVE_CUT], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_FLASH] = {gMoveNames[MOVE_FLASH], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_ROCK_SMASH] = {gMoveNames[MOVE_ROCK_SMASH], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_STRENGTH] = {gMoveNames[MOVE_STRENGTH], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_SURF] = {gMoveNames[MOVE_SURF], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_FLY] = {gMoveNames[MOVE_FLY], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_DIVE] = {gMoveNames[MOVE_DIVE], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_WATERFALL] = {gMoveNames[MOVE_WATERFALL], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_TELEPORT] = {gMoveNames[MOVE_TELEPORT], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_DIG] = {gMoveNames[MOVE_DIG], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_SECRET_POWER] = {gMoveNames[MOVE_SECRET_POWER], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_MILK_DRINK] = {gMoveNames[MOVE_MILK_DRINK], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_SOFT_BOILED] = {gMoveNames[MOVE_SOFT_BOILED], CursorCb_FieldMove},
    [MENU_FIELD_MOVES + FIELD_MOVE_SWEET_SCENT] = {gMoveNames[MOVE_SWEET_SCENT], CursorCb_FieldMove},
};


Next, find the definition of
sActionStringTable
. Add an entry to the end like so:

Spoiler:
static const u8 *const sActionStringTable[] =
{
    [PARTY_MSG_CHOOSE_MON]             = gText_ChoosePokemon,
    [PARTY_MSG_CHOOSE_MON_OR_CANCEL]   = gText_ChoosePokemonCancel,
    [PARTY_MSG_CHOOSE_MON_AND_CONFIRM] = gText_ChoosePokemonConfirm,
    [PARTY_MSG_MOVE_TO_WHERE]          = gText_MoveToWhere,
    [PARTY_MSG_TEACH_WHICH_MON]        = gText_TeachWhichPokemon,
    [PARTY_MSG_USE_ON_WHICH_MON]       = gText_UseOnWhichPokemon,
    [PARTY_MSG_GIVE_TO_WHICH_MON]      = gText_GiveToWhichPokemon,
    [PARTY_MSG_NOTHING_TO_CUT]         = gText_NothingToCut,
    [PARTY_MSG_CANT_SURF_HERE]         = gText_CantSurfHere,
    [PARTY_MSG_ALREADY_SURFING]        = gText_AlreadySurfing,
    [PARTY_MSG_CURRENT_TOO_FAST]       = gText_CurrentIsTooFast,
    [PARTY_MSG_ENJOY_CYCLING]          = gText_EnjoyCycling,
    [PARTY_MSG_ALREADY_IN_USE]         = gText_InUseAlready_PM,
    [PARTY_MSG_CANT_USE_HERE]          = gText_CantUseHere,
    [PARTY_MSG_NO_MON_FOR_BATTLE]      = gText_NoPokemonForBattle,
    [PARTY_MSG_CHOOSE_MON_2]           = gText_ChoosePokemon2,
    [PARTY_MSG_NOT_ENOUGH_HP]          = gText_NotEnoughHp,
    [PARTY_MSG_X_MONS_ARE_NEEDED]      = gText_PokemonAreNeeded,
    [PARTY_MSG_MONS_CANT_BE_SAME]      = gText_PokemonCantBeSame,
    [PARTY_MSG_NO_SAME_HOLD_ITEMS]     = gText_NoIdenticalHoldItems,
    [PARTY_MSG_UNUSED]                 = gText_EmptyString2,
    [PARTY_MSG_DO_WHAT_WITH_MON]       = gText_DoWhatWithPokemon,
    [PARTY_MSG_RESTORE_WHICH_MOVE]     = gText_RestoreWhichMove,
    [PARTY_MSG_BOOST_PP_WHICH_MOVE]    = gText_BoostPp,
    [PARTY_MSG_DO_WHAT_WITH_ITEM]      = gText_DoWhatWithItem,
    [PARTY_MSG_DO_WHAT_WITH_MAIL]      = gText_DoWhatWithMail,
    [PARTY_MSG_ALREADY_HOLDING_ONE]    = gText_AlreadyHoldingOne,
    [PARTY_MSG_MOVE_ITEM_WHERE]        = gText_MoveItemWhere,
};


And finally, we need to adjust the
ITEM
menu so that it actually includes our new menu option.

Find the definition of
sPartyMenuAction_GiveTakeItemCancel
, and modify it:

Spoiler:
static const u8 sPartyMenuAction_GiveTakeItemCancel[] = {MENU_GIVE, MENU_TAKE_ITEM, MENU_CANCEL2};
static const u8 sPartyMenuAction_GiveTakeItemCancel[] = {MENU_GIVE, MENU_TAKE_ITEM, MENU_MOVE_ITEM, MENU_CANCEL2};


Find the definition of
sItemGiveTakeWindowTemplate
and modify it:

Spoiler:
static const struct WindowTemplate sItemGiveTakeWindowTemplate =
{
    .bg = 2,
    .tilemapLeft = 23,
    .timemapTop = 13,
    .tilemapTop = 11,
    .width = 6,
    .height = 6,
    .height = 8,
    .paletteNum = 14,
    .baseBlock = 0x39D,
};


And that's it. Let me know if you have problems.

Edit: Oh, since I forgot to mention, my code here is licensed under the 0BSD license. In short, use it for whatever. Attribution is appreciated, but not required.
I'd like to point out that sub_81221EC is now called MenuHelpers_CallLinkSomething()
(this change was in https://github.com/pret/pokeemerald/commit/74edaed4265cc7e964a5383c3e0fb8ef256f2bf8)
and SE_HAZURE is now called SE_FAILURE
and 2 instances of schedule_bg_copy_tilemap_to_vram should be ScheduleBgCopyTilemapToVram (https://github.com/pret/pokeemerald/commit/da3062097a2372539dd7d4b5a43a2098deafc1cb)

[PokeEmerald] Surfboard instead of HM Surf

Spoiler:


Adds in a Surfboard that lets the player just walk into water.
No long, annoying animations~


How to use:
  • Add the code to your pokeemerald decomp as described below.
  • Give the player the item ITEM_SURFBOARD
  • Have the player walk into water
  • The player will now be surfing on the water

How to add:
Same case for this, MUS_NAMINORI is now MUS_RG_SURF
The changes for music file names are here: https://github.com/pret/pokeemerald/commit/30142411799650c17367ce4652269e8ecca7ceef

For future reference for pret renaming, use git log -n 1 -S <insert your problem function/variable here>

If this shouldn't be here I apologise but these need to be updated to current pret naming conventions.
-

Lunos

Random Uruguayan User

Male
Montevideo (Uruguay)
Seen 10 Hours Ago
Posted 2 Days Ago
2,767 posts
12.7 Years
Preset Playable Character Name (Em)
I was bored, so after seeing a post presenting a different way to achieve this result in "Whack a Hack", I was inspired to come up with a variant of it myself.
As the title suggests, this makes it so the game won't let you select a name for the playable characters of the game.
Instead, their names are forced set by us.

To incorporate this into a project automatically, you'll have to track my repository via
git remote
and pull my preset_player_name branch using
git pull
.
In other words:
git remote add lunos https://github.com/LOuroboros/pokeemerald
git pull lunos preset_player_name
Showcase:


I think it's fairly obvious by just looking at the code, but the strings that manage the playable characters' names are
gText_DefaultMaleName
and
gText_DefaultFemaleName
.

And that's pretty much it.