- Pokémon Essentials Version
 - v19.1 ➖
 
Code
			
				Ruby:
			
		
		
		module Settings
  # Players can use Pokemon that are not yet the required type,
  #but can evolve into it
  PREVOS_INCLUDED = true
end
class PokemonGlobalMetadata
  attr_accessor :monotype
end
#Sets the given variable to the ID number of the type used in the run
def pbSetMonoVariables(varnum)
  $game_variables[varnum] = GameData::Type.get($PokemonGlobal.monotype).id_number
end
#Returns true if a monotype run is active
def pbMonoActive?
  return true if $PokemonGlobal.monotype
end
#Turns off monotype run
def pbEndMono
  $PokemonGlobal.monotype = nil
end
def pbChooseMono
  choices = []
  GameData::Type.each do |type|
    choices.push(type.real_name) if !type.pseudo_type
  end
  choices.push(_INTL("Cancel"))
  choice = pbMessage(_INTL("Which type would you like to use?"),choices,choices.length)
  choice = choices[choice]
  if choice != "Cancel"
    choice = choice.upcase.to_sym
    $PokemonGlobal.monotype = choice
  end
end
module GameData
  class Species
    #Adapted from Pokemon class
    # @return [Array<Symbol>] an array of this Pokémon's types
    def types
      ret = [self.type1]
      ret.push(self.type2) if self.type2 && self.type2 != self.type1
      return ret
    end
 
    # @param type [Symbol, String, Integer] type to check
    # @return [Boolean] whether this Pokémon has the specified type
    def hasType?(type)
      type = GameData::Type.get(type).id
      return self.types.include?(type)
    end
    #New utilities:
    def can_evolve_into_usable?(type,exclude_invalid = true)
      @evolutions.each do |evo|
        next if evo[3]   # Is the prevolution
        next if evo[1] == :None && exclude_invalid
        species = GameData::Species.get(evo[0])
        return true if species.usable_monotype?(type)
      end
      return false
    end
    
  
    def usable_monotype?(type=$PokemonGlobal.monotype)
      return true if type==nil
      return true if self.hasType?(type)
      return true if self.can_evolve_into_usable?(type) && Settings::PREVOS_INCLUDED
      return false
    end
  
  end
end
  
class Pokemon
 
  # The core method that performs evolution checks. Needs a block given to it,
  # which will provide either a GameData::Species ID (the species to evolve
  # into) or nil (keep checking).
  # @return [Symbol, nil] the ID of the species to evolve into
  def check_evolution_internal
    return nil if egg? || shadowPokemon?
    return nil if hasItem?(:EVERSTONE)
    return nil if hasAbility?(:BATTLEBOND)
    species_data.get_evolutions(true).each do |evo|   # [new_species, method, parameter, boolean]
      next if evo[3]   # Prevolution
      species = GameData::Species.get(evo[0])
      next if !species.usable_monotype?
      ret = yield self, evo[0], evo[1], evo[2]   # pkmn, new_species, method, parameter
      return ret if ret
    end
    return nil
  end
 
  def usable_monotype?(type=$PokemonGlobal.monotype)
    return GameData::Species.get_species_form(self.species,self.form).usable_monotype?
  end
end
#===============================================================================
# Giving Pokémon to the player (will send to storage if party is full)
#===============================================================================
def pbAddPokemon(pkmn, level = 1, see_form = true)
  return false if !pkmn
  if pbBoxesFull?
    pbMessage(_INTL("There's no more room for Pokémon!\1"))
    pbMessage(_INTL("The Pokémon Boxes are full and can't accept any more!"))
    return false
  end
  pkmn = Pokemon.new(pkmn, level) if !pkmn.is_a?(Pokemon)
  if !pkmn.usable_monotype?
    type = GameData::Type.get($PokemonGlobal.monotype).real_name
    pbMessage(_INTL("#{pkmn.speciesName} can't be used in a monotype #{type} challenge."))
    return false
  end
  species_name = pkmn.speciesName
  pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[80]\1", $Trainer.name, species_name))
  pbNicknameAndStore(pkmn)
  $Trainer.pokedex.register(pkmn) if see_form
  return true
end
def pbAddPokemonSilent(pkmn, level = 1, see_form = true)
  return false if !pkmn || pbBoxesFull?
  pkmn = Pokemon.new(pkmn, level) if !pkmn.is_a?(Pokemon)
  return false if !pkmn.usable_monotype?
  $Trainer.pokedex.register(pkmn) if see_form
  $Trainer.pokedex.set_owned(pkmn.species)
  pkmn.record_first_moves
  if $Trainer.party_full?
    $PokemonStorage.pbStoreCaught(pkmn)
  else
    $Trainer.party[$Trainer.party.length] = pkmn
  end
  return true
end
#===============================================================================
# Giving Pokémon/eggs to the player (can only add to party)
#===============================================================================
def pbAddToParty(pkmn, level = 1, see_form = true)
  return false if !pkmn || $Trainer.party_full?
  pkmn = Pokemon.new(pkmn, level) if !pkmn.is_a?(Pokemon)
  if !pkmn.usable_monotype?
    type = GameData::Type.get($PokemonGlobal.monotype).real_name
    pbMessage(_INTL("#{pkmn.speciesName} can't be used in a monotype #{type} challenge."))
    return false
  end
  species_name = pkmn.speciesName
  pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[80]\1", $Trainer.name, species_name))
  pbNicknameAndStore(pkmn)
  $Trainer.pokedex.register(pkmn) if see_form
  return true
end
def pbAddToPartySilent(pkmn, level = nil, see_form = true)
  return false if !pkmn || $Trainer.party_full?
  pkmn = Pokemon.new(pkmn, level) if !pkmn.is_a?(Pokemon)
  return false if !pkmn.usable_monotype?
  $Trainer.pokedex.register(pkmn) if see_form
  $Trainer.pokedex.set_owned(pkmn.species)
  pkmn.record_first_moves
  $Trainer.party[$Trainer.party.length] = pkmn
  return true
end
def pbAddForeignPokemon(pkmn, level = 1, owner_name = nil, nickname = nil, owner_gender = 0, see_form = true)
  return false if !pkmn || $Trainer.party_full? || !pkmn.usable_monotype?
  pkmn = Pokemon.new(pkmn, level) if !pkmn.is_a?(Pokemon)
  if !pkmn.usable_monotype?
    type = GameData::Type.get($PokemonGlobal.monotype).real_name
    pbMessage(_INTL("#{pkmn.speciesName} can't be used in a monotype #{type} challenge."))
    return false
  end
  # Set original trainer to a foreign one
  pkmn.owner = Pokemon::Owner.new_foreign(owner_name || "", owner_gender)
  # Set nickname
  pkmn.name = nickname[0, Pokemon::MAX_NAME_SIZE] if !nil_or_empty?(nickname)
  # Recalculate stats
  pkmn.calc_stats
  if owner_name
    pbMessage(_INTL("\\me[Pkmn get]{1} received a Pokémon from {2}.\1", $Trainer.name, owner_name))
  else
    pbMessage(_INTL("\\me[Pkmn get]{1} received a Pokémon.\1", $Trainer.name))
  end
  pbStorePokemon(pkmn)
  $Trainer.pokedex.register(pkmn) if see_form
  $Trainer.pokedex.set_owned(pkmn.species)
  return true
end
def pbGenerateEgg(pkmn, text = "")
  return false if !pkmn || $Trainer.party_full?
  pkmn = Pokemon.new(pkmn, Settings::EGG_LEVEL) if !pkmn.is_a?(Pokemon)
  if !pkmn.usable_monotype?
    type = GameData::Type.get($PokemonGlobal.monotype).real_name
    pbMessage(_INTL("#{pkmn.speciesName} can't be used in a monotype #{type} challenge."))
    return false
  end
  # Set egg's details
  pkmn.name           = _INTL("Egg")
  pkmn.steps_to_hatch = pkmn.species_data.hatch_steps
  pkmn.obtain_text    = text
  pkmn.calc_stats
  # Add egg to party
  $Trainer.party[$Trainer.party.length] = pkmn
  return true
end
alias pbAddEgg pbGenerateEgg
alias pbGenEgg pbGenerateEgg
def pbStartTrade(pokemonIndex,newpoke,nickname,trainerName,trainerGender=0)
  myPokemon = $Trainer.party[pokemonIndex]
  opponent = NPCTrainer.new(trainerName,trainerGender)
  opponent.id = $Trainer.make_foreign_ID
  yourPokemon = nil
  resetmoves = true
  if newpoke.is_a?(Pokemon)
    newpoke.owner = Pokemon::Owner.new_from_trainer(opponent)
    yourPokemon = newpoke
    resetmoves = false
  else
    species_data = GameData::Species.try_get(newpoke)
    raise _INTL("Species does not exist ({1}).", newpoke) if !species_data
    yourPokemon = Pokemon.new(species_data.id, myPokemon.level, opponent)
  end
  if !yourPokemon.usable_monotype?
    pbMessage(_INTL("#{pkmn.speciesName} can't be used in a monotype #{type} challenge."))
    return false
  end
  yourPokemon.name          = nickname
  yourPokemon.obtain_method = 2   # traded
  yourPokemon.reset_moves if resetmoves
  yourPokemon.record_first_moves
  $Trainer.pokedex.register(yourPokemon)
  $Trainer.pokedex.set_owned(yourPokemon.species)
  pbFadeOutInWithMusic {
    evo = PokemonTrade_Scene.new
    evo.pbStartScreen(myPokemon,yourPokemon,$Trainer.name,opponent.name)
    evo.pbTrade
    evo.pbEndScreen
  }
  $Trainer.party[pokemonIndex] = yourPokemon
end
	There is, unfortunately, one additional step to take- find this section in Item_BattleEffects -
			
				Ruby:
			
		
		
		    if battler.semiInvulnerable?
      scene.pbDisplay(_INTL("It's no good! It's impossible to aim at a Pokémon that's not in sight!")) if showMessages
      next false
    end
	
			
				Ruby:
			
		
		
		    species = GameData::Species.get(battler.species)
    if !species.usable_monotype?
      type = GameData::Type.get($PokemonGlobal.monotype).real_name
      scene.pbDisplay(_INTL("You can't catch this Pokémon in a monotype #{type} challenge!"),) if showMessages
      next false
    end
	Using this Script
The setting PREVOS_INCLUDED at the top is to allow for Pokemon that gain or change types on evolving. For example, in a Fire run, you would still be able to use Eevee, because it can evolve into Flareon.There's a fair number of calls here-
pbChooseMonohas the player choose the type to use, or none at all. (The list is pulled from the Types database, you shouldn't have to do anything to adjust it for new types you add)pbMonoActive?returns true if monotype rules are in place. You could use this as a global switch by naming a switchs:pbMonoActive?pbSetMonoVariables(x)sets game variable x to the ID number of the type being used- 0 for Normal, 1 for Fighting, and so on. (Unfortunately, since variables are 0 by default, you'll have to either combine it with pbMonoActive?- or, if you don't think it'll be too confusing, add 1 to the variable again and just work with the values offset)pbEndMonoremoves the challenge rules. It doesn't do anything else- be sure to give any prizes or anything before you take them off!- The script call 
$PokemonGlobal.monotypewill return the internal name of the type being used. 
While a challenge run is in play:
- If a Pokemon isn't eligible for the run (has the required type or can evolve into the required type), the player can't receive it through gifts (egg or standard), through catching (will get a message like when you try to catch in doubles), or through trading.
 - Every script that gives a Pokemon will return false if it can't be used in the monotype challenge. Be sure to avoid any potential softlocks for the player!
 - Pokemon can only evolve if their evolution is eligible for the run. This should, to my knowledge, account for all stages in a chain- for example, you can obtain Caterpie in a mono Flying run, because it will evolve into Metapod, which will evolve into Butterfree.
 
Future Goals
- Get a nicer UI rather than just selecting from text
 - Figure out the deal with the Poke Ball handler so I can make this completely plug-n-play
 
- Credits
 - Credits to TechSkylander1518, please!
 
	
