You are not logged in.
Pages: 1
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)
Offline
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.
Current Projects:
Pokémon Christmas
Pokémon Red++
Offline
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)
Offline
Pages: 1