Jump to content

GeoGern

+Premium Members
  • Posts

    25
  • Joined

  • Last visited

Posts posted by GeoGern

  1. Is it just a function of number of zones, or do points per zone play into the performance as well?

     

    Yes, the number of points in a zone makes a difference. This is part of what I meant when I stated earlier that the complexity of a zone is factor in how many zones a cartridge can support.

     

    It seems that as part of processing zones, you would need to process each point that defines a zone...so the more points, the more processing, correct?

     

    It is important not to confuse "processing" with "memory usage." While both are factors in determining whether or not a cartridge will successfully run on a particular device, they are certainly not the same thing. Yes, more points in a zone means that more processing needs to be done on each location update to determine the state (and other attributes) of the zone. Completely separate from the processing ramifications of a "complex" zone are the memory requirements. In the current Engine architecture, each point in a zone is a full-blown object, so more points in a zone means more objects in memory.

     

    I'm not prepared to get into further details in this forum. And, as I have stated previously, we don't have hard numbers about actual limits. However, I think the general principles described by myself and other lackeys on this thread about being judicious with the number (and complexity) of zones, items, characters, etc, are valid. And the key point that the current generation of Wherigo-capable devices are limited in memory (and CPU capacity) as compared to laptops and desktops is worth remembering.

     

    Feel free to contact me privately if you (or anyone reading this thread) have further specific questions that you think I might be able to answer.

     

    -peter

  2. you'll probably notice I used the tutorial sample lua file Jeremy posted to learn how to do the Play Anywhere dynamic zones before you posted your script file. It actually wasn't as hard as I was expecting and the builder still was able to open my hand-modified lua file.

     

    My original attempt was to use your GetZonePoints function to move each zone near my current location when the cartridge started. In my player, this didn't work though because I was trying to use an offset of Player.ObjectLocation, which apparently wasn't set yet.

     

    My workaround was to fire a short countdown timer upon starting the cartridge. When the timer tick fires, I move the zone. This bought the device enough time to have Player.ObjectLocation set to my current location.

     

    I did see in your Lua file where you use Player.RefreshLocation(). I thought about trying that at cartridge start, but figured my workaround was good enough, so why bother!

     

    I am glad to hear that you found a solution that works for you. That is one of my favourite aspects of having Lua as the base scripting launguage for Wherigo; there are many ways to solve a problem, and if one way doesn't make sense or doesn't work for your specific problem, another way most likely will.

     

    As for the small issue you mentioned, that is why both the Wherigo Tutorial and the technique I posted above both wait for some sort of action/input from the user before attempting to create or move the zone(s) to current location. By waiting (either for action from the user, or with a timer as you did), you give the device a chance to ensure that the location information is accurate and up to date.

     

    -peter

  3. I took your (trenkle) comment as a challenge ;) and I created a bit of script code that can be added to pretty much any cartridge to turn it into a "Play Anywhere" cartridge. Before I talk a bit about how to use it, please note that this technique is NOT Groundspeak supported and not something I am guaranteeing to work for everyone (or anyone, really...). It is something of a hack, it has been very minimally tested, and may cause a singularity to open up in your vicinity that destroys the universe as we know it. You've been warned. ;)

     

    The basic idea here is that you create a regular, location-specific cartridge using the builder. You put in all your zones and characters and items and whatnot. You test it in the Emulator. You go outside and test it. You feed it to your dog and see if he likes it. When you're satisfied that it is ready, you open up the script for your cartridge, copy my code into the end of your cartridge, and set a single coordinate that acts as the "reference point" for all the existing zones, objects, etc, and then re-build the cartridge and now it is a "Play Anywhere" cartridge. It works by translating all the points in your cartridge to the location where the user plays it, using the reference point you set as the player's relative starting point. Please see the readme.txt in the zip file for usage details.

     

    A few things to note about this: Besides being totally unsupported (beyond what I am able to provide in these forums), this method of creating a "Play Anywhere" cartridge is not how the Wherigo Tutorial cartridge does it. The Tutorial uses "dynamic zones" and other advanced concepts that is the topic for another day in another thread. This method currently triggers a Builder bug that may make your script un-editable in the Builder after you paste my code in to it. The bug has been noted and hopefully will be fixed soon. Oh, and did I mention that this method is not official and is not supported? Good.

     

    So, have fun with this. Please _do_ give me feedback if you use this or make use of parts of it, or don't ever touch it but think it might be cool to create a singularity in your neighborhood.

     

    Cheers,

    -peter

    MakeLocationless.zip

  4. There is no hard limit on the emulator or the device.

     

    And to follow-up on what David said:

    The question as asked about the Emulator, but it is worth mentioning the "limits" for the actual device.

     

    While there is no "hard" (arbitrarily imposed) limit* on the number of zones (or items, characters, etc), there is a practical limit to the total number that can exist in a single cartridge. Since all objects (zones, characters, items, etc) are loaded into memory at once, and each object is composed of a number of elements (points for zones, inventory, description, etc), you will find that memory will quickly become exhausted if you include too many in your cartridge. We have not done any "scientific" tests of what those limits are, but on the Colorado, our current recommendation is that you have no more than 10 zones in a cartridge. You can probably get away with more (depending on the complexity of the zones and what other objects exist in the cartridge), but really don't recommend it. Please keep in mind that the Garmin Colorado and even the PPC devices are NOT desktop computers with gigabytes of hard drive and memory space available.

     

    -peter

     

    * Well, technically, there *is* an arbitrary limit, since (due to the technical nature of the Wherigo Engine architecture), all objects need to fit within a 16-bit addressing space. However, this particular limit might easily change in future versions of the Engine and even if it doesn't, it is way beyond the memory limits described above.

  5. Hi CJ,

     

    I am sorry my previous post didn't really clear up the confusion. Here's some more detail, and hopefully that will help. Of course, please do keep asking questions if you're confused or I don't do an adequate job of answering your question(s).

     

    First, the scenario you are describing is essentially this (correct me if I am wrong): You have two independent, simultaneous events (ZCartridge:OnStart and Zone:OnEnter) that are both competing to display something on the screen. This is normally not a great idea; my colleague, David, has written up a document that lists some of the pitfalls and best practices of cartridge building, so perhaps I can entice him to chime in here and talk a bit about it. I understand that you have to set up the cartridge story, etc; the Village Robot cartridge does the same thing: it has an opening MessageBox that is displayed when the cartridge starts _and_ it has a MessageBox that is displayed when the user enters the first (and only active) zone. The solution that the Village Robot cartridge used was to have the cartridge starting location be _away_ from the first zone so that the user starts the cartridge, reads the intro text, and then walks into the first zone.

     

    Of course, maybe you have good reasons for starting the cartridge inside the zone. If so, then the approach you described is pretty much what you'll need to do: use a variable to keep track of what event is displaying text on the screen and not allow other events to display something on the screen while another event has the screen "locked" (so to speak). Now, that leads me to your confusion with MessageBox callbacks. I call them callbacks because that is what the Wherigo Library (script code) calls them. But, the Builder calls them "Script to run when button is clicked" (which is really just saying the same thing). To further the confusion, the Builder only supports this on the "Show MessageBox to Player" action, and not on the "Show a series of Dialog messages" action. (It is possible to have a "final callback" in a Dialog API call, but you'll need to drop down to the Lua script to do this.)

     

    So, at a "pseudo-code" level, this is what you need to do:

    * Create a variable "Isthisthestartup" and default it to the string YES (or the boolean true)

    * In the OnStart event, show a (single) messagebox to the user (I'll refer this to Msgbox A)

    * For Msgbox A, create a "script to run when button is clicked" (callback) that shows the next part of the dialog string you want to show (called Msgbox B ).

    * Repeat the previous step for as many parts of the Dialog string you have.

    * In the callback (script to run...) for the final messagebox, set the "Isthisthestartup" variable to the string NO (or the boolean false).

    * In the Zone:OnEnter event, check the Isthisthestart variable, and if it is YES (or true), do nothing.

    Else, show your dialog/messagebox to the user.

     

    This idea can be gernalised to any "competing" events by using a "locking" variable that all potentially "competing" events check before displaying text to the user. If the "locking" variable is false, then that event sets it to true, displays the text, and in the callback for the messagebox, sets the locking variable back to false.

     

    Yes, this is somewhat difficult. The alternative approach is to just assume that, depending on how you design the cartridge, some messageboxes may get "overwritten" and always give the user a way to display the message again (by talking to a character, examine an object, etc.). You can see this style in a number of "traditional" gaming systems (like Zelda for the DS, etc).

     

    Also, a key point here is that messagebox callbacks give you, the cart author, a way to "run code" only after the user has acknowledged the messagebox, rather than when an event occurs. So you can do all sorts of things with messagebox callbacks; like show a messagebox, and then show a GetInput right after the user reads the messagebox.

     

    Does this help?

    -peter

  6. I am glad that you figured it out, CJ.

    The Book example that I posted in another thread was, necessarily, very simple so that it didn't confuse by adding too much detail or functionality. But what you've discovered is that there is a much better way (IMHO) of handling "invalid" commands. Rather than always having a command (like "Grab") enabled on an item like the Book, it makes much more sense to only have it enabled (and visible to the user) when it makes sense to allow the user to invoke the action. So, yes, the object commands have the ability to be enabled and disabled. When they are enabled, they show up in the UI for the user to select, and then they are disabled, they are hidden in the UI and the user cannot select them.

     

    This means that rather than having script in the zitemBook:OnGrab() event that checks whether or not the book is already in the user's inventory, I can, for example, start the book in the user's inventory and have the Grab command disabled (zitemBook.Commands.Grab.Enabled = false). Then, when they "drop" the book or "give" the book to another character, I would enable the book's Grab command (zitemBook.Commands.Grab.Enabled = true) in the script code that "moves" the book in to the inventory of the new location/character.

     

    Keep playing around and enjoying the experience of discovering what it possible with Wherigo. :laughing:

     

    -peter

  7. Formal documentation is coming, and hopefully these, and many other, details will be covered in the documentation as it is initially published and then fleshed out. However, here are some quick answers to your questions in the meantime.

     

    Some of what you are looking for is actually done in the underlying C-code of the Wherigo Engine, but can be found via various Lua libraries. The logging, for example, is actually done by the Engine, and so the date and time are supplied by the C runtime libraries. However, there is a Lua library called "os" that exposes the API calls to get the current date and time. There is an API in the "os" library called "date" that will return the current date and time formatted however you'd like (within reason, of course). For example:

    now = os.date("%c")

    This will set the variable "now" to a string that represents the current date and time using the system's locale format.

     

    Of course, I need to make a few warning comments here: First, it should hopefully be obvious that the date/time reported by the system are only as accurate as what the user sets the device to. In other words, if the user has the time on their device set incorrectly, you'll get an incorrect date/time returned. Also, the "standard" Lua libraries are not fully supported on the PPC device, so not all API call are implemented (or implemented as you might expect). This includes the os.date() API. Sadly, the PPC support for the ANSI C runtime library is, uhm... "broken," and so most of the format specifiers for os.date() don't actually work. I know that os.date("%c") works, but I haven't tried any others and don't expect them to work. So, caveat emptor.

     

    As for DeviceID, that is available in the Lua "Env" table. For example:

    usersDeviceID = Env.DeviceID

    This will set the Lua variable "usersDeviceID" to a string containing the user's DeviceID.

     

    There are many others. Some of them can be found by an enterprising Lua hacker by playing around with the runtime environment in the Builder. Many of them will eventually be documented. But, until then, I guess you can ask about specific things.

     

    Also, and this hopefully also goes without saying, please don't assume that anything I reveal on these forums is "binding" and will always work or always be supported. One reason for not publicly documenting some of this is that we're still determining just what should stay in and what should be removed (or left in, but completely unsupported). We want to learn from all of you what features and functionality are important and what is maybe less so.

     

    Cheers,

    -peter

  8. Hi Don,

     

    Yep, that is definitely possible. When you create a "Get Input" in the Builder and tell it to save the input to a ZVariable, it automatically creates code that will store the user's inputted text into a cartridge variable. So, at any time you can create a MessageBox (or other display widget) that will "echo back" the contents of that cartridge variable.

     

    For example, say you have a ZInput that stores the text entered into a ZVariable called "userinput". You can then do a MessageBox that dispays the text "You previously entered: <userinput>" (where <userinput> is replaced with whatever the user actually typed). In the MessageBox script you would concatenate the string "You previously entered: " with the variable "userinput":

    [[You previously entered: ]] .. userinput

     

    Also, it might be worth mentioning here (as I have mentioned in another thread) one of the differences between the current devices that support Wherigo. While the PPC devices (and the desktop Emulator) provide an easy and convenient method for entering text, the Garmin Colorado has neither a touchscreen, nor a multi-button keypad (like a mobile phone), so entering long strings of text on that device can become quite tedious. So don't be surprised if users with a Colorado device (or other future devices like the Colorado) don't enter much in the way of text.

     

    Cheers,

    -peter

  9. Under Cartridge / Events / When a cartridge is started / Script reads:

    Show a series of Dialog messages to the player

    Show screen task screen

     

    When the player enters the zone (which they begin in)

    Show message to player.

     

    When I play the cartridge on the emulator, the series of messages blast by without me hitting OK, the Zone 1 message appears. After I hit OK, the task bar screen comes on.

     

    I've tried getting rid of the Zone 1 show message when player enters zone. And the series of Dialog messages still blasts by.

     

    Hi CJ,

     

    If I understand correctly what you're describing here, it sounds like you're encountering the "non-modal" aspect of the Wherigo platform. As I briefly explained over in another thread, the application does not ever "stop" to wait for user input (whether it is asking for text to be typed in, or just a button to be pressed). So, if your cartridge displays a MessageBox to the user and then tells the User Interface (UI) to display a specific screen (like the Tasks Screen) or display a different MessageBox, whatever is being displayed will be replaced with the new screen/message. In your description above, because you have an OnStart Dialog string *and* you have a MessageBox that is displayed when a user enters a zone, you will get the "odd" behaviour you are describing when the user starts the cart in the zone.

     

    One solution to this is to use the MessageBox "callback" routines to only have "stuff happen" in response to the user dismissing the MessageBox. So, for example, you could put the "show task screen" in the callback for the OnStart MessageBox so that the Tasks Screen is only shown after the user has read thru the message. You could also make the initial zone start inactive so that the zone OnEnter event does not occur right after the OnStart. Then, make the zone active after all the initial OnStart display stuff is done.

     

    Hope this helps some.

    -peter

  10. Creating "Play Anywhere" cartridges is considered an "advanced" topic (for more than one reason), so while it *can* be done in the Builder, it is not something that the Builder goes out of its way to make easy. So, yes, you will need to write some Lua script to make a Play Anywhere cart. You are on the right track, however, in defining your zones at design-time and then "moving" the zones at run-time to where the user is.

     

    -peter

  11. I wasn't originally going to post this or respond to any of the comments made by others about preventing users from cheating on cartridges, but after much consideration I decided that maybe I could offer an alternative view point for cartridge authors to consider.

     

    But first, please note that I am not responding to any one person or attempting to "attack" anyone else's opinions or posts on this forum. In fact, I am posting this in a new thread so that hopefully no one will think I am singling them out. Also, my purpose in these forums is not to get in to ideological debates or to justify technical or procedural decisions made in the Wherigo platform. I am hoping that by posting this I will provide food for thought and maybe some help with understanding why the Wherigo platform is what it is today.

     

    To start with, Wherigo is more than just geocaching. It is more than just gaming. Wherigo is a platform for enabling all sorts of location-based activities, whether those activities be education, tourism, vertical market applications, or, yes, even gaming. With such a broad range of applicability, not all desired features will necessarily be "baked in" to the core platform. And some features, like cheat prevention, could even conflict with the goals of another activity. Also, please be aware that Wherigo (like location-based activities as a whole) is in it's infancy and has much room for growth and improvement. Of course, I recognise that gaming is the crazysexycool and exciting thing right now and something that the core geocaching audience is going to think of first and relate to best.

     

    Another thing to keep in mind is that "openness" is an important concept that we tried to keep in mind while designing Wherigo. We _want_ to see what the creative community (you!) can do with Wherigo and we _want_ to encourage discovery and learning with Wherigo. But "openness" also comes with a cost, and preventing some forms of cheating can be one of those costs. That doesn't mean that it can't be done and that there aren't creative solutions to combating the enterprising "cracker." But, it might take a bit more effort, or it might even require some non-technical solutions.

     

    I say all this merely as an alternative viewpoint. I am guessing that some of you will disagree with me, and that's okay. But healthy disagreement is good for the platform and the community, as it will promote dialog and "out-of-the-box" thinking. Perhaps by leaving cheat prevention as "an exercise for the reader" someone will come up with an unexpected solution that will be light-years better than anything we could have dreamed up within our insulated little cubicles here in the Lily Pad. That'd be wonderful! And who knows, maybe that solution will even be incorporated into future versions of Wherigo! (Author-permitting, of course.)

     

    On to some specific comments that I'd like to address:

     

    The GWC file format is easily decompiled.

    Well, I suppose that depends on who is making that claim. Certainly clever programmers and hackers are going to discover that there is no "Digital Restrictions Management" (DRM) or encryption used to protect the contents of the GWC file. Yes, someone is going to figure out where things like the "completion code" and other important bits of data are stored in the file and post instructions on how to decompile the cartridge. (Well, partially. As far as I have been able to find, there is currently no decompiler for Lua 5.1, so the actual script code will be difficult to decompile. Right now. Until someone writes a Lua 5.1 decompiler, etc.) So, yeah, someone who wants to can come along and grab the cartridge completion code for your cart and "unlock" it on the website and claim to have completed the cart when they didn't really. Actually, we should *be* so lucky. If Wherigo becomes so popular that this becomes a serious problem then I'll personally be glad to be faced with it. But Wherigo unfortunately does not have that problem at this time. Of course, future versions of Wherigo may make strides to address this issue by protecting carts in some way, but please remember that we, the Wherigo developers, only have so much time and resources and getting into an "arms race" with the world-wide cracker community isn't something that does anyone (other than the crackers) any good. Wouldn't you like to see bugs addressed and new features added?

     

    The answers to questions asked of the user are easily found by opening the GWC file in a text editor.

    Well, again, I think this depends on who's making that claim. Sure, anyone can open a GWC file in a text (or hex) editor, or dump the strings to a file, or decompile the cart, etc. But not everyone is going to be sophisticated enough to determine whether "ZCartridge" or "zitemSecretCode" or "42 + 23 = l33t sekret" is important to solving the game or just random script code. There are, of course, technical solutions to this available to you, the cartridge author, right now. You could include a bunch of strings and words and phrases in your cart. How is the "cheater" to know which one is the correct one? (See above about my thoughts on decompiling the script code.) Use rot13 or some other encryption scheme to "protect" the answers. Better yet, hash the answers so that they cannot even be decrypted! Sure, most of these suggestions are not easily done by the beginner cart author, but proper protection of secret information isn't an easy concept. Not if you are serious about keeping determined crackers at bay. Of course, you could enhance (or even replace) your technical protections altogether by using social- or community-based methods. Is someone completing a lot of carts all over the country (or world) within days (or hours) of the cart being released? "Expose" them to the community (or confront them directly). Or maybe take some cues from people that have dealt with this issue for a lot longer: virtual cache owners. Ask the user to provide some sort of evidence apart from the completion code; maybe a photo of them playing the cart; or a word or phrase emailed (or posted) separately; or the log file from the device when the cart was played. There are so many ways that I won't even try to list more here. And some helpful early adopters have already posted there own (excellent) suggestions on this forum. Please remember that sometimes solutions can be more than just technically solved.

     

    But what about the Emulator?!?

    Yes, cartridges can currently be played in the Emulator. This is a Good Thing. Not only does it allow the cartridge author to design and test without having to constantly run outside to check their changes, but it gives people not in your area a chance to experience your creativity and design skills. It *is* a good suggestion to give you, the cart author, the ability to deny others to play your cart in the Emulator, and I am sure we'll look in to the possibility of adding that in a future version. (Although, honestly, you're more likely to do more harm than good to your cart by taking advantage of this potential feature. But, I respect your right to make that decision for your own creations.) And there are already some clever ideas floating around the forums to accomplish this right now. You can, of course, incorporate questions that can only be answered by being physically present at the location the cart is designed for. You could also check the user's altitude and block them from playing if it is 0 and remains 0, as the Emulator currently does not simulate altitude and always sets the player's altitude to 0. Again, search the forums for some other insightful thoughts on this issue.

     

    Without feature/protection X, I won't make a cartridge.

    I am sorry you feel that. Honestly, I am. Of course, I am biased, having invested a lot of my own energies in to this platform; but for someone to walk away because of a shortcoming that exists today is disappointing. As Jeremy has said, we want this platform on as many different devices as possible and we want to improve and grow Wherigo into something that can truly make an impact on a lot of people. But it's not going to happen instantaneously and it's not going to happen without feedback and participation from *you*. I personally believe it is better to get something out there now, than to wait until Wherigo is perfect and meets everyone's needs. (Like that is ever going to happen anyway!) So join us! Help us make it the platform that *you* want. Or sit back, walk away, or give up. But know that in doing so Wherigo may never become what you want, because we're unlikely to get to where *you* are going without you.

     

    Cheers,

    -peter

  12. Other than sound, could you give a quick ballpark evaluation of how Wherigo might be different on the colorado vs PPC?

     

    In addition to what Jeremy said, user input is different between the PPC and the Colorado device. Both support multiple choice, numeric, and full alphanumeric input. However, the PPC version uses the built in touchscreen (or hardware keyboard, if your PPC has one) input methods: tap keyboard, block recogniser, letter recogniser, etc. And the Colorado uses the Rock-N-Roll wheel to scroll thru the available characters (alpha, numeric, punctuation, etc). Multiple-choice input is essentially the same between the two devices.

     

    The take-away here is to recognise that user input (beyond simple true/false and multiple choice) may be more "challenging" on one device than another. Keeping requested alphanumeric input to a short word or phrase is a recommended best practice.

     

    Oh, and I don't recall if it has been mentioned elsewhere or if the Builder warns the cartridge author of this fact, but it is worth pointing out that Wherigo on the Colorado device _only_ supports images in JPEG format, while the PPC version is a bit more forgiving. So if you're testing solely on the emulator or a PPC device, you may be surprised the first time a user reports that some or all images don't display on their Colorado device. Again, the best practice here is to simply ensure that any images you use are pre-converted to JPEG format. At some point the Builder and/or Linker will become smarter about this and handle the necessary translations on the fly. But not in the current version.

     

    -peter

  13. How do I make a new file. Again, not trying to be a pain, just hanging in there.

     

    In your Windows File Explorer, click on the File->New menu and select something like "Text Document."

    Or

    Using the Wherigo Builder, create a new cartridge (File->New Cartridge...), give it a name, close the Cartridge Base Information window, save the cartridge

     

    Then, edit the new cartridge script file you just saved/created in Notepad and replace the contents of the file with the code from this thread.

     

    Be sure that the file you create has a '.lua' file suffix, otherwise the Builder will not see it and will not open it.

     

    -peter

  14. There is a Wherigo library? I could use a little more info...maybe a book on how to do this. I am not nocking this thing at all, but I bet we could all use a little more info on how these come togeather.

     

    Matt

     

    Hi Matt,

     

    I guess I was a bit too technical with my previous post. The 'Wherigo library' is a bit of code in the Builder and Player that implements the basic functions and objects that you, the cartridge author, can use to create your own carts. So when I said that the Wherigo library does not have a built-in "book object," I meant that there isn't any base functionality that does exactly what you want.

     

    While the Wherigo platform can certainly use some documentation and "how-to" tutorials (and I believe that some are being worked on by various Groundspeak Lackeys), none are available yet. So, the next best thing is just to dive in and try experimenting, learning from what others have posted, and asking questions.

     

    To get you started, I created a very simple sample cartridge that contains the code for what I described in my previous post. It's not the best example in the world, and I would almost certainly do things differently in my own carts, but it is simple and it should give you something to start with and to look at. Just copy-n-paste the text from the ed of this post in to a new file (I called mine 'BookExample.lua') and then open that up in the Builder.

     

    Cheers,

    -peter

     

    require "Wherigo"
    ZonePoint = Wherigo.ZonePoint
    Distance = Wherigo.Distance
    Player = Wherigo.Player
    
    -- #Author Directives Go Here# --
    -- #End Author Directives# --
    
    cartBookExample = Wherigo.ZCartridge()
    
    -- MessageBox Callback Functions Table used by the Builder --
    cartBookExample.MsgBoxCBFuncs = {}
    
    -- Cartridge Info --
    cartBookExample.Id="9a7be9ee-1245-45b9-b954-fad684d63fb5"
    cartBookExample.Name="BookExample"
    cartBookExample.Description=[[]]
    cartBookExample.Visible=true
    cartBookExample.Activity="Fiction"
    cartBookExample.StartingLocationDescription=[[]]
    cartBookExample.StartingLocation = Wherigo.INVALID_ZONEPOINT
    cartBookExample.Version=""
    cartBookExample.Company=""
    cartBookExample.Author=""
    cartBookExample.BuilderVersion="2.0.4628.3428"
    cartBookExample.CreateDate="1/8/2008 9:07:09 AM"
    cartBookExample.PublishDate="1/1/0001 12:00:00 AM"
    cartBookExample.UpdateDate="1/8/2008 9:09:37 AM"
    cartBookExample.LastPlayedDate="1/1/0001 12:00:00 AM"
    cartBookExample.TargetDevice="PocketPC"
    cartBookExample.TargetDeviceVersion="0"
    cartBookExample.StateId="1"
    cartBookExample.CountryId="2"
    cartBookExample.Complete=false
    cartBookExample.UseLogging=false
    
    -- Zones --
    
    -- Characters --
    
    -- Items --
    zitemBook = Wherigo.ZItem(cartBookExample)
    zitemBook.Id="3f67910b-1a0c-4f51-8de2-9b3dfab4e3b1"
    zitemBook.Name="Book"
    zitemBook.Description=[[This book can be picked up, opened, and read.]]
    zitemBook.Visible=true
    zitemBook.ObjectLocation = Wherigo.INVALID_ZONEPOINT
    zitemBook.Locked = false
    zitemBook.Opened = false
    zitemBook.Commands = {
     Grab = Wherigo.ZCommand{Text="Grab", CmdWith=false, Enabled=true},
     Open = Wherigo.ZCommand{Text="Open", CmdWith=false, Enabled=true},
     Read = Wherigo.ZCommand{Text="Read", CmdWith=false, Enabled=true},
     EnterCode = Wherigo.ZCommand{Text="Enter Code", CmdWith=false, Enabled=true},
    }
    zitemBook.Commands.Grab.Custom = true
    zitemBook.Commands.Grab.Id="e647c9e2-791d-44d3-a3a9-487ddf498379"
    zitemBook.Commands.Grab.WorksWithAll = true
    zitemBook.Commands.Open.Custom = true
    zitemBook.Commands.Open.Id="fcd03e61-2d26-482d-b996-7a8094068854"
    zitemBook.Commands.Open.WorksWithAll = true
    zitemBook.Commands.Read.Custom = true
    zitemBook.Commands.Read.Id="d2e171f5-6f17-41b7-872f-67ea3da90c0c"
    zitemBook.Commands.Read.WorksWithAll = true
    zitemBook.Commands.EnterCode.Custom = true
    zitemBook.Commands.EnterCode.Id="ad0fa62a-51e7-48ed-938b-733aa4ab88c5"
    zitemBook.Commands.EnterCode.WorksWithAll = true
    
    -- Tasks --
    
    -- Cartridge Variables --
    UnscrambledCode = ""
    cartBookExample.ZVariables = {UnscrambledCode = ""}
    
    -- Builder Variables (to be read by the builder only) --
    buildervar = {}
    buildervar.UnscrambledCode = {}
    buildervar.UnscrambledCode.Id ="9353f34e-75f5-45ff-8f38-ac1ed6321071"
    buildervar.UnscrambledCode.Name = "UnscrambledCode"
    buildervar.UnscrambledCode.Type = "String"
    buildervar.UnscrambledCode.Data=[[]]
    buildervar.UnscrambledCode.Description=[[]]
    
    
    -- ZTimers --
    
    -- Inputs --
    zinputEnterCode = Wherigo.ZInput(cartBookExample)
    zinputEnterCode.Id="85cc3b72-244e-45c2-b05f-2c6e1394ccd1"
    zinputEnterCode.Name="EnterCode"
    zinputEnterCode.Description=[[Allow the user to supply an unscrambled code.]]
    zinputEnterCode.Visible=true
    zinputEnterCode.InputType="Text"
    zinputEnterCode.InputVariableId="9353f34e-75f5-45ff-8f38-ac1ed6321071"
    zinputEnterCode.Text=[[Please enter the unscrambled code.]]
    
    --
    -- Events/Conditions/Actions --
    --
    
    -------------------------------------------------------------------------------
    ------Builder Generated functions, Do not Edit, this will be overwritten------
    -------------------------------------------------------------------------------
    
    function cartBookExample:OnStart()
    -- #GroupDescription=When the cart is started --
    -- #Comment=When the cart is started --
    zitemBook:MoveTo(Player)
    end
    
    function zitemBook:OnGrab()
    -- #GroupDescription=Script --
    -- #Comment=Script Comment --
    if	not Player:Contains(zitemBook) then
    zitemBook:MoveTo(Player)
    else
    Wherigo.MessageBox{Text=[[You already have the book!]],}
    end
    end
    
    function zitemBook:OnOpen()
    -- #GroupDescription=Script --
    -- #Comment=Script Comment --
    if	not Player:Contains(zitemBook) then
    Wherigo.MessageBox{Text=[[You have to be holding the book in order to open it.]],}
    else
    if   zitemBook.Opened == true then
    Wherigo.MessageBox{Text=[[The book is already open.]],}
    else
    zitemBook.Opened = true
    end
    end
    end
    
    function zitemBook:OnRead()
    -- #GroupDescription=Script --
    -- #Comment=Script Comment --
    if	not Player:Contains(zitemBook) or zitemBook.Opened ~= true then
    Wherigo.MessageBox{Text=[[You can't read what you don't have and is not open.]],}
    else
    Wherigo.MessageBox{Text=[[The scrambled code is "wighero".]],}
    end
    end
    
    function zitemBook:OnEnterCode()
    -- #GroupDescription=Script --
    -- #Comment=Script Comment --
    Wherigo.GetInput(zinputEnterCode)
    end
    
    function zinputEnterCode:OnGetInput(input)
    UnscrambledCode = input
    -- #GroupDescription=Script --
    -- #Comment=Script Comment --
    if   Wherigo.NoCaseEquals(UnscrambledCode,"Wherigo") then
    Wherigo.MessageBox{Text=[[You did it!]],}
    else
    Wherigo.MessageBox{Text=[[Sorry, that's not correct.]],}
    end
    end
    ------End Builder Generated functions, Do not Edit, this will be overwritten------
    -------------------------------------------------------------------------------
    ------Builder Generated callbacks, Do not Edit, this will be overwritten------
    -------------------------------------------------------------------------------
    --#LASTCALLBACKKEY=0#--
    ------End Builder Generated callbacks, Do not Edit, this will be overwritten------
    -- #Author Functions Go Here# --
    -- #End Author Functions# --
    -- Nothing after this line --
    return cartBookExample
    

  15. On the locationless note - I'd like to be able to write something that require one to ascend to a certain altitude above the starting point. I don't suppose there is any way of doing that?

     

    There are no "triggers" (or events, as we call them in the Wherigo terminology) for altitude, so it will be a bit more difficult to make something automatically happen once a user has passed a certain altitude. But, the user's actual altitude _is_ available for you to query. The Player object has an 'ObjectLocation' property that contains the user's current lat, lon, and alt.

     

    For example:

    curAltitude = Player.ObjectLocation.altitude:GetValue("ft")

    This will set the variable 'curAltitude' to the user's current altitude (in feet).

     

    -peter

  16. Thanks, Ranger Fox, for your informative and helpful write-up. I am sure that others will find this useful.

     

    I have a couple of explanations/corrections to add:

     

    -- I originally typed this post to display two message boxes, one to show the random number and one to tell if it is a higher or lower number. However, showing two message boxes one after another does not work well. It'll show the boxes, but the first will give way to the next without requiring user input. Instead, we'll create one message box to display and it will say the number AND if it is a higher or lower number.

     

    The Wherigo toolset is written with the concept that "time does not stop" in mind. This means that there are no "pause and wait for the user to respond" constructs in the library. (In computer science "speak," all UI elements are non-modal and it is not possible to block the logic flow to wait for input.) What does all this mean? Well, put simply, any MessageBox, GetInput, etc, will replace (or overwrite) any MessageBox, GetInput, etc, that is already being displayed. So placing two MessageBoxes back-to-back will have the side-effect of causing the first one to flash very briefly and then be immediately replaced with the second one.

     

    This doesn't mean that it is not possible to display two MessageBoxes (or whatever else) in row, but just that you have to do it in a special way. One way (the hard way) is to use MessageBox callbacks, and only display the second MessageBox once the user has acknowledged the first one. Another way, the easier way, is to use the Wherigo Library "Dialog()" API, which defines a sequence of MessageBoxes to be displayed, one after the other, like you would see in a character dialog (one person talks, then the other, etc). You can find the "Dialog()" API in the Builder at the bottom of the list of actions to select from when you are building the action script for a function.

     

    Open your .lua cartridge file in Notepad. First, type the following line at the top of the file:

    requires "math"

    WARNING: You will have to insert the above statement manually after EVERY TIME you save your cartridge. It keeps losing that statement, which was the cause of my confusion. Odd, but it happens.

     

    This is due to the fact that the Builder is very particular about what Lua script it can parse and in what format. And because it is very particular about what it can parse, it is very particular about what it writes out. Essentially, you should not count on it to preserve _any_ changes you make to the script file outside of the Builder, unless those changes are made in very specific areas. One such area is the "Author Directives" at the top of the file. Rather than placing the

    require "math"

    line at the very top of the file, it should be placed about 6 (or so) lines down, inside the "Author Directives" section of the file. This will cause the Builder to preserve that line and not remove it the next time you edit the file in the Builder.

     

    In fact, you should be _very_ careful about any changes you make to the script file outside of the Builder (if you intend to continue to edit the file int he Builder in the future). Not only is it possible to "lose" changes, but it is also possible to "break" the file such that the Builder will not open it any more. The recommendation here is to only edit lines inside the following script blocks: "Author Directives" and "Author Functions". If you edit lines anywhere else you essentially do so at your own risk.

     

    -peter

  17. The latter part of my post is the source of one of my tests, a complete cartridge. You'll see a few places I played around with the random function. Move the player to the parking zone and watch the exception trigger when it tries to assign a random value to the Random variable. Referencing the variable as either "Random" or "buildervar.Random" will produce the same effect. The exception is "attempt to index global variable 'math' (nil value)".

     

    Now, I don't know if Lua is case sensitive (I program with C#), so perhaps the exception really occurs because I named a variable the same as a function. I renamed the variable to "Ran" and the exception repeated.

     

    Okay. Then what about "math.random" being the wrong way to reference the function? I tried referencing the function only, "random(0,100)". Same exception.

     

    Hrm. Now I am puzzled. I ran your code on my machine and I do not get an exception; it runs just fine. In fact, I can "watch" the Random variable change to different values as I move the player in and out and in the Parking Area Zone.

     

    First, a couple of answers to questions you posed:

    Yes, Lua is case-sensitive, so random is not the same as Random.

    Lua does not have namespaces like C#, but it achieves a similar concept thru the use of tables. So, the 'random()' function is in the 'math' library and (because of the way the library was "imported") needs to be referenced via 'math.random()' and not just 'random()'. In fact, if you had a variable (or function... in Lua they are the same thing: functions are a "first-class" data type) in the 'global' table (same place that Random "lives) named 'random' it would not be the same thing as 'math.random' (unless you explicitly "aliased" random to refer to math.random).

     

    So... what to do now?

     

    My first suggestion is to make sure that you are re-compiling the script into GWC format each time you make changes to the file. When you launch the Wherigo Emulator, it does not automatically re-compile the cartridge. You have to do that part manually. It is possible that you are getting the nil value exception each time because even though you are making code changes, you're always emulating the same original script.

     

    If that is not it (because you already knew this, or you gave it a try and you're still getting an exception), then perhaps you have a corrupt installation of the Builder. This seems highly unlikely, since it shouldn't run at all, rather than run but complain about the math library being nil.

     

    And if all else fails, perhaps you can send me the GWC file that you have compiled that is giving you the exception and I can pick thru it.

     

    Also, in case you are not aware, there is an excellent online Lua book that you might find helpful:

    http://www.lua.org/pil/

     

    Cheers,

    -peter

  18. I am not sure I understand what you're asking (so someone else may jump in here and correct me or clarify), but if you're asking if this version of Wherigo supports (virtual) container objects that can be made "invisible" (or hidden from the user), the answer is yes. Most all "things" in the Wherigo "universe" can be marked visible or invisible.

     

    -peter

  19. So, I am asking:

    Since the Colorado can not play sound files...will you have to create 2 versions of a cartridge for people that have a PPC and people that have a Colorado?

     

    If you created a Wav for the PPC...what happens if someone puts it on the Colorado...would it just beep or do nothing...or crater?

     

    The GWC file format has the capability of storing "alternate" versions of a media resource (like a sound or an image) alongside the "primary" version. This allows a cartridge to contain both a WAV and an FDL (what we call the sound files for the Colorado) for the same sound resource. This means that you, the cartridge author, do not need to provide multiple versions of the same cart. Of course, you _do_ still need to provide multiple versions of the same media resource, but the Wherigo Linker and "just-in-time" creation capabilities of the Wherigo web site do all the work of creating an appropriate GWC file for the type of device the user has.

     

    If a user happens to play a cartridge on a Colorado device that has only WAV files in it for sounds, the user simply will not hear anything. The Wherigo Player application on the Colorado is smart enough to know that it cannot handle that media type and so it just ignores it. The is true for the Windows PPC version of the Player application: since it does not support the FDL sound format, it will simply ignore those if that is all that is present in the GWC file.

     

    Hope this helps some.

    -peter

  20. Since there are no built-in "book" objects in the Wherigo library, you will need to create your own book object and define the actions that it supports. So, to do what you describe, you will need to:

     

    * Create a new ZItem called "Book" (or whatever you want to call it).

    * Add a new action (command) to allow the user to "grab" it. You can call this "Take" or "Grab" for example.

    * Define the new "Grab" action. A good idea of this type of action is to move it into the user's inventory.

    * Add a new action to allow the user to open it (for example: "Open") and define the action. Depending on how fancy you want to get here, you might check to make sure the book is in the user's inventory before they are allowed to open it, and also keep track of whether the book is already opened, so it can't be opened again.

    * Add a new action to allow the user to read or examine it (for example: "Read") and define the action. Again, you may want to check to make sure it is opened before allowing the user to read it, etc. The result of this action might be to show a MessageBox that contains the 'code' the user needs to figure out.

    * Add a new action to allow the user to enter the the decoded variable. When this action is run, it could display a ZInput to allow the user to enter the text (or number) and then check the validity of it.

    * Etc...

     

    Hopefully this gives you an idea of what to do.

    Cheers,

    -peter

  21. I've got it to work on my PC and completed the tutorial (and logged it). I somehow have two files in my Wherigo folder on my desktop, one wherigo_player_tutor.gwc of 641kb and one wherigo_player_tutor.gwl of 20kb

     

    The GWC file is the original cartridge file and the GWL file is the cartridge log file. It is simply a text log of various things that happened while playing the cart. It is safe to delete the GWL file if you no longer need it. (And you don't for the Tutorial cart.)

     

    Cheers,

    -peter

  22. Yeah, in the Lua source, I created a variable called "Random" and tried to set its value when the player enters a zone. This produces an exception when the line runs in the emulator.

     

    Can you provide any more details about the exception that was generated? The line you provided looks okay. Also, the Lua "math" library is not loaded by default, so be sure to "require" the math library before using any functions from it. In the Tutorial cartridge, this is done near the top of the file (in the "Author Directives" section) by this line:

     

    require "math"

     

    Cheers,

    -peter

  23. A minor side question:

    Is there a way to reset a timer before the tick event fires? Stopping a timer, logically, does not mean the timer is reset when it is resumed.

     

    Actually, the current implementation of the ZTimer object resets the timer each time it is started. So, stopping a timer and then starting it again has the same effect as resetting it.

     

    Cheers,

    -peter

  24. There currently isn't any public/documented list of Wherigo-specific APIs for creating cartridges in a text editor. However, I can tell you it is definitely possible, as I have created a number of cartridges w/o the aid of the Builder.

     

    Since cartridges are just Lua script files that make use of both the standard Lua libraries and a custom Wherigo library, all that is needed is access to the Wherigo "Linker" that will turn the Lua script and associated media resources into a GWC file. This "Linker" is embedded in to the Builder and will eventually be exposed via a web-service call on the Wherigo.com site.

     

    However, this is getting ahead of the horse, so-to-speak. My advice for now would be to stick to the Builder and see what is possible with it. If you are feeling like an "intrepid hacker" you might pick up quite a bit of the Wherigo-specific Lua syntax simply by examining what the Builder produces. And hopefully the future will bring proper documentation and support for "advanced" cartridge building using your favourite text-editor and OS.

     

    As a specific answer to your question about a "randomisation function," the Lua "math" library contains a random() API that will generate random numbers. In fact, this is used by the Tutorial cartridge.

     

    Cheers,

    -peter

×
×
  • Create New...