Jump to content


  • Content Count

  • Joined

  • Last visited

 Content Type 




Pokemon Reborn Development Blog

Pokemon Rejuvenation Development Blog

Everything posted by silverlime

  1. There are a few things wrong with this code segment: if (thismove.id == PBMoves::LAVASURF || thismove.id == PBMoves::LAVAPLUME || thismove.id == PBMoves::ERUPTION) $febackup = 6 $fefieldeffect = 6 @battle.pbChangeBGSprite @battle.pbDisplay(_INTL("The flate ignited the cave!")) end If you can't tell, this changes the cave field to the Big Top Arena (6), when it should change it to Volcanic Field (7). There's also a typo with "flate". Also you guys seem to have coded in Field transformations doubly. The transformations under "# FIELD TRANSFORMATIONS 1" are for status moves and the transformations under "# FIELD TRANSFORMATIONS 2" are for damaging moves I believe (as discovered from my own testing and looking at how Reborn coded these), but you guys put all moves in both sections for the rejuvenation specific field transformations.
  2. It's great to see new ways to improve game speed, and I'm glad you're still giving updates about this. The level thing with saving it as a new variable so it's not called thousands of times seemed pretty simple, so I tried adding it in my copy of essentials, but for some reason, the Pokemon's level doesn't increase when it levels up. I guess there are some other places that have to be updated to account for this variable as well?
  3. It's nice to see that some characters are still getting new overworld sprites that look even better than before. I'm surprised Cella only got 3 votes. I thought she was a very well-made character that fits in well with the story. Also I'm surprised that 6 people spelled Casssandra with 3 s's.
  4. I've found another thing that should probably be addressed in the AI, this time for Parting Shot. Here's the code for reference: when 0x13D # Parting Shot if (!opponent.pbCanReduceStatStage?(PBStats::ATTACK) && !opponent.pbCanReduceStatStage?(PBStats::SPATK)) || (opponent.stages[PBStats::ATTACK]==-6 && opponent.stages[PBStats::SPATK]==-6) || (opponent.stages[PBStats::ATTACK]>0 && opponent.stages[PBStats::SPATK]>0) score*=0 else if attacker.pbNonActivePokemonCount==0 if attacker.pbOwnSide.effects[PBEffects::StealthRock] score*=0.7 end if attacker.pbOwnSide.effects[PBEffects::StickyWeb] score*=0.6 end if attacker.pbOwnSide.effects[PBEffects::Spikes]>0 score*=0.9**attacker.pbOwnSide.effects[PBEffects::Spikes] end if attacker.pbOwnSide.effects[PBEffects::ToxicSpikes]>0 score*=0.9**attacker.pbOwnSide.effects[PBEffects::ToxicSpikes] end if (attacker.pbSpeed>pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0) score*=1.1 end sweepvar = false for i in pbParty(attacker.index) next if i.nil? temprole = pbGetMonRole(i,opponent,skill,count,pbParty(attacker.index)) if temprole.include?("Sweeper") sweepvar = true end end if sweepvar score*=1.5 end if roles.include?("Lead") score*=1.1 end if roles.include?("Pivot") score*=1.2 end loweredstats=0 loweredstats+=attacker.stages[PBStats::ATTACK] if attacker.stages[PBStats::ATTACK]<0 loweredstats+=attacker.stages[PBStats::DEFENSE] if attacker.stages[PBStats::DEFENSE]<0 loweredstats+=attacker.stages[PBStats::SPEED] if attacker.stages[PBStats::SPEED]<0 loweredstats+=attacker.stages[PBStats::SPATK] if attacker.stages[PBStats::SPATK]<0 loweredstats+=attacker.stages[PBStats::SPDEF] if attacker.stages[PBStats::SPDEF]<0 loweredstats+=attacker.stages[PBStats::EVASION] if attacker.stages[PBStats::EVASION]<0 miniscore= (5)*loweredstats miniscore+=100 miniscore/=100.0 score*=miniscore raisedstats=0 raisedstats+=attacker.stages[PBStats::ATTACK] if attacker.stages[PBStats::ATTACK]>0 raisedstats+=attacker.stages[PBStats::DEFENSE] if attacker.stages[PBStats::DEFENSE]>0 raisedstats+=attacker.stages[PBStats::SPEED] if attacker.stages[PBStats::SPEED]>0 raisedstats+=attacker.stages[PBStats::SPATK] if attacker.stages[PBStats::SPATK]>0 raisedstats+=attacker.stages[PBStats::SPDEF] if attacker.stages[PBStats::SPDEF]>0 raisedstats+=attacker.stages[PBStats::EVASION] if attacker.stages[PBStats::EVASION]>0 miniscore= (-5)*raisedstats miniscore+=100 miniscore/=100.0 score*=miniscore if attacker.effects[PBEffects::Toxic]>0 || attacker.effects[PBEffects::Attract]>-1 || attacker.effects[PBEffects::Confusion]>0 score*=1.3 end if attacker.effects[PBEffects::LeechSeed]>-1 score*=1.5 end miniscore=130 if attacker.hasWorkingAbility(:SHADOWTAG) || attacker.hasWorkingAbility(:ARENATRAP) || opponent.effects[PBEffects::MeanLook]>=0 || opponent.pbNonActivePokemonCount==0 miniscore*=1.4 end ministat=0 ministat+=opponent.stages[PBStats::ATTACK] if opponent.stages[PBStats::ATTACK]<0 ministat+=opponent.stages[PBStats::DEFENSE] if opponent.stages[PBStats::DEFENSE]<0 ministat+=opponent.stages[PBStats::SPEED] if opponent.stages[PBStats::SPEED]<0 ministat+=opponent.stages[PBStats::SPATK] if opponent.stages[PBStats::SPATK]<0 ministat+=opponent.stages[PBStats::SPDEF] if opponent.stages[PBStats::SPDEF]<0 ministat+=opponent.stages[PBStats::EVASION] if opponent.stages[PBStats::EVASION]<0 ministat*=(5) ministat+=100 ministat/=100.0 miniscore*=ministat if opponent.hasWorkingAbility(:UNAWARE) || opponent.hasWorkingAbility(:DEFIANT) || opponent.hasWorkingAbility(:COMPETITIVE) || opponent.hasWorkingAbility(:CONTRARY) miniscore*=0.1 end miniscore/=100.0 score*=miniscore end end There are 2 problems I see with this. First of all, the score increases if the user has Shadow Tag/Arena Trap, but this wouldn't matter because it's switching out anyway. Secondly, the score severely decreases if the opponent has Unaware, but Unaware only ignores stat changes on the opponent, so lowering the Pokemon's stats with Unaware would still work (and is arguably more helpful to lower them on than a regular Pokemon). EDIT: Also, the AI for Reflect and Light Screen, when increasing the score if the attacker has Sturdy or Focus Sash, it doesn't check if the attacker is at full HP (Aurora Veil does this though). Many checks with Sturdy also fail to check if the opponent/attacker has Mold Breaker as well, which is important to note, as this seems inconsistent. The AI also checks existing weather for sturdy in weather setting moves while it should assume the weather that would be set by the move
  5. I found a few more bugs recently (sorry, not sure if some of these have already been found): 1. You can get all of Ren's Pokemon when you play as him if you send his to the PC when catching new ones 2. Rage Powder doesn't seem to work properly, as it failed to redirect a Shadow Ball from a Palossand on Desert Field 3. If you use a Revive on a Pokemon when you have only 1 left in doubles, this happens: 4. You can trigger an event early in the Narcissa quest if you go to the house on past Route 5 and open the locked door even if you haven't started the quest yet. It also brings you back to Goldenleaf earlier than should be possible I believe.
  6. Another couple random tiles that don't seem like they belong: Typo: eminated should be emanated
  7. Tile priority error x2: Also I don't think this tree belongs here: Or this lamp: I'm not sure that you're supposed to be able to walk on these tiles:
  8. I don't think this partial palm tree belongs in the building like this:
  9. Comparing the actual damage multiplier with the one the AI uses, it seems like there's a discrepancy. Actual: if attacker.hp<=(attacker.totalhp/3).floor if (attacker.hasWorkingAbility(:OVERGROW) && isConst?(type,PBTypes,:GRASS)) || (attacker.hasWorkingAbility(:BLAZE) && isConst?(type,PBTypes,:FIRE)) || (attacker.hasWorkingAbility(:TORRENT) && isConst?(type,PBTypes,:WATER)) || (attacker.hasWorkingAbility(:SWARM) && isConst?(type,PBTypes,:BUG)) atkmult=(atkmult*1.5).round end elsif $fefieldeffect == 7 && (attacker.hasWorkingAbility(:BLAZE) && isConst?(type,PBTypes,:FIRE)) atkmult=(atkmult*1.5).round elsif $fefieldeffect == 15 && (attacker.hasWorkingAbility(:OVERGROW) && isConst?(type,PBTypes,:GRASS)) atkmult=(atkmult*1.5).round elsif $fefieldeffect == 15 && (attacker.hasWorkingAbility(:SWARM) && isConst?(type,PBTypes,:BUG)) atkmult=(atkmult*1.5).round elsif ($fefieldeffect == 21 || $fefieldeffect == 22) && (attacker.hasWorkingAbility(:TORRENT) && isConst?(type,PBTypes,:WATER)) atkmult=(atkmult*1.5).round elsif $fefieldeffect == 33 && (attacker.hasWorkingAbility(:SWARM) && isConst?(type,PBTypes,:BUG)) atkmult=(atkmult*1.5).round if $fecounter == 0 || $fecounter == 1 atkmult=(atkmult*2).round if $fecounter == 2 || $fecounter == 3 atkmult=(atkmult*3).round if $fecounter == 4 elsif $fefieldeffect == 33 && (attacker.hasWorkingAbility(:OVERGROW) && isConst?(type,PBTypes,:GRASS)) case $fecounter when 1 if attacker.hp<=(attacker.totalhp*0.67).floor atkmult=(atkmult*1.5).round end when 2 atkmult=(atkmult*1.5).round when 3 atkmult=(atkmult*2).round when 4 atkmult=(atkmult*3).round end end AI: # Pinch abilities if skill>=PBTrainerAI.mediumSkill if attacker.hp<=(attacker.totalhp/3).floor if (attacker.hasWorkingAbility(:OVERGROW) && isConst?(type,PBTypes,:GRASS)) || (attacker.hasWorkingAbility(:BLAZE) && isConst?(type,PBTypes,:FIRE)) || (attacker.hasWorkingAbility(:TORRENT) && isConst?(type,PBTypes,:WATER)) || (attacker.hasWorkingAbility(:SWARM) && isConst?(type,PBTypes,:BUG)) atk=(atk*1.5).round end end end if skill>=PBTrainerAI.bestSkill if $fefieldeffect == 7 && (attacker.hasWorkingAbility(:BLAZE) && isConst?(type,PBTypes,:FIRE)) atk=(atk*1.5).round elsif $fefieldeffect == 15 && (attacker.hasWorkingAbility(:OVERGROW) && isConst?(type,PBTypes,:GRASS)) atk=(atk*1.5).round elsif $fefieldeffect == 15 && (attacker.hasWorkingAbility(:SWARM) && isConst?(type,PBTypes,:BUG)) atk=(atk*1.5).round elsif ($fefieldeffect == 21 || $fefieldeffect == 22) && (attacker.hasWorkingAbility(:TORRENT) && isConst?(type,PBTypes,:WATER)) atk=(atk*1.5).round elsif $fefieldeffect == 33 && (attacker.hasWorkingAbility(:SWARM) && isConst?(type,PBTypes,:BUG)) atk=(atk*1.5).round if $fecounter == 0 || $fecounter == 1 atk=(atk*2).round if $fecounter == 2 || $fecounter == 3 atk=(atk*3).round if $fecounter == 4 elsif $fefieldeffect == 33 && (attacker.hasWorkingAbility(:OVERGROW) && isConst?(type,PBTypes,:GRASS)) case $fecounter when 1 if attacker.hp<=(attacker.totalhp*0.67).floor atk=(atk*1.5).round end when 2 atk=(atk*1.5).round when 3 atk=(atk*2).round when 4 atk=(atk*3).round end end end Notice how the AI (at best skill) will think there are 2 damage boosts if the user is at low HP and has a field that activates the ability (in actuality, only 1 damage boost can be applied even if both HP and field conditions are met)
  10. Damn I forgot about truck guy. I couldn't think of a third person so I voted for Neved idk why lol, but I would definitely change him to truck guy if I could now.
  11. Tile error in the River's End Lab: Also, the Cofagrigus in the Saki housesitting quest doesn't make any moves at all. If you activate the dark crystal again in Darchlight Caves, Florin's speech about the mirror is repeated:
  12. These look really nice! I especially like Amanda, Valarie, Florin, and Adam's revisions. I hope Aelita's (first I think) vs sprite will eventually be revised because her leg really bothers me for some reason. I think it looks a bit short from the knee down and the foot seems to be in a strange position. These look great and you should take your time, but since I've noticed that about her sprite, I can't unsee it.
  13. After going down this ladder, the player gets stuck in this position and the sound for bumping into something keeps playing.
  14. After this interaction, cinematic bars are permanently stuck on: After these people tell you to go away when first encountering them, if you use Rock Climb to get up there, they don't say anything if you talk to them. You can walk over this ledge below the player even though the stairs are to the left (both are passable): Perhaps this sofa tile should appear over the player:
  15. The player can end up on top of Melia in the Chuch of Theolia: And the player can walk on these tiles: Melia's Sprite doesn't appear in this cutscene:
  16. PC Healing is inconsistent: When selecting "Store", the Pokemon will be healed, but when selecting "Move" and "Place", the Pokemon will not be healed. Also, Unnerve from my Houndoom didn't prevent an opposing Pelipper from eating its Wacan Berry when an electric move was used against it by Houndoom's partner. Also you might consider changing the priority on these door tiles to 3 so that the player always remains under them:
  17. As I have implemented Reborn/Rejuvenation AI & Field Effects, I often find myself looking through the scripts of both games. One thing I noticed with Forewarn was that code was added which I think was meant to add the detected move to the AI move memory. However, there seem to be a few problems that I've found (Sorry this is kind of long. I've been working through it to fix it for my game as well): The code for forewarn starts with this line: if self.hasWorkingAbility(:FOREWARN) && @battle.pbOwnedByPlayer?(@index) && onactive but this means that if an opponent's Pokemon is the one with Forewarn, it will just skip over activating, meaning that the AI will not detect an opposing Pokemon's moves if it is the one sending out a Pokemon with Forewarn. Then here's the bigger problem: if moves.length>0 move=moves[@battle.pbRandom(moves.length)] movename=PBMoves.getName(move) @battle.pbDisplay(_INTL("{1}'s Forewarn alerted it to {2}!",pbThis,movename)) if (self.index==0 || self.index==2) && !@battle.isOnline? # Move memory system for AI warnedMove = PokeBattle_Move.pbFromPBMove(@battle,PBMove.new(move),self) if @battle.aiMoveMemory[0].length==0 && warnedMove.basedamage!=0 @battle.aiMoveMemory[0].push(warnedMove) elsif @battle.aiMoveMemory[0].length!=0 && warnedMove.basedamage!=0 dam1=@battle.pbRoughDamage(warnedMove,self,@battle.battlers[1],255,warnedMove.basedamage) dam2=@battle.pbRoughDamage(@battle.aiMoveMemory[0][0],self,@battle.battlers[1],255,@battle.aiMoveMemory[0][0].basedamage) if dam1>dam2 @battle.aiMoveMemory[0].clear @battle.aiMoveMemory[0].push(warnedMove) end end if @battle.aiMoveMemory[1].length==0 @battle.aiMoveMemory[1].push(warnedMove) else dupecheck=0 for i in @battle.aiMoveMemory[1] dupecheck+=1 if i.id == warnedMove.id end @battle.aiMoveMemory[1].push(warnedMove) if dupecheck==0 end if @battle.aiMoveMemory[2][self.pokemonIndex].length==0 @battle.aiMoveMemory[2][self.pokemonIndex].push(warnedMove) else dupecheck=0 for i in @battle.aiMoveMemory[2][self.pokemonIndex] dupecheck+=1 if i.id == warnedMove.id end @battle.aiMoveMemory[2][self.pokemonIndex].push(warnedMove) if dupecheck==0 end end end This code (starting with the line with the comment '# Move memory system for AI') seems to have been copied from the other area in Pokebattle_Battler where the AI remembers which move one of the player's Pokemon uses except that it was changed to use warnedMove instead of choice[2]. Since this was the only change made, each time it refers to self it is referring to the Pokemon with Forewarn, not the actual Pokemon with the move. However, this introduces yet another problem because Forewarn doesn't reveal which opponent has the move in double battles. Based on how the code is currently, I think it would work like the following (though there's not an easy way to actually see how it would work so I'm just going off logic): If the Pokemon with Forewarn is owned by the player, the message will be played correctly, stating the move that was detected on the opponent's Pokemon. Then, the AI registers the the move detected on its own Pokemon as a move of the player's Pokemon. It should work so that if the player's Pokemon has Forewarn, the AI doesn't remember the move, and only a message should be played. If the AI sends out the Pokemon with Forewarn, it should register the move detected on the player's Pokemon as a move of that Pokemon. I've tried to fix the code for my own game and I'll post it here in case it's correct or helpful (I made it so the player and opponent are both alerted which Pokemon carries the move, but I'm still not really sure how the aiMoveMemory array works so there might be a problem with that): # Forewarn if self.hasWorkingAbility(:FOREWARN) && onactive PBDebug.log("[Ability triggered] #{pbThis} has Forewarn") highpower=0 fwmoves=[] moveusers=[] for foe in [pbOpposing1,pbOpposing2] next if foe.fainted? for j in foe.moves movedata=PBMoveData.new(j.id) power=movedata.basedamage power=160 if movedata.function==0x70 # OHKO power=150 if movedata.function==0x8B # Eruption power=120 if movedata.function==0x71 || # Counter movedata.function==0x72 || # Mirror Coat movedata.function==0x73 || # Metal Burst power=80 if movedata.function==0x6A || # SonicBoom movedata.function==0x6B || # Dragon Rage movedata.function==0x6D || # Night Shade movedata.function==0x6E || # Endeavor movedata.function==0x6F || # Psywave movedata.function==0x89 || # Return movedata.function==0x8A || # Frustration movedata.function==0x8C || # Crush Grip movedata.function==0x8D || # Gyro Ball movedata.function==0x90 || # Hidden Power movedata.function==0x96 || # Natural Gift movedata.function==0x97 || # Trump Card movedata.function==0x98 || # Flail movedata.function==0x9A # Grass Knot if power>highpower fwmoves=[j.id] highpower=power moveusers=[foe] elsif power==highpower fwmoves.push(j.id) moveusers.push(foe) end end end r=@battle.pbRandom(fwmoves.length) fwmove=fwmoves[r] fwuser=moveusers[r] if @battle.pbOwnedByPlayer?(@index) if fwmoves.length>0 movename=PBMoves.getName(fwmove) @battle.pbDisplay(_INTL("{1}'s Forewarn alerted it to {2}'s {3}!",pbThis,fwuser.pbThis,movename)) end elsif @battle.pbIsOpposing?(@index) if fwmoves.length>0 warnedMove = PokeBattle_Move.pbFromPBMove(@battle,PBMove.new(fwmove)) if @battle.aiMoveMemory[0].length==0 && warnedMove.basedamage!=0 @battle.aiMoveMemory[0].push(warnedMove) elsif @battle.aiMoveMemory[0].length!=0 && warnedMove.basedamage!=0 dam1=@battle.pbRoughDamage(warnedMove,fwuser,self,255,warnedMove.basedamage) dam2=@battle.pbRoughDamage(@battle.aiMoveMemory[0][0],fwuser,self,255,@battle.aiMoveMemory[0][0].basedamage) if dam1>dam2 @battle.aiMoveMemory[0].clear @battle.aiMoveMemory[0].push(warnedMove) end end if @battle.aiMoveMemory[1].length==0 @battle.aiMoveMemory[1].push(warnedMove) else dupecheck=0 for i in @battle.aiMoveMemory[1] dupecheck+=1 if i.id == warnedMove.id end @battle.aiMoveMemory[1].push(warnedMove) if dupecheck==0 end if @battle.aiMoveMemory[2][fwuser.pokemonIndex].length==0 @battle.aiMoveMemory[2][fwuser.pokemonIndex].push(warnedMove) else dupecheck=0 for i in @battle.aiMoveMemory[2][fwuser.pokemonIndex] dupecheck+=1 if i.id == warnedMove.id end @battle.aiMoveMemory[2][fwuser.pokemonIndex].push(warnedMove) if dupecheck==0 end end end end
  18. silverlime


    Downloading this ended my randomizer save file so that from this point onward no Pokemon are randomized (I still have the old ones with their random moves). Does anybody know, am I supposed to keep playing on 18.2 where I started the randomizer or is there a way to fix this?
  19. I don't think these are problems with the randomizer, but I encountered them in the randomizer, so I'll post them here. Strength Sap doesn't seem to factor in stat changes to the target's attack when calculating the amount healed, but this is what happens in the actual games. (I used it against the same Pokemon twice with successful attack drops, but the amount healed remained exactly the same.) When an opposing Pokemon dies from corrosive field entry damage, none of my Pokemon gain xp.
  20. Found a problem with Doom Desire. After using it, on the strike turn, it says "___ took the Chatter attack", the attack doesn't do any damage, and this error message pops up: --------------------------- Pokemon Rejuvenation --------------------------- [Pokemon Rejuvenation V12.1] Exception: NoMethodError Message: undefined method `>=' for nil:NilClass PokeBattle_Move:4220:in `pbReduceHPDamage' PokeBattle_Battle:5846:in `__clauses__pbEndOfRoundPhase' PokeBattle_Battle:5809:in `each' PokeBattle_Battle:5809:in `__clauses__pbEndOfRoundPhase' PokeBattle_Clauses:42:in `pbEndOfRoundPhase' PokeBattle_Battle:4710:in `pbStartBattleCore' PokeBattle_Battle:4709:in `logonerr' PokeBattle_Battle:4709:in `pbStartBattleCore' PokeBattle_Battle:4693:in `loop' PokeBattle_Battle:4714:in `pbStartBattleCore' EDIT: Also, if I'm using random moves, how am I supposed to use the TMX moves without buying all the golden items? The TM number for each TMX move stays the same, but when you use it on a Pokemon, it teaches a move that is different from the one listed in the TM. Is there a mod like the one included in Reborn's randomizer where you don't need HM moves to interact with the field?
  21. When I battle Gorebyss against a trainer or in the wild at a certain part of the game, it just skips its turn and doesn't do anything. Upon catching one, I realized that its moveset is Sacred Fire, Ice Ball, Struggle, and Lunge, so Struggle might be causing the problem. EDIT: Found out something else really weird. When I hover over Struggle in the move choices, it actually causes a turn to pass for both Pokemon without either of them being able to do anything, so Pokemon still take burn damage, etc. However, after that battle, the following message popped up before the game crashed: "Script 'Pokebattle_ActualScene' line 427: NoMethodError occurred. undefined method '>' for nil:NilClass"
  22. This character's walking sprite when facing left doesn't animate smoothly, though the running sprites are fine: Pokemon Rejuvenation 2020-05-21 15-24-42_Trim_Trim.mp4
  23. The Crystal Cavern field makes it so Rock moves become randomly either Fire, Water, Grass, or Psychic type, so that would explain why Rollout sometimes wouldn't affect Mightyena. Moves like Sucker Punch and Quick Attack shouldn't work against Nim because Psychic Terrain disables priority moves, though I'm not sure why it would affect Lunatone (unless the field was changed when you used it against Lunatone).
  24. I have random items turned on, and sometimes one appears that is unable to be collected. This normally isn't a problem if it's an item in the overworld because it will be a different item the next time, but since one of my Pokemon is holding it, it can't be removed and no item can be given to it. The item seems to have no name. Here are some screenshots that could help: Also, sometimes (relatively frequently) when battling another Pokemon, it doesn't take its turns at all. I haven't seen any pattern with this, but it happens pretty often so I thought I'd mention it. Also, if a Pokemon gets the random move Struggle, when hovering over the slot that it appears to occupy (top right in this case), this error occurs:
  25. You can walk on this tile and the one below it in Crawli's Gym This is more of a suggestion, but maybe you'll consider changing the amount of tiles this trainer can see ahead of her to 1 so that she doesn't block you like this and cause you to go out of the map to reset her position..
  • Create New...