You are not logged in.
I'm helping my friend out with a hack and we are trying to recreate the Pinkan Berry effect from the Orange Islands anime.
I theorized the best way to do this would be to create a Pinkan state, like Sleep or Paralysis, to do this. I thought it might be possible since certain moves can temporarily change a sprite's palette, such as defense curl or minimize.
After some digging, all I can really find are these calls for animations:
anim_obp0
followed by a value such as $e4 or $54. I do not know what these are referencing.
Here is an image illustrating what I'm attempting to do.
Essentially, it would be a universal palette for every sprite, as a state. It can be cured if an item was coded to do so. Feeding a Pokemon the berry would induce this state.
If anyone has some ideas let me know :p
Offline
Sorry for the double post.
So far, I have added the palette itself and included it within the palette pointers for pokemon, hopefully this is a good first step.
PinkanPalette: INCLUDE "gfx/pics/pinkan.pal"
I'm going to see how the shiny code works and see if instead of checking stats, it can check a status like poison does and see if I can work with that.
EDIT: Yeah, that doesn't really seem to help at all. Does anyone have an idea of how I can do this?
Last edited by Kuroko Aizawa (2016-09-10 21:12:49)
Offline
Using a status effect would either prevent Pinkan Pokémon from being poisoned/burned/etc, or make them lose their color when they get status.
Crystal has a CaughtData byte for each Pokémon that stores its caught location (look at wram.asm, main.asm:SetCaughtData, and event/poke_seer.asm for how it works). You could check this byte when viewing the stat screen, or for a wild battle, check the player's current location and use the Pinkan palette if they're on that island. If you don't care about Poké Seer accuracy, have the Pinkan Berry edit the caught location.
I would suggest editing gfx/pics/palette_pointers.asm so that palette #0 has normal pink and shiny pink, then edit gfx/color.asm:GetMonPalettePointer to only execute "add hl, bc" if the Pokémon is not supposed to be pink.
Last edited by Rangi (2016-09-10 22:04:12)
My projects on GitHub:
• Polished Map 4.5.4 or 2.5.4++
• Tilemap Studio 3.2.2
• Pokémon Polished Crystal 2.2.0 or 3.0.0 beta
• Pokémon Red★/Blue★: Space World Edition 2020-11-01
Offline
Using a status effect would either prevent Pinkan Pokémon from being poisoned/burned/etc, or make them lose their color when they get status.
Crystal has a CaughtData byte for each Pokémon that stores its caught location (look at wram.asm, main.asm:SetCaughtData, and event/poke_seer.asm for how it works). You could check this byte when viewing the stat screen, or for a wild battle, check the player's current location and use the Pinkan palette if they're on that island. If you don't care about Poké Seer accuracy, have the Pinkan Berry edit the caught location.
I would suggest editing gfx/pics/palette_pointers.asm so that palette #0 has normal pink and shiny pink, then edit gfx/color.asm:GetMonPalettePointer to only execute "add hl, bc" if the Pokémon is not supposed to be pink.
Yeah, it's supposed to be a temporary effect, in the anime it's explained that it's temporary, and only permanent if they have eaten it their whole life. I thought it would be neat to make it a temporary thing. I want it to purposely be a status, which, yes, would prevent them from being burned or poisoned, frozen, etc.
If you don't care about Poké Seer accuracy, have the Pinkan Berry edit the caught location.
I would suggest editing gfx/pics/palette_pointers.asm so that palette #0 has normal pink and shiny pink, then edit gfx/color.asm:GetMonPalettePointer to only execute "add hl, bc" if the Pokémon is not supposed to be pink.
Would this allow every Pokemon to reference the same palette? That sounds like a good idea and while not quite what I was thinking that could work just as well.
Offline
Would this allow every Pokemon to reference the same palette? That sounds like a good idea and while not quite what I was thinking that could work just as well.
Yes, they'd all be referencing the 0th/first palette. Just check for PNK status instead of location and your plan should work.
Also, it would be neat if you encounter wild Pokémon that already have the PNK status on Pinkan Island. Kind of like how Pokémon in Headbutt trees are sometimes asleep. (Look around "call CheckSleepingTreeMon" in battle/core.asm.)
Last edited by Rangi (2016-09-10 22:34:03)
My projects on GitHub:
• Polished Map 4.5.4 or 2.5.4++
• Tilemap Studio 3.2.2
• Pokémon Polished Crystal 2.2.0 or 3.0.0 beta
• Pokémon Red★/Blue★: Space World Edition 2020-11-01
Offline
Would this allow every Pokemon to reference the same palette? That sounds like a good idea and while not quite what I was thinking that could work just as well.
Yes, they'd all be referencing the 0th/first palette. Just check for PNK status instead of location and your plan should work.
Also, it would be neat if you encounter wild Pokémon that already have the PNK status on Pinkan Island. Kind of like how Pokémon in Headbutt trees are sometimes asleep. (Look around "call CheckSleepingTreeMon" in battle/core.asm.)
Haha, yes! That's exactly what I was thinking. The whole reason I went with this approach xD
Offline
I would suggest editing gfx/pics/palette_pointers.asm so that palette #0 has normal pink and shiny pink, then edit gfx/color.asm:GetMonPalettePointer to only execute "add hl, bc" if the Pokémon is not supposed to be pink.
I just have another quick question about this, will I have to add a function to check for the PNK status, because it's looking like this:
GetMonPalettePointer:
ld l, a
ld h, $0
add hl, hl
add hl, hl
add hl, hl
ld bc, PokemonPalettes
add hl, bc
ret
GetMonNormalOrShinyPalettePointer:
push bc
call GetMonPalettePointer
pop bc
push hl
call CheckShininess
pop hl
ret nc
rept 4
inc hl
endr
ret
How do I tell it "Pokémon is not supposed to be pink?"
Offline
Haha, yes! That's exactly what I was thinking. The whole reason I went with this approach xD
Cool. :) Have you gotten far mapping out the Orange Islands? Are there any official sources to refer to, besides the overview map and the anime?
My projects on GitHub:
• Polished Map 4.5.4 or 2.5.4++
• Tilemap Studio 3.2.2
• Pokémon Polished Crystal 2.2.0 or 3.0.0 beta
• Pokémon Red★/Blue★: Space World Edition 2020-11-01
Offline
Haha, yes! That's exactly what I was thinking. The whole reason I went with this approach xD
Cool. :) Have you gotten far mapping out the Orange Islands? Are there any official sources to refer to, besides the overview map and the anime?
My friend is pretty much going off of the anime, but we've been citing some stuff from Naranja as well, because I think Serg!o did a lot right with his hack that we can use. I don't think anything has been mapped yet, but I did make a world map for him (which I believe I've posted in the custom graphics thread).
Offline
How do I tell it "Pokémon is not supposed to be pink?"
Before bc gets overwritten with PokemonPalettes in GetMonPalettePointer, it contains the address of the Pokémon's DVs (which CheckShininess uses to determine shininess). Pokémon data structures are defined with the box_struct and party_struct macros, themselves defined in macros/wram.asm. You can see that Status is 10 bytes past DVs, so you could write some routine like this:
CheckPink:
push bc
rept 10 ; maybe 9 or 11, not sure about off-by-one errors here
inc bc
endr
ld a, [bc]
; now compare a to PNK and return 0 or 1
pop bc
ret
Since status conditions only exist outside the PC, things get a bit complicated. You can either add a check for it the player is viewing a deposited Pokémon, and if so don't use the pink palette; or move the status into the box_struct instead of one of the Poké Seer bytes.
You can start by ignoring the box/party distinction, but then when you view a deposited Pokémon's stats, it will be reading whatever byte is just past the box_struct and treating it as the status. Not a major problem, really.
Last edited by Rangi (2016-09-10 23:07:15)
My projects on GitHub:
• Polished Map 4.5.4 or 2.5.4++
• Tilemap Studio 3.2.2
• Pokémon Polished Crystal 2.2.0 or 3.0.0 beta
• Pokémon Red★/Blue★: Space World Edition 2020-11-01
Offline
The PC shouldn't be too big of an issue, since it's a temporary status anyway, I think I'm starting to understand. After implementing the function, I should have to use:
call CheckPink
somewhere in GetMonPalettePointer, but in order to tell it what to do if it's not pink, won't I have to add another function like ".NotShiny"? I apologize, I'm not very good with assembly, referencing the crib sheet I have just tells me what a function does, although bluntly.
EDIT: Oh boy xD So now it seems there's no built in way to just inflict status on pokemon out of battle, so there goes that plan. I'm trying to add a function for the Pinkan Berry but it seems there is only item capability of curing stat effects and not giving them :s
I think I'll go ahead and make it based off of location for now.
Last edited by Kuroko Aizawa (2016-09-10 23:49:15)
Offline
in order to tell it what to do if it's not pink, won't I have to add another function like ".NotShiny"?
Yes, you'd do something like this:
GetMonPalettePointer:
call CheckPink ; return 0 in a if not pink, 1 if pink
jr nz, .pink
ld l, a
ld h, $0
add hl, hl
add hl, hl
add hl, hl
ld bc, PokemonPalettes
add hl, bc
ret
.pink:
ld hl, PokemonPalettes
ret
My projects on GitHub:
• Polished Map 4.5.4 or 2.5.4++
• Tilemap Studio 3.2.2
• Pokémon Polished Crystal 2.2.0 or 3.0.0 beta
• Pokémon Red★/Blue★: Space World Edition 2020-11-01
Offline
So now it seems there's no built in way to just inflict status on pokemon out of battle, so there goes that plan. I'm trying to add a function for the Pinkan Berry but it seems there is only item capability of curing stat effects and not giving them :s
Then write one! Look at the code for MiracleBerry and base it on that. The core action would be:
ld a, MON_STATUS
call GetPartyParamLocation
ld a, (1 << PNK)
ld [hl], a
Edit: I haven't tested this, but here's a try:
PinkanBerry:
; Choose a Pokémon to use it on
ld b, PARTYMENUACTION_HEALING_ITEM
call UseItem_SelectMon
; Exit early if the player canceled
jp c, PinkanBerry_ExitMenu
; Get the chosen Pokémon's current status
ld a, MON_STATUS
call GetPartyParamLocation
; If it's already pink, no effect
ld a, [hl]
and (1 << PNK)
jp nz, NoEffectMessage
; Make it pink
ld a, (1 << PNK)
ld [hl], a
; Play a sound effect
call Play_SFX_FULL_HEAL
; Describe the effect
; TODO:
; • add PARTYMENUTEXT_MAKE_PINK after the other PARTYMENUTEXT consts in constants/item_constants.asm
; • add your text to .MenuActionTexts in engine.party_menu.asm
ld b, PARTYMENUTEXT_MAKE_PINK
ld [PartyMenuActionText], a
call ItemActionTextWaitButton
; Use up the Pinkan Berry
call UseDisposableItem
call ClearPalettes
ret
PinkanBerry_ExitMenu:
; wItemEffectSucceeded of 0 means it was canceled
; it's set to 1 by default before calling PinkanBerry
xor a
ld [wItemEffectSucceeded], a
call ClearPalettes
ret
Last edited by Rangi (2016-09-11 00:07:48)
My projects on GitHub:
• Polished Map 4.5.4 or 2.5.4++
• Tilemap Studio 3.2.2
• Pokémon Polished Crystal 2.2.0 or 3.0.0 beta
• Pokémon Red★/Blue★: Space World Edition 2020-11-01
Offline
It's still not referencing anything properly yet, but at least I know the palette is working. Going to look into the seer some more to see if I can work out how to make it check for location code. I don't see any instance of it making an exception for a certain location, so that bit is going to be tricky. I think Route 29 for starters will be good for a test map.
EDIT: Hmm, okay. Give me a few minutes, I'll see if I can sort it out xD
Last edited by Kuroko Aizawa (2016-09-11 00:07:21)
Offline
const PARTYMENUTEXT_MAKE_PINK
.Text_MakePink:
text_jump MakePinkText
db "@"
MakePinkText::
text_from_ram StringBuffer1
text " has"
line "turned pink!"
done
I've done all of the above. I think all that's left now is somehow connecting checkpink values to the PNK status effect.
Last edited by Kuroko Aizawa (2016-09-11 01:34:25)
Offline
I think this would work:
CheckPink:
push bc
rept 10
inc bc
endr
ld a, [bc]
cp (1 << PNK)
pop bc
ret
My projects on GitHub:
• Polished Map 4.5.4 or 2.5.4++
• Tilemap Studio 3.2.2
• Pokémon Polished Crystal 2.2.0 or 3.0.0 beta
• Pokémon Red★/Blue★: Space World Edition 2020-11-01
Offline
Ok, so I tried that out, and everything is still #0's palette by default. Also, the Pinkan Berry is not usable, it can only be given to pokemon to hold. This might be due to me replacing Item19 with the PinkanBerry.
I'm still looking at it, I'll update this post if I figure it out.
EDIT: So I've got a functioning berry in the game, when you use it, it says "(Pokemon) was cured of poison."
Not sure why it's displaying that text, but on top of that it doesn't seem to do anything, as my cyndaquil was still normal status. I'll keep plugging at it :)
Last edited by Kuroko Aizawa (2016-09-11 01:46:24)
Offline
Ok, so I think it was a typo on my part, when defining the status itself, but upon fixing that I'm hit with some error regarding ALL_STATUS:
ERROR: main.asm(254) -> engine/color.asm(874) :
Expression must be 8-bit
ERROR: main.asm(355) -> items/item_effects.asm(2841) :
Expression must be 8-bit
ERROR: main.asm(355) -> items/item_effects.asm(2845) :
Expression must be 8-bit
ERROR: main.asm(1712) -> battle/core.asm(4597) :
Expression must be 8-bit
ERROR: main.asm(1712) -> battle/core.asm(4628) :
Expression must be 8-bit
ERROR: main.asm(1712) -> battle/core.asm(4629) :
Expression must be 8-bit
C:\cygwin\usr\local\bin\rgbasm.exe: Assembly aborted in pass 1 (6 errors)!
make: *** [Makefile:52: main.o] Error 1
My guess is that somewhere PNK isn't defined as a status and the game is trying to figure out why it isn't included :s back to searching.
EDIT: After some more messing around, I'm wondering if the engine can't support any more statuses? The conflicting code is most certainly this:
; status
const_value SET 3
const PSN
const BRN
const FRZ
const PAR
const SLP ; 7 turns
const PNK
ALL_STATUS EQU (1 << PSN) + (1 << BRN) + (1 << FRZ) + (1 << PAR) + (1 << PNK) + SLP
I think I'm going to just work with location, instead of status. This is proving to be a lot of work for something that could be abused anyway (as in, status infliction immunity).
Last edited by Kuroko Aizawa (2016-09-11 02:16:11)
Offline
Try this:
const_value SET 2
const PNK
const PSN
const BRN
const FRZ
const PAR
const SLP ; 7 turns
Status conditions are stored in one 8-bit byte. Bits 3 to 7 are used for PSN through SLP. Pretty sure 0, 1, and 2 are unused.
Last edited by Rangi (2016-09-11 02:32:23)
My projects on GitHub:
• Polished Map 4.5.4 or 2.5.4++
• Tilemap Studio 3.2.2
• Pokémon Polished Crystal 2.2.0 or 3.0.0 beta
• Pokémon Red★/Blue★: Space World Edition 2020-11-01
Offline
Try this:
const_value SET 2 const PNK const PSN const BRN const FRZ const PAR const SLP ; 7 turns
Status conditions are stored in one 8-bit byte. Bits 3 to 7 are used for PSN through SLP. Pretty sure 0, 1, and 2 are unused.
Ok, now we are getting somewhere. So, it ended up doing something, however, it said my cyndaquil was cured of paralysis, and then it put it to SLP xD So we are definitely on the right track here.
EDIT: by changing "ld b, PARTYMENUTEXT_MAKE_PINK" to "ld a, PARTYMENUTEXT_MAKE_PINK", I was able to get it to display the correct text. All that's left is getting the correct status afflicted. Then I can try to fix the code that checks for the status.
Last edited by Kuroko Aizawa (2016-09-11 03:04:33)
Offline
So I kept trying to rearrange the constants of the statuses but nothing is really working. The only way I can get the status afflicted to change to something else is by putting PNK at the end, and then it will default to whatever is first in the order. However, if PNK is first in order, it will default to SLP. I don't understand, maybe there is somewhere else I need to define PNK.
; status
const_value SET 2
const PSN
const BRN
const FRZ
const PAR
const SLP ; 7 turns
const PNK
EDIT: So here's an update. I have the PNK status inflicting normally, which is great, but when you go into battle, after selecting a move the status becomes SLP, I've tested this with other status afflictions and others do not have this effect. Still looking into it.
Last edited by Kuroko Aizawa (2016-09-11 17:14:21)
Offline
Whoever defined the SLP constant did not think it through. Unlike the other constants, SLP is a mask for the number of turns to be asleep (up to 7).
SLP EQU 7
const_value = 3
const PSN
const BRN
const FRZ
const PAR
const PNK
Last edited by comet (2016-09-11 17:24:43)
Offline
Whoever defined the SLP constant did not think it through. Unlike the other constants, SLP is a mask for the number of turns to be asleep (up to 7).
SLP EQU 7 const_value = 3 const PSN const BRN const FRZ const PAR const PNK
Beautiful, that fixed it, Comet!
That means we are at the last step, which is fixing the check here:
CheckPink:
push bc
rept 10
inc bc
endr
ld a, [bc]
cp (1 << PNK)
pop bc
ret
GetMonPalettePointer:
call CheckPink ; return 0 in a if not pink, 1 if pink
jr nz, .pink
ld l, a
ld h, $0
add hl, hl
add hl, hl
add hl, hl
ld bc, PokemonPalettes
add hl, bc
ret
.pink:
ld hl, PokemonPalettes
ret
Going to need to brush up on my z80 for this, but let's see if I can figure out what's not working here.
EDIT: Correct me if I'm wrong, but I think the issue is in CheckPink. I don't see anything wrong with GetMonPalettePointer.
EDIT2: As far as I can tell it's just checking for status with nothing to relay it to, but I could be mistaken. I suck at this lol.
Last edited by Kuroko Aizawa (2016-09-11 17:49:41)
Offline
Your logic appears to be backwards. Try changing "jr nz, .pink" to "jr z, .pink" instead. The cp function returns z if the comparison matched, and nz if it did not. Also, a =/= 0 if they are pink, a = whatever their status byte is regardless of their status. You loaded a with it, and did a comparison. Nothing about that changed the value in a, all it did was change the z and c flags depending on the results of that comparison. The value in a will still be the same as what you loaded it with before the comparison.
Last edited by Mateo (2016-09-11 18:11:47)
I am not very active on this forum. I only pop in from time to time.
Offline
CheckPink:
push af
push bc
rept 9
inc bc
endr
ld a, [bc]
cp (1 << PNK)
pop bc
pop af
ret
GetMonPalettePointer:
call CheckPink ; return 0 in a if not pink, 1 if pink
jr z, .pink
ld l, a
ld h, $0
add hl, hl
add hl, hl
add hl, hl
ld bc, PokemonPalettes
add hl, bc
ret
.pink:
ld hl, PokemonPalettes
ret
We've nearly got it done now, this code seems to apply to all of the sprites and fixes the palette issues we had, however it still isn't checking for the PNK status properly yet. So close xD
Offline