Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Special Support - A great place to learn to Script

Everyone wants to learn to script, but no one really knows where to start. In my honest opinion, the best place to learn is just by reading the default scripts. I learned to script with the japanese RMXP, so I didn't have English comments at my disposal, so everyone of the new generation has that upperhand. Anyways, what I think the best thing to do to learn to script is read the default scripts, and understand each line.

So what I am offering here is support for anyone trying to learn to script. If there is a line of code you don't understand, ask me here. If there is something you want to know, like where in the script editor does something happen, ask here.
  • Ask about a certain line of code : What it means, does, etc.
  • Ask where the coding is for a certain function
PLEASE DO NOT ASK SOMETHING OTHER THAN EXISTING CODE, OR WHERE IN THE DEFAULT SCRIPTS TO FIND A CERTAIN BLOCK OF CODE. Your post will be deleted.

This is a Trial and Error topic. Hopefully, it can lead to more a use full FAQ for beginners.
 
im not quite sure where to post this question so i thought this area with the scripting might be a good place i found a script that makes rmxp script compatible with rmvx. So i thought i'd try out the triple triad script and i get this same error in several of the scripts for it. Line 30 the line number varie's from each script a few lines or so

line 30 Name error occured unitialized constant SDK

i get this error with each of these scripts

Triple Triad 1
Triple Triad 2
Triple Triad 3
Triple Triad 4
Triple Triple comp
Triple Triad EP 1
The RMXP SDK   

the same error comes up with all of them can someone help please ? :cry:
 
Put the SDK script BEFORE the Triple Triad scripts at the Script list. It should work now.
If it doesn't, probably that "RMXP script compatibility" RMVX script (O_Õ) doesn't work. OR you may have to change its position (to the end?/to the beggining?) at the Scripts list.

SEE YA!!!!!
Ps: Yeah, script order matters.
 
@Seph: Nice topic indeed, though however, it slowly becomes a 'help me setup the SDK' thread :p Either way, since the whole looking-at-default-scripts is the way to go really, I guess this topic deserves is spot, even though it's slightly misused... you should add that to your signature spoiler, btw.

So yeah, I skipped most of what I was already aware of, and I surprisingly early ended up on the last page... either way, the only question coming to my mind is regarding the gsub(!) method, the way they're used in Window_Message... this is from VX, btw:
Code:
class Window_Message < Window_Selectable
  #--------------------------------------------------------------------------
  def convert_special_characters
    @text.gsub!(/\\V\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
    @text.gsub!(/\\V\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
    @text.gsub!(/\\N\[([0-9]+)\]/i) { $game_actors[$1.to_i].name }
    @text.gsub!(/\\C\[([0-9]+)\]/i) { "\x01[#{$1}]" }
    @text.gsub!(/\\G/)              { "\x02" }
    @text.gsub!(/\\\./)             { "\x03" }
    @text.gsub!(/\\\|/)             { "\x04" }
    @text.gsub!(/\\!/)              { "\x05" }
    @text.gsub!(/\\>/)              { "\x06" }
    @text.gsub!(/\\</)              { "\x07" }
    @text.gsub!(/\\\^/)             { "\x08" }
    @text.gsub!(/\\\\/)             { "\\" }
  end
  #--------------------------------------------------------------------------
end
Well, normally, it isn't hard for me to determine which code does what, especially with a that-wide variety of uses, but yeah... there're way too many /'s and \'s for me to see clearly... I can do the gsub(string, replacement_string) thing, but yeah, a little decrypting of this more complex thing would be nice, and if possible, a list of the available pattern operators, or however you'd call them... I get that there's a bunch of those, but I can't really find anything regarding that.
 

Zeriab

Sponsor

I will focus mainly the regular expression rather than gsub since it seems you are asking for help with those rather than how gsub works.
First of all I would redirect you to a regular expressions reference. You can find one in my regex tutorial: http://rmxp.org/forums/index.php?topic=21009.0
Alternatively you can use Rubular which is excellent for testing regular expressions: http://www.rubular.com/
It is really gold having a reference when looking at or creating regular expressions.

Let's go through the first: /\\V\[([0-9]+)\]/i
First notice the options, it's the i after the last /. It means that the regular expression is case insensitive.
Now let's look at the contents of the regular expression. We can split it up to these tokens
\\ - V - \[ - ( - [0-9]+ ) \]
The \\ is an \ escaped. The escape system works by adding a backslash in front of a special character to have it considered as a normal character. In this case we escape the backslash with a backslash and the result is \\
Next is the V which simple the V character. Since the case insensitive option is used it is actually V or v.
The \[ is like the \\ with you having a special character you need to escape. So that bit is treated as the character [.
The ( is a bit special since what it does together with ) is that it marks and area of the regular expression. It groups a part of the regular expression however the grouping features are not used. I will come back to how this is used, just know that it does not change which strings will match the regular expression in this case.
The [0-9] bit of [0-9]+ is one digit. The special thing about [something] is that it represents one character which can be any one of the character within the square brackets. This is also the reason why we had to escape the brackets before. Because we wanted to look for the [ character in the string. You could also have used \d instead for matching a digit. It's a matter of taste really. Note that \d and \D is different despite the case insensitive option.
The + means at least one. Basically the text has to have at least one digit. It can have any number of digits as long as there are at least one.
Finally we have \] which is an escaped end bracket. So we look for the ] character.
Putting it all together we have a regular expression matching a any string that has \V[digits] in it somewhere. (It does not have to be a capital v)

The gsub method then finds any part in the string which matches that and replaces it with something else. Now we come into the use of the parentheses. $1 is set to what the first group matches, $2 to what the second group matches and so on.
For example, if you have \v[23] then the part in () is the digits and thus $1 is set to "23".
So the \v[23] is replaced with whatever $game_variables[23] returns. It returns an integer, but it is automatically converted to a string. By the to_s method I am pretty sure but I have not tested.

I see that the next line does the same, but there won't be anymore matches of that particular regular expression since they all were removed last time. (Well assuming that all variables contain numbers)
You can just as well delete the duplicate line since it won't do anything except consuming cpu cycles in all but the strangest of situations.
/\\N\[([0-9]+)\]/i and /\\C\[([0-9]+)\]/i work similar with V being exchanged with N and C respectively. Look at how the number part are used in the substitution. ($1)

\\G looks for \G in the text. It is not case insensitive so it will not match \g. Just a little thing to notice.
\\\. is \ and . both escaped. The . is a special character that can match any character. When escaped it's simple the .  we are looking for. So it will match \. in the text.
\\\| will match \|. The special character | is used as or. For example a|b matches a or b. We escape it since it's a special character
\\!, \\> and \\< will match \!, \> and \< respectively. Notice that ! is not a special character and thus we have no need to escape it. Likewise with > and <.
\\\^ will match \^. The ^ special character can be used inside []'s. For example [^something] will match any character but the characters specified inside. I. e. all characters but e,g,h,i,m,n,o,s,t.
\\\\ will match \\. We need to escape both of the \'s thus giving us \\\\.

If you need more help feel free to ask.

*hugs*
- Zeriab
 
What is the difference between a module and a class?

I've noticed you don't need an initialize method in a module...Why is this?

Is it harder to script one than the other?
Also, how would you go about checking if a certain event's conditions such as switch1,switch2,variable are valid, and the event pages and such?
 
Modules serve two main purposes: they work as namespaces to better structure your code and avoid name clashes, and they can also be mixed in with classes to give them more functionality.

The first role is pretty simple. Suppose you have written a method called foo which does a certain thing, and someone else wrote another method foo that does something different, and for some reason the two of you had to combine these method in one context (in the same project for example). If you invoke foo, which method would be actually called? By default this would be a naming conflict and you'd have to change one of the method names. An alternative is to put these methods in different modules and use the fully qualified module name to refer to them. eg.

Code:
module My
  def My.foo
    p 'my foo'
  end
end

module Other
  def Other.foo
    p 'other person's foo'
  end
end

My.foo
Other.foo

The reason we have to put My or Other before the method name (def My.foo) is because these are module methods that could be called using the module name (same as class methods), you could also use self.foo in both classes for the same effect.  As you see, this usage allows you to use code from different sources without getting into naming conflicts. Modules can also contain classes and constants. Ruby has a Math module that includes methods like sqrt and constants like PI. Modules can also help structure your code if you put related classes and methods in their own module.

Modules also have another use as mixins. Basically, if you have a module with some instance methods in it, you could mix it with your class to add these methods to your class as if they were defined inside it. It's similar to the concept of multiple inheritance in other programming languages but without the dangers associated with that. Ruby allows a class to inherit from only one parent, but you can include as many modules as you like.

Code:
module FooModule
  def foo
    p 'module foo!'
  end
end

class BarClass
  include FooModule
  def bah
    p 'blah'
  end
end

BarClass.bah
BarClass.foo

As you can see, by including FooModule, BarClass gets methods defined inside FooModule.

An interesting applications of mixin is including the built-in Comparable module to allow comparison between objects of your class. Instead of manually writing methods to compare the objects, you could just define one method in your class, and include the module Comparable. The method you define is <=>, which takes one argument and compares it to self (making this class the left hand side and the argument the right hand side of the <=> operator). It should return 1 if self > argument, 0 is they are equal, and -1 otherwise. If you define that method and include Comparable, you get >, <, >=, <=, == and a between? method for free! Here's an example:

Code:
class Hero
include Comparable
  def initialize(lv)
    @level = lv
  end
  def <=>(other)
    if self.level > other.level
      return 1
    elsif self.level == other.level
      return 0
    else
      return -1
    end
  end
end

h1 = Hero.new(1)
h2 = Hero.new(2)
h3 = Hero.new(90)

p h1 > h2 # false
p h2 <= h3 # true
p h3 == h1 # false
p h2.between?(h1, h3) # true

Note that you didn't define any of these methods (>, <, etc.), they are defined in the Comparable module. Also note that the <=> method could've been written as simply return @level <=> level, because the <=> is already defined for numbers and other built-in classes. The reason you have to implement a method yourself is because the methods inside module Comparable assume your class has that method and call it to implement the new methods. For example, the method < in Comparable might look something like:

Code:
module Comparable
    ...
    def <(other)
        return self.<=>(other) == -1
    end
    ...

And then you include it and your class has the < method which simply checks if your <=> returns -1. Another useful module is Enumerable which gives you tons of useful methods for collections (find, sort, max, include?, etc.) if you implement the each method!

Finally, it's important to note that while similar, classes and modules are different! They serve different purposes. It could be said a module is a class that:
- can have no instances (no FooModule.new, that's why there's no initialize method: you don't create module objects)
- can have no subclasses (you include a module, not inherit it)
- uses the keyword module, not class
- can't be mixed in with classes

I probably made several technical and spelling mistakes but I didn't think I'd write so much. Sorry! :P
       
 
I'm refining the way my iPod script is being set up, and it's going fine except for one thing. I need to search the RTP's directory for any bgm-files the user might have.
How do I access the RTP directory from within a script?
Any help would be greatly appreciated
 
Well, the RTP folder isn't the place where you'd store custom music either way, as you're not supposed to add or remove files from that directory. Instead, you should probably check for a directory within the game folder to enable people to choose what music they want to listen to... you could also enable them to choose a custom directory on their PC (preferable method, if you ask me) from which you get your music.
I didn't understand this as a request on how to script either of the latter ones, but I can help you out if you need something. I'd tell you about the RTP directory, but I simply don't know how to...
 
I want to be able to access both the user's game BGM folder as well as the RTP, so that, if the user wants to use RTP music they don't have to copy it to the game's BGM folder
 
Beran":3fl7makb said:
I want to be able to access both the user's game BGM folder as well as the RTP, so that, if the user wants to use RTP music they don't have to copy it to the game's BGM folder

I'm not sure if it will always work (it should), but you can try this code:
Code:
  def self.getRGSSFolder()
    # A windows API call to get 'special folders'
    getFL = Win32API.new("shell32.dll", "SHGetSpecialFolderLocation", 'llp', 'l')
    # temp will store the pointer (4 bytes) returned by the API call,
    # for now it's just a string of four null characters
    temp = 0.chr * 4
    # The folder we're looking file is the common program files folder, where RMXP
    # stores RTP files, a pointer to an item identifier list (pidl) structure is saved in temp
    getFL.call(0, Win32::CSIDL_PROGRAM_FILES_COMMON, temp)
    # Since ruby doesn't natively understand C language pointers we have to store them
    # in strings and then use unpack to get an integer value (4 bytes)
    pidl = temp.unpack('l')[0]
    # Now we use another API call to convert the pidl returned to a string path
    getFP = Win32API.new("shell32.dll", "SHGetPathFromIDList", 'lp', 'l')
    # buf will store the returned path (to common files folder),
    # We create a 260 long string of spaces
    buf = 32.chr * 260
    # This call will convert the pidl we got earlier into a string path stored in buf
    result = getFP.call(pidl, buf)
    # That method returns true (1) on success, so we check that
    if (result > 0)
      # We get rid of any extra spaces by slicing the buffer at the 
      # null (end of string) character
      buf = buf.slice(0,buf.index(0.chr))
      # Return the buf value (something like C:\Program Files\Common Files) appended
      # to \Enterbrain\RGSS\Standard\, where RMXP (legal version) stores the RTP
      return buf + "\\Enterbrain\\RGSS\\Standard\"
    end
  end

This code is not mine, it's based on code by Kevin Gadd in his Fmod Ex binding script. I added comments to make it more understandable, but I don't know much about WinAPI and I could be wrong! You'll still need to add \Audio\BGM to the returned string to get the full path of RTP music, which you could then use for a Dir object or something. Hope it helps.
 
This should be an easy one.  I know to check if an actor has a state, it'd be
Code:
$game_party.actors[0].state?(1)
But how do I check if an actor does not have a certain state inflicted.  Wouldn't there be a "!" added in there somewhere?
 
Ah, that did it.  Thank you kindly.

Actually, I've got another question if someone could help me out.  I'm trying to access information about an actor's weapon, such as the weapon's atk, the animation it plays on the attacker and the target.  It's not in the FAQ, and I did some searching around, but I keep getting errors.  Can anyone help?
 
After a quick search through the engine's basic scripts, the way I've found that works is using
Code:
$data_weapons[$game_actors[actor_id]].function
replace actor_id with the actor ID who's weapon you're after and function with either atk(for attack) animation1_id(for the animation when USING the weapon) or animation2_id(for the animation when the weapon is used on you).
You can find more functions in the helpfile under RPG::Weapon
Hope that helps
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top