PDA

View Full Version : [Essentials script] Hansiec's Mystery Gift System


Umbreon
October 22nd, 2012, 08:10 AM
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:


=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.

Maruno
October 22nd, 2012, 09:20 AM
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.

Umbreon
October 22nd, 2012, 09:32 AM
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.

~Angel~
October 22nd, 2012, 09:51 AM
<-- Something I did not know o_o That you were Ho-Oh112. But, Nice job.

Umbreon
October 22nd, 2012, 10:03 AM
<-- Something I did not know o_o That you were Ho-Oh112. But, Nice job.

Thanks.

@Maruno -- I added all (or most) of your improvements, the pokemon should now never fail to load even if you make heavy changes to it, eggs now have lots more options, ect.

krakacen
October 25th, 2012, 04:49 PM
Can do a tutorial to create the gift and how to get it?

Umbreon
October 26th, 2012, 07:03 AM
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.
November 5th, 2012, 12:17 PM
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.

Umbreon
November 5th, 2012, 12:41 PM
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.