Chaos Project

RPG Maker => RPG Maker Scripts => Script Troubleshooting => Topic started by: Apidcloud on February 06, 2011, 03:49:10 pm

Title: .txt files in rgss
Post by: Apidcloud on February 06, 2011, 03:49:10 pm
Hi there everyone (:
Im here to ask if any of u can recomend some links or scripts with stuff with .txt files and that... (open, using stuff inside it, etc)

I really want to start studying it (:

Thanks
Title: Re: .txt files in rgss
Post by: Blizzard on February 06, 2011, 03:58:31 pm
This one: http://www.ruby-doc.org/core/classes/File.html
And possibly this one, too: http://www.ruby-doc.org/core/classes/IO.html
You might be interested in this one as well: http://ruby-doc.org/core/classes/Dir.html
Title: Re: .txt files in rgss
Post by: Apidcloud on February 06, 2011, 04:13:31 pm
wowa xD
Thanks a lot, I'm sure it will help me ^^

By the way, do you know any script that uses .txt file as a 'source'?
For instance, imagine that a script needs numbers and names for a lot of stuff.
Then, the scripter using rgss, reads that codes ans uses them for something.

That's what I'm more interested with xD
Title: Re: .txt files in rgss
Post by: Storm on February 06, 2011, 04:26:30 pm
You can use FileTest.exist?(filename) to check file if it is exist.
And use
Dir.glob("*."+filetype){|f|
  //Command (f = eachfile)
}

To each everyfile in the folder, you can put Dir.chdir(foldername){ to select a folder first. (Don't put an extra })

Use this to open a file.
File.open(filename,openingType){|f|
  //Command (f = eachfile)
}

You can choose a basic openingType from below..


f.read(characterCount) and f.write(value) will work for you as a command.
You can use writeFile(pathToFile+filename"."+filetype,value) to write a file right away too..

Hope this helped you. :)
Title: Re: .txt files in rgss
Post by: Apidcloud on February 06, 2011, 04:31:26 pm
Well... I didn't understand it that well XD, maybe because im really at the beginning of this part of rgss :P

Thanks a lot ^^

Well, may I ask for an example? xD
So, imagine that i create a new txt file even before opening project xD

I put data that I will need in rgss scripts, such as:

Text file, named 'example'
something => does_that
... (so on)

Now, using rgss to pick up that data and use it...
File.open("example", rb)
#stuff picking up that data <.<
File.close

So, what should I begin with there?
Title: Re: .txt files in rgss
Post by: Storm on February 06, 2011, 04:43:56 pm
Quote from: Apidcloud on February 06, 2011, 04:31:26 pm
Well... I didn't understand it that well XD, maybe because im really at the beginning of this part of rgss :P

Thanks a lot ^^

Well, may I ask for an example? xD
So, imagine that i create a new txt file even before opening project xD

I put data that I will need in rgss scripts, such as:

Text file, named 'example'
something => does_that
... (so on)

Now, using rgss to pick up that data and use it...
File.open("example", rb)
#stuff picking up that data <.<
File.close

So, what should I begin with there?


I don't think so.. I'm finding it out too..
I'm wondering like you too, but still.. you can't convert STRING into FUNCTIONS!
If you find it let me know because none of the computer languages (PHP, RGSS, VB, C+, etc.) can convert string into functions.
Title: Re: .txt files in rgss
Post by: Apidcloud on February 06, 2011, 04:49:54 pm
Well, I've done an example with a string but...with numbers it would be possible or not? xD
Title: Re: .txt files in rgss
Post by: Storm on February 06, 2011, 04:56:34 pm
Quote from: Apidcloud on February 06, 2011, 04:49:54 pm
Well, I've done an example with a string but...with numbers it would be possible or not? xD


I'm thought you are talking about converting String into Functions! XD
Oh well, you just read a file you want to, and when you got the number just use [YOUR NUMBER].to_f.

Now you converted it to fixnum. (Number) :)
Title: Re: .txt files in rgss
Post by: ForeverZer0 on February 06, 2011, 04:59:39 pm
Look into actual Ruby. That is how it is done with that, simply reading .rb files.
If you simply want to execute a whole file, or load it into memory, save a text document with an .rb extension and use:
require "TEXT_DOC_NAME"


If you want to use an external text file and execute code off of it, something like this should work:


lines = IO.readlines('TEXT_DOC_NAME.txt')
# You can use the ".join" method to combine the lines into a single string, otherwise it will be an array of lines
eval(lines[LINE_INDEX_TO_EXECUTE])


If you want to create an instance of the file:


file = File.open('TEXT_DOC_NAME.txt', 'rb')
# Do something
file.close


To write text to the doc:


file = File.open('TEXT_DOC_NAME.txt', 'wb')
file.write("This is a string")
file.write("\r\nThis is on the second line\r\n")
file.write("\tThis is the third line, and indented")
file.close



EDIT:
And "yes", you can convert strings into functions. I even came up with ways to construct and add new methods to instances of classes at runtime.
Title: Re: .txt files in rgss
Post by: Storm on February 06, 2011, 05:06:33 pm
Quote from: ForeverZer0 on February 06, 2011, 04:59:39 pm
Look into actual Ruby. That is how it is done with that, simply reading .rb files.
If you simply want to execute a whole file, or load it into memory, save a text document with an .rb extension and use:
require "TEXT_DOC_NAME"


If you want to use an external text file and execute code off of it, something like this should work:


lines = IO.readlines('TEXT_DOC_NAME.txt')
# You can use the ".join" method to combine the lines into a single string, otherwise it will be an array of lines
eval(lines[LINE_INDEX_TO_EXECUTE])


If you want to create an instance of the file:


file = File.open('TEXT_DOC_NAME.txt', 'rb')
# Do something
file.close


To write text to the doc:


file = File.open('TEXT_DOC_NAME.txt', 'wb')
file.write("This is a string")
file.write("\r\nThis is on the second line\r\n")
file.write("\tThis is the third line, and indented")
file.close



EDIT:
And "yes", you can convert strings into functions. I even came up with ways to construct and add new methods to instances of classes at runtime.



OH!!! Thanks Zer0! I totally forgot of the require method! I focused too much about the script so I forgot about the files.. DARN!
Title: Re: .txt files in rgss
Post by: Apidcloud on February 06, 2011, 05:15:20 pm
Well thanks a lot xD
Im going to test some stuff here with all that (:

lvl up everyone xd
Title: Re: .txt files in rgss
Post by: Blizzard on February 06, 2011, 05:31:52 pm
@F0: You don't need to use \r if you open the files in 'w' or 'r' mode. Windows automatically adds them if you don't use 'w+', 'r+', 'wb' or 'rb'. Actually 'w' and 'r' are Windows hacks, all other OSes use binary file modes and it's kinda more convenient that way, too, because of multiplatform compatibility.
Title: Re: .txt files in rgss
Post by: ForeverZer0 on February 06, 2011, 05:36:36 pm
@blizz
You are right, its just kind of a (bad?) habit I got into. Honestly, I have only wrote code under Windows platforms, so I have never really concerned myself with cross-platform compatibility, which is something I should pay more attention to now that I'm getting into other languages. Never really had the need when writing scripts for RGSS, though.
Title: Re: .txt files in rgss
Post by: Blizzard on February 06, 2011, 05:39:30 pm
I used to do it as well. But then I just switched to \n. xD
Title: Re: .txt files in rgss
Post by: Storm on February 06, 2011, 05:47:09 pm
Quote from: Blizzard on February 06, 2011, 05:39:30 pm
I used to do it as well. But then I just switched to \n. xD


I used to say "\n" is the basic of string. XD
Title: Re: .txt files in rgss
Post by: Ryex on February 06, 2011, 06:03:08 pm
in case your wondering to convert a string into a function call first convert it to a symbol then send a message to the object with the function

look into the .call method to learn more. in the ruby-docs it should be under object
Title: Re: .txt files in rgss
Post by: Apidcloud on February 06, 2011, 07:01:49 pm
Hmmm, Im testing some stuff here...although...it's difficult xD
document = "Something.txt"
file = File.open(document, rb)
for line in 0...file.lines
  IO.readlines(document)[line]
end
#I don't know exactly what I've to do now?
file.close


Well <.< I don't even know if this works at really...Can some1 help? xd
I accept advices for the logic of this code...

Note:
pick up .txt data and use it for something..?
Title: Re: .txt files in rgss
Post by: ForeverZer0 on February 06, 2011, 10:09:51 pm
file = File.open(document, "rb")

Note the quotes used around rb.
This sets the local variable "file" as an instance of the file. You can iterate it with methods like:
file.each_line {|line| print line } 

and...
file.lines.each {|line| print line }

You will also need to make sure to close the file when you are done with it.

OR you can do this, not both.

lines = IO.readlines(document)

This simply creates a normal array, with each element being a string line of the document.
You can iterate the array normally, and have no need to close the file.

What you do with code totally and utterly depends on what it is, and what exactly you are trying to accomplish. I really can't help you with that until I know what you are trying to do.
Title: Re: .txt files in rgss
Post by: Blizzard on February 07, 2011, 02:21:18 am
I personally prefer the File.open way because it's a lot more readable. You can really see that it's a file that's being read.
I also prefer to open a file, use readlines or read, then close the file handle and after all of that work with the data that I read. I like doing it this way so the file is open as short as possible and other programs can open it afterwards. I do the same when writing to files. I first prepare the whole data, open the file, write everything into it and then close it right away.
Also, when using readlines or readline, keep in mind that the string will contain the \n at the end of the line if there is one. So you might want to use line.gsub!("\n") {''} on each line.
Title: Re: .txt files in rgss
Post by: Storm on February 07, 2011, 03:56:55 am
Quote from: Ryex on February 06, 2011, 06:03:08 pm
in case your wondering to convert a string into a function call first convert it to a symbol then send a message to the object with the function

look into the .call method to learn more. in the ruby-docs it should be under object


Can you actually link me the page or an example? There are so many calls.
Title: Re: .txt files in rgss
Post by: Apidcloud on February 07, 2011, 06:22:59 am
Thanks a lot everyone :P
Im at school right now, but as soon as i arrive home I will practise it a bit...

Another question...u said that it will make my document an array right?
How does it works in this case?
line[0] = #information on first line
line = #information on i line


like that?
Title: Re: .txt files in rgss
Post by: Blizzard on February 07, 2011, 06:33:17 am
Exactly.
Title: Re: .txt files in rgss
Post by: Storm on February 07, 2011, 06:43:47 am
Quote from: Apidcloud on February 07, 2011, 06:22:59 am
Thanks a lot everyone :P
Im at school right now, but as soon as i arrive home I will practise it a bit...

Another question...u said that it will make my document an array right?
How does it works in this case?
line[0] = #information on first line
line = #information on i line


like that?


It splits into array.
Example, this is your text document:
+-------------------------------+
| Dear Blah,                              |
| How are you doin?                   |
| If you received my msg just call |
| me back, ok?                          |
|                                             |
| Love,                                    |
| Awesome Face                        |
+-------------------------------+

line[0] = Dear Blah,
line[1] = How are you doin?
line[2] = If you received my msg just call
line[3] = me back, ok?
line[4] =
line[5] = Love,
line[6] = Awesome Face
Title: Re: .txt files in rgss
Post by: Apidcloud on February 07, 2011, 09:12:40 am
Hmmm ok, and what if I want to split my lines? xD
Something like this:

#Document
1 => 2
3 => 4
#

How would i use 'values' and 'keys' of arrays?
Title: Re: .txt files in rgss
Post by: Ryex on February 07, 2011, 11:57:09 am
for this you need regular expressions, there is a good tut here on this forum (http://forum.chaos-project.com/index.php/topic,56.0.html) that explains how they work

take this code example with you as it dose what you want.

string = "1 => 2"
string.gsub(/([0-9]+)\s=>\s([0-9]+)/)
key = $1
value = $2


of course there is like 10 ways to do the second line. Regexp are heavily intragrated in to ruby

you could do it like this

case string
when /([0-9]+)\s=>\s([0-9]+)/
  key = $1
  value = $2
end


this is most useful when there is several patterns the string could follow

you could also do this

if string =~ /([0-9]+)\s=>\s([0-9]+)/
  key = $1
  value = $2
end



good luck
Title: Re: .txt files in rgss
Post by: Apidcloud on February 07, 2011, 12:06:32 pm
Thanks a lot xD
Although, shouldnt we use: key = $1.to_i #? xD

Well, I was doing something like that as well
Thanks again for the help

Bye~
Title: Re: .txt files in rgss
Post by: Ryex on February 07, 2011, 01:02:36 pm
yes true, the way I did it you'll just have strings, if you want to format those strings use to_i for an integer and to_f for floating point values.
Title: Re: .txt files in rgss
Post by: Apidcloud on February 07, 2011, 03:06:32 pm
Outch xD I could do something oO but it is returning an error.
Permission denied to acess the document lol

whats happening? <.< I used this as 'file' opening:
file = File.open("Data", "rb").each_line {|line|}

When I test the prject and this part comes up, it appears
---------------------------
Teste
---------------------------
Erro no Script Text -part 2, em 266 na linha 'Errno::EACCES'

Permission denied - Data
---------------------------
OK   
---------------------------

Someone help here T_T
Title: Re: .txt files in rgss
Post by: ForeverZer0 on February 07, 2011, 04:07:30 pm
Your not using the call right. Nor are you including the file extension. I'm at work at the moment, I'll explain more when I get home here in a about an hour.
Title: Re: .txt files in rgss
Post by: Apidcloud on February 07, 2011, 04:24:07 pm
Forgot about the extension .txt <.< epic fail xD Thanks (:

@Edit <.< I though all my logical was ok...but i was wrong XD screen gets froze everytime i call this...
So, my code consists in picking up the strings and numbers from the .txt file and use them as teletransportation data...
In the document, there are lines as this one:
"string" = "string", number, number, number.
Here is the code:

@map_name   = []
    @respawn_map =[]
    @respawn_x   = []
    @respawn_y   = []
    @respawn_dir = []
$old_map_id = $game_map.id
data = load_data("Data/MapInfos.rxdata")
    return if !File.exists?("Data")
    file = File.open("Data.txt", "rb")
    file.each_line do |line|
      case line
      when /(\".*\")\s\=\>\s(\".*\")\,\s(\d+)\,\s(\d+)\,\s(\d+)\,\s(\d+)\./i
        @map_name.push     = $1
        @respawn_map.push  = $2
        @respawn_x.push    = $3.to_i
        @respawn_y .push   = $4.to_i
        @respawn_dir.push  = $5.to_i
      end
    end
    file.close
    for i in 1...data.size
      if data[i].name != nil
        actual_name = data[i].name
        respawn_name = data[i].name
      end
      if actual_name == @map_name
        actual_id = i
        break
      end
      if respawn_name == @respawn_map
        respawn_id = i
        break
      end
    end
    for j in 0...@map_name.size
      return if @map_name.nil?
      if $old_map_id == actual_id
        $game_temp.player_new_map_id = respawn_id
        $game_temp.player_new_x = @respawn_x[j]
        $game_temp.player_new_y = @respawn_y[j]
        $game_temp.player_new_direction = @respawn_dir[j]
        $game_player.refresh
        $game_map.update
        $scene = Scene_Map.new
      end
    end
Title: Re: .txt files in rgss
Post by: ForeverZer0 on February 07, 2011, 07:38:28 pm
I fail to see any reason to make a simple task so complicated as all that. You can simply write an array to the text doc, then in the game set a variable to it using the "eval" function.

ex. Text Document (Array is used like this: [MAP_ID, RESPAWN_X, RESPAWN_Y, DIRECTION])

[1, 20, 20, 2]
[2, 15, 30, 4]
[3, 18, 9, 6]
[4, 2, 45, 8]


Then within the code, set it to a variable:

@respawns = IO.readlines("Data.txt") # No need to include "rb" or close file with this method
@respawns.collect! {|array| eval(array) } # Execute block on each element, then change array to returned value


If you want the map names in the array, run a method to add them. You could do this different ways, or even include it in the text document if you would like. I wouldn't even worry about, but just use the ID to find it if it was ever needed.

Either way, you now have an array labeled "@respawns", whose elements are arrays of integers.
To set the current respawn, just reference the desired one by its index, or line number of the text document if it helps you to think of it that way (remember the index is 0 based).


temp = @respawns[WHATEVER_INDEX_YOU_LIKE]
$game_temp.player_new_map_id = temp[0]
$game_temp.player_new_x = temp[1]
$game_temp.player_new_y = temp[2]
$game_temp.player_new_direction = temp[3]
$game_player.refresh
$game_map.update


You actually could do it with less code than that, but this should demonstrate how it works a little easier.

I am curious though, why would you ever do it this way. If you are merely trying to learn, that it fine, I have done much stranger things in the process of learning Ruby, but I would highly suggest against something so inefficient for an actual game. You could simply store the values in array within the game, and not use a file at all.
Title: Re: .txt files in rgss
Post by: Apidcloud on February 09, 2011, 11:05:01 am
First of all XD
Im doing this...most likely to learn something about File, IO and Dir classes...and I already did this(without txt file) inside the script :P
Now I wanted to 'change' that information into .txt folder and then use rgss to take all that, string and integers...
Im going to try to use what u said.

One more time, thanks a lot for the help ^^

@Edit:
I failed using what u said there XD

Im going to explain my previous code..
Without .txt file, I could just do a class with this type of conditions:

if $old_map_id == 1
$game_temp.player_new_map_id = 2
       $game_temp.player_new_x = 10
       $game_temp.player_new_y = 20
       $game_temp.player_new_direction = 6
       $game_player.refresh
       $game_map.update
       $scene = Scene_Map.new
end


With txtfile ->
First of all, I though about creating some arrays, what would store the values of .txt document.

@map_name   = []
@respawn_map =[]
@respawn_x   = []
@respawn_y   = []
@respawn_dir = []


Then, I thought about using regexp to take the lines that follow it:

data = load_data("Data/MapInfos.rxdata")
   return if !File.exists?("Data")
   file = File.open("Data.txt", "rb")
   file.each_line do |line|
     case line
     when /(\".*\")\s\=\>\s(\".*\")\,\s(\d+)\,\s(\d+)\,\s(\d+)\,\s(\d+)\./i
       @map_name.push     = $1
       @respawn_map.push  = $2
       @respawn_x.push    = $3.to_i
       @respawn_y .push   = $4.to_i
       @respawn_dir.push  = $5.to_i
     end
   end
   file.close

Each of these variables, will store the correspondent $'s.

After this, I needed to check the name of the maps(map where actor dies, and where it respawns) and then convert it to id:

for i in 1...data.size
     if data[i].name != nil
       actual_name = data[i].name
       respawn_name = data[i].name
     end
     if actual_name == @map_name
       actual_id = i
       break
     end
     if respawn_name == @respawn_map
       respawn_id = i
       break
     end
   end


Finally, as each array have the same size, I only needed to use the size of one to make all necessary conditions...

for j in 0...@map_name.size
     return if @map_name.nil?
     if $old_map_id == actual_id
       $game_temp.player_new_map_id = respawn_id
       $game_temp.player_new_x = @respawn_x[j]
       $game_temp.player_new_y = @respawn_y[j]
       $game_temp.player_new_direction = @respawn_dir[j]
       $game_player.refresh
       $game_map.update
       $scene = Scene_Map.new
     end
   end


This latter code, with .txt logic it is freezing the screen all the time I call it xD

Someone help please? :P
Title: Re: .txt files in rgss
Post by: ForeverZer0 on February 09, 2011, 06:47:37 pm
Just make a hash with the map IDs as the keys. Then you can simply use a single array to store all the needed data like the x, y, and direction.

All of the loops, iterations, and regular expressions are unneeded and are very inefficient. They have no real practical use, and are the likely use of your problem. It would be a good idea to rethink your initial approach than to try to force a bad one to work. I've had to rewrite entire scripts for this reason. About 3/4 of the way through, I see an easier way to do it, so I erase everything I've done and start over. The final result is usually 1/2 the code, easier to use, easier to overview, and is far more efficient. Sometimes you just need to go back to the drawing board. Everything you are trying to do could be done in 20 lines of code or less.

For the last example of code you have, I do see one obvious error right off the bat. The "return if @mapname.nil?" is quite worthless. The iteration would never get far enough to check that line, and would through an error if it was nil. I imagine you meant "@mapname[j] == nil" (I prefer using comparison, not ".nil?"). This will check the element for this iteration. I don't believe you need to call "$scene = Scene_Map.new" IF this is being called from Scene_Map. 

What my previous post said should work. The only thing I see that I forgot to mention is what Blizzard mentioned earlier about the "/n" not being removed. That can be fixed by substituting this line:
@respawns.collect! {|array| eval(array) }

...with this one:
@respawns.collect! {|array| eval((array.gsub(/\n/) { '' })) }
Title: Re: .txt files in rgss
Post by: Apidcloud on February 13, 2011, 11:16:34 am
I just arrived home xD that's the reason I couldn't asnwer here...I'm going to try to use that again :P

Thanks
Title: Re: .txt files in rgss
Post by: Zeriab on February 17, 2011, 04:41:39 am
Lemme warn you that you cannot load text files normally form within an encrypted archive.
If you want to encrypt your game you can convert the text file to a format load_data understands. (You can load the file as a string and save it using save_data)
One problem with that approach is that you cannot search for all file and you have to try and load a file to check if it exist. Since the files are encrypted they are not immediately available for the players to edit. Even if they decrypt the game it's still bothersome to edit marshalled files.

You can have them outside of the encrypted archive which is most easily achieved by not putting them in the data folder or some subfolder, but rather create another folder for the text files. This way you can use the file system utilities all you want. The player will be able to see and depending on your format edit it. Which for some cases is positive.

Of course you can have combination where you use one way for some files and the other for other files.

*hugs*
Title: Re: .txt files in rgss
Post by: Apidcloud on February 17, 2011, 09:20:06 am
Thanks XD

At the moment im studying something else (something that i really need to do, and fast...), so when im over with it, I'll try it again XD

See ya