You are not logged in.
Since I'm "thinking out loud" in this thread more than asking one question, I'm just going to tweak it a little and make a running list of the bugs, the questions, and the solutions. Perhaps others will find this useful~ - Nate, 10/18/2016
- Pokemon Status Screen Blinks; modification made to allow unique stat screen sprites. Old issue, that Pokemon sprites would not update with change in party position, fixed by reloading sprite data. Doing so causes screen to "blink", and we see for a split second the map, no sprites, before the whole status screen & party are redrawn.
- TeamMoves and LoneMoves; Core system updated to separate Pokemon & Trainer values to allow up to 255 Pokemon in game. TeamMoves and LoneMoves appear not to work now. Trainer ID and Team are calculated correctly but do not appear to impact the checks regarding adding moves to the Pokemon. PARTIAL FIX: On Rival battles, ensure all LoneMove code is included AFTER the team is fully selected (link); still working on the TeamMoves...
FIXED BUGS & SOLUTIONS
- "Pokedex Off"; Had to do with the NUM_POKEMON bytes and flags. Solution was to adapt the 255+ Pokemon project's Pokedex solution (link)
- "Status Screen Pallet"; Hardcode setting after changing data order to Pokedex order set the pallets for many Pokemon on the status screen to VICTREBELL, the last Pokemon in the normal data order. (link) - Thanks Danny for the tip.
- "Starter Pokemon Script"; very simple error regarding constant settings for re-arranged Pokemon
- "Scripting"; This one defied some programming logic but makes a basic sense. EACH NPC and Sign needs its own pointer and cannot be assigned to the same pointer as something else. That pointer can point at the same space, but the item needs its own entry on the text or script table to properly work. (link)
- Unique Status Screen Pokemon Icons, do not update on switch; Because the old sprite program loaded ALL of the possible sprites into memory at the same time and the new one does not, it relies on the existing internal index. Solution was to reload the sprites, which loaded them in the correct order. (link)
- Buggy New Items; Various issues with various solutions.
* General New Item Tutorial (link)
* Items that impact the party need to be added to a list for the menu (link)
* Needed to update the code in the "engine/items/items.asm" file to indicate how many bytes to grab to determine stacking/key item status (link; also noted in replies on general new item tutorial, though forgotten by the time I got to that point in the previous thread)
I'm having some issues now that I have "sorted" my Pokedex and data, IE put all of the data in proper Pokedex order as opposed to the initial order. I'm going through the likely culprits now, but wanted to see if anyone else has had the same issues and can point me in the right direction:
- The Pokedex is "off", where it wasn't before; previously, as I caught or saw new Pokemon, my dex updated appropriately. Now, my Seen and Caught values are correct but the new 150+ pokemon do not appear in the Pokedex.
- The pallets are off on the stats screen; in combat they all appear correct, they are assigned to the appropriate "slots" in the pallet file, but they are not correct in the stats screen.
- My Starter Pokemon script seems to have...shifted. The 'mon are not where they belong. I can manually correct things like the "Do you want XXX pokemon?" to reflect the actual monster in the space, but I'd rather understand why it shifted.
Prior to adjusting the order of the data, it was fine. Pallets were good, starter pokemon worked the way they should, and the Pokedex worked. For the most part, the data all appears to be in the correct order itself, which was a big question. Now I just need to iron that part out...
Second item for my inquiring mind is a script.
Player meets an NPC, has an interaction, and is warped to a new location. This works fine.
Flags are checked as appropriate, sprites are shown and hidden as appropriate.
Once warped in, script is supposed to execute an exposition text, give the player an item (shifted my Pokedex granting script), and then release the player.
Issue is, on warping to the new location, the script executes the text entry associated with the NPC sprite there, not the scripted text I want it to run.
Last edited by daMoose52 (2016-10-24 17:28:04)
Always the simple stuff; starter script issue was a mixup in my Constants. I had two starters in the wrong spot. The pallet issue and the others is still a thing, however.
The PokeDex display data is a byte off...if my starter is #155, the Pokedex displays up to #147. On catching Pokemon #161, the dex updates to #153.
AND the Pokedex issue stems from what I have dealt with before, which is the number of pokemon in the game.
SO, question then for those who have done it; how do we get the pokedex count to "play nice" so to speak? Everything works when I have a NUM_POKEMON set to 248, but then that excludes the space between 249 & 254 (though I kept those top end ones for the Fossil and Ghost pokemon, going up through #251).
Still working on the pallet issue for the status screen.
Have a sort-of-hack-y work around for the script issue...
Pokedex solution stems from the project to increase the pokedex past the 255 limit;
Following their example, in the code where it checks for the maximum seen Pokemon, you turn it to a two-byte value.
; find the highest pokedex number among the pokemon the player has seen ld hl,wPokedexSeenEnd - 1 ld bc, (wPokedexSeenEnd - wPokedexSeen) * 8 + 1 .maxSeenPokemonLoop ld a,[hld] ld d,8 .maxSeenPokemonInnerLoop dec bc sla a jr c,.storeMaxSeenPokemon dec d jr nz,.maxSeenPokemonInnerLoop jr .maxSeenPokemonLoop .storeMaxSeenPokemon ld a,c ld [wWhichTrade],a ; max seen pokemon ld a,b ld [wWhichTrade + 1],a
Pardon some of the old wRam variables, I'm working with a much older copy with many extensions so I've not "updated" my core.
BUT, the idea is you load "bc" with the max seen, not "b", and you make a handful of adjustments down that line as needed (c variables become d variables, and the addition of the code toward the bottom, load wWhichTrade+1 with a portion of that).
Still working on the pallet for the stats screen; the sub 151 pallets seem to work, which means its something in my new pallets.
Think I'm going to need to adjust the script I am referencing as well; it all seems to work well now, but I cannot get the sprites to do what I want, which is similar to issues I had earlier in some scripts. I want the sprite to turn to the left, make an item disappear, and the sprite to turn back down. The required sprite does vanish as expected, but no turning or sprite updates. I THINK that happens between loading/activating of scripts as that appears to be the case in the older scripts I was working on.
I posted in the appropriate thread for this, but I'm also having update issues in my party menu when the positions change. I've applied the code from Danny to do the unique sprites in the menus which all appears to work fine EXCEPT for when swapping party positions.
The palette bug on the status screen is a known issue.
In engine/palettes.asm, take a look at SetPal_StatusScreen.
Change `cp VICTREEBEL + 1` to `cp NUM_POKEMON + 1`
The reason they orignally used VICTREEBEL is because VICTREEBEL is the last mon in the original order. If you make the internal order the same as dex order, you can simply use NUM_POKEMON.
I don't quite understand what you are trying to explain with the bugs in the dex.
I haven't done a whole lot of testing, but take a look at this to see how I put everything in dex order:
Alright, that was totally escaping me and I had zero clue; but that makes perfect sense!
The dex issue came up because I was trying to work things out now that I had all of these "new" slots, but my dex wasn't showing correctly what I had seen (I would see #161, but the PokeDex would not register that high, it was a byte behind). I recall running into that issue before so it was especially aggravating because I thought I had it taken care of.
What it was, in trying to use all of the new slots, NUM_POKEMON 255, it was causing issues with the Max Seen portion of the pokedex. The folks working on the 255+ pokemon ended up having the solution, making it so that it read two bytes for the flag array on seen Pokemon. Works like a charm now~
Still tinkering with my scripts; issue I'm having with the text is that it seems to be ignoring the text elements.
I have a sign text at the 3rd entry, but it loads the second text entry in its stead.
ViridianPokegodShrineScript: ; 5cd5d (17:4d5d) call EnableAutoTextBoxDrawing ; ld hl, ViridianPokegodShrineTrainerHeaders ld de, ViridianPokegodShrineScriptPointers ld a, [W_ViridianPokegodShrineCURSCRIPT] call ExecuteCurMapScriptInTable ld [W_ViridianPokegodShrineCURSCRIPT], a ret ViridianPokegodShrineScriptPointers: ; 5cd7b (17:4d7b) dw ViridianPokegodShrineScript1 ViridianPokegodShrineScript1: ; 5cd83 (17:4d83) ; ld a, [wd7b1] ; bit 0, a ; ret nz ; call CheckFightingMapTrainers ; ld a, [wTrainerHeaderFlagBit] ; and a ; ret nz ; ld a, [wd7b1] ; bit 1, a ; ret nz ; xor a ; ld [hJoyHeld], a ; ld [wcf0d], a ; ld a, [W_YCOORD] ; cp $3 ; ret nz ; ld a, [W_XCOORD] ; cp $4 ; ret nz ; ld a, $1 ; ld [wcf0d], a ; ld a, $1 ; ld [wd528], a ; ld a, $1 ; ld [$ff8c], a ; ld a, $8 ; ld [$ff8d], a ; call SetSpriteFacingDirectionAndDelay ; ld a, $1 ; ld [$ff8c], a ; call DisplayTextID ret ViridianPokegodShrineTextPointers: ; 5ce03 (17:4e03) dw ViridianPokegodShrineText1 dw ViridianPokegodShrineText2 dw ViridianPokegodShrineText3 ViridianPokegodShrineText1: ; 5ce44 (17:4e44) db $08 ; asm ld hl, ViridianPokegodShrineText_1 call PrintText call YesNoChoice ld a, [wCurrentMenuItem] and a jr nz, .pokeshrine_yes ;ld hl, ViridianCityText_19157 ;call PrintText jr .pokeshrine_no .pokeshrine_yes ;ld hl, ViridianCityText_19152 ;call PrintText .pokeshrine_no jp TextScriptEnd ViridianPokegodShrineText_1: TX_FAR _Viridian_PokegodShrineText1 db "@" ViridianPokegodShrineText2: db $08 ld hl, ViridianPokegodShrineText_2 call PrintText jp TextScriptEnd ViridianPokegodShrineText_2: TX_FAR _Viridian_PokegodShrineText2 db "@" ViridianPokegodShrineText3: TX_FAR _Viridian_PokegodShrine_Statue_Text db "@"
Further tinkering with the scripting burr; my "Sign" is loading the text of the NPC at the indicated space, not the text at the indicated space...
Solution to the scripting/text question:
Each element (NPC, Sign, etc) needs its own, unique, entry for the pointer table and object file. One cannot simply point to the same element without creating overlapping issues...
ViridianPokegodShrineObject: ; 0x5cf9b (size=72) db $3 ; border block db $2 ; warps db $b, $4, $5, $ff db $b, $5, $5, $ff db $2 ; signs db $9, $3, $6 ; Statue Text db $9, $6, $7 ; Statue Text db $5 ; people db SPRITE_GAMBLER, $3 + 4, $5 + 4, $ff, $ff, $1 db SPRITE_GAMBLER, $4 + 4, $3 + 4, $ff, $ff, $2 db SPRITE_GAMBLER, $6 + 4, $3 + 4, $ff, $ff, $3 db SPRITE_GAMBLER, $5 + 4, $6 + 4, $ff, $ff, $4 db SPRITE_GAMBLER, $7 + 4, $6 + 4, $ff, $ff, $5 ; warp-to EVENT_DISP VIRIDIAN_POKEGOD_SHRINE_WIDTH, $b, $4 EVENT_DISP VIRIDIAN_POKEGOD_SHRINE_WIDTH, $b, $5
This is my updated file; I had ORIGINALLY set the NPCs so that one of them was set to the first text message ($1), the rest were set to the second ($2), and the signs were set to the third ($3).
The NPCs all used the text messages as appropriate, but the signs used the 3rd NPC's text.
ViridianPokegodShrineTextPointers: dw ViridianPokegodShrineText1 dw ViridianPokegodShrineText2 dw ViridianPokegodShrineText3
This was my original text pointer table;
ViridianPokegodShrineTextPointers: dw ViridianPokegodShrineText1 dw ViridianPokegodShrineText2 dw ViridianPokegodShrineText2 dw ViridianPokegodShrineText2 dw ViridianPokegodShrineText2 dw ViridianPokegodShrineText3 dw ViridianPokegodShrineText3
This is the updated text pointer table, with one pointer entry for each sign and NPC element. THIS works just fine~
Forgive the rambling; it IS helping me think "out loud" and learn some of the quirks of the ASM and structure of the game. Other languages I'm used to would have worked the way I had expected (We have 3 text entries; the NPC and/or Sign just loads X where X is the stated sign entry...) and I hadn't realized that this structure would not~
No worries. Thinking out loud on the forums is often very helpful. Glad you got the issue figured out.
New questions :D
"LoneMoves" and "TeamMoves" and Rival scripts; something about them is different, they are loaded entirely different than the rest of the trainer events I have seen.
I am attempting to set my rival up with some TeamMoves, but cannot get either TeamMoves or LoneMoves to work.
I know with the Lone it has to be set in the script ahead of time, I have done the PokeDex extension and have the trainers on their own track with the wIsTrainerBattle setting.
Any pointers there whilst I continue to mine & tinker?
Why not do what I did and make your own system, since the vanilla one sucks anyway :p
Note: This wouldn't work as-is for you since I haven't added dex expansion yet, but it's an example.
Last edited by Mateo (2016-10-17 14:32:17)
I am no longer active on this forum. I only pop in from time to time.
I've thought about it ^_^ I saw the routine for Yellow and like that, but I'm not up *quite* enough on all of the rules of the code there if I cannot get the stock one to work correctly in the first place.
I HAVE tinkered a little in that area; I hope to have a routine that scales some encounters to your team so that some parts of the game are a greater challenge rather than just level-up and roll over the trainers. Gym Leaders are a lot like that; I want to emphasize narratively that each Gym Leader isn't there to be beaten and passed over but that each one, through their pokemon, trainers, and moves, have a lesson to teach and that the best way to beat them is to learn that lesson and use that solution against them. IE Brock & Bide, will have a team a little better set to absorb and dish out. Erika with her grass Pokemon would teach about status effects in essence, teaching the player to plan accordingly. By making them a similar level, its harder to steamroll and one will have to be smarter about overcoming them ^_^
Oh, cool! What exactly were the lessons you see each Gym Leader teaching us?
Yeah, a while back I rolled my own routine to read move data stored in Yellow's format, since pokeyellow wasn't that far along yet. Then I redid it to just read 4 move IDs stored after the Level/ID combo for each Pokémon on the team for that trainer type. Easier to read since the team data is all together and whatnot. Also did a lot of other changes that don't apply to moves, too, and still planning to do more. Like you say, it's an ongoing process as you get more familiar with it and start adapting it to fit your needs.
I am no longer active on this forum. I only pop in from time to time.
Still working on all of that; I plan on BLUE (who replaces Giovonni as the Viridian leader in my storyline and is a "mentor" at the start of the game) laying out some of it, and then riffing off each existing trainer. As I said, with Brock & Bide, it would have to do with timing, using the opponent to your advantage; Erika, with a lot of the grass Pokemon who specialize in status conditions, would enforce that. Misty was always a Type-advantage sort of challenge (her and Brock it made the most difference who your starter was as to how easy the battles would be). I see Koga also being a "timing" challenge, using Fly-esque moves for a Ninja-like "Now you see me now you don't" scenario; between that and poison, it can make an interesting battle. Figure re-write the scenario to more closely match the opening Rival scenario, where even if you lose you don't "black out" per-say, but get a moment to converse with the leader about what the lesson is supposed to be.
It'll all be worked out as the planning carries on. Big thing is making sure the code works to land a reasonable APL (average party level) that's not so easy to game (IE have one good Pokemon, five weak Pokemon, throw the math so that its an easy battle) and of course address this annoying burr with the LoneAttack and TeamMoves :D
Given the way most people raise Pokémon, doing an average of the player's party will probably always result in an easy fight. Best case scenario, both parties are similar in level, player has stat EXP while AI trainers don't, so opponent has disadvantage from the start. Worst case, trainer has HM slaves that bring the average down even more by a few levels, making it even easier.
Personally, I feel like the better way is to base the enemy level on the highest level member of the player's team. If they raise evenly, its still close to the average. If they raise them unevenly, its harder for them. But you'd probably want to keep it a couple levels above the player's team, and/or work out a way to give trainers Stat EXP. Even still, it's going to be tough to come up with a system to adequately scale bosses to the player.
I am no longer active on this forum. I only pop in from time to time.
I'm just more worried about the code than the logic; I self-publish a share of Dungeons & Dragons scenarios and party balance, action economy, etc. are all things that weigh in for a lot of the adventuring. I'm reasonably sure I can land something to come up with a clean mid-range number to add or subtract to for Gym Leader levels.
You ARE right about the Stat EXP being a different critter than I'd otherwise be used to, and I forget that sometimes with the Pokemon games.
BUT: This task at hand first, I want to make sure the application of TeamMoves/LoneMoves works out right :D
Keeping up with the thinking out loud:
Working on the TeamMoves and LoneMoves, I cannot get them to trigger seemingly at all. I'll be trying a Brock battle in Pewter to see if the scripts still call it all properly or if I buggered up the system some how.
In reviewing the WRAM, it appears everything is loading in for the most part. Trainer Class is correct, party grouping is correct, values line up the way they should so it should be triggering the checks but it doesn't appear to be...
Partial Solution: Lone Attacks & Rival Battles
Seems like the Rival Battles load all sorts of code as it sorts out which team you're supposed to face. To set the LoneMoves value for that, you need to ensure that the code for that is placed, essentially, at the very end.
This is my 1st Rival appearance on Route 22:
Route22Script1: ; 50f62 (14:4f62) ld a, [wd730] bit 0, a ret nz ld a, [wcf0d] cp $1 jr nz, .asm_50f78 ; 0x50f6d $9 ld a, $4 ld [wd528], a ld a, $4 jr .asm_50f7a ; 0x50f76 $2 .asm_50f78 ld a, $c .asm_50f7a ld [$ff8d], a ld a, $1 ld [$ff8c], a call SetSpriteFacingDirectionAndDelay xor a ld [wJoyIgnore], a ld a, $1 ld [$ff8c], a call DisplayTextID ld hl, wd72d set 6, [hl] set 7, [hl] ld hl, Route22RivalDefeatedText1 ld de, Route22Text_511bc call SaveEndBattleTextPointers ld a, 1 ld [wIsTrainerBattle], a ld a, SONY1 + TRAINER_START ld [W_CUROPPONENT], a ld hl, StarterMons_50faf ; $4faf call Route22Script_50ed6 ld a, $9 ;<--Sets the LoneMove ID ld [W_GYMLEADERNO], a ;<--Loads that into memory xor a ;<--Wipes out A ld a, $2 ld [W_ROUTE22CURSCRIPT], a ret
Anywhere before the call to "Route22Script_50ed6" the data written is overwritten as the team is selected and loaded. AFTER that call, when the party is set, the data sticks.
This is NOT a solution to my issues with the TeamMoves...we'll see about that.
Now here's an interesting one; Enemy Mon being affected by Status Effects (Burned is what I ran into) seem to cause a crash post-trainer battle...anyone run into this??
Well, i must admit i am a total noob, but here's my two cents
I found the system of LoneMoves and TeamMoves of Red/Blue was a little restrictive, so i opted for removing that code and replacing it with Yellow's code SpecialTrainer, which is the same for gym leaders and elite four battles. You can edit the movesets of rival battles and and even normal trainers, you just got to specify the roster, trainer class and the ordinal of the pokemon. Then you could replace data/trainer_moves.asm with Yellow's format.
Leaving aside the fact that the bank in which this data is stored is a bit crowded, i have found no issues with this.
Status effects crash the game in special move battles only, or in all battles?