Simple Modifications Directory Page 11

Started by Avara December 30th, 2018 2:48 PM
  • 118691 views
  • 340 replies
Seen 1 Day Ago
Posted 1 Day Ago
195 posts
4.2 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 1 Week Ago
Posted 1 Week Ago
1,390 posts
7.8 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 1 Hour Ago
Posted 1 Day Ago
2,891 posts
13.3 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 1 Hour Ago
Posted 1 Day Ago
2,891 posts
13.3 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 15 Hours Ago
Posted 3 Days Ago
856 posts
1.1 Years
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

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

Entei
Hatch @ 793
Level 100 @ 1,018
Shiny: No
Points: 100

Buffel Saft

Male
Seen 2 Days Ago
Posted 1 Week Ago
1,407 posts
8.4 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
GetBerryCountByBerryTreeId()
.
Replace it with the following:
static u8 GetBerryCountByBerryTreeId(u8 id)
{
    struct BerryTree *tree = GetBerryTreeInfo(id);
    const struct Berry *berry = GetBerryInfo(tree->berry);
    u16 currentMap = gMapHeader.regionMapSectionId;

    if (currentMap == MAPSEC_ROUTE_119 || currentMap == MAPSEC_ROUTE_120 || currentMap == MAPSEC_ROUTE_123)
        return berry->maxYield;
    else
        return gSaveBlock1Ptr->berryTrees[id].berryYield;
}
Then you'll probably need to add
#include constants/map_groups.h 
at the top of src\berry.c so the compiler recognizes the map names.

The maps used here are just examples, so you can change them to whatever condition you want.
Seen 1 Day Ago
Posted 1 Day Ago
195 posts
4.2 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 1 Day Ago
Posted 1 Day Ago
195 posts
4.2 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 15 Hours Ago
Posted 3 Days Ago
856 posts
1.1 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;
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

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

Entei
Hatch @ 793
Level 100 @ 1,018
Shiny: No
Points: 100

Lunos

Random Uruguayan User

Male
Montevideo (Uruguay)
Seen 1 Hour Ago
Posted 1 Day Ago
2,891 posts
13.3 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 1 Week Ago
Posted 1 Week Ago
1,390 posts
7.8 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 15 Hours Ago
Posted 3 Days Ago
856 posts
1.1 Years
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

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

Entei
Hatch @ 793
Level 100 @ 1,018
Shiny: No
Points: 100

Seen July 12th, 2021
Posted July 10th, 2021
11 posts
1 Years
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 1 Hour Ago
Posted 1 Day Ago
2,891 posts
13.3 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 July 12th, 2021
Posted July 10th, 2021
11 posts
1 Years
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 1 Hour Ago
Posted 1 Day Ago
2,891 posts
13.3 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 10 Hours Ago
Posted 10 Hours Ago
47 posts
11.3 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 15 Hours Ago
Posted 3 Days Ago
856 posts
1.1 Years
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

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

Entei
Hatch @ 793
Level 100 @ 1,018
Shiny: No
Points: 100

takyon

Villain

Seen December 13th, 2021
Posted June 23rd, 2021
17 posts
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 1 Hour Ago
Posted 1 Day Ago
2,891 posts
13.3 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.
Male
Seen 10 Hours Ago
Posted 3 Days Ago
228 posts
5.9 Years
[Pokeemerald] Remove warp's fadescreen effect

There might come a day where you want to fade the screen to black in a script and play a fanfare, print a message, or do something else, and immediately warp. If you try this in vanilla emerald, the screen will fade FROM black, and then back TO black. Instead, let's create a flag that removes the fadescreen part of the warp script commands and we can do something like this:

Before:


After:


Here's a wiki post with the simple instructions.
Male
Seen 10 Hours Ago
Posted 3 Days Ago
228 posts
5.9 Years
[Pokeemerald] Flag to force Shiny Pokemon

This lets you create a flag that, when set, will cause newly created pokemon (with the player's OTID) to be shiny.

Check out the wiki post for information

Example script:
givemon SPECIES_TORCHIC, 13, 0
givemon SPECIES_ARON, 12, 0
setflag FLAG_SHINY_CREATION
givemon SPECIES_MUDKIP, 15, 0
clearflag FLAG_SHINY_CREATION

Lunos

Random Uruguayan User

Male
Montevideo (Uruguay)
Seen 1 Hour Ago
Posted 1 Day Ago
2,891 posts
13.3 Years
Global Field Tints (Em)
I was bored, so I ported what in Pokefirered is known as
gGlobalFieldTintMode
.
What does this let you do? It allows you to put a tint on the elements shown on screen.
It should be a nice complement for flashback scenes and stuff like that.
Normally, in FRLG it's purely used in the flashbacks of the Quest Log feature of the game, which plays when you resume a savefile.

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


To cast a tint, simply call either
Script_SetGrayscaleTint
or
Script_SetSepiaTint
in your script.
Once you're done, call
Script_RemoveTint
to remove the tint.

Bugs:
-Palette glitches when walking in the tall grass
Fixed.

-The rain looks black in game
I've no idea how to solve this and I also don't feel like working on this any longer.
Any valuable information on how to fix this or ideas about what to try would be well received.

And that's pretty much it.
Seen 1 Week Ago
Posted November 27th, 2021
46 posts
3.1 Years
[Pokeemerald] Updated debug menu!



Now with:
-SOUND!!!
-easy way to run custom scripts
-poison all party mons
-max money & max coins
-trigger daycare egg (no more running like crazy to test daycare changes)
-completly fill pc with pokemon

Also lots of small fixes!

Credits for the additions:
Sierraffinity
Jaizu

Spoiler:

[Pokeemerald] Fully functional debug menu with Flags, Vars, Items, Pokemon and more!
This is my implementation of a debug menu based on Ketsuban's tutorial and some code from Pyredrid, AsparagusEduardo and Ghoulslash.


Features:
Spoiler:

Utility:
Heal player party
Clock: check and set

Fly to all cities: ----------------------------Warp to any map warp: --------------Check saveblock space:

Check weekday: does nothing, left in as a simple spot to add some test stuff for you guys

Change Trainer name, gender and OIT:



Flags:
Added some usefull debug flags like ignore collision, no wild encounters (Inmortal) and no trainers attacking you.
Toggle any flag ingame: -------------Toggle specific usefull flags


Vars:
Read and change any vars ingame:


Give:
Items:


All TMs:


Pokemon in 2 versions:
---Simple: only takes the ID (source code, not ingame) and a level:

---Complex: ID, level, shiny?, nature and ability (including hidden with PE), individual IVs and up to 4 custom moves.



How to:
Add and clone it into your repo:
git remote add xaman https://github.com/TheXaman/pokeemerald/
git pull xaman tx_debug_system
make clean
make debugging

Access ingame:
From now one if you want the menu to show up you have to run your make command with the addition parameter: debugging or debugging _modern, for example make debugging -j8. Those parameters already include DINFO=1.
To access ingame press R + Start.



That it, now enjoy and if you find any bugs or if you write some cool additions you think others could profit from, please let me know in this threat, via pm or over on github!


Credits: If you use this, you have to give credit to all following people!
TheXaman
Ketsuban
Pyredrid
AsparagusEduardo
Ghoulslash
ExboSeed