Checking if a file exists?

GiantAngryBoar
05 Mar 2014, 05:09
Hey, all,

I'm working on a game that's slated to be a bit heavy on the graphics and sound side of things. In particular, I intend to have an image and a musical track for every room, and for each object, an image for taking it, and an image for examining it. In order to cut back on quite a few manual "play sound" and "picture" function calls, I overrode various functions from the core library, so that in addition to doing what they usually do, they will also automatically generate .wav and .png filenames from object names and then attempt to present them.

My problem is I'm not absolutely sure I'm going to want to have a sound and a picture for every single room or object. And even if I will, until I do, it would be helpful for testing purposes if I could run the game without various media files that may still be in the works and not be presented with an error informing me they don't exist.

As such, I'm wondering if there's any way to test for file existence in Quest. Let's say such a function were called "file exists." Then consider the following:
play sound (object.name + ".wav")

If object doesn't have an associated sound file, this would give us an error.
if (file exists (object.name + ".wav")) {
play sound (object.name + ".wav")
}

This code, however, would not, which is what I want.

Is there any such function, or any way to implement one?

Thanks in advance

HegemonKhan
05 Mar 2014, 05:31
I'm not sure on this, as I've not worked with media files yet... but let me take a stab at it anyways, lol

1. http://quest5.net/wiki/Category:All_Fun ... t_Commands (page 1, range: A-S)
2. http://quest5.net/w/index.php?title=Cat ... t#mw-pages (page 2, range: S-Z)

3. http://quest5.net/wiki/GetFileData

4. (maybe) http://quest5.net/wiki/HasAttribute
5. (maybe) http://quest5.net/wiki/IsDefined

for #3 (GetFileData):

if (GetFileData (object.name + ".wav")) { // or: if (GetFileData (object.name + ".jpg")) // or whatever picture (or sound too) file entension (that can work with quest), just used ".jpg" as an example
-> play sound (object.name + ".wav") // or: picture (object.name + ".jpg") // or whatever picture (or sound too) file entension (that can work with quest), just used ".jpg" as an example
}

same format for #4 and #5 too, just change the "if (.....)" syntax for the "HasAttribute" or "IsDefined"

----------

HK Edit:

actually, I don't think the "GetFileData" works... so try:

4. (maybe) http://quest5.net/wiki/HasAttribute
5. (maybe) http://quest5.net/wiki/IsDefined
and
*6. (maybe) http://quest5.net/wiki/GetObject
7. (Maybe) http://quest5.net/wiki/HasObject

I think #6 (GetObject) is probably what you want, do the same format as shown for "GetFileData", but change the syntax, of course.

GiantAngryBoar
05 Mar 2014, 05:41
Shoot, you had me going there! Looks like GetFileData returns a string, and throws an error if the file doesn't exist. HasAttribute and IsDefined didn't seem to work either. They seem to be for checking if something exists in the program namespace, not in the filesystem.

Hm, but I think we're close with GetFileData. Maybe if I can find what library it's defined in, I can take a closer look at it and see how it figures out to throw that error. Thanks for the lead.

EDIT: Say, you wouldn't happen to know where GetFileData is defined, would you? I can't find it in any of the libraries so far.

HegemonKhan
05 Mar 2014, 05:51
edited my previous post (sorry, bad habit of mine)

I think "GetObject" or "HasObject", will work, now that I think I understand that the media files are put into quest as Objects (Object.name + ".extension_name")

"GetObject" ("Get") is more direct (in checking if it exists and returns the object for scripting upon it ~ if it exists of course) than "HasObject" ("Has") which just checks if it exists or not ("=true" or "=false"):

exists = returns Object (true)
not exists = null (false ~ similiar to an "error" return)

if (GetObject (Object)) { // the quest engine understands that it is "=true", so you don't need to write it in
-> then do script
else { // the quest engine understands that it is "=false" (as it's "null" ~ not exists), so you don't need to write it in
-> then do script
}

------

I'm not sure where it would be... sorry

just keep looking through all the library~game files (quest files: *.aslx)

or

you can open up quest in the GUI~Editor, and in the lower left:

Filter -> Show Library Elements -> check it on

what this does is shows now all the built-in code (same stuff as the quest files) in the 'tree of stuff' above, as the greyed font color, which you can then click on, and modify it (though do note that this is global built-in code, so make sure that it'll work) ~ and doing it this way is safe, as you got to click on the "copy" button on the right side, which protects the quest engine (so you don't mess it up, having to re-download quest), as opposed to editing the actual quest files themselves (possibly making the stupid mistake of not backing them up first ~ aka not editing a self-copy~copied file).

GiantAngryBoar
05 Mar 2014, 06:04
My god, thank you, this is amazing! This is exactly everything I need!
... Except that GetFileData still doesn't show up.
I just don't even.

Also, my bad, I'm not sure I'm understanding what you mean by media files being put into Quest as objects, but I think I may have misled you. Loading a media file into Quest doesn't create an object. Rather, I already have an object, such as a cactus, and I have it set up so that the already existing object looks for a file called cactus.png when the player examines it. So checking if "cactus" is defined or has an attribute won't help me, because I already know the object exists, but even if the object exists, I still can't guarantee that the file exists.

HegemonKhan
05 Mar 2014, 06:09
hmm... maybe then you got to use the "GetFileData" combined with the "GetObject":

and also...

sorry, for not adding this in previously... maybe by doing this "string matching" of the GetFileData, it'll get the result that you want....

if (GetFileData (cactus.png) = "cactus.png") {
-> GetObject (cactus_object) {
-> // whatever script you want to do with your cactus (object), ie: picture (cactus_object.cactus.png)
} else if (GetFileData (cactus.png) = null) {
-> // whatever script

HegemonKhan
05 Mar 2014, 06:23
otherwise, quest jsut may not be able to check if a file exists or not...

you may have to make~write the code for checking if the file exists outside of quest, such as a *.bat file... and then, whether quest can get the *.bat file and (and~or the computer can then within quest) run those code lines...

-----------

actually, this *SHOULD* (HK crosses his fingers) work:

http://quest5.net/wiki/GetFileURL

wiki wrote:Returns a string containing the full path to the specified file. The file must exist in the same directory as the game.

This can be used to access a game's resources such as sounds and pictures, and pass their URLs to the player UI.
(HK comment: this hopefully is our means of "checking if a file exists or not", via "getting the file's actual file path on your computer")


if (GetFileURL (cactus.png) = "your_file_path") {
... yada yada yada

"your_file_path", ie:

"c:/programs/quest/cactus.png"

if (GetFileURL (cactus.png) = "c:/programs/quest/cactus.png") {
... yada yada yada

"GetFileURL (cactus.png)" if I understand it right, returns the file path, so now we got a "checking of the file", and just need to then "check string match" it:

conceptual: if (string = string) {
if (GetFileURL (cactus.png) = "c:/programs/quest/cactus.png") {
conceptual: GetFileURL (cactus.png) automatically returns~outputs~algebraic substitutes for you: "c:/programs/quest/cactus.png"
conceptual: if ("c:/programs/quest/cactus.png" = "c:/programs/quest/cactus.png") {

----------

P.S.

sorry that I until now, passed over the "GetFileURL", as I wrongly thought it had to do with website's url~address... like to get the picture or sound from the internet's webpage, oopsy! my bad for not looking at "GetFileURL" sooner.

george
05 Mar 2014, 07:04
I'm not sure if this is really possible in the way that you're describing. GetFileData is defined here,

http://quest.codeplex.com/SourceControl ... onOwner.cs

In that same file is GetFileURL, which seems a more promising function to use. (see the wiki entry here http://quest5.net/wiki/GetFileURL ).

But the error checking on both those functions isn't very useful. For example you can pass almost any string to GetFileURL and get back a path (a bogus path if the file isn't there).

I do see a possible workaround, but it'll require external tools. What you do is create a script (not a Quest script -- you could use Python for example) in your game directory that will find every picture and image file and print the name to a text file. Then in Quest you load that file with GetFileData. Now you have an up-to-date list of every media file that currently exists in your game. You can check that list before you play a media file, and if the file name isn't in your list, you don't try to play the sound or show the image.

edit: cross-posted with HK's last post

HegemonKhan
05 Mar 2014, 07:09
your workaround of generating a file list is still useful though too, as it reduces the amount of coding you'd need to do:

ie, not fun doing:

if (GetFileURL (file1) = "path1") {
if (GetFileURL (file2) = "path2") {
if (GetFileURL (file3) = "path3") {
if (GetFileURL (file4) = "path4") {
if (GetFileURL (file5) = "path5") {
if (GetFileURL (file6) = "path6") {
if (GetFileURL (file7) = "path7") {
if (GetFileURL (file8) = "path8") {
etc etc etc

george
05 Mar 2014, 07:11
Perhaps HK, but it does seem like a bug that GetFileURL doesn't return a sensible error if the file isn't actually there. But maybe there's a way around this I don't know, hopefully someone else will weigh in.

HegemonKhan
05 Mar 2014, 07:14
well the string matching check should work... albeit a bit tedius... there's maybe (or as you say, should be) another better way built-in than having to add in the string matching (though you could just add this to the built-in function itself too, I suppose, meh ~ though not sure how you could code in all the different file paths... is there a way to generate all the file paths into a list, along with generating the files themselves into a list, and then thus being able to use quest's "foreach" or an external coding lines of doing it?)... and~or a specific string "algorithm-like parser~compiler~whatever it is called, lol" for it...

there is the error ( http://quest5.net/wiki/Error ), but you still need the coding~scripting I mention above, anyways... meh

this is way above my level of coding ability~knowledge, lol. too advanced coding for me, hehe.

-----------

couldn't you just create a function:

in-scripting: media_file_checking_function ("cactus.png","c:/programs/quest/cactus.png") // maybe the quotes aren't needed

<function name="media_file_checking_function" parameters="file_x,path_x">
if (GetFileURL (file_x) = path_x) {
-> // do script
else if (GetFileURL (file_x) = null) { // or: else if (not GetFileURL (file_x) = path_x) {
-> // do script
}

though, this doesn't address the problem (the lack of not having a method of) generating (listing, thus iterating, thus "foreach" checking of) your files' paths

--------

oooo, this actually isn't hard at all (I didn't realize this previously, lol):

(well, you'll have to first figure out how to code in using an outside list file as described by george)

but then, you'd just need to do this:

foreach (file_x,your_outside_file_list) {
-> list add (global_data_object.file_path_string_list, GetFileURL (file_x))
}

foreach (path_x, global_data_object.file_path_string_list) {
-> if (path_x = "file_path") {
->-> // do script
-> }
}

you could actually also code in it to be even more functional (and more concise~condensed~efficient) too...

GiantAngryBoar
05 Mar 2014, 15:33
Ah, well, thanks a ton for your help, george, HK. I can't see any other way to do this either so I'm going to go with using an external tool like george said. I'll edit with my solution for others' reference when it's done.

george
05 Mar 2014, 15:45
HK, you can't use GetFileURL, because that function doesn't check if the file's not there.