home home

downloads files

forum forum

docs docs

wiki wiki

faq faq

Cube & Cube 2 FORUM


[MODDING] Your first Sauerbraten MOD, Tutorial 1

by liquido on 11/15/2007 17:05, 77 messages, last message: 06/29/2010 07:30, 67586 views, last view: 05/05/2024 12:37, closed on 06/29/2010 09:29

[MODDING] Your first Sauerbraten MOD, Guide 1
---------------------------------------------
by liquido (jose.tapadas@yahoo.com)

(btw: i'm new to this forum :) ]

»»» [1]: INTRO:
===============

After googlin', searching and looking on the documentation I've noticed that there is a lot of spread information and nothing that a noob (must like me) could get as a platform to start coding for this great game engine, so I decided to write this guide so a modder-to-be could have some base to start on.
ATTENTION: Basic C/C++ knowledge required (if you don't know much don't worry!)

»»» [2]: THE TOOLS:
===================

Well as you know the Sauer is coded in C/C++ so in order to change something on it we need:

1. A C/C++ compiler:
Assuming you are using windows I recommend MinGW - Minimalist GNU for Windows, which has the Linux GNU tools all included on a win32 package
2. A C/C++ IDE (in order to help you browse through the code of Sauer and your mod.
3. Sauerbraten source code and engine (http://sauerbraten.org/)

To get all of this CodeBlocks has a package with all included:

Code::Blocks IDE, with MINGW compiler, Filesize: 13,597,181 Bytes | Version: 1.0rc2
download »» http://prdownloads.sourceforge.net/codeblocks/codeblocks-1.0rc2_mingw.exe?download

Now you need to configure the compiler so you can access it from any location and not only the MiniGW dir, so open Control Panel > System > Enviroment Variables search for "PATH" choose edit and add on the end of it ";C:\Program Files\CodeBlocks\bin".

»»» [3]: YOUR FIRST COMPILED SAUER:
===================================

On Sauer folder we have a well organized dir-structure so, with a little bit of inspection you can easily figure that we have a bi(nary) folder (with the game executable) and a src (source code folder). On this folder we wanna focus on 3 folders engine, fpsgame, rpggame.
It's not hard to figure that "engine" contains the Sauer game-engine (which contains the game physics, graphical rendering, etc..), fpsgame and rpggame contains both the fps and rpg game modes (or MOD's) which are included on Sauerbraten package.
Lets prepare a modding workspace on our engine, start by creating a new folder called "modgame" and copy into it all of the contents of the folder "fpsgame". We are going to mod the fps mode of Sauerbraten. Go inside your new folder and open all the .CPP and .H files with CodeBlocks. Go to "Search > Replace" and replace "fps" for "mod" on ALL FILES of that folder (when i say ALL I say ALL or it won't work!), save your progress and close CodeBlocks.
Still inside "modgame" rename "fps.cpp", "fpsserver.h" and "fpsrender.h" to "mod.cpp", "modserver.h" and "modrender.h".
Go back to the ..\src\ and go into mingw folder. Now create a copy of the "lib" folder and rename it to "lib.mingw", copy this folder into the ..\src\ folder. Copy the "MakeFile.mingw" into ..\src\ and "make.mingw.bat" into your Sauerbraten main dir (i.e. C:\Program Files\Sauerbraten).
Let's take a breath here to explain things:

* as you have noticed we are creating a new gamemode called "mod", based on the fps gamemode included on Sauer.
* on Sauer, fps and rpg modes, the gamemode binary is coded on "gamemode.cpp" (fps.cpp and rpg.cpp) and all the features are divided in something we call module coding, modules, weapons features on weapons.h, client features on client.h, all of them included on fps.cpp or rpg.cpp.
* if you are into the oo programming you will find interesting that all of the entities, actions and stuff on Sauer are divided into C/C++ classes which makes it very simple to develop.
* if you are not realy into OOP just forget (for now) the * above.
* the make file is something very usefull when programming very large projects with multiple files and compiler flags so it's a script who makes it for us.

We have created a mod workbench based on the fps game mode so lets include it on our makefile as a group ou files to compile, open the MakeFile.mingw and add just before of:

rpggame/rpg.o

the line:

modgame/mod.o \

To remove a compiling error on Sauerbraten scroll up and remove the line which adds:

engine/crypto.o \

(a feature removed from the cube time)

Save the MakeFile and close it. You are now ready to compile your mod and Sauer.
Run the "make.mingw.bat" and you should see somthing like this:

------------

C:\Program Files\Sauerbraten>cd src

C:\Program Files\Sauerbraten\src>mingw32-make all -fMakefile.mingw
g++ -O3 -fomit-frame-pointer -Wall -fsigned-char -Ienet/include -Iinclude -Ishar
ed -Iengine -Ifpsgame -o ../bin/sauerbraten-mingw.exe shared/tools.o shared/geom
.o engine/3dgui.o engine/bih.o engine/client.o engine/command.o engine/console.o
engine/cubeloader.o engine/grass.o engine/lightmap.o engine/main.o engine/mater
ial.o engine/menus.o engine/normal.o engine/octa.o engine/octaedit.o engine/octa
render.o engine/physics.o engine/rendergl.o engine/rendermodel.o engine/renderpa
rticles.o engine/rendersky.o engine/rendertext.o engine/renderva.o engine/server
.o engine/serverbrowser.o engine/shader.o engine/sound.o engine/texture.o engine
/water.o engine/world.o engine/worldio.o fpsgame/fps.o modgame/mod.o rpggame/rpg
.o -Lenet -Llib.mingw -lstdc++ -lenet -lmingw32 -lSDLmain -lSDL -lSDL_image -lSD
L_mixer -mwindows -lfmod -lz -lopengl32 -lglu32 -lws2_32 -lwinmm
strip ../bin/sauerbraten-mingw.exe

C:\Program Files\Sauerbraten\src>PAUSE
Press any key to continue . . .

-------------

Which means that everything went right!
Create a .BAT file called "mod.bat" on Sauer's main folder with the line :

bin\sauerbraten-mingw.exe -gmod

Save it.
This -gmod tells Sauer to run the game "mod".
Run it and....voila, your first mod!
Not very exciting because it's exacly the same that the fps mode but just have patience, you have compiled your first early-stage pseudo mod!

»»» [3]: YOUR FIRST MOD:
========================

Ok, lets do a actual MOD to the game.
Go to your mod's source folder (\src\modgame) and find a file called "weapon.h", open it!
As you can see from the first comment line:

// weapon.h: all shooting and effects code, projectile management

So this is the file where you find all the event handling, modeling and mumbojumbo when we are talking about weaponery stuff on Sauer. Search for the function:

void shoot(modent *d, vec &targ)

As you imagine this is the function which handles what to do when you fire your weapon on your game, so let's do some little moding.
On Sauer (and on most game engines, quake, source, doom, you name it!) we have something called entities which is basically everything that is interactive within the game, being it monsters, pick-ups, lights and even yourself the player, and on this shoot function we pass modent *d, which is a pointer to the entity who shoot's the weapon (so *d = (points) to ourselves for what we are concearned) and the vector &targ to the target of our shooting craziness. So lets mess up..cof...mod a little bit, scroll down until you find the line:

if(d->gunselect) d->ammo[d->gunselect]--;

Which is pretty much self explainatory, you d (ourselves) shoot go to the weapon ammo slot and dec. (--) by one ammo piece. Change it to:

if(d->gunselect) d->ammo[d->gunselect]++;

And this obviously will increase the ammo everytime you fire.
Save "weapon.h", run the "make.mingw.bat", then run your "mod.bat" and start shooting...free ammo on every trigger press!
I know this is very basic but it's a very important step on your journey as a modder ;)
Congratulations your first (micro) Sauerbraten MOD is complete.

Cumps, liquido... ;]

[keywords: mod, modding, Sauerbraten, tutorial, coding, develop, guide, noob, compile]

Go to first 20 messagesGo to previous 20 messages    Board Index   

#58: Re: ..

by MovingTarget on 03/13/2008 20:25, refers to #57

I'm guessing you need SDL installed.

reply to this message

#59: Re: ..

by SheeEttin on 03/13/2008 21:18, refers to #58

Yeah. That'd probably be it, the error referencing SDL sources 'n all...

reply to this message

#60: Re: ..

by tman_elite on 03/14/2008 02:11, refers to #59

Thank you a lot!
I didn't have the development version of sdl, just the regular one. Now that I know how to mod the source, config for monsters and weapons isn't as important. I still like the idea of a config for monsters though.

reply to this message

#61: ..

by IllvilJa on 03/14/2008 11:29

That's a common pitfall, to have package xyz installed on Linux but not xyz-devel and then failing compiling program abc which requires xyz.

Good you solved it.

(BTW, damn, I write too long posts, don't I...? Just look below what came out "from the top of my head")

I'm still ambivalent by the requirement to use a C/C++ compiler to implement some more basic changes to a sauerbraten mod. On one hand, more ppl (who don't know C/C++ that well or at all) would do more amazing things if some more of the game aspects were part of config files external to the C/C++ code.

For people who are going to mess around with the C/C++ code anyway, it is definitively a good exercise to edit weapons.h in the fpsgame directory (or even better, copy the fpsgame directory into something else like "mygame" and hack that instance) and then compile and run. But for those who don't intend to mess with the C/C++ code (for whatever good reason, there are a few), such an exercise is just an obstacle.

Then of course, you cannot put EVERYTHING into .cfg files. Sooner or later, if you want to add a too specialized or advanced feature in the mod, you need to modify the C/C++ code directly, but as a matter of fact, games like Battlefield 1942 and Battlefield 2 (both being closed source) have great mods created for them, mods that AFAIK do not modify the closed source C++ code of the games but instead focus on modifying script code, texture, models, animations, images etc. to create the mod contents.

That said, I've managed to follow the advice of working directly with the C/C++ code to create my own private copy of the fpsgame (called 'wargame', yay!) and managed to invoke that game using the -gwar command line flag! So now I got a map with ugly Nintendo-ish graphics on which tanks drive around (ugly, turretless tanks defined using no more than 48 triangles :-D). There are still tons of problems with the mod, like the tanks being able to fire all kinds of strange ammunition, and the ammo being fired from the wrong place of the tank model (a bit above the model..?), and the tanks can do weird things like jump and strafe (something I need to disable). Also, the tanks are ALWAYS aligned with the horisontal plane, no matter what slope they are moving on (hm... work is needed with the physics, maybe I can override some stuff in the engine by using object orientation and create extended classes in the wargame directory, so I don't have to touch the engine directory with modifications). Also there are the issue that the tanks are far wider and lower than the default bounding box, so one has to hit them at wierd places, and parts of them disappear into nearby buildings when driving to close, so I need to (and can :-D) fix that too. Another ugly thing, when the player views up and down (that's the thing called "changing the pitch", right?), there is NO visual indication of that on the tank. Ugly, ugly, ugly.

Hacking in C/C++ gives quite some options, if nothing else the option to disable problematic features (jumping tanks, huh? ;-) ).

Hm. If I create a map WITHOUT slopes (just impassable mountains and buildings) and then disable the ability to change the pitch (keep the gun level with the ground all the time), remove all weapons and just recreate one single weapon (rocketlike but just much faster with no trailing smoke or impact explosion, simulating a kinetic armor piercing projectile), then I think I have a complete game! Hell know if I even need to have additional ammo or health for the players in the initial version. Bitter fight until death, no resupplies and no repairs!

(And next step perhaps... add vehicle classes, just like the Battlefield series and Team Fortress 2 have player classes. Then the player can choose between two or more different tanks. Or perhaps a simplistic helicopter?)

Perhaps that IS the way to create a mod? Remove all features that distracts development, include the fewest possible features of the envisioned game (one vehicle, one weapon, one ammo) into the mod, accept that graphics are pretty much god ugly (like literally 5 minutes in GIMP per texture). Then it is ready, expose one's poor, unsuspecting friends to the horrible product and test it out.

Ah. That was the thing. What is the best way to distribute the mod? Assuming that I want as many ppl to be able to successfully install it (not just the C/C++ and open source savvy), the download and install process much be as reliable, simple and pain free as possible. And, given that criteria, my gut feeling is that compiling the mod as part of the installation probably is ruled out. Just because it works for me and some others to compile it, I'm quite certain it won't work that smoothly for everyone. Not everyone know how to apply even the simplest of tweaks to a stubborn building environment (even if said environment is packed out of the box of a .zip or .tar.gz file) and those who fail might be lost players of the mod :-(.

Thoughts on best way to distribute a C/C++-modified mod of Sauerbraten are most welcome.

Hm, Aard and co, you wouldn't mind to have a Battlefield-series inspired mod being part of the Sauerbraten official distribution, that is, to have a 'wargame' next to 'fpsgame' and 'rpgame'? Ok, just kidding, I'm quite convinced you DON'T want it, even if I think you would get QUITE a few fans out there if Sauerbraten actually DID include a more Battlefield-inspired wargame (you know, infantrymen and vehicles, albeit with more simple physics than in the BF series). AFAIK, there is no opensource alternative to the BF series out there, so there is a crying need. (Enemy Territory is partially closed source, isn't it?)

reply to this message

#62: Re: ..

by SheeEttin on 03/14/2008 15:20, refers to #61

Yeah, that is rather long... I'm going to reply to it with something pretty short, though.

Compiling Sauerbraten is pretty easy, at least on Linux. Just "make; make install" and you're done.
On Windows, with a Windows version of make or Code::Blocks and a Windows C compiler, it's similarly easy.
On a Mac, I hear xcode is also easy, but I've never used it.

Perhaps that upcoming mod (what's its name?) with the Lua VM could backport it to Sauer and make it easier to play with little changes.

On your tank mod, there's already a tank game that doesn't allow pitch changes. It's called BZFlag (which I think you're aware of, given some phrases in your post). Personally, I don't like it; it's too limiting. (Besides, it'd kind of be a waste of Sauer's geometry, wouldn't it?)

On distributing a mod, the best ways would be to put it up on Quadropolis as well as Sourceforge.
For packaging it, Linux users would be fine with a TGZ archive, while Windows users would probably appreciate the usual installer (even if it's really just unpackaging something into C:\Program Files\, like Sauer does). Sauer uses the Nullsoft Scriptable Install System, which is nice and free. Not sure what you'd do for a Mac, never having used one. Sauer distributes a DMG, which I believe is a disk image... No idea how that works.

reply to this message

#63: Re: ..

by MovingTarget on 03/14/2008 15:49, refers to #62

There still isn't a tutorial on the wiki for compiling Sauer on the Mac yet... although if you look there has been another method for Windows added, using MSVC++. It worked for me.

Oh, and the mod you're referring to is ET:CE, the one CannonFodder's (ezombie) working on.

reply to this message

#64: ..

by IllvilJa on 03/14/2008 17:55

Thanks for good answers!

ET:CE was actually a new one for me, but as far as I can tell, it does not include driven vehicles, which is one of my envisioned aims. However, there seem to be some clever solutions on things in that game, so I'll keep an eye on it.

Also, I'm trying to keep down the graphics requirements to a bare minimum (I am in the process of installing Gentoo on a 233Mhz Pentium II laptop with 128 MB RAM and 2 MB video ram and I'm serious in testing the stripped down mod on that box). My aim is to make the mod possible to run, and run well, on quite old hardware. Old laptops seem to "hang around" and if half a dozen of them are brought alive and got this mod installed then "Presto! Instant LAN!" or whatever.

I mean, I love BF2 and it's mods BUT there is just ONE single machine here at home that meets the sys requirements of BF2.

Regarding BZFlag, I don't recall any Sauerbraten/Cube mod with that name. Or perhaps it were another opensource game? Anyway, I had good old "Battlezone" (I'm old, I remember when that game arrived in the Arcades!) in my mind when deciding to initially fixing the cannon pitch. Of course that will spoil some of the joy, and I'll ensure that pitchable cannons becomes a priority eventually.

reply to this message

#65: Re: ..

by MovingTarget on 03/14/2008 18:01, refers to #64

BZFlag is another open source game.

reply to this message

#66: ..

by ezombie on 03/16/2008 07:59

Eh?

I heard my name... :D

Yeah, I hear you about the whole 'not really made to mod' observation. Can't really blame em though. The devs focused on making the game *run well* first and foremost, and I thank them for that.

The VM -> engine interface is tricky at best, and downright brain numbing at times. I have had to refactor it three times now due to writing myself into a corner :/

I was hoping *not* to strip too much out, but I must finally concede and follow your approach of slash and burn. The upside is that re-implementing such things as assasin & capture mode is a shade easier when using a dynamic language such as Lua.

I'm not sure how much of Sauer will be left when it's fully converted, frankly. I am trying my darnedest not to touch files outside of 'fpsgame', but my life might be a bit easier if I go ahead and apply the proverbial trimmers to 'shared'...

WOW - I certainly tend to ramble after a long Saturday staring at Sauer code in Eclipse, don't I? - LOL

reply to this message

#67: Re: distribution

by ezombie on 03/16/2008 18:23

FYI, the server part of the 'simple online update' system some of us yacked about awhile ago is done:

http://master.usef-et.org/repo/?sauer

It's written as an apache module for the utmost in speed. This is needed due to the fact that it is walking the entire file tree and stat() + hashing all the files - realtime.

They finally pulled Lua VM -> APR support into the official Apache tree, so I grabbed myself a section of the current SVN trunk and managed to get it compiled nicely for 2.2... Now I get to write memcached apache request handlers directly in Lua :D

(BTW - it runs 'hello world' at over 17K rps)

Got it down to 2-4 secs for the FULL sauer assasin tree. 3647 files, 266MB. Maintainer update is through ftp or rsync, downloads are through http w/streaming LZO compression. A simple text conf file is used to control the client (license agreement, welcome text, what local files to not delete/overwrite, commands to run after install/update, etc.)

The client merely performs a controlled sync by downloading only the files that have been changed/added, plus removing files that are stale - subject to the exclude patterns in the conf file.

Call it 'opensource cross-platform super streamlined steam without all the headache' if that helps get you in the right frame of mind.

I'm still working on the cross platform GUI client. Got a nice beta going so far... will need someone with a MACOSX to help out with that build/test. And yes, it is completely written in Lua as well (using wxLua for the UI). So people are free to copy/customize it, no compiler needed. The linker that creates a single executable from the (statically linked) wxLua VM + Lua script is also written in Lua.

My thought is that 1) you package the online updater in an installer (NSIS, NullSoft) - or 2) you simply download the single executable (no dependencies) and run it.

I would be happy to give anyone in the Sauer community a ftp/rsync login for maintaining their own repo module. Just no funky stuff or pr0n please. ;)

reply to this message

#68: Re: distribution

by ezombie on 03/16/2008 20:48, refers to #67

If you want to use the repo manually, the index file presented is structured like this:

[MD5 hash]:[size in bytes]:[filename with path relative to base directory]

To retrieve an index file, simply pass the module name to the repo:

http://master.usef-et.org/repo/?sauer

You can filter the results by adding a relative path:

http://master.usef-et.org/repo/?sauer/bin

Notice no slashes on the beginning or end of the request (part after the '?'). To grab a file, simply specify the file with relative path:

http://master.usef-et.org/repo/?sauer/src/readme_source.txt

It will download as normal.

If you want the file stream to be compressed, simply add a '.lzo' to the end of the name. Though you will not want *that*, unless you have a LZO stream decompressor handy.

reply to this message

#69: Sauer Compiling on Mac

by Oh No Ghost! on 03/18/2008 05:10

Can somebody point me in the right direction with compiling Sauer using XCode, and the .xcodeproj file in the Linux release of Assassin Edition?

Whenever I compile and run Sauer, the screen goes dark for a second, then back to normal with the following feedback:

[Session started at 2008-03-17 20:49:07 -0700.]
2008-03-17 20:49:08.706 sauerbraten[1105] LCC Scroll Enhancer loaded
init: sdl
init: enet
init: video: mode
init: video: misc
init: gl
Renderer: NVIDIA NV34MAP OpenGL Engine (NVIDIA Corporation)
Driver: 1.5 NVIDIA-1.4.18
Rendering using the OpenGL 1.5 GLSL shader path.
WARNING: Using Apple GLSL depth bug workaround. (use "/apple_glsldepth_bug 0" to disable if unnecessary
WARNING: Non-power-of-two textures not supported!
could not load texture data/notexture.png
could not find core textures

sauerbraten has exited with status 1.

The compilation apparently doesn't have any errors, but it gives this warning:

warning: no rule to process file '$(PROJECT_DIR)/../shared/sbtrace.d' of type text for architecture ppc

Whenever I compile the Launcher, it comes up no problem, but warns me about "placing sauer in a directory without any weird symbols" whenever I try to press play, and I get the following feedback:

[Session started at 2008-03-17 20:56:05 -0700.]
2008-03-17 20:56:07.243 launcher[1120] Missing sauebraten?!
2008-03-17 20:56:07.627 launcher[1120] LCC Scroll Enhancer loaded

launcher has exited with status 0.

I'm at a loss as to what to do here. I hear people say that you need to download things like SDL, SDL_mixer, OpenGL, etc- but I'm confident that I did download those, and even if I didn't, they were included in the XCode developer's kit. Where should these files be, so I can check to see if they are there?

reply to this message

#70: Re: Sauer Compiling on Mac

by MovingTarget on 03/18/2008 13:16, refers to #69

When it says "can't find core textures" it means you're either running the .exe from the bin/ folder, or you're running it and/or have it in a different folder. You must always have it in the bin/ folder but run it from it's parent directory.

reply to this message

#71: Re: Sauer Compiling on Mac

by Oh No Ghost! on 03/18/2008 14:58, refers to #70

Ahahaha, that worked perfectly. Thanks!

reply to this message

#72: Re: distribution

by ezombie on 03/18/2008 19:13, refers to #68

FYI - it has now been named YODA (Yet Another Download Application)

I changed the server component so it only hands out one directory at a time. This gives three big benefits:

1) It scales MUCH better
2) Client code is even simpler
3) You can now have *empty* directories get created on the client.

It is working great BTW - I tested it on flaky wireless connection (33% strength, constant packet loss, usually only get 40-70Kbps rates and big downloads freeze up). It ran through nice and steady, with an effective speed of 90Kpbs!.

Effectively slicing a large package it into many small downloads works extremely well on bad connections. I even canceled it a couple times, then restarted it a few minutes later.

Now I just need to add the module list to the server and client, and then I will whip up and test the Linux version.

My current thought is that you install YODA (like steam, but ours only takes 4MB -> pwnd), then you simply 'add' one or more repo URLs. This is like the way Eclipse does package installation. Each repo can hold one or more 'modules', or software packages.

Each module has a conf file written in Lua - which is downloaded and executed. This way you can optionally override/add to the built-in functions and fully script the client functionality if you want.

A simple one would be this:


module = {
title = "ET:CE"
desc = [[
ET:CE - A World At War

This is a team-based multiplayer online fps game,
inspired by Wolfenstein:Enemy Territory.
]]
prologue = nil
epilogue = [[
You have finished installing/updating ET:CE.

Thank you for playing and check out etce.usef-et.org for
more information!
]]
exclude = {"^update", "profiles/.*$", "downloads/.*$"}
clean = {"^data", "^bin", "^packages/et"}
}

This will be branched into a seperate project at some point (likely when someone else wants to use it). BTW, We are offering free repo hosting for any opensource application that asks.

reply to this message

#73: I'm not sure what went wrong...

by tman_elite on 03/19/2008 00:48

I can compile sauer fine in Linux now, but I tried porting an early version of my mod to my windows computer (to see if it worked) and when I tried to run it, it complained about not finding a bunch of dll's, (sdl, verify, java, jpeg, and some more) and when I downloaded them all, it complained about (something) 50 could not be located in direct link library jpeg.dll. I tried messing around with the codeblocks compiler but it kept doing the same thing.

reply to this message

#74: Re: I'm not sure what went wrong...

by tman_elite on 03/24/2008 20:58, refers to #73

It was "Ordinal 50 could not be located in the direct link library jpeg.dll."

Has anyone else had this problem?

reply to this message

#75: Not dieing

by )FC($k!llz_ on 06/29/2010 05:21

I might not get any help with this, but i made the mod th ammo counts up, and i also made the guns shoot faster. Me and another dude were playing online, but i wasted over 300 bullets on him standing still, and he wouldnt die. What did i do wrong? They die fine with only bots.

reply to this message

#76: Re: Not dieing

by SheeEttin on 06/29/2010 06:33, refers to #75

Probably, his client and/or the server decided you hadn't finished shooting, so you weren't allowed to shoot again. So he only saw the first shot.

Also, cheating is generally frowned upon...

reply to this message

#77: Re: Not dieing

by )FC($k!llz_ on 06/29/2010 07:30, refers to #76

I see.

And i wouldnt call it cheating. We were both testing the mods we made. We both said it was ok.

reply to this message

Go to first 20 messagesGo to previous 20 messages    Board Index   


Thread closed!

This thread has been closed, which is why you can't post any more messages in it.


content by Aardappel & eihrul © 2001-2024
website by SleepwalkR © 2001-2024
53864887 visitors requested 71640033 pages
page created in 0.054 seconds using 10 queries
hosted by Boost Digital