Jump to content


  • Posts

  • Joined

  • Last visited

Everything posted by matejcik

  1. hello, you have to make sure that in the OnGetInput functions, you check for nil result (i think you are already doing this? you say that you set a default if the question is not answered) and if the result is nil (the question is canceled), you must NOT display messages in this branch. what your code probably looks like: 1. Ask input: "hello, what is your name?" 2. wait for result 3. if result is empty, set name to "Default" 4. Show message: "hello, <name>" if another thing (another zone proximity, for example) steps in and displays a message at (2), then the first code continues to (3) and then (4), the message from (4) collides mid-air with the new one, and the game crashes. This is a bug with input boxes, you can do the same thing with message boxes safely, but doing it to an input box will cause the crash. i'm not exactly sure what's going on in the second case, but it's probably something similar.
  2. just posting this here, that should force me to keep the schedule :e) more than a year after posting this, I'm close to finishing a bug-free version of the code. In the upcoming weeks, I will probably publish the code on here for the Public Beta.
  3. ...and finished the second part of the programmer's guide. hope this is all
  4. posted the first part of the programmer's guide yes, the input will stay on screen until the user is done with it. a message from another event will be queued. what can happen, though, is that after the input, another message will be displayed before that "I'm hungry" one. I'm not sure whether that's a good thing. we will see.
  5. Programmer's Guide 1. Interaction model Unlike traditional Wherigo API (which i will call legacy API from now on), in the blocking API, there is an implicit message queue. That means that if you send a message to the screen before the user is done with the previous one, nothing bad happens. When the user clicks OK on the first message, your next message will be shown. Also unlike the legacy API, some of our functions are blocking. In legacy API, you would do this: Wherigo.MessageBox{Text="start timer"} ztimer:Start() and the timer would start immediately - before you finished reading the message text. With blocking API, when you do this: UI.Confirm{nil, "Start timer?"} ztimer:Start() the timer will start only after the user clicks OK. In other words, Confirm will block program execution until it is finished. You may be thinking now, "What about timer events? What about zone events? Will they be stuck waiting too?" And the answer is no, they won't. Let's say you have two zones, zone A and zone B: function zoneA:OnEnter() zoneB.Active = true UI.Confirm{nil, "you are in zone A"} end function zoneB:OnEnter() zoneC.Active = true UI.Confirm{nil, "you are in zone B"} end When you enter zone A, zone B will become active and you will see a messagebox. Let's say that you don't click OK and keep it on the screen. When you walk into zone B, zone C will become active (that's the first line), and then the Confirm call will block until you click OK on both the first and the second messagebox. You: (walk into zone A) Cartridge: "you are in zone A" You: (walk into zone <--- at this point, there are two events "running" (they're suspended, actually) at the same time You: (click OK on "you are in zone A") <--- the first OnEnter is unblocked and finishes. only one event is "running" now. Cartridge: "you are in zone B" You: (click OK on "you are in zone B") <--- the second OnEnter can finish To make this possible, a third property of the blocking API is necessary: the same event cannot run twice at the same time. That means that, in the previous example, if you left zone A and returned to it before clicking OK, the OnEnter would not run again. 2. API Overview There are seven functions available: UI.Message, UI.Confirm, UI.Choice, UI.Input, UI.Notify, UI.Cancel, UI.Wait You cannot use these functions and traditional Wherigo functions (MessageBox, Dialog, GetInput) at the same time. Well, you can, but if you do it, everything will break horribly. Stick to the one or the other. First let's look at UI.Message in detail. There are several ways to call it: UI.Message { Sender=zObject, Text="some text", Media=zmediaSomeMedia } UI.Message { zObject, "some text", zmediaSomeMedia } UI.Message { zObject, "some text"} Notice that it's "UI.Message { ... }". It won't work with regular parentheses. (the function signature is actually UI.Message(table). Lua allows you to call UI.Message {something} instead of UI.Message({something}) in this case.) The Sender argument can be a Zone, ZCharacter, ZItem, ZTask or even ZCartridge. In the first example with the bear, I've been using the Bear character as Sender. This is to emphasise that the messages are part of a conversation, and that someone or something is talking to you. Sender can also be Player (if it is something the user is saying), or nil if you want the message "from nobody". At this point, Sender is only used for the picture, but it just might do something interesting in new versions of the player apps. Text is obvious. Media, when specified, overrides Sender's picture. So if you want to show many pictures and you don't have characters to represent them, just use Sender=nil and Media=yourPicture. All functions, except Cancel and Wait, take these first three arguments, but they can usually have more. All functions return nil when canceled (more about that later). Where not specified, the function returns true when not canceled. 3. Functions UI.Message This function is non-blocking. That means that, in the following code, timer will be started immediately, without waiting for the user: UI.Message{nil, "start timer"} timer:Start() The messages from UI.Message are still queued though. Look at the bear example to see them in action. UI.Message is the "normal" message that you would be using most of the time. UI.Confirm Counterpart of Message that is blocking. Useful for waiting before starting timer, activating a zone, whatever. This one has an optional argument, Button, that lets you specify button text. UI.Confirm{nil, "start timer?", Button="start"} timer:Start() UI.Choice Multiple-choice question. Similar to ZInput of type MultipleChoice. Has an argument Options that specifies the available options. Blocks until the user answers, returns text and index of the option: text, index = UI.Choice{zcharBear, "What kind of food do you have?", Options={"fish", "steak", "vegetables"}} -- text == "steak", index == 2 text = UI.Choice{zcharBear, "What kind of food do you have?", Options={"fish", "steak", "vegetables"}} -- text == "steak" UI.Input Text input - similar to ZInput of type Text. Has no more arguments. Blocks until the user answers, then returns the answer text. UI.Cancel Cancels everything on screen, and removes everything from the event queue. Blocks until processing is done. Simply put, you call Cancel to clear the screen for you - as if the user started clicking OK on everything in rapid succession, until nothing remained. (Unfortunately, on legacy players, there is no function to remove a message or input from screen. so instead, it is replaced by a messagebox that says "Canceled." But this one is not queued - if you call UI.Message immediately after UI.Cancel, the users will see your message.) A small example looks like this: function item:OnAskQuestion() UI.Confirm{zcharBear, "you have 10 seconds to answer me"} timer:Start() reply, idx = UI.Choice{zcharBear, "how many heads does a turtle have?", Options={"three", "lemon", "tuesday"}} timer:Stop() if idx == 3 then UI.Message{zcharBear, "that's correct!"} else UI.Message{zcharBear, "sorry, that is wrong"} end zoneCave.Active = false end function timer:OnTick() UI.Cancel() UI.Message{charBear, "too late! now i eat you!"} end What's going on here? After clicking OK on the Confirm, a timer is started. Then the bear asks you a multiple-choice question, and the OnAskQuestion handler is suspended until you answer. If you answer within 10 seconds, timer is stopped and the bear will tell you whether you were right or wrong. If, however, you wait too long, timer's OnTick will fire and call UI.Cancel. At that moment, every UI operation from the suspended OnAskQuestion is considered canceled. We can't just kill the event (well we could but that would be stupid), so we let it finish - but the blocked UI.Choice call will return immediately, and every following UI call will simply be skipped. Let's do it step by step. OnAskQuestion: "reply, idx = UI.Choice{zcharBear, "how many heads does a turtle have?", Options={"three", "lemon", "tuesday"}}" Screen: "how many heads does a turtle have?" <--- OnAskQuestion is now suspended and waiting for user reply <--- 10 seconds pass OnTick: "UI.Cancel" Screen: "canceled" <--- OnTick is suspended, waiting until queued events are finished. <--- OnAskQuestion is resumed. reply and idx are nil OnAskQuestion: "timer:Stop()" <--- nothing happens - the timer is already stopped OnAskQuestion: "UI.Message{zcharBear, "sorry, that is wrong"}" <--- nothing happens - OnAskQuestion is canceled, so all UI operations are ignored. OnAskQuestion: "zoneCave.Active = false" <--- zoneCave is deactivated. This still happens, even though the event was canceled. OnAskQuestion: done <--- all queued events are done. OnTick is resumed OnTick: "UI.Message{charBear, "too late! now i eat you!"}" Screen: "too late! now i eat you!" UI.Wait Takes no arguments, does nothing, but blocks until the screen is clear (or until canceled) I can't come up with an example where this function would be useful. But maybe some exist, and it was easy to implement, so we left it in. UI.Notify Displays a notification message which is not queued. Does not block. The message is displayed immediately, and if you try to display anything after it, the notification will disappear. This is similar to how the original Wherigo.MessageBox works. But with one key difference: when you click OK on a Notify message, you go back to where you were before. Let's go back to the example from UI.Cancel. We will extend the time limit to 30 seconds, and add a second timer: annoyingTimer = ZTimer{Type="interval", Duration=5} function timer:OnStart() annoyingTimer:Start() end function timer:OnStop() annoyingTimer:Stop() end function annyoingTimer:OnTick() UI.Notify{nil, "you have " ..tostring(timer.Remaining).." seconds remaining"} end That's it. During the time the multiple-choice input is shown, you will get a message every 5 seconds. If you click OK on the notification, you go back to the multiple-choice. If you don't, another notification will replace it, showing the new time. Note 1: Due to the way this is implemented, if a Notify box covers an Input, whatever you typed into the input will be lost. I suspect that this will be especially annoying on Garmins. So don't do it. Note 2: If you show a Notify box, then the first UI action that would be shown will make it go away. The result of this rule is a bit weird: If you show a Notify on an empty screen, then the next UI.Message will overwrite it. But if you show Notify on top of a waiting Confirm or something like that, then all other UI events will go to the queue, and the notification will stay visible until the user clicks OK - or until another notification (which would be shown immediately) clears it. Or, obviously, until it is canceled.
  6. Fellow programmers, geocachers, Wherigo creators, me and some other guys are playing around with this new concept of doing things in Wherigo. It looks like this: Most of you would be able to create this sort of interaction without much trouble, right? Well, have a look at the Lua code underneath it. function zcharBear:OnTalk() name = UI.Input {zcharBear, "Hi, what's your name?"} UI.Message {zcharBear, "Well, "..name..", I'm hungry."} UI.Message {Player, "Um ... okay, that's ... i'll just ..."} response = UI.Choice {zcharBear, "Do you have anything to eat?", Options={"Sure", "I'm afraid not"}} if response == "Sure" then UI.Message {zcharBear, "Gimme!"} else UI.Message {zcharBear, "Hmm, too bad. Now I'll have to eat you!"} end end You will notice that there are no callbacks, and that instead of creating a ZInput, we just get the response directly and use it right away. Pretty cool, huh? Disclaimer 1: This is only relevant for those of you who write cartridges (at least partially) by hand. There is no builder support. Disclaimer 2: What I'm posting here is closed alpha-release. It's alpha, meaning there are bugs, and it's closed, meaning that i won't post the code here - for now anyway. That said, the code exists and is readily usable, in the form of an author script. I'd like to hear your opinions on the new API model, and possibly your experiences with programming with it. Q: But how can I get the code? A: PM me if you're interested. I'll send it to you - if i judge you worthy /mwa ha ha/. No, seriously, just ask. Q: Then why don't you just post the code here? A: Because I don't want everyone and their grandma to include it in their cartridges before we manage to iron out the kinks. Here's a little secret: something very much like this will end up as part of OpenWIG, WhereYouGo and other modern players. We're trying to design the API right, so we are showing it to you early - but if everyone started using this version now, we would have a compatibility nightmare on our hands. For this reason, I will only send the code to people who have been active on the forums, and i'll want you to promise that you won't give the code to anyone else before it is ready. Q: Ha ha, I bet I could write something like this myself. A: Really? Cool. Why don't you join the discussion here and share your ideas about how it's supposed to work? Q: Okay, I got the code. What now? A: You already got the "installation instructions" in your PM. The next post in this thread contains a short programmer's guide. Have fun!
  7. matejcik


    short answer: If you're using Earwigo or URWIGO, you can check a box "prevent running in emulator" and the builder will turn on some prevention measures. If you're using the legacy Builder, you're out of luck - there is some code you can paste into Author section that does this, but it is messy, and if you're using the legacy Builder, i suggest switching to earwigo/urwigo anyway. if all you're worried about is lazy cachers who sit at home and click in emulator instead of actually going to the field, this is a great solution. long answer: First of all, playing in emulator is not "cheating". In some cases it is legitimate, in some cases people want to use the emulator for playing even though they are actually in the field. (this is less the case nowadays when everyone and their grandma has a smartphone, but in the early days many people had netbooks but not Wherigo-enabled devices) It is only cheating if you say the player has to be in the field, and even then it is the same as if they asked their friend for the final coordinates - i.e. no different from other forms of geocaching cheating that you can't prevent. Second of all, realize that deep within its bowels, your cartridge contains the final coordinates and it has to give them away at some point. Crafty people will manage to override the emulator check. Crafty people will feed fake GPS data to a smartphone application, thus "emulating" even without the emulator. Even craftier people will simply break into the cartridge and retrieve the coordinates without ever launching a player. This cannot be avoided - simply because your cartridge already contains the coordinates, and it has to give them away, it will always be possible to convince the cartridge to give them away sooner. (see also: so far, every game or computer program released was eventually cracked. once you have the code on your computer, you can mess with it.) There is only one way to make the cartridge completely "cheat"-proof: not including the final coordinates at all, instead calculating them along the way as if it was a multi or a mystery cache. This would require coding parts of the cartridge by hand and programming some formulas. I don't know if anyone ever did this, but i know for a fact that it can be done.
  8. Yeah, it actually is that hard. We here are a bunch of independent developers and we simply don't have access to that kind of data. The iPhone app is now owned by Groundspeak, so they technically could bring it more in line with the Geocaching app, but from what I gathered, they aren't all that interested in doing it. So there you have it.
  9. Also, i'm apparently dumb because you apparently know that you can "make my own mapping table". I skipped over that part and assumed that you didn't know about the possibility. Sorry. Yes, that's the only way to do it. Inputs always return strings, or nil if they are cancelled. (but cancelling inputs can crash garmins, so it's not like you need to solve that possibility) Oh well. At least here's some code to get you started.
  10. what you are attempting will not work. however, there are ways. let me show you a magic piece of code going into your OnGetInput method local options = {} options["Supermarket"] = zoneSupermarket options["DIY store"] = zoneDIYstore options["Mason"] = zoneMason -- .... local zone = options[input] zone.Active = true (By the way, you don't need to set zone visibility unless you are hiding them! It's not like inactive zones forget everything. You can keep a zone visible forever and just toggle active on/off. Inactive zone is not used by the player so it won't be displayed.) There are even more drastic ways to do this. This goes in the function where you call GetInput: local zonesInYellowPages = {zoneSupermarket, zoneDIYstore, zoneMason, ...... } mapping = {} zinputWhatever.Choices = {} for k,zone in ipairs(zonesInYellowPages) do mapping[zone.Name] = zone table.insert(zinputWhatever.Choices, zone.Name) end and this goes into OnGetInput: local zone = mapping[input] zone.Active = true (FWIW, zinputs are fake objects. if you're writing code by hand, you don't need to create the multiple-choice in builder, you can just write this: Wherigo.GetInput {Text="Pick one", Media=zmediaBla, InputType="MultipleChoices", Choices=choices} )
  11. one: the Android player is currently without maintainer, as RangerFox said. It is open-source, but without the maps component, which is sort of a big deal. If a volunteer were to step up and implement a maps component based on some opensource OSM implementations, that would be very cool. I'll do it at some point in the future, but that point seems to be pretty far away. If any of you want to dabble in Android development, this is a great place ;e) The original maintainer designed the app pretty well and the maps component should be easily pluggable. He also told me that if someone updates the app, he is willing to publish the updates under his account, to follow the update path. The OpenWIG core engine can be dropped in without modifications. At this point the one in WhereYouGo is somewhat outdated. two - an app developer's perspective: I'm reluctant about giving cartridge creators too many options. The player apps run in a limited-resources environment as it is, and by becoming a "platform" in itself, we would at some point have to solve the same problems the creators of Android and iOS are solving for "native" apps. One simple example is data usage: what if you want to conserve your data by not using the online maps, or precaching them on a WiFi, and then the cartridge just goes straight ahead and downloads a 500kB page every two seconds just to parse some status from the middle of it? Obviously, if you were concerned about data usage, you would turn off data on the phone (and we haven't started talking about streaming yet, where this all becomes moot anyway). Still, this is exactly the kind of thing that would happen sooner or later. Not to mention that parsing a 500kB page in embedded Lua is not something you want to do in the cartridge anyway. Now there are two approaches: a) FORBID EVERYTHING accept that this is the way things go in the real world and give them creators enough rope to shoot themselves (and their users) in the foot I will strongly object to just dumping LuaSocket or similar straight into players. For one, it's not asynchronous by design. That is something that's an absolute requirement in Wherigo, otherwise Horrible Things Will Happen. At minimum, we need an api that works like jQuery's AJAX: instantiate a request, associate callbacks, go merry on your way until they .. um ... call back. (notice that it is very similar to how GetInput works, by the way ;e) ) I'd go even further and say that the response must be a properly formatted JSON string no longer than, say, 4096 bytes. Yes, there is a third, hybrid approach: carefully measure the length of rope given out, so that if the creator tries really hard, they can still shoot themselves in the foot, but probably not repeatedly. By which i mean, very carefully designing an API that can, by applying enough pressure in just the right places, be convinced to do the evil things I speak of, but is generally hard to abuse otherwise. Designing this is a fun way to spend time, but to do it right is hard. As in, HARD. And I'd like to point out that the designer(s?) of Wherigo API did a very decent job, but we now know that they didn't get it completely right either - the nonsense that is Distance class is one example, the horrid mess of saving cartridge state is another. oh and three: Most people who create cartridges are not programmers, and they often have a hard time. The existing builders are lowering the barrier to entry (which, btw, was completely artificially set to absurd heights by how the original Builder generates sourcecode - if the API itself is a perfectly respectable job, the way Builder works with it and compiler compiles it is a horrifying vortex of chaos and discord, brought forth by an ancient and unspeakable evil from the eldritch dimensions. And i really mean that, too. I have a hard time coming up with ways to design it any worse) by presenting a nicer (by which i mean "actually usable") UI, and helping along the way, but they are no help at all when it comes down to the original issue that most people who create cartridges are not programmers. Great job with RangerFox's Wherigo\\kit, by the way. That is the direction builder apps should be heading, IMNSHO. Take notes, folks ;e) (whoa, i'm even more opinionated than usual. heh.) But. The point is what Afterburned said. Unless we have a simple and usable builder for everyday people, we can play around with cool features all we like, because we'll be the only ones using them. four: Speaking of some sort of web-retrieving API, i think the best way to do that would be to have a dedicated server providing a limited set of online-enabling features for cartridges, and simple built-in calls in the API to talk to this server and this server only. (with possible advanced interface somewhere under the hood). That way you could have an online-enabled experience created completely inside some builder. Just a thought. I haven't even started thinking about what exactly would this server have to do. and five: Given the current state of technology, i don't think it's impossible to have server-side cartridges anymore. THAT would be an interesting development.
  12. well, that indicates a memory leak, that's beyond doubt. now the question is whether the leak is in openwig, or in S60's java, or in your cartridge. in any case, it's interesting. is your cartridge doing anything potentially memory-consuming, besides showing the messageboxes? can you post the cartridge?
  13. If you can see errors in the gwl log, please post them here. If you actually see errors, as opposed to a seeming freeze of the application, it is an issue different from the one I mentioned, and it might be fixable ;e)
  14. i don't think there is. you could use ShowScreen and see if that closes the messagebox. but beware that on Garmins, only ShowScreen(MAIN_SCREEN) works and the others crash the player
  15. messageboxes do not stack, they cancel each other. many cartridges show a messagebox every second to display a timer for something, and it works without problem you should try to find out whether the errors start a) after 30 minutes regardless of messagebox timing after a number of messageboxes (try showing a messagebox in an endless loop - if the number of messageboxes is really the problem, it should crash pretty quickly) c) when something specific happens - you enter a zone, something else is displayed etc. there is a known bug in the legacy players that when you close an Input by showing a messagebox from a timer, it causes a crash. isn't this your problem? also, you didn't say which player shows this problem. if it is an Oregon, for example, i wouldn't be surprised if it started crashing on its own for no reason. also, some Nokia S60-based phones with openwig stop displaying output after some time.
  16. hello, you apparently didn't finish reading the wiki article ;e) after explaining this trick, it goes on to say: ;e) IOW, this only works on media that you show through Messages or Dialogs. If you want to change the media for items, zones, tasks and other object, you need to do it "the usual way", by assigning to the Media property: Set Value Character:Hero:Media => zmediaHeroShaven
  17. "i" is not what you think in the function. try using "self" instead: self.Active = false; (when you set a zone to inactive, you don't need to set it invisible, it basically drops from the radar and won't show ever again, unless you set it back to active)
  18. first, create the items regularly without setting Container second, as long as you're in custom Lua anyway, don't put names of zones in the array, put the zones themselves! i.e. coord3 = {zoneDoorway, zoneLivingroom, zoneDarkforest (......) } no strings, no quotes, direct object references third, use items' MoveTo method: zitemOne:MoveTo(coord3[math.random(10)]) this sets the Container and assigns the ObjectLocation in one fell swoop and you don't have to do it manually fourth, if you don't want to use the same zone twice, don't forget to remove it: r = math.random(#coord3) -- pick a random number from 1 to current length of coord3 z = table.remove(coord3, r) -- remove the element and put it into z zitemOne:MoveTo(z) -- move item to zone z
  19. well, i examined at least the second one pretty deeply, and found nothing. so chance is that the problem is really with the player sw, despite how unlikely i found it earlier... sorry i doubted you, i guess ;e) the closest guess for -one true- underlying bug would be that the iPhone player does something strange with saving, and variable values are not properly restored. and that the players who had issues did at some point or another switch out of the app and had it restart on them, so they loaded with the wrong values. this could also explain that the iPhone4S had no issue (more memory = better chance of keeping the app running in the background) now, this is an educated guess, but still only a guess. a comparison of code generated from Earwigo and Urwigo in this regard would be interesting - if nothing else, i believe that Earwigo generates the "buildervar" array for compatibility, and the iPhone Player might be using that for some nefarious purpose. do you have the original code with the custom Lua? if it crashes Oregons and made iPhones act funky, it could be a valuable debugging material, as i don't really believe that a generic piece of custom Lua can crash the Oregon just by virtue of being custom another possibility is that iPhone's Lua balks at certain kinds of for-loops (urwigo uses them internally in places). it is pretty far-fetched though - if we accept this, anything at all is possible. i hope that Shawn joins the discussion, he will at least be able to confirm or deny all this with certainty.
  20. this is not true, George is not using obfuscation. - by the way, kudos for that, and for making the cartridges open-source! i'm looking over the cartridges now and finding nothing wrong, subtly or otherwise. i'll give it a bit more time and see if something shows up
  21. well, as it happens, cartridges are somewhat more deterministic than waving around a dead chicken. ...unless it's on an Oregon, but the problem there is "player picks a random time to crash completely", not break the cartridge in a funky way. if your cartridge is doing fine on an Oregon, then it is very likely that it's you doing something wrong, not the player software. also, as far as i remember, you're the first person to publicly complain about "magically" broken iphone player. there have been complaints about missing features, but nothing even remotely resembling what you are describing seeing as you mention timers, and failures that look very random and magic, my guess is race conditions. a race condition is an issue where you think that some time-based events will happen in a specific order, when they in fact happen differently and mess up your program's idea of what is going on. in event-based programming like Wherigo, the same can happen with player-initiated events. maybe you think an event can only happen after something, and it actually happens before, because the player works a bit differently... the other possibility is that the iPhone software is deeply broken just now - because historically it was pretty reliable, so you would have to hit bad luck to encounter a version so buggy. OR you stumbled upon some rarely-used feature that has a bug, and used it so much it broke your cartridge. my suggestion is to post a link to your source code, so that we can have a look at it and see if there's something subtly wrong ;e) a link to the cartridges would be nice too.
  22. you do need the SD card. that's why you had trouble linking the phone and the PC - after you install a SD card, the phone will simply show up as a new drive and you can copy files over (technically, the phone will act as a SD card reader, so you can do all this in a different SD card reader and put the card in the phone afterwards) when that works, the steps are simple: 1. connect the phone (you might have to click something like "connect USB storage" on the phone) 2. create a Whereyougo folder on the phone 3. put the cartridge(s) into that folder 4. safely disconnect the cartridges should then show up in WhereYouGo app
  23. first of all, i don't really see a reason for doing this - no other cartridge has an "exit" command ;e) so i presume people would be used to just quitting their Wherigo player when they feel like it. (you can give out the completion code when they find the geocache - the best practice here is to place an item called "completion code" into their inventory and setting its description to completion code. that way, it's available whenever they need it) but if you feel like being "graceful", to each their own i guess so second of all - why not place the item into player's inventory instead of a zone? (btw what you're doing is technically supposed to work. why it doesn't is beyond me; there are some strange bugs on iPhone related to item commands at the moment, but the Oregon should be perfectly okay with it)
  24. Well there's OpenWIG for desktop, which is very functional and very available for download from openwig.googlecode.com But to use it as an emulator, one has to jump through some hoops - either tediously enter coordinates by hand, or use a simulated GPS source linked to a map. (after all, DesktopWIG is supposed to be an actual player for people with smartbooks, so turning it into an emulator would basically make it an instant cheating device.) there were talks with YourSelf (URWIGO's creator) of integrating desktopwig as an emulator into it, but that effort is somewhat stalled now. i guess i wouldn't be conceptually against building some kind of map source directly into desktopwig, but then i'd have to modify it so that it can't pass the emulator tests, which would entail learning about how those work, etc .e)
  25. simple enough: 1. show a message 2. start a timer 3: if the player clicks ok, stop the timer 4. when the timer expires, show a different message, overwriting the first one
  • Create New...