alright hello let's look at this function really quickly. it's a mess, so buckle up
https://github.com/pret/pokeemerald/blob/master/src/pokemon.c#L4641
we're gonna scroll all the way down to
https://github.com/pret/pokeemerald/blob/master/src/pokemon.c#L4816
this is where the ev's and shtuff are located. the pp and other stuff.
that case 4 is referencing the 4th gItemEffect element.
so the stuff that goes under [4] = ITEM4_... | ITEM4_... are hardcoded constants that the code reads. you can not move the ITEM5 stuff to ITEM4 without rewriting the code. if you did, it would be treated as if it were like a revive or something.
that being said, you don't have to make any sacrifices; every time that something uses a variable amount as specified on some parameter, it uses itemEffect[var_3C], incrementing var_3C after the effect of the vitamin is applied.
var_3C at its instantiation is set to 6.
https://github.com/pret/pokeemerald/blob/master/include/constants/item_effects.h#L52
if you look in the gItemEffect constant definitions, everything element 6 and above is something specified by the item itself. i believe that the vitamins will probably have like 10 there, a potion will have 20, a hyper potion 100, a max potion 0xFF, etc.
so let's actually take a look at the hondew berry right quick:
const u8 gItemEffect_HondewBerry[10] = {
[5] = ITEM5_EV_SPATK | ITEM5_FRIENDSHIP_ALL,
[6] = -10,
[7] = 10,
[8] = 5,
[9] = 2,
};
basically, the way you can think of this is that the game will apply everything in the order the code finds it
that doesn't make sense by itself so i'll explain:
the code starts with [0], finds nothing, then moves on to [1]
the code finds nothing in [1], then moves on to [2]
and bam nothing there either
this continues until [5] where it finds ITEM5_EV_SPATK. note that this is the least significant bitfield that it encounters, i.e. ITEM5_EV_SPATK is less than ITEM5_FRIENDSHIP_ALL
so it then takes a look at itemEffect[var_3C]. var_3C is currently 6 (because the code found nothing that required a variable value in [0] through [4]), so it takes a look at itemEffect[6] (-10), and essentially adds that to the current EV value in special attack. there's obviously code for getting the evs down to 100 if the evs are above 100, but that's beside the point
var_3C being used for the first time, it is incremented to 7.
it continues searching through [5], where it hits ITEM5_FRIENDSHIP_ALL, which is really actually ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID | ITEM5_FRIENDSHIP_HIGH.
what this means?
it hits ITEM5_FRIENDSHIP_LOW. it checks if the mon's friendship is low, applies itemEffect[var_3C] if it is, then increments var_3C
i.e. [7] is the value used for ITEM5_FRIENDSHIP_LOW.
this then makes [8] the value used for ITEM5_FRIENDSHIP_MID and then [9] the value used for ITEM5_FRIENDSHIP_HIGH
does that make sense overall?
edit: to then actually go into it, let's say i wanted my hondew berry to heal my pokemon halfway as well as revive it while also giving my pokemon 10 ev's in both hp and special defense. and screw it, we'll only let it raise our pokemon's friendship by 50 if and only if the mon is in the middle friendship range:
const u8 gItemEffect_HondewBerry[10] = { // this 10 is actually the highest number you use below +1. it is 10 here because i only go to [9]
[4] = ITEM4_REVIVE | ITEM4_HEAL_HP | ITEM4_EV_HP, // ITEM4_EV_HP < ITEM4_HEAL_HP so it is checked first, and then ITEM4_REVIVE doesn't take a parameter (no incrementing var_3C)
[5] = ITEM5_EV_SPDEF | ITEM5_FRIENDSHIP_MID,
[6] = 10, // raise hp ev by 10
[7] = ITEM6_HEAL_HALF, // heal hp by half
[8] = 10, // raise spdef ev by 10
[9] = 50; // raise friendship by 50 only if in middle range
};
one other thing to note is that for some reason [4] checks for pp raise before anything else. the code just checks for it before going in on the loop for some reason (see
here)