Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

2 Neutral

About silverlime

  • Rank
  • Birthday December 29

Profile Information

  • Gender

Recent Profile Visitors

635 profile views
  1. 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.
  2. 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
  3. 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.
  4. Another couple random tiles that don't seem like they belong: Typo: eminated should be emanated
  5. 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:
  6. I don't think this partial palm tree belongs in the building like this:
  7. 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)
  8. 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.
  9. 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:
  10. 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.
  11. After going down this ladder, the player gets stuck in this position and the sound for bumping into something keeps playing.
  12. 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:
  13. 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:
  14. 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:
  15. 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
  • Create New...