Wat is Wherigo?
Wherigo lijkt op geocaching, maar heeft extra opdrachten en verhalen.
Je downloadt een speciaal spel, dat heet een cartridge, op je telefoon of GPS. Als je dan buiten loopt, geeft het spel je opdrachten. Soms moet je iets vinden, soms moet je een vraag beantwoorden, of naar een bepaalde plek lopen.
Wherio’s onder de motorkap
Dit gaat niet over het spelen van Wherigos, maar over de technologie erachter! Dit wordt dus een beetje nerdy. Met het kijkje achter de schermen krijg je informatie over:
- de bestandsformaten;
- de structuur van een Wherigo cartridge;
- de structuur van een Wherigo Lua-bestand.
Er zijn verschillende hulpmiddelen waarmee je een Wherigo cartridge kunt maken:
De bestandsformaten
In het Wherigo-cartridge-ecosysteem bestaan de volgende bestandstypen:
- _Cartridge.lua: Dit bestand bevat alle instructies en gegevens die nodig zijn om de cartridge te spelen. Dit omvat vooral de zones, karakters, items, taken, timers en invoer.
- .GWZ (Groundspeak Wherigo Zip): Dit bestand is de samenvatting van alle mediabestanden en het _cartridge.lua-bestand als een zip-bestand. Het wordt geüpload naar de Wherigo-portalen.
- .GWC (Groundspeak Wherigo Cartridge): Dit bestand is de daadwerkelijke cartridge. Het wordt tijdens het downloaden gemaakt van het GWZ-bestand. Extra speler specifieke informatie zoals naam, ID en voltooiingscode wordt toegevoegd.
- .OWL: Dit bestand bevat een logboek van activiteiten tijdens het spelen. Als de cartridge crasht, kan de programmeur hier volgen wat mogelijk tot de crash heeft geleid.
De structuur van een Wherigo cartridge
Een GWC-bestand bestaat uit vijf delen:
- Handtekening
- Informatie over de bestaande bestanden
- Header met algemene informatie over de cartridge
- Startcoördinaat en beschrijving van de start
- Aanmaakdatum
- Type cartridge
- Naam en ID van de speler
- Naam van de cartridge
- Beschrijving van de cartridge
- Versie
- Auteur en bedrijf
- Voltooiingscode
- LUA-bytecode
- Bestanden met afbeeldingen, geluiden, teksten
De structuur per byte is zoals in de volgende tabel. Hierbij geldt:
- Nummers worden opgeslagen in het formaat “Little endian”. Dit betekent dat de kleinste byte eerst komt.
- Strings eindigen met 0x00. Dit betekent dat er een speciale code aan het einde staat om het einde aan te geven.
- Dubbele getallen worden opgeslagen in “double-precision floating point” formaat. Dit betekent dat ze met hoge precisie worden opgeslagen.
Earwigo heeft meer gegevensvelden toegevoegd in de header!
Adres | Lengte | Inhoud | Opmerking |
---|---|---|---|
@0000 | Begin Handtekening | ||
2 Byte | Versie | 0x02 gevolgd door 0x0a or 0x0b | |
4 Byte | CART | ||
1 Byte | 0x00 | ||
@0007 | Aantal objecten | ||
2 Byte | |||
@0009 | ID en adres van elk object | 6 Bytes per object | |
2 Byte | Objekt-ID | ||
4 Byte | Adress of object | ||
@xxxx | Begin van de Header | @0009 + Aantal objecten * 6 Byte | |
4 Byte | Lengte van de Header | ||
8 Byte | Breedtegraad | ||
8 Byte | Lengtegraad | ||
8 Byte | Hoogte | ||
4 Byte | Aanmaakdatum | Seconds vanaf 10.02.2004 01:00 | |
2 Byte | Object-ID van Splashscreen | -1 als er geen Splashscreen is | |
2 Byte | Objekt-ID van Icoon | -1 als er geen Icoon is | |
? Byte | Type van Cartridge | Tourgids, Puzzel, etc. | |
? Byte | Name van Speler | ||
4 Byte | Speler-ID | ID uit de Groundspeak-database | |
? Byte | Naam van Cartridge | ||
? Byte | GUID van Cartridge | ||
? Byte | Omschrijving van Cartridge | ||
? Byte | Omschrijving van Startlocatie | ||
? Byte | Versie | ||
? Byte | Auteur | ||
? Byte | Bedrijf | ||
? Byte | Aanbevolen apparaat | Garmin Colorado, Windows PPC, etc. | |
4 Byte | Lengte van Voltooiingscodes | ||
? Byte | Voltooiingscodes | ||
? Byte | Extra gegevensvelden door Earwigo; bijvoorbeeld: – Land – Staat – Voltaaid – Datum van laatste spel – Publicatiedatum –Update datum – Builder Versie | ||
@yyyy | Begin van Data/Bestanden | @0009 + Aantal objecten * 6 Byte + lengte Header | |
LUA-Bytecode | Objekt-ID = 0 | ||
4 Byte | Grootte van LUA-Bytecode | ||
? Byte | LUA-Bytecode | ||
@zzzz | Mediabestanden | Object-ID = 1, 2, 3, … | |
1 Byte | geldig object | als 0, object is verwijderd | |
4 Byte | Objecttype | 1 = BMP 2 = PNG 3 = JPG 4 = GIF 17 = WAV 18 = MP3 19 = FDL 20 = SND 21 = OGG 33 = SWF 49 = TXT | |
4 Byte | Objectgrootte | ||
? Byte | Inhoud van object |
Lees meer over de structuur van een Wherigo-cartridge op WFoundation/WF.Compiler op GitHub (en)
De structuur van een Wherigo Lua-bestand
Een Wherigo-cartridge wordt altijd – ongeacht met welke bouwer deze is gemaakt – vertaald naar de LUA programmeertaal. Je kunt ook Wherigo-cartridges maken zonder een bouwer – dat betekent dat je het LUA-bestand volledig zelf schrijft.
Urwigo maakt het LUA-bestand volgens de volgende bestandsstructuur:
Urwigo maakt het LUA-bestand volgens de volgende bestandsstructuur:
--hier initialiseert Urwigo de LUA
-code require "Wherigo"
--Het pakket Wherigo is nodig
ZonePoint = Wherigo.ZonePoint
-- Deze definities zijn bedoeld om de schrijfwijze te verkorten, hier de in het pakket Wherigo gedefinieerde
--tabel voor een punt, bestaande uit Latitude (geografische breedte), Longitude (geografische lengte) --en Altitude (hoogte)
Distance = Wherigo.Distance
-- Let op: enkele functies uit het pakket Wherigo hebben het gegevenstype Distance nodig
-- let hier vooral op hoe je van het type Distance naar een kommagetal voor meters -- (of ook heet) komt en andersom
Player = Wherigo.Player
-- Speler-object - bevat enkele eigenschappen die interessant zijn – vooral
-- Player.OriginalPoint (van het objecttype ZonePoint) dat altijd de actuele coördinaat bevat
function czTN(str)
-- de naam is willekeurig
-- deze functie is bedoeld om de teksten te versleutelen
-- de tabel dtable is de sleutel
local res = ""
local dtable = "x%\006QF6MLe\022hA)J7o_+\021VK}\n\0162\029\0009$<H\005s0pG\0268T?N-!Z\027D\001]b\019C3(.q~g ;tOB\024/{u>v|nyX\t\0205^[\f41=&c\015I:\004\rf\018S\017\031a@#w\030mi\"\002zU'\014\bkl\\\023\028\003\a`Y*Wd,ER\vPj\025r"
for i = 1, #str do
local b = str:byte(i)
if b > 0 and b <= 127 then
res = res .. string.char(dtable:byte(b))
else
res = res .. string.char(b)
end
end
return res
end
-- hier volgen een reeks functies die Urwigo nodig heeft voor het correct functioneren
objAdvent = Wherigo.ZCartridge()
--De cartridge wordt geïnitialiseerd, d.w.z. er wordt één cartridge-object aangemaakt.
-- De gegevens van de cartridge worden later dan als eigenschappen opgeslagen
-- Media –
--Hier worden de media-objecten - afbeeldingen en geluiden - aangemaakt
_xTL7U = Wherigo.ZMedia(_clqD) _xTL7U.Id = "533a5ac6-d250-4088-8783-82ab011d7cac" _xTL7U.Name = _czTN("\f##m^B!") _xTL7U.Description = "" _xTL7U.AltText = "" _xTL7U.Resources = { { Type = "mp3", Filename = "Applaus.mp3", Directives = {} } }
-- Cartridge Info –
--Hier komen alle instellingen van de cartridge
objAdvent.Id = "f8d030af-9734-41cb-b096-71347d242fb6"
objAdvent.Name = "Agent Karl Toffel"
objAdvent.Description = "Deze ronde leidt door Kladow."
objAdvent.Visible = true
objAdvent.Activity = "Geocache"
objAdvent.StartingLocationDescription = "Hier moeten jullie starten" objAdvent.StartingLocation = ZonePoint(52.472533, 13.135383, 0)
objAdvent.Version = "1"
objAdvent.Company = ""
objAdvent.Author = "Aski-Team"
objAdvent.BuilderVersion = "URWIGO 1.20.5218.24064"
objAdvent.CreateDate = "13/06/2014 20:17:27"
objAdvent.PublishDate = "1/1/0001 12:00:00 AM"
objAdvent.UpdateDate = "21/09/2014 16:58:43"
objAdvent.LastPlayedDate = "1/1/0001 12:00:00 AM"
objAdvent.TargetDevice = "PocketPC"
objAdvent.TargetDeviceVersion = "0"
objAdvent.StateId = "1"
objAdvent.CountryId = "2"
objAdvent.Complete = false
objAdvent.UseLogging = true
objAdvent.Media = _0ci
-- Zones –
--Definitie van de zones
_zoneDrachenlager = Wherigo.Zone(objAdvent)
zoneDrachenlager.Id = "6215691a-b997-4277-b1b5-d4bf62368489" zoneDrachenlager.Name = "Drachenlager"
zoneDrachenlager.Description = "Dit zou nooit getoond moeten worden," zoneDrachenlager.Visible = false
zoneDrachenlager.DistanceRange = Distance(0, "meters") zoneDrachenlager.ShowObjects = "OnEnter"
zoneDrachenlager.ProximityRange = Distance(0, "meters") zoneDrachenlager.AllowSetPositionTo = false
zoneDrachenlager.Active = false
zoneDrachenlager.Points = { ZonePoint(52.51552, 13.57171, 0), ZonePoint(52.51552, 13.57213, 0), ZonePoint(52.51526, 13.57213, 0), ZonePoint(52.51526, 13.57171, 0) } zoneDrachenlager.OriginalPoint = ZonePoint(52.515389, 13.571918, 0) zoneDrachenlager.DistanceRangeUOM = "Meters" zoneDrachenlager.ProximityRangeUOM = "Meters"
zoneDrachenlager.OutOfRangeName = ""
zoneDrachenlager.InRangeName = ""
-- Characters –
--Definitie van de personen objBlondine = Wherigo.ZCharacter({Cartridge = KlausKlabuster, Container = zBI}) objBlondine.Id = "8aec9cae-8d8f-402d-a33b-4f39abd04244"
objBlondine.Name = "Blondine"
objBlondine.Description = "Een blonde engel. Omringd door mannen als motten om een licht."
objBlondine.Visible = true
objBlondine.Media = objbarfrau
objBlondine.Icon = objicobarfrau
objBlondine.Commands = { cmdanquatschenundflirten = Wherigo.ZCommand({ Text = "anquatschen und flirten", CmdWith = false, Enabled = true, EmptyTargetListText = "Niet beschikbaar" }), cmdzumTanzenauffordern = Wherigo.ZCommand({ Text = "zum Tanzen auffordern", CmdWith = false, Enabled = true, EmptyTargetListText = "Niet beschikbaar" }) }
objBlondine.Commands.cmdanquatschenundflirten.Custom = true objBlondine.Commands.cmdanquatschenundflirten.Id = "f8da54ff-157b-4927-a942-66b39c6b2596"
objBlondine.Commands.cmdanquatschenundflirten.WorksWithAll = true objBlondine.Commands.cmdzumTanzenauffordern.Custom = true objBlondine.Commands.cmdzumTanzenauffordern.Id = "47639b5b-e941-4fa8-a065-25a812946f87"
objBlondine.Commands.cmdzumTanzenauffordern.WorksWithAll = true objBlondine.ObjectLocation = Wherigo.INVALID_ZONEPOINT
objBlondine.Gender = "Female" objBlondine.Type = "NPC"
-- Items –
--Definitie van de items/voorwerpen
objMuelleimer = Wherigo.ZItem({Cartridge = KlausKlabuster, Container = zMP}) objMuelleimer.Id = "14e91fa0-8c16-412f-9c97-ff24031f83a0"
objMuelleimer.Name = "Muelleimer"
objMuelleimer.Description = ""
objMuelleimer.Visible = true
objMuelleimer.Media = objmuelleimer
objMuelleimer.Icon = objicomuelleimer
objMuelleimer.Commands = { cmdansehen = Wherigo.ZCommand({ Text = "ansehen", CmdWith = false, Enabled = true, EmptyTargetListText = "Nothing available" }) } objMuelleimer.Commands.cmdansehen.Custom = true objMuelleimer.Commands.cmdansehen.Id = "210f3095-0117-42c0-b2cc-24c488d30200"
objMuelleimer.Commands.cmdansehen.WorksWithAll = true objMuelleimer.ObjectLocation = Wherigo.INVALID_ZONEPOINT
objMuelleimer.Locked = false
objMuelleimer.Opened = false
-- Tasks –
--Definitie van de taken
tGM = Wherigo.ZTask(KlausKlabuster)
tGM.Id = "a869d211-89ad-432
Lees meer over LUA bestanden op:
- Jakuje/webwig op github (en)
- Das Wherigo Handbuch (de)
De functies binnen de categorie Wherigo/Urwigo gereedschap
GC Wizard biedt binnen deze categorie de volgende functies:
Urwigo Hash Breaker
Bovenaan het scherm staat een schuifknop waarmee je kunt kiezen tussen Haal Hash-waarde op en Breek Hash-waarde.
Haal Hash-waarde op
Als je kiest voor ‘haal Hash-waarde op’ verschijnt er een tekstveld waarin je de tekst plaatst waarvan je de hash-waarde wilt weten.
Onder Uitvoer zal de hash-waarde worden getoond. Je kunt deze waarde kopiëren met de kopiëren knop .

Breek Hash-waarde
Als je kiest voor ‘breek Hash-waarde’ verschijnt er een tekstveld waarin je de hash-waarde invoert. Je kunt hier zelf de waarde invoeren of de waarde veranderen met de plus- en min-knop.
Nadat je op de knop Indienen hebt getikt zal GC Wizard de hash-waarde gaan ontsleutelen en het resultaat onder Uitvoer tonen. Je kunt deze waarden kopiëren met de kopiëren knop .

Wherigo Analyser
Bovenaan het scherm staan twee knoppen waarmee je een bestand in GC Wizard kunt laden:

Opent de bestandsverkenner en hiermee open je een afbeelding vanaf je apparaat.

Toont een tekstveld waarin je de URL naar de afbeelding plaatst en een knop ‘Open’ om de afbeelding in GC Wizard te laden.
Als het inladen is gelukt zul je de tekst zien: Geladen: naam van het _gcw-bestand.
Daaronder verschijnt het gedeelte: LUA bestand – Broncode
Hier staat een schuifknop, Haal details op. Je hebt de keuze Online en Offline.
Online
Als je kiest voor Online zal GC Wizard de broncode van internet halen en uitpakken. Onder de schuifknop verschijnt de volgende knop:

Als je op deze knop tikt zal GC Wizard de broncode online opzoeken, uitpakken en downloaden. Hiervoor moet je eerst nog toestemming geven.
Offline
Als je offline kiest zal GC Wizard niets uitpakken. Je moet in dit geval zelf de uitgepakte versie aan GC Wizard geven. Je kunt dit op twee manieren doen:

Als je op deze knop tikt zal GC Wizard de broncode van je apparaat halen. Hiervoor opent de bestandsverkenner van je apparaat.

Als je op deze knop tikt zal GC Wizard de broncode van internet halen. Hiervoor verschijnt een tekstveld waarin je de URL van de broncode opgeeft. Nadat je op Open hebt getikt zal GC Wizard de URL bezoeken en het bestand downloaden.
De gegevens analyseren
Onder het gedeelte LUA bestand – Broncode staat een knop en een keuzemenu.

Aan- en uitzetten van de expert modus.
In het keuzemenu staan de gegevens uit het _gwc-bestand en het LUA-bestand:
- Inventaris – Lijst met items
- Koptekst
- Lijst met berichten/dialogen
- Lijst met invoerobjecten met mogelijke antwoorden
- Lijst met tekens
- Lijst met zones
- Lijst van mediabestanden
- Resultaten van het analyseren van GCW cartridge
Onder Uitvoer zie je de resultaten van de gegevens die je hebt gekozen.

Urwigo Tekstontsleuteling
Deze functie versleutelt en ontsleutelt tekst vanuit een dtabel waarde uit een LUA code van een Wherigo cartridge.
De dtabel uit de Lua code halen
Hieronder zie je een voorbeeld van een deel van een LUA-code waarin een versleutelde tekst en een dtabel staat. Met de Urwigo Tekstontsleuteling functie kun je deze tekst ontsleutelen.
Voorbeeld versleutelde tekst
function _WKlqK:OnGetInput(input)
if input == nil then
input = ""
end
if _Urwigo.Hash(string.lower(input)) == 13166 then
_lj9.Visible = false
_lj9:MoveTo(nil)
_WlWcy.Visible = true
Wherigo.ShowScreen(Wherigo.MAINSCREEN)
else
_Urwigo.MessageBox({
Text = _czTN(")^:w^FF:w\tFl\t:c^m:!S\v^\127Y:F^S\vx:a^!:w\t\127:3\v\tY:gB:wd\127:9\t!^9<:\v^<+"),
Callback = function(action)
if action ~= nil then
Wherigo.ShowScreen(Wherigo.MAINSCREEN)
end
end
})
end
end
Voorbeeld dtabel
dtable = "x%\006QF6MLe\022hA)J7o_+\021VK}\n\0162\029\0009$<H\005s0pG\0268T?N-!Z\027D\001]b\019C3(.q~g ;tOB\024/{u>v|nyX\t\0205^[\f41=&c\015I:\004\rf\018S\017\031a@#w\030mi\"\002zU'\014\bkl\\\023\028\003\a`Y*Wd,ER\vPj\025r"
De functie gebruiken
Bovenaan het scherm staat een schuifknop met de keuze Versleutelen en Ontsleutelen.
Versleutelen
Als je ‘versleutelen’ kiest verschijnen er twee tekstvelden. In het eerste tekstveld voer je de tekst van de dtabel in. In het tweede tekstveld plaats je tekst, die je wilt laten versleutelen.
Onder Uitvoer komt de versleutelde tekst te staan.

Ontsleutelen
Als je ‘ontsleutelen’ kiest verschijnen er twee tekstvelden. In het eerste tekstveld voer je de tekst van de dtabel in. In het tweede tekstveld plaats je tekst, die je wilt laten ontsleutelen.
Onder Uitvoer komt de ontsleutelde tekst te staan.

Earwigo Tekstontsleuteling
Deze functie versleutelt en ontsleutelt tekst vanuit een LUA code van een Wherigo cartridge.
Bovenaan het scherm staat een schuifknop met de keuze Versleutelen en Ontsleutelen.
Daaronder staat een tekstveld waarin je de tekst plaatst die je wilt versleutelen of wilt ontsleutelen.
De versleuteling en ontsleuteling vindt plaats volgens twee algoritmen:
- gsub_wig
- WWB_deobf
De resultaten worden getoond in een gelijknamig gedeelte in GC Wizard.
In het onderstaande voorbeeld staat een voorbeeld van een tekst in een LUA-code met een gsub_wig versleuteling:
function zinputInput1:OnGetInput(input)
if Wherigo.NoCaseEquals(input, gsub_wig("yyponml")) then
Wherigo.MessageBox({
Text = gsub_wig("8Qh jMc iYRVgURv21") .. "<BR>\n" ..
gsub_wig("NUXhRd QVXigyxw"),
Media = zmedia7404907b588e464d96fe70c0c512fbed,
Callback = cartStetsgernfuerSiebesch.MsgBoxCBFuncs.MsgBoxCB6
})
else
Wherigo.MessageBox({
Text = gsub_wig("CUXRRd PRbhQUxwv") .. "<BR>\n" .. "<BR>\n" ..
gsub_wig("GhdPVQc Vi kRUeOi10z"),
Media = zmediadb646ac9929941db8aeb8679f3df73de,
Callback = cartStetsgernfuerSiebesch.MsgBoxCBFuncs.MsgBoxCB5
})
end
end

