SHARE
TWEET

Nuzlocke Permadeath

NettoHikari1131 May 11th, 2019 (edited) 250 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ################################################################################
  2. # Nuzlocke Permadeath v1.1
  3. # by NettoHikari
  4. #
  5. # June 16, 2020
  6. #
  7. # This script allows the developer to enable a Nuzlocke-style permadeath for
  8. # Pokemon battles, where any Pokemon that faints is immediately removed from the
  9. # player's party. The difference between this and other Nuzlocke scripts is that
  10. # Pokemon get removed DURING battle instead of after.
  11. #
  12. # Credits MUST BE GIVEN to NettoHikari
  13. # You should also credit the authors of Pokemon Essentials itself.
  14. #
  15. #-------------------------------------------------------------------------------
  16. # INSTALLATION
  17. #-------------------------------------------------------------------------------
  18. # Copy this script, place it somewhere between "Compiler" and "Main" in the
  19. # script sections, and name it "Nuzlocke Permadeath".
  20. #
  21. # Before using this script, make sure to start a new save file when testing.
  22. # Since it adds new stored data, the script will probably throw errors when used
  23. # with saves where the script wasn't present before. In addition, if you decide
  24. # to release your game in segments, it is important to have this script
  25. # installed in the very first version itself, so as not to cause any problems to
  26. # the player.
  27. #
  28. #-------------------------------------------------------------------------------
  29. # SCRIPT USAGE
  30. #-------------------------------------------------------------------------------
  31. # This script offers two types of permadeath modes: SOFT and NUZLOCKE. In SOFT
  32. # mode, any Pokemon that faint are sent to the Pokemon Storage after the battle,
  33. # while in NUZLOCKE mode, they are lost forever (except for their held items).
  34. # To switch between permadeath modes, call "pbSetPermadeath(mode)" at the start
  35. # of your game (it is set to NORMAL by default at the beginning), replacing
  36. # "mode" with one of three modes: :NORMAL, :SOFT, or :NUZLOCKE. For example,
  37. # to enable the standard permadeath mode, use:
  38. #
  39. # pbSetPermadeath(:NUZLOCKE)
  40. #
  41. # and to disable it, use:
  42. #
  43. # pbSetPermadeath(:NORMAL)
  44. #
  45. # These can be called at anytime throughout your game, so for example, you can
  46. # change modes for specific event battles. To find out if the current permadeath
  47. # mode is either SOFT or NUZLOCKE use the function "pbPermadeathActive?". To
  48. # find out if a specific mode is enabled, use the function
  49. # "pbPermadeathModeIs?(mode)", replacing "mode" with what you're checking for.
  50. #
  51. # I highly suggest reading the "Additional Notes" section below for more
  52. # information on what the script does.
  53. #
  54. #-------------------------------------------------------------------------------
  55. # ADDITIONAL NOTES
  56. #-------------------------------------------------------------------------------
  57. # - On the outside, every time a Pokemon faints in SOFT or NUZLOCKE mode, it
  58. #   LOOKS like it's been removed from the party immediately. However, what
  59. #   happens internally is that all fainted Pokemon are hidden from the player's
  60. #   view until the end of the round (so technically, they are still part of the
  61. #   player's party). Then, at the end of each round, the player's party is
  62. #   swept for fainted Pokemon, and they are removed and placed into another
  63. #   list called "@faintedlist" (defined in PokeBattle_Battle below). Think of
  64. #   this list as a sort of "purgatory", meaning that the Pokemon here still
  65. #   exist as long as the battle is active, just not in the main party.
  66. # - At the very end of the battle in SOFT mode, @faintedlist is swept and all
  67. #   Pokemon in it are stored in the Pokemon Storage (unless the storage is full,
  68. #   in which case they are simply lost like NUZLOCKE mode).
  69. # - Any battles marked as "can lose", meaning that the game will continue
  70. #   even if the player loses the battle, automatically have NORMAL mode on.
  71. # - When a Pokemon dies in NUZLOCKE mode, it drops its held item into the
  72. #   player's bag.
  73. # - Pokemon can die from fainting in field due to poison if both NUZLOCKE and
  74. #   POISONINFIELD are enabled. For SOFT mode, the Pokemon get stored in the
  75. #   Pokemon Storage.
  76. # - When the player loses a battle with permadeath enabled, meaning that the
  77. #   trainer's entire party is dead, the game simply returns to the title screen
  78. #   with a "GAME OVER" screen, going back to the player's last save.
  79. #
  80. #-------------------------------------------------------------------------------
  81. # I hope you enjoy this script!
  82. # - NettoHikari
  83. ################################################################################
  84.  
  85. module PBPermadeath
  86.   NORMAL   = 0 # Standard mode
  87.   SOFT     = 1 # "Soft" nuzlocke (fainted Pokemon get transferred to Pokemon Storage)
  88.   NUZLOCKE = 2 # "Hard" nuzlocke (fainted Pokemon get deleted at the end of battle)
  89. end
  90.  
  91. class PokemonGlobalMetadata
  92.   # Sets battles to NORMAL, SOFT, or NUZLOCKE
  93.   attr_accessor :permadeathmode
  94. end
  95.  
  96. def pbSetPermadeath(mode)
  97.   if mode.is_a?(Symbol)
  98.     mode = getConst(PBPermadeath, mode)
  99.   end
  100.   return if mode < 0 || mode > 2
  101.   $PokemonGlobal.permadeathmode = mode
  102. end
  103.  
  104. def pbPermadeathModeIs?(mode)
  105.   if mode.is_a?(Symbol)
  106.     mode = getConst(PBPermadeath, mode)
  107.   end
  108.   return $PokemonGlobal.permadeathmode == mode
  109. end
  110.  
  111. def pbPermadeathActive?
  112.   return !pbPermadeathModeIs?(:NORMAL)
  113. end
  114.  
  115. class PokeBattle_Battle
  116.   # Keeps track of whether or not battle can be lost
  117.   attr_accessor :canlose
  118.   # Stores fainted Pokemon until end of battle (like a "purgatory")
  119.   attr_accessor :faintedlist
  120.  
  121.   alias permadeath_pbStartBattle pbStartBattle
  122.   def pbStartBattle(canlose=false)
  123.     @canlose = canlose
  124.     @faintedlist = []
  125.     permadeath_pbStartBattle(canlose)
  126.   end
  127.  
  128.   alias permadeath_pbReplace pbReplace
  129.   def pbReplace(index,newpoke,batonpass=false)
  130.     oldpoke=@battlers[index].pokemonIndex
  131.     permadeath_pbReplace(index,newpoke,batonpass)
  132.     # Party order is already changed in pbFaint, so undo party order change here
  133.     if pbPermadeathBattle? && pbOwnedByPlayer?(index) &&
  134.           oldpoke < $Trainer.party.length && $Trainer.party[oldpoke].fainted?
  135.       bpo=-1; bpn=@party1order.length-1
  136.       for i in 0...6
  137.         bpo=i if @party1order[i] > 5 && @party1order[i] < 12
  138.       end
  139.       p=@party1order[bpo]; @party1order[bpo]=@party1order[bpn]; @party1order[bpn]=p
  140.     end
  141.   end
  142.  
  143.   alias permadeath_pbEndOfRoundPhase pbEndOfRoundPhase
  144.   def pbEndOfRoundPhase
  145.     # Cancel effect of Future Sight from dead Pokemon
  146.     if pbPermadeathBattle?
  147.       priority = pbPriority
  148.       for i in priority
  149.         next if !i || i.fainted?
  150.         next if i.effects[PBEffects::FutureSightUserPos] < 0
  151.         next if pbIsOpposing?(i.effects[PBEffects::FutureSightUserPos])
  152.         attacker = @party1[i.effects[PBEffects::FutureSightUser]]
  153.         if attacker.fainted?
  154.           i.effects[PBEffects::FutureSight]        = 0
  155.           i.effects[PBEffects::FutureSightMove]    = 0
  156.           i.effects[PBEffects::FutureSightUser]    = -1
  157.           i.effects[PBEffects::FutureSightUserPos] = -1
  158.         end
  159.       end
  160.     end
  161.     permadeath_pbEndOfRoundPhase
  162.     pbRemoveFainted
  163.   end
  164.  
  165.   alias permadeath_pbEndOfBattle pbEndOfBattle
  166.   def pbEndOfBattle(canlose=false)
  167.     pbRemoveFainted
  168.     permadeath_pbEndOfBattle(canlose)
  169.     if pbPermadeathBattle? && pbPermadeathModeIs?(:SOFT)
  170.       for i in @faintedlist
  171.         storedbox = $PokemonStorage.pbStoreCaught(i)
  172.       end
  173.     end
  174.   end
  175.  
  176.   def pbPermadeathBattle?
  177.     return pbPermadeathActive? && !@canlose
  178.   end
  179.  
  180.   def pbRemoveFainted
  181.     return if !pbPermadeathBattle?
  182.     pokeindex = 0
  183.     # Loop through Trainer's party
  184.     loop do
  185.       break if pokeindex >= $Trainer.party.length
  186.       if @party1[pokeindex] && @party1[pokeindex].isFainted?
  187.         # Begin by deleting Pokemon from party entirely
  188.         @faintedlist.push($Trainer.party[pokeindex])
  189.         $Trainer.party.delete_at(pokeindex)
  190.         $PokemonTemp.evolutionLevels.delete_at(pokeindex)
  191.         $PokemonTemp.heartgauges.delete_at(pokeindex) if $PokemonTemp.heartgauges
  192.         # Remove from double battle party as well
  193.         if @doublebattle && $PokemonGlobal.partner
  194.           @party1[pokeindex] = nil
  195.           for i in pokeindex...5
  196.             @party1[i] = @party1[i + 1]
  197.           end
  198.           @party1[5] = nil
  199.         end
  200.         # Fix party positions of current battlers
  201.         if @battlers[0].pokemonIndex == pokeindex
  202.           @battlers[0].pokemonIndex = $Trainer.party.length
  203.         elsif @battlers[0].pokemonIndex > pokeindex
  204.           @battlers[0].pokemonIndex -= 1
  205.         end
  206.         if @doublebattle && !$PokemonGlobal.partner
  207.           if @battlers[2].pokemonIndex == pokeindex
  208.             @battlers[2].pokemonIndex = $Trainer.party.length
  209.             @battlers[2].pokemonIndex += 1 if @battlers[2].pokemonIndex == @battlers[0].pokemonIndex
  210.           elsif @battlers[2].pokemonIndex > pokeindex
  211.             @battlers[2].pokemonIndex -= 1
  212.           end
  213.         end
  214.         # Fix participants for exp gains
  215.         for i in [1, 3]
  216.           next if !@battlers[i]
  217.           participants = @battlers[i].participants
  218.           for j in 0...participants.length
  219.             next if !participants[j]
  220.             participants[j] -= 1 if participants[j] > pokeindex
  221.           end
  222.         end
  223.         pokeindex -= 1
  224.       end
  225.       pokeindex += 1
  226.     end
  227.     # Reset party order as shown on summary screen
  228.     for i in 0...6
  229.       @party1order[i] = i
  230.     end
  231.     # Put left side (or only) battler in first spot
  232.     if @battlers[0].pokemonIndex != @party1order[0] &&
  233.             @battlers[0].pokemonIndex < $Trainer.party.length
  234.       oldpokeindex = @party1order.index(@battlers[0].pokemonIndex)
  235.       oldpoke = @party1order[0]
  236.       @party1order[0] = @battlers[0].pokemonIndex
  237.       @party1order[oldpokeindex] = oldpoke
  238.     end
  239.     # If right side battler exists, put in second spot
  240.     # unless left side battler is gone, then put in first spot
  241.     if @doublebattle && !$PokemonGlobal.partner
  242.       poi = $Trainer.ablePokemonCount > 1 ? 1 : 0
  243.       if @battlers[2].pokemonIndex != @party1order[poi] &&
  244.               @battlers[2].pokemonIndex < $Trainer.party.length
  245.         oldpokeindex = @party1order.index(@battlers[2].pokemonIndex)
  246.         oldpoke = @party1order[poi]
  247.         @party1order[poi] = @battlers[2].pokemonIndex
  248.         @party1order[oldpokeindex] = oldpoke
  249.       end
  250.     end
  251.     # End battle if player's entire party is gone
  252.     @decision = 2 if $Trainer.ablePokemonCount == 0
  253.   end
  254. end
  255.  
  256. class PokeBattle_Battler
  257.   alias permadeath_pbFaint pbFaint
  258.   def pbFaint(showMessage=true)
  259.     return true if @fainted || !fainted?
  260.     ret = permadeath_pbFaint(showMessage)
  261.     if @battle.pbPermadeathBattle? && @battle.pbOwnedByPlayer?(@index)
  262.       if showMessage && pbPermadeathModeIs?(:NUZLOCKE)
  263.         if @battle.party1[@pokemonIndex].hasItem?
  264.           # Informs player that fainted's held item was transferred to bag
  265.           @battle.pbDisplayPaused(_INTL("{1} is dead! You picked up its {2}.",
  266.               pbThis, PBItems.getName(@battle.party1[@pokemonIndex].item)))
  267.         else
  268.           @battle.pbDisplayPaused(_INTL("{1} is dead!",pbThis))
  269.         end
  270.       end
  271.       # Remove fainted from party order
  272.       pokeindex = @battle.party1order.index(@pokemonIndex)
  273.       for i in pokeindex...5
  274.         @battle.party1order[i] = @battle.party1order[i + 1]
  275.       end
  276.       @battle.party1order[5] = 100
  277.       # Remove fainted from opposing participants arrays
  278.       @battle.battlers[1].participants.delete(@pokemonIndex)
  279.       if @battle.doublebattle && @battle.battlers[3].participants
  280.         @battle.battlers[3].participants.delete(@pokemonIndex)
  281.       end
  282.       # Add held item to bag
  283.       if @battle.party1[@pokemonIndex].hasItem? && pbPermadeathModeIs?(:NUZLOCKE)
  284.         $PokemonBag.pbStoreItem(@battle.party1[@pokemonIndex].item)
  285.       end
  286.     end
  287.     return ret
  288.   end
  289. end
  290.  
  291. # Removes Pokemon fainted by poison
  292. Events.onStepTakenTransferPossible+=proc {|sender,e|
  293.   if $PokemonGlobal.stepcount%4==0 && POISONINFIELD
  294.     $Trainer.party.delete_if{|poke|
  295.       if pbPermadeathActive? && poke.fainted?
  296.         if pbPermadeathModeIs?(:SOFT)
  297.           $PokemonStorage.pbStoreCaught(poke)
  298.         else
  299.           if poke.hasItem?
  300.             # Informs player that fainted's held item was transferred to bag
  301.             Kernel.pbMessage(_INTL("{1} is dead... You picked up its {2}.",
  302.                 poke.name, PBItems.getName(poke.item)))
  303.           else
  304.             Kernel.pbMessage(_INTL("{1} is dead...",poke.name))
  305.           end
  306.           $PokemonBag.pbStoreItem(poke.item) if poke.hasItem?
  307.         end
  308.         true
  309.       end
  310.     }
  311.   end
  312. }
  313.  
  314. # Sends player back to title screen if all Pokemon lost
  315. module Kernel
  316.   class << Kernel
  317.     alias permadeath_pbStartOver pbStartOver
  318.   end
  319.  
  320.   def self.pbStartOver(gameover=false)
  321.     if pbPermadeathActive?
  322.       if pbInBugContest?
  323.         Kernel.pbBugContestStartOver
  324.         return
  325.       end
  326.       Kernel.pbMessage(_INTL("\\w[]\\wm\\c[8]\\l[3]GAME OVER!"))
  327.       Kernel.pbCancelVehicles
  328.       pbRemoveDependencies
  329.       $game_temp.to_title = true
  330.     else
  331.       self.permadeath_pbStartOver(gameover)
  332.     end
  333.   end
  334. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top