Jump to content

Emulator check


dgreno

Recommended Posts

I decided I wanted people to get out and play my first Wherigo in the real world, so I wanted to detect the presence of an emulator and shut down the game if they were using the emulator.

 

There are lots of bits and pieces on the forum about how to do this, but nothing that made it real obvious to me how to implement it.

 

Here's my solution. I make no claims of this being elegant, but it works. I've already gotten several notes from people who tried to run my "Facial Recognition" Wherigo on the emulator and hit the wall and I know that people using both a PocketPCs and Colorado have been able to play the game in the real world, so it's field tested to some limited extent.

 

Summary:

 

During a player session, a system string variable named Env.DeviceID holds the value "Desktop" when running on the emulator and various other strings for other devices. I couldn't find a way to directly read this variable from code generated by the Builder, so I kludged a couple of lines of Author Script to load my own variable, DeviceID with the contents of Env.DeviceID when I trigger my code.

 

How to do it:

 

Create a string variable called "DeviceID"

 

Create a zone called "FakeZone" and set it to inactive and invisible and set the DistanceRange to -1 so it can always be seen when visible and active

 

Use the Author Script command to write a handler for the OnDistance event for the FakeZone. Then whenever you make the FakeZone active, this handler will get called. The code, in its simplist form looks like this...

function zoneFakeZone.OnDistant()

DeviceID=Env.DeviceID

end

 

Any time after you make FakeZone active, the variable DeviceID will tell you if you're running in the emulator.

 

Caveats:

 

This works for me. It may not work for you or for the next versions of the Builder and/or Player.

 

There may be (probably are) more elegant, more clever, or cooler ways to do this. Please tell me about them.

 

Smart guys will probably figure out how to beat this within a few hours. Act fast!

Sample code:

 

I've attached a sample source file, emul8not.lua, to this post. It is the simplest code I could knock together quickly that shows this thing in action. Load it, compile it and run it. On the emulator, when you click the "CheckForEmulator" task, you'll get a message telling you that you've been a bad boy and all game zones will vanish. On a handheld player, clicking the "CheckForEmulator" task has no effect other than making FakeZone active.

 

Enjoy.

 

Dave

emul8not.zip

Edited by dgreno
Link to comment

This is great. Even I can seem to understand it. I think. Have to actually implement but it looks pretty simple.

 

Once I understand it, I am going to add a second test for the player being the Builder. With that, this code can become part of the foundation for each cartridge and still allow me to test in the Emulator.

Link to comment

Bravo for you. When I saw what you were doing, I thought, "I hope he's going to make the fake zone inactive after he's finished so it doesn't consume resources." Good job seeing and implementing this coding practice.

 

Though not published, there's an OnStart event for the cartridge you can use instead of a fake zone. This is also a possibility in the author functions section:

function cartemul8not:OnStart()
DeviceID = Env.DeviceID
if   Wherigo.NoCaseEquals(DeviceID,"Desktop") then
	Wherigo.MessageBox{Text=[[Sorry, but emulator use is discouraged]],Buttons={"OK",},} 
	zoneMainZone.Active = false
end
end

 

Note you will have to change the cartridge's name in the function to match your own. Using OnStart means you won't have to busy yourself with adding something to trigger the code.

 

Good job and thank you for sharing!

Link to comment

Actually it's even simpler and can be done completely within the Builder. No need to create Author blocks or anything.

 

I do it in the Cartridge (OnStart) event so it triggers immediately upon the startup of the game.

 

Create two variables; DeviceID and Env.DeviceID (Capitalization of Env.DeviceID is critical since this is actually a system variable we are making use of.)

You do not need to set these variables to anything, just create them.

 

In the Cartridge (OnStart) event do a 'Set DeviceID equal to Env.DeviceID'.

Then a simple 'If DeviceID equal to "DeskTop"' to read/compare the DeviceID. (Capitalization of 'DeskTop' is critical.)

 

What I do when I detect emulator usage is display a message griping them out, then make all zones invisible and inactive.

 

Attached is a LUA of the bare minimum to detect emulator usage.

EmulatorCheck.zip

Edited by Audion
Link to comment

Hmmmm. When I try the Audion version, nothing happens. I do not get the message.

 

When I try coding it myself, the check fails. I am still allowed to play the cartridge.

 

Two questions: Why would you create a variable in the builder that has the same name as a system variable? Isn't that a conflict?

 

Second, why the intermediate step of setting DeviceID to the Env.DeviceID? Can't you just test the system variable directly??

Link to comment

Hmmmm. When I try the Audion version, nothing happens. I do not get the message.

 

When I try coding it myself, the check fails. I am still allowed to play the cartridge.

 

Two questions: Why would you create a variable in the builder that has the same name as a system variable? Isn't that a conflict?

 

Second, why the intermediate step of setting DeviceID to the Env.DeviceID? Can't you just test the system variable directly??

 

Well that's rather embarrassing.

 

I goofed. I had forgotten exactly how I had done it. You are correct about not wanting to create the Env.DeviceID variable. In fact, apparently you can't. The Builder automatically removes the dot so your variable name becomes EnvDeviceID, and THAT is why my uploaded cartridge did not work.

 

Now I am remembering correctly. You create the DeviceID variable (or whatever else you want to call it) And then set that variable equal to the VALUE 'Env.DeviceID'. And this is why there has to be the intermediate step also.

 

To temporarily remove the emulator check simply change the word 'DeskTop' within the IF/THEN statement to anything other than 'DeskTop'.

 

Fixed (and tested, as I should have done in the first place), LUA file attached.

EmulatorCheck.zip

Link to comment

That works better.

 

One question: I assume you had to build part of that with a text editor in order to get the period in Env.DeviceID?

 

No since you are entering it as the VALUE to set DeviceID equal to. Entered this way the Builder just assumes you are entering text so you can enter whatever you want. You can do the whole thing from within the Builder.

Edited by Audion
Link to comment

Sorry to be bearer of bad news, but the check for desktop is VERY easy to get around. :laughing:

 

Indeed - all you have to do is to go into the .gwc file with a hex editor and change the first occurrence of the string "DeskTop" to something else. To frustrate this hack you probably need to i) choose random names for your string variables so it is hard to find the bit of code where this check is made, and ii) obfuscate (by hashing or whatever) the test string. Even that will probably not prevent the determined hacker, but then if they get more fun out of the hacking than they do out of actually doing what is intended with the cartridge that is up to them I suppose.

Link to comment

I say.. make it difficult to run in demo mode or in the Emulator.. if that's the way that you as the game author desire, (personally I think good idea) but if someone is hell bent on cheating or lookng into the code at Hex level then they've probably got bigger issues.

 

The Wherigo'er who claims cartridge completion where all they did is cheat would be the same person who wins 100mtr sprints on the juice.

Link to comment

These days, I think the longer your cartridge takes to complete, the more someone will want to cheat.

 

For example, I just came from doing a Wherigo cartridge in Columbia, SC. It was monster, requiring you to travel over sixty miles and drive back and forth, especially to one common place. You also had to wait, doing nothing, for a long timer to expire (twenty minutes, I think). I drove three hours to cache in the area. I was not looking forward to spending 3+ hours on a single cartridge. Yes, the cartridge was interesting, but the time commitment, in my opinion, is not friendly to out-of-town cachers. The only reason I continued to play the cartridge was because I had previously played it in the emulator and lined up the day's cache route along the story's sequence.

 

By the way, in the four or five months that particular cartridge cache has been out, only one person has signed the log book. This is similar to the result of someone setting up a twenty stage multi-cache with the same driving distance: very few people will ever visit and find it as intended.

 

As much as you want to prevent people from cheating, I'd say the best rule of thumb is to create something that makes people want to play it for shear enjoyment and not just to log a find. Keep things interesting, be aware the player has other things s/he has to do that day, and don't include unnecessary steps. For what you make the player do, make sure it seems reasonable and not that you're just adding filler. Do make sure the time needed to complete the cartridge is reasonable. Remember: the cacher has chosen to find your cache above the other few hundred caches in the area. Feel honored your cache has been chosen and have some respect.

 

There are quite the number of similarities between this line of discussion and writing a novel. Look at some successful novels: the plot is understandable and fun to experience, the storyline progresses at a constant pace, and most actions or conversations seem necessary either for the plot or realism. If your reader becomes bored, s/he will skip ahead a paragraph or page and give you another chance. If that happens many more times, you may lose your reader altogether. Also, don't forget reading a novel requires a time commitment: those cliffhangers at the end of every chapter compel the reader into picking the book up sooner than normal if s/he has to put it down to deal with something else in his/her life. In some cartridges, people are creating a short story. Same principle. Figure out what makes a great story and craft a good one--but remember the person is actually playing the part and everything is part of that experience: the scenery, construction and road conditions, what's going on in the park/trail/city/etc. that day, transit time, time of day and year your cartridge is being played (when will the sun set relative to when the player began?), preoccupation with other things, personal schedule--and most of this is out of your control, but still part of the cacher's overall experience.

 

In short, if you don't want someone to cheat, make your cartridge more fun to do. Make them know and feel cheating will deprive them of a wonderful experience they'll talk about with others for months to come. And for those who insist on cheating, who cares? They just missed the point of it all. At least your Wherigo cache will receive another "Found It" log, which could serve to interest others to play (and at least you know your cache container is still in its hiding place).

 

This was a long post. Did anyone feel the urge to skip ahead or stop reading? Did you? If so, that's my fault for not making this post more succinct and gripping. It's the same with a cartridge.

Link to comment

An excellent response, Ranger Fox. And I concur completely.

 

My recent cart is shorter and simpler than my first; it will yield coords on emulator play (there's a multiple choice question - keep trying til you get it right) That's fine with me. If people don't want to learn a bit about oaks, hey, they don't want to. They may still enjoy hunting the ammo can. If they're interested, a short walk will show them some trees and offer some info on them. That's it.

Link to comment

By the way, that's not to say people shouldn't do anything to prevent people from playing in the emulator. A little deterrence is a good thing. During a number run, if I didn't care to complete a multi and I had the final coordinates available, I would use them. It's simple: it's a number run and the multi takes time.

 

It is a good thing to check for the emulator somewhere in the cartridge. As I've said before, put the check somewhere at a spot (cliffhanger) that will hook them into playing the cartridge to see what happens next. However, don't go overboard when preventing cheating: too many questions, hidden zones the player must cross, zones too small to navigate to, etc. If you go overboard, it could make the cartridge too difficult to play, losing those genuinely eager and excited to have the experience you carefully set up for them.

Link to comment

Tried pasting in rangerfox's code in the onstart section of a cartridge but it now fails to publish to my machine. I already have an onstart function of showing a splash screen. Do I have to delete this function or have I made a coding boob?

 

Thanks

 

function cartBackwellWander:OnStart()
-- #GroupDescription=start up --
-- #Comment=start up Comment --
Wherigo.MessageBox{Media=zmediasplashscreen,Buttons={"click here to continue",},}
Wherigo.PlayAudio(zmediapacmanintro)
end

function cartBackwellWander:OnStart()
DeviceID = Env.DeviceID
if   Wherigo.NoCaseEquals(DeviceID,"Desktop") then
	Wherigo.MessageBox{Text=[[Sorry, but emulator use is discouraged]],Buttons={"OK",},} 
	zoneMainZone.Active = false
end

Link to comment

Tried pasting in rangerfox's code in the onstart section of a cartridge but it now fails to publish to my machine. I already have an onstart function of showing a splash screen. Do I have to delete this function or have I made a coding boob?

 

Thanks

 

function cartBackwellWander:OnStart()
-- #GroupDescription=start up --
-- #Comment=start up Comment --
Wherigo.MessageBox{Media=zmediasplashscreen,Buttons={"click here to continue",},}
Wherigo.PlayAudio(zmediapacmanintro)
end

function cartBackwellWander:OnStart()
DeviceID = Env.DeviceID
if   Wherigo.NoCaseEquals(DeviceID,"Desktop") then
	Wherigo.MessageBox{Text=[[Sorry, but emulator use is discouraged]],Buttons={"OK",},} 
	zoneMainZone.Active = false
end

 

 

 

This should do it.

 

 

function cartBackwellWander:OnStart()

-- #GroupDescription=start up --

-- #Comment=start up Comment --

 

DeviceID = Env.DeviceID

 

if Wherigo.NoCaseEquals(DeviceID,"Desktop") then

Wherigo.MessageBox{Text=[[sorry, but emulator use is discouraged]],Buttons={"OK",},}

zoneMainZone.Active = false

 

else

 

Wherigo.MessageBox{Media=zmediasplashscreen,Buttons={"click here to continue",},}

Wherigo.PlayAudio(zmediapacmanintro)

 

end

end

Link to comment

Hmm, just humour me Gary, that suggested code isnt working, just remind me, its been a while:

 

I edit the LUA file in notebook, then open it in builder and publish to machine to creat a GWC file to run in the emulator?

 

Done that and error message pops up 'unable to save cartridge' after editing the script.

 

Thanks

 

Bruce,

 

Then its quite possible that you have a typo.

 

Try commenting out a line at a time until it works. By the way, to comment out a line you use --

 

Let me know if you need anymore help.

 

Gary

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...