You are not logged in.
UPDATE: it works!
I hope you aren't all sick of me yet :P I'm just really eager to learn how these games work, and I've been learning quite a lot from here! Anyways, as the title implies, I am trying to add Foresight to Red version. I'm pretty sure I have converted the code correctly, but whenever I use the attack, the game just freezes. Let me walk you through my process. I'm sorry for how verbose this is, I just wanted to make this as detailed as possible.
First, I went in to wram.asm and added a W_PLAYERBATTSTATUS4 and W_ENEMYBATTSTATUS4 to d06e and d073 respectively. This bytes seemed not to be used, so I thought it might be okay. Anyways, after that, I added in some variables in to the end of status_constants:
;volatile statuses 4 HasNightmare EQU 0 UsingCurse EQU 1 UsingProtect EQU 2 BeenIdentified EQU 3 UsingPerishSong EQU 4 UsingEndure EQU 5 HasAnEncore EQU 6 UsedDefenseCurl EQU 7 ;unused
....these are just placeholders for eventual other moves of course, but what we care about is BeenIdentified, $3. I also replaced the type matchup table with the exact one pokecrystal used.
anyways, I went and looked at the original code for Foresight in pokecrystal's code, and it LOOKS like there are only two critical components to it. They look like the following:
BattleCommand_Foresight: ; 376a0 ; foresight ld a, [AttackMissed] and a jr nz, .failed call CheckHiddenOpponent jr nz, .failed ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVarAddr bit SUBSTATUS_IDENTIFIED, [hl] jr nz, .failed set SUBSTATUS_IDENTIFIED, [hl] call AnimateCurrentMove ld hl, IdentifiedText jp StdBattleTextBox .failed jp FailForesight ; 376c2
which was inside foresight.asm, and:
.TypesLoop: ld a, [hli] cp $ff jr z, .end ; foresight cp $fe jr nz, .SkipForesightCheck ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVar bit SUBSTATUS_IDENTIFIED, a jr nz, .end jr .TypesLoop .SkipForesightCheck: cp b jr nz, .SkipType ld a, [hl] cp d jr z, .GotMatchup cp e jr z, .GotMatchup jr .SkipType .GotMatchup: etc....
which is part of the code that determines the type of a move for effectiveness. ANYWAY! I rewrote both of those, inserting the latter in to the type loop in pokered's Core.asm:
.loop ld a,[hli] ; a = "attacking type" of the current type pair cp a,$ff jr z,.done ; foresight cp $fe jr nz, .SkipForesightCheck ;jp nz, PrintDidntAffectText ;ld bc, W_ENEMYBATTSTATUS4 ld a,[W_ENEMYBATTSTATUS4] bit BeenIdentified, a jr nz, .done jr .loop .SkipForesightCheck: cp b ; does move type match "attacking type"? jr nz,.nextTypePair etc......
and then the actual effect code, in e_2.asm .....why there? I dunno. Do you have a better idea? Please advise.
ForesightEffect_: ; 376a0 ; foresight callab MoveHitTest ld a, [W_MOVEMISSED] ; W_MOVEMISSED and a jr nz, .failed ld a, [W_ENEMYBATTSTATUS1] bit Invulnerable, a jr nz, .failed ld a,[W_ENEMYBATTSTATUS4] bit BeenIdentified, [hl] jr nz, .failed set BeenIdentified, [hl] call PlayMoveAnimation ld hl, IdentifiedText jp PrintText .failed jp PrintButItFailedText_ IdentifiedText: ; 3fb49 (f:7b49) TX_FAR _IdentifiedText db "@" ; 376c2
....now just from a glance it LOOKS like I rewrote these correctly, but.........the game freezes whenever I use the attack. In addition to obviously adding the text for the command, I also added ForesightEffect to the effect pointer table (as well as made an effect constant for it) but then also defined this in core.asm:
ForesightEffect: ld hl, ForesightEffect_ ld b, BANK(ForesightEffect_) jp Bankswitch
the same way stuff like transform does it, etc.
Now, I'm pretty sure I'm understanding how the original code works, and functionally, it LOOKS like I rewrote it to work in red version correctly. But like I said, the game freezes. I'm sure there'a glaringly obvious error in what I've done and I'm hoping someone will point that out for me. Particularly, I'm pretty confused by what BATTLE_VARS_SUBSTATUS1_OPP and GetBattleVar are supposed to be, so I tried to aproximate their functionality? I SUSPECT that the issue is NOT in the routine from core.asm, as the game functions perfectly when the move is not used, but then again I could be wrong. Sorry for how verbose this post is, like I said, I just wanted to be as detailed as possible.
Last edited by KeiTaRo (2017-03-12 03:02:36)
Well you're trying to call PlayMoveAnimation as if it was in the same bank as your code, but it isn't. So that's making it call unrelated data from the bank it is in, and that's probably at least part of what's causing the crash.
Also, I see your code only cares about the opponent having been foresighted, with no checks whatsoever to allow the opponent to use Foresight on you. Might want to fix that. Also, you are trying to set a bit in hl as if you had loaded hl with W_ENEMYBATTSTATUS4, but you haven't, you loaded register a with whatever value was there. So that means you are trying to set a bit in whatever hl currently holds.
Check them out on Github
EDIT: here it is in action, if anyone is curious, heh.
AUGH! I swear, every time I feel like I'm making progress, really basic things like this trip me up. Indeed, fixing those things made this code work flawlessly. Adding the enemy/player check code broke it, but then I realized a simple mistake there as well (the failed text was being called from a different bank, and broke the game if you used Foresight twice) Thanks for looking at the code for me. For those who are wondering, here is the final finished routine for that effect, if you want to use Foresight in your own hack (maybe this will help someone else learn too!):
ForesightEffect_: ; foresight ld a, [H_WHOSETURN] and a ld a, [W_PLAYERBATTSTATUS1] jr nz, .hitTest ld a, [W_ENEMYBATTSTATUS1] .hitTest callab MoveHitTest bit Invulnerable, a jr nz, .failed ld a, [W_MOVEMISSED] ; W_MOVEMISSED and a jr nz, .failed ld hl, W_PLAYERBATTSTATUS4 ld a, [H_WHOSETURN] and a jr z, .foresightEffect ld hl, W_ENEMYBATTSTATUS4 .foresightEffect] bit BeenIdentified, [hl] jr nz, .failed set BeenIdentified, [hl] callab PlayCurrentMoveAnimation ld hl, IdentifiedText jp PrintText .failed ld c, $32 call DelayFrames ld hl, PrintButItFailedText_ ld b, BANK(PrintButItFailedText_) jp Bankswitch IdentifiedText: ; 3fb49 (f:7b49) TX_FAR _IdentifiedText db "@"
and the modified loop, which goes in AdjustDamageForMoveType in core.asm:
.loop ld a,[hli] ; a = "attacking type" of the current type pair cp a,$ff jr z,.done ; foresight cp $fe jr nz, .SkipForesightCheck ld a, [H_WHOSETURN] and a ld a, [W_ENEMYBATTSTATUS4] jr nz, .beenIdentified ld a, [W_PLAYERBATTSTATUS4] .beenIdentified bit BeenIdentified, a jr nz, .done jr .loop .SkipForesightCheck: cp b ; does move type match "attacking type"? jr nz,.nextTypePair ld a,[hl] ; a = "defending type" of the current type pair cp d ; does type 1 of defender match "defending type"? jr z,.matchingPairFound cp e ; does type 2 of defender match "defending type"? jr z,.matchingPairFound jr .nextTypePair
if anyone uses this in their own hack, let me know if you encounter any issues with it. I noticed Crystal also did some stuff with foresight in the accuracy check code, but it doesn't seem necessary? I'm pretty happy that I could get this working at least...! Thanks again for your help.
One minor thing I am not completely sure about is [H_WHOSETURN] ... aware that it returns the value of who's turn it is, and based on existing code in the game it seemed like the Enemy's would come before the player in the routine....this is not always the case though, as you can see in the difference between my two code chunks. I guess what I'm saying is, how do I know what order to check the parameters in, other than trial and error?
Last edited by KeiTaRo (2017-03-11 04:03:32)