• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Hansiec's Mystery Gift System

1,748
Posts
14
Years
  • Intro:
    Alright, for those of you who don't know I am Ho-oh 112 ok, and I thought to re-make my mystery gift system from scratch making it better in a few places.

    The Code:

    Code:
    =begin
      * Mystery Gift
      
      * By Hansiec
      
      * Allows for the game's host to give out items via the internet
      
      * Gifts supported:
        Eggs
        Pokemon
        Items
        Game Variables
        Game Switches
        
      * TODO:
        Add Badge checks
        Add Mystery Cards (storing 3 gifts by default)
        Add more gift types (script execution support, badge support, ect.)
        Add a GUI (Graphical User Interface)
        Add Menu Support (From the load menu)
        Add Anything worth while from user requests
        
      Although there may only be 1 per gift.
      
      * Full Features:
        Obviously supports gifts of the things above
        Allows for downloaded gifts (if you know what I mean by this)
        No Switches/Variables needed to work this
        Built in Encryption/Mystery Gift Creator
        A Custom Encryption Key (below this commentary) for better safety
        Only 1 gift per person (unless you change the gift)
        Everyone get's the EXACT SAME GIFT right down to the personalID of a pokemon.
        
        
        Do not mistake this for Raptor's Mystery Gift System as this is coded in a
        different manor (Yes this is needed to say as of complaints of my previous
        system)
        
      * Call Methods:
        (Normally you call with MysteryGift.function)
        MysteryGift.create_x (x being egg/pokemon/item/variable/switch/pglobal)
         * This creates a mystery gift code (depending on what you selected)
        MysteryGift.get_gift(url) (url being the url of your gift)
         * This downloads and attempts to give you the selected gift. I have done some
           checks against hacks/double gifts but I most likely missed some.
           
           
      Improvements:
        Added a never to fail pokemon compiler
        Added more features to the eggs
        Added a check if $PokemonGlobal.last_gift exists
        Added a default URL (although you can use something else)
        Added a/an check for the pokemon and it actually displays the correct info.
        Added a confirmation message after making the gift code
        Added a default file to save your gift codes in (MysteryGift.txt)
        Removed the PokemonGlobal option
    =end
    
    ENCRYPTION_KEY = "any string here! 0.o o.0 0.0 o.o ??>><<??"
    GIFT_DEFAULT_URL = "http://localhost/MysteryGift.txt"
    
    class PokeBattle_Pokemon
    =begin
      def to_s
        moves=[]
        for i in 0..3
          if @moves[i] != nil
            moves[i] = [@moves[i].id, @moves[i].ppup]
          else
            moves[i] = [-1, -1]
          end
        end
        ary=[
        @iv[0],
        @iv[1],
        @iv[2],
        @iv[4],
        @iv[5],
        @iv[6],
        @ev[0],
        @ev[1],
        @ev[2],
        @ev[4],
        @ev[5],
        @ev[6],
        @species,
        @personalID,
        @trainerID,
        @pokerus,
        @item,
        @name,
        @exp,
        @happiness,
        @status,
        @statusCount,
        @eggsteps,
        moves[0][0],
        moves[0][1],
        moves[1][0],
        moves[1][1],
        moves[2][0],
        moves[2][1],
        moves[3][0],
        moves[3][1],
        @ballused,
        @obtainMap,
        @obtainLevel,
        @hatchedMap,
        @language,
        @ot,
        @otgender,
        @abilityflag.to_i,
        @genderflag.to_i,
        @natureflag,
        @shinyflag.to_i,
        @cool,
        @beauty,
        @smart,
        @tough,
        @cute,
        @sheen,
        isShadow?.to_i
        ]
        str=""
        for i in ary
          str+=i.to_s+"!@#"
        end
        return str
      end
    =end
      def to_s
        save_data(self,"TEMP_FILE")
        f=File.open("TEMP_FILE", 'rb')
        data=""
        data+=f.read while !f.eof?
        f.close
        File.delete("TEMP_FILE")
        return data
      end
    end
    
    # The below methods add simple to_i and to_b values for the booleans and fixnums
    class TrueClass
      def to_i
        return 1
      end
    end
    
    class FalseClass
      def to_i
        return 0
      end
    end
    
    class Fixnum
      def to_b
        if self == 1
          ret = true
        else
          ret = false
        end
        return ret
      end
    end
    
    
    # Adds the methods to_mpokemon and crypt to the string class
    class String
    =begin
      def to_mpokemon
        ary=self.split("!@#")
        ret = PokeBattle_Pokemon.new(1,1)
        for i in 0..ret.iv.length-1
          ret.iv[i]=ary[i].to_i
        end    
        for i in 0..ret.ev.length-1
          ret.ev[i]=ary[i+5].to_i
        end
        ret.species=ary[12].to_i
        ret.personalID=ary[13].to_i
        ret.trainerID=ary[14].to_i
        ret.pokerus=ary[15].to_i
        ret.item=ary[16].to_i
        ret.name=ary[17]
        ret.exp=ary[18].to_i
        ret.happiness=70
        ret.status=ary[20].to_i
        ret.statusCount=ary[21].to_i
        ret.eggsteps=ary[22].to_i
        moves=[[ary[23].to_i,ary[24].to_i],[ary[25].to_i,ary[26].to_i],
        [ary[27].to_i,ary[28].to_i],[ary[29].to_i,ary[30].to_i]]
        ret.ballused=ary[31].to_i
        ret.obtainMode=4 # Fateful Encounter
        ret.obtainMap=ary[32].to_i
        ret.obtainLevel=ary[33].to_i
        ret.hatchedMap=ary[34].to_i
        ret.language=ary[35].to_i
        ret.ot=ary[36]
        ret.otgender=ary[37].to_i
        ret.abilityflag=ary[38].to_i.to_b
        ret.genderflag=ary[39].to_i.to_b
        ret.natureflag=ary[40].to_i
        ret.shinyflag=ary[41].to_i.to_b
        ret.cool=ary[42].to_i
        ret.beauty=ary[43].to_i
        ret.smart=ary[44].to_i
        ret.tough=ary[45].to_i
        ret.cute=ary[46].to_i
        ret.sheen=ary[47].to_i
        ret.makeShadow if ary[48].to_i == 1 || ary[48] == "true"
        for i in 0..moves.length-1
          break if moves[i][0] == -1
          ret.moves[i] = PBMove.new(moves[i][0])
          ret.moves[i].ppup = moves[i][1]
        end
        ret.calcStats
        return ret
      end
    =end
      def to_mpokemon
        f=File.open("TEMP_FILE", 'wb')
        f.write(self)
        f.close
        ret=load_data("TEMP_FILE")
        File.delete("TEMP_FILE")
        return ret
      end
      
      def crypt(salt)
        ret=self
        for i in 0..length-1
          ret[i] ^= salt[i%salt.length-1]
        end
        return ret
      end
    end
    
    # Inserts the last gift variable to pokemon global so we don't need to use variables
    class PokemonGlobalMetadata
      attr_accessor :last_gift
      attr_accessor :mystery_items
      alias init_mystery initialize
      def initialize
        init_mystery
        init_mysterygift
      end
      
      def init_mysterygift
        @last_gift = ""
        @mystery_items = []
      end
    end
    
    
    # Our Mystery gift class
    class Mysterygift
      
      # Creates a file (of what you want to name it) with a code for a mystery gift egg
      def create_egg
        species=pbChooseSpeciesOrdered(1)
        dexdata=pbOpenDexData
        pbDexDataOffset(dexdata,getID(PBSpecies,species),21)
        eggsteps=dexdata.fgetw
        dexdata.close
        return if species < 1
        p=PokeBattle_Pokemon.new(species,EGGINITIALLEVEL)
        p.eggsteps = eggsteps
        params=ChooseNumberParams.new
        params.setRange(0,99999)
        params.setDefaultValue(0)
        p.form=Kernel.pbMessageChooseNumber(_INTL("Set the form."),params)
        p.shinyflag = 1 if Kernel.pbMessage(_INTL("Make the pokemon shiny"), ["Shiny", "Not Shiny"], 1) == 0
        p.makeShadow if Kernel.pbMessage(_INTL("Make the pokemon shadow"), ["Shadow", "Not Shadow"], 1) == 0
        p.ballused = $BallTypes[15] # Cherish ball
        p.ot = Kernel.pbMessageFreeText(_INTL("Enter an Owner"), "", false, 10)
        p.name = _INTL("Egg")
        p.item = pbChooseItemList(1)
        id = Kernel.pbMessageFreeText(_INTL("Enter a numer ID"), "", false, 5)
        if id.to_i > 0
          p.trainerID = id
        end
        for i in 0..3
          move = pbChooseMoveList
          p.moves[i] = PBMove.new(move) if move != 0
          p.resetMoves if move == 0 && i == 0
          break if move == 0
        end
        commands=[]
        (PBNatures.getCount).times do |i|
          commands.push(PBNatures.getName(i))
        end
        cmdwin=pbListWindow([],200)
        command=pbCommands2(cmdwin,commands,-1,0,true)
        if command>=0
          p.setNature(command)
          p.calcStats
        end
        g = Kernel.pbMessage(_INTL("Set the pokemon's gender"), ["Male", "Female"], 0)
        p.genderflag = g if p.genderflag != 2
        params=ChooseNumberParams.new
        params.setRange(0,2)
        params.setDefaultValue(0)
        p.abilityflag=Kernel.pbMessageChooseNumber(_INTL("Set ability flag."),params)
        fn=Kernel.pbMessageFreeText(_INTL("Enter a Filename"), "", false, 256)
        fn=fn.split("\r")[0]
        fn = "Mysterygift.txt" if fn == ""
        if fn != ""
          File.open(fn, "wb"){|f|
          f.write(p.to_s.crypt(ENCRYPTION_KEY))
          f.write("\npokemon")
          }
          Kernel.pbMessage(_INTL("Your mystery gift code has been saved in: {1}.", fn))
        end
      end
      
      # Creates a file (of what you want to name it) with a code for a mystery gift pokemon
      def create_pokemon
        species=pbChooseSpeciesOrdered(1)
        return if species < 1
        p=PokeBattle_Pokemon.new(species,1)
        params=ChooseNumberParams.new
        params.setRange(1,PBExperience::MAXLEVEL)
        params.setDefaultValue(0)
        level=Kernel.pbMessageChooseNumber(_INTL("Set the level."),params)
        return if level == 0
        p.level = level
        params=ChooseNumberParams.new
        params.setRange(0,99999)
        params.setDefaultValue(0)
        p.form=Kernel.pbMessageChooseNumber(_INTL("Set the form."),params)
        p.shinyflag = 1 if Kernel.pbMessage(_INTL("Make the pokemon shiny"), ["Shiny", "Not Shiny"], 1) == 0
        p.makeShadow if Kernel.pbMessage(_INTL("Make the pokemon shadow"), ["Shadow", "Not Shadow"], 1) == 0
        p.ballused = $BallTypes[15] # Cherish ball
        p.ot = Kernel.pbMessageFreeText(_INTL("Enter an Owner"), "", false, 256)
        n=Kernel.pbMessageFreeText(_INTL("Enter a nickname"), "", false, 10)
        p.name = n if n != ""
        p.item = pbChooseItemList(1)
        id = Kernel.pbMessageFreeText(_INTL("Enter a numer ID"), "", false, 5)
        if id.to_i > 0
          p.trainerID = id
        end
        for i in 0..3
          move = pbChooseMoveList
          p.moves[i] = PBMove.new(move) if move != 0
          p.resetMoves if move == 0 && i == 0
          break if move == 0
        end
        commands=[]
        (PBNatures.getCount).times do |i|
          commands.push(PBNatures.getName(i))
        end
        cmdwin=pbListWindow([],200)
        command=pbCommands2(cmdwin,commands,-1,0,true)
        if command>=0
          p.setNature(command)
          p.calcStats
        end
        g = Kernel.pbMessage(_INTL("Set the pokemon's gender"), ["Male", "Female"], 0)
        p.genderflag = g if p.genderflag != 2
        params=ChooseNumberParams.new
        params.setRange(0,2)
        params.setDefaultValue(0)
        p.abilityflag=Kernel.pbMessageChooseNumber(_INTL("Set ability flag."),params)
        fn=Kernel.pbMessageFreeText(_INTL("Enter a Filename"), "", false, 256)
        fn=fn.split("\r")[0]
        fn = "Mysterygift.txt" if fn == ""
        if fn != ""
          File.open(fn, "wb"){|f|
          f.write(p.to_s.crypt(ENCRYPTION_KEY))
          f.write("\npokemon")
          }
          Kernel.pbMessage(_INTL("Your mystery gift code has been saved in: {1}.", fn))
        end
      end
      
      # Creates a file (of what you want to name it) with a code for a mystery gift item
      def create_item
        item = pbChooseItemList(1)
        return if item == 0
        fn=Kernel.pbMessageFreeText(_INTL("Enter a Filename"), "", false, 256)
        fn=fn.split("\r")[0]
        fn = "Mysterygift.txt" if fn == ""
        if fn != ""
          f=File.open("#{fn}", "wb")
          f.write([item].to_s.crypt(ENCRYPTION_KEY))
          f.write("\nitem")
          f.close
          Kernel.pbMessage(_INTL("Your mystery gift code has been saved in: {1}.", fn))
        end
      end
      
      
      # Creates a file (of what you want to name it) with a code for a mystery gift variable
      def create_variable
        params=ChooseNumberParams.new
        params.setRange(1,5000)
        params.setDefaultValue(0)
        id=Kernel.pbMessageChooseNumber(_INTL("Select a variable id."),params)
        return if id == 0
        if Kernel.pbMessage(_INTL("Set as a string or an integer"), ["String", "Integer"], 0) == 0
          val = Kernel.pbMessageFreeText(_INTL("Set the variable's value"), "", false, 9999)
        else
          params=ChooseNumberParams.new
          params.setRange(1,999999999)
          params.setDefaultValue(0)
          val=Kernel.pbMessageChooseNumber(_INTL("Set the variable's value."),params)
        end
        fn=Kernel.pbMessageFreeText(_INTL("Enter a Filename"), "", false, 256)
        fn=fn.split("\r")[0]
        fn = "Mysterygift.txt" if fn == ""
        if fn != ""
          f=File.open("#{fn}", "wb")
          v=""
          v="i" if val.is_a?(Numeric)
          f.write("#{id},#{val},#{v}".crypt(ENCRYPTION_KEY))
          f.write("\nvar")
          f.close
          Kernel.pbMessage(_INTL("Your mystery gift code has been saved in: {1}.", fn))
        end
      end
      
      
      # Creates a file (of what you want to name it) with a code for a mystery gift switch
      def create_switch
        params=ChooseNumberParams.new
        params.setRange(1,5000)
        params.setDefaultValue(0)
        id=Kernel.pbMessageChooseNumber(_INTL("Select a switch id."),params)
        val = Kernel.pbConfirmMessage(_INTL("Set the switch's value"), ["True", "False"], 0).to_b
        fn=Kernel.pbMessageFreeText(_INTL("Enter a Filename"), "", false, 256)
        fn=fn.split("\r")[0]
        fn = "Mysterygift.txt" if fn == ""
        if fn != ""
          f=File.open("#{fn}", "wb")
          f.write("#{id},#{val}".crypt(ENCRYPTION_KEY))
          f.write("\swt")
          f.close
          Kernel.pbMessage(_INTL("Your mystery gift code has been saved in: {1}.", fn))
        end
      end
      
      # Actual mystery gift function to call for
      def get_gift(url=GIFT_DEFAULT_URL)
        $PokemonGlobal.init_mysterygift if $PokemonGlobal.last_gift == nil
        string = pbDownloadToString(url)
        if string == ""
          Kernel.pbMessage(_INTL("Unable to connect to the server, cannot get the gift."))
          return false
        end
        if string == $PokemonGlobal.last_gift
          Kernel.pbMessage(_INTL("You have already received this gift!"))
          return false
        end
        data = string.split("\n")
        if data.length > 2
          for i in 0..data.length-2
            data[0]+="\n"+data[i+1]
          end
          data[1]=data[data.length-1]
        end
        if data[1].include?("item")
          #Kernel.pbReceiveItem(data[0].crypt(ENCRYPTION_KEY).to_i)
          $PokemonGlobal.mystery_items.push(data[0].crpyt(ENCRYPTION_KEY).to_i)
        elsif data[1].include?("pokemon")
          poke=data[0].crypt(ENCRYPTION_KEY).to_mpokemon
          if pbAddPokemonSilent(poke)
            name=PBSpecies.getName(poke.species)
            if poke.eggsteps > 0
              name = "Egg"
            end
            x = "a"
            # this small snippet determines if we must say a or an
            vowels = ["a", "e", "i", "o", "u", "A", "E", "I", "O", "U"]
            for i in vowels
              if name[0] == i[0]
                x = "an"
                break
              end
            end
            Kernel.pbMessage(_INTL("You have received {3} {1} from {2}!", name,poke.ot,x))
          end
        elsif data[1].include?("var")
          dat=data[0].crypt(ENCRYPTION_KEY).split(",")
          dat[1]=dat[1].to_i if dat[2]=="i"
          $game_variables[dat[0].to_i]=dat[1]
        elsif data[1].include?("swt")
          dat=data[0].crypt(ENCRYPTION_KEY).split(",")
          $game_switches[dat[0].to_i]=dat[1].to_i.to_b
        elsif data[1].include?("eval")
          eval(data[0].crypt(ENCRYPTION_KEY))
        end
        return true
      end
      
      def has_gifts?
        $PokemonGlobal.init_mysterygift if $PokemonGlobal.mystery_items == nil
        return $PokemonGlobal.mystery_items.length > 0
      end
      
      def give_items
        for i in 0..$PokemonGlobal.mystery_items.length-1
          Kernel.pbReceiveItem($PokemonGlobal.mystery_items[i])
          if i < $PokemonGlobal.mystery_items.length-1
            Kernel.pbMessage(_INTL("Oh it seems as if I still have some packages for you."))
          end
        end
      end
      
    end
    # initializes the mystery gift class as MysteryGift
    MysteryGift = Mysterygift.new

    Also, I made this in a class form and made it as different as possible to raptor's trade system so I don't need to go down that road again.


    Finally, I am open to suggestions as long as they are worth it.

    Please before complaining of an error, be sure that you try this on a clean version of essentials, as all the functions (except the pokemon global function) has been tested and succeeded, or you may just be using this wrong. I did not setup a test gift like last time so there is no actual example.

    Also, there is a description of every function and what it does and how to call them normally.
     
    Last edited:

    Maruno

    Lead Dev of Pokémon Essentials
    5,285
    Posts
    16
    Years
  • I haven't tried this out, but here's a few things I noticed when reading through the code:

    You have a very wordy way of saving a Pokémon's details to a string and back. It's also not future-proof, as it would need to be changed if any property of a Pokémon was to change/be added.

    When creating a Mystery Gift file, there's no confirmation message that the file was in fact created (nor error message if it wasn't). If there's an error, you have to type in everything again from the start (which is an utter pain for Pokémon, which most Mystery Gifts will be).

    Speaking of Pokémon, eggs should be allowed to be customised in (almost) every way that Pokémon can be. Pichu with Volt Tackle, for instance.

    I don't think it's useful to include a PokemonGlobal option, since anything it might be used for can just as easily be done with a Global Variable. Your code also implies that the Mystery Gift itself creates the scripts required to use the PokemonGlobal variable... which should already exist, otherwise there would be crashes when the game tries to check that variable but can't because it doesn't exist (and if the game doesn't check it at all, what's the point of creating it halfway through the game? It still won't be used).

    It would be nice if the url of the Mystery Gift file was a string variable in the scripts (like a Setting). It would be more convenient than using it as an argument in the method's call.
     
    1,748
    Posts
    14
    Years
  • I haven't tried this out, but here's a few things I noticed when reading through the code:

    You have a very wordy way of saving a Pokémon's details to a string and back. It's also not future-proof, as it would need to be changed if any property of a Pokémon was to change/be added.

    When creating a Mystery Gift file, there's no confirmation message that the file was in fact created (nor error message if it wasn't). If there's an error, you have to type in everything again from the start (which is an utter pain for Pokémon, which most Mystery Gifts will be).

    Speaking of Pokémon, eggs should be allowed to be customised in (almost) every way that Pokémon can be. Pichu with Volt Tackle, for instance.

    I don't think it's useful to include a PokemonGlobal option, since anything it might be used for can just as easily be done with a Global Variable. Your code also implies that the Mystery Gift itself creates the scripts required to use the PokemonGlobal variable... which should already exist, otherwise there would be crashes when the game tries to check that variable but can't because it doesn't exist (and if the game doesn't check it at all, what's the point of creating it halfway through the game? It still won't be used).

    It would be nice if the url of the Mystery Gift file was a string variable in the scripts (like a Setting). It would be more convenient than using it as an argument in the method's call.


    Alright then, I'll get to adding these improvements in.
     
    1,748
    Posts
    14
    Years
  • Can do a tutorial to create the gift and how to get it?

    after you create a gift (as stated above) upload the file you've just created (usually you save it into a text file) to a website where you can view the file as a webpage (like stated in my previous system where I used webs.com) afterwards take the link there and put it into my link I used for testing (localhost://MysteryGift.txt) and test it.
     

    Rayquaza.

    Lead Dev in Pokémon Order and Chaos
    702
    Posts
    12
    Years
  • Could you provide some sort of a template on eggs, pokemon and so on? I'm completely clueless to what you were trying to say in the last tutorial.
     
    1,748
    Posts
    14
    Years
  • Code:
    Mysterygift.create_egg # creates an egg (inside the file of choosing)
    Mysterygift.create_pokemon # creates a pokemon (inside the file of choosing)
    Mysterygift.create_item # creates an item (inside the file of choosing)
    # continue on to things like switchs/variables/ect.

    Upload the file (created with one of the above functions) to a place where you can download it (the direct download link, rapidshare, mediafire, ect. won't work) again you may use webs.com stated in my other one

    Then finally grab the link of the file and paste it into the "" on the GIFT_DEFAULT_URL line. Finally test it and report errors.
     
    Back
    Top