Mihai | 2012-02-04 09:29
*
Cube 2 based game: Marble Arena 2
118
points ]
 (12 votes)
*
*
Starred Content

Hi,

My name is Mihai Gabriel Ailioai, and i'm the developer of Marble Arena 2, a marble game based on the marvelous Cube 2 engine. I wasn't really sure if i could post any info here being that it's not one of the official games supported by this community, but hopefully it will be ok and my post won't be deleted :)

It's a very bright and colorful game, available for PC, Mac and Linux, and it keeps pretty much all of the editing power Cube 2 has, but has a layer of GUI on top so that people don't have to use the console at all, hopefully making it more newbie friendly.
It has 50 official levels, and we've released another 22 maps ported from Marble Arena 1, and we also have a nice little community of people creating their own levels. Nothing near what i've seen here, but hopefully we'll get there someday. It's based heavily on physics, there's no shooting or killing, although we have a nice lightning bolt shield powerup that could slightly impress the killer in you :)

Check it out, you might like it, and who knows, maybe even be convinced to create some levels for it :P

www.marble-arena.com

Edit: March 1'st 2012

New version released. It includes 32 new levels, autosave and ability to customize controls, and what was requested the most around here: working console and custom scripts. Have fun !

FischKopF | 2012-01-15 18:54

Red Eclipse has far more advanced gameplay mechanics than Sauerbraten has. It has many features that people initially requested for sauerbraten and comes with a bigger variety of gameplay modes. For me, this is the true successor to Sauerbraten, since it's a superior game in every respect. So i'm wondering, why do SO much ppl still play sauerbraten? When i go online, i see only 2 (!) servers with ppl on it. That pisses me off, since its such an awesome game. I personally stopped caring about sauerbraten the day Red Eclipse v1.0 came out. Maybe Red Eclipse is just badly advertised and people just don't know about it. I wonder if they would have called it "Cube Engine 3", more people would play it and give it the appreciation it deserves...

Another thing i've noticed, with better advertisement about the map editor i can see Red Eclipse becoming a Minecraft killer. Because ppl play Minecraft because they wanna build stuff, right? Thats exactly what they can do in Red Eclipse, plus they also get an excellent fun FPS as well.

RaZgRiZ | 2011-12-12 13:00



Cubescript is hard to read to those who are either too accustomed to reading everything with syntax highlighting or don't like cubescript in any way. Or when someone is truly horrible at doing things right. Apart from that however..

He may not be the first, or the second, or the third, what does it matter. For cubescript, it's practically the first command-line quick-connect script, with mine coming second but being SVN only. I do wonder however how you're doing to implement such a thing into the framework, is it based on cubescript at all? Or are you hoping to convert it to another language?

And i'm confident he will add the comments necessary. Would would go past thing chance for fame? ^_^
reply to 3starRaZgRiZ

mapc | 2011-12-12 17:46



(I switched from the gandalf acc to this one, sorry for the confusion).

Yes, apply 1 and 2 for me :D (but it is not that bad).
Sadly cbs is a very bad designed language: There is for instance only a global namespace and there is only strings. Even the lists are space separated, not escaped strings. (I'd like to give you a complete lists, but this would be one or two paragraphs of text, so not in this comment ;) ).

Yes, thats why I am thinking about integrating it :). However, command line again means a problem with the global namespace :(
The framework is entierely cubescript and aims at resolving some of the issues, nicer installation, plugin-based (no more hazzle with adding stuff to autoexec.cfg) and a little bit of namespacing:

(concatword $namespace $varname) = $value

Yup, hope so :)

Cheers,
mapc

srbs | 2011-12-14 04:46



@mapc
"I'd like to give you a complete lists, but this would be one or two paragraphs of text, so not in this comment ;)"
I'd love to see this list.

"Sadly cbs is a very bad designed language:"
Not every language NEEDS every feature known to the programming world. It is perfectly adequate for what it is designed for.

What isn't designed very well is, in fact, your "framework." For large projects like that, one should (as with all languages) first learn the features, quirks, and idioms of said language and design accordingly. And if my config.cfg file is some 500KB after using 0.9.4, I won't ever use it again, especially since every function of every script has variable names relating to the current plug-in

@Razgriz
"Would would go past thing chance for fame?"
wut?

srbs

mapc | 2011-12-15 12:48



@srbs

I do not criticize the lack of features in the language, but the way the language is designed (in other words: how you do, what you do with cbs).

Your last argument was an ad hominem argument (http://en.wikipedia.org/wiki/Ad_hominem) and therefore a rhetorical trick without being constructive at all. Please stop this, I am annoyed by this.
Your config file is that big, because the way configuration works (described below) and because of the lack of memory management (described also below). Big codebase => Big conf. This issue can not be resolved without having control of the configuration process. Sorry.
The framework is btw written with some of the issues below in mind. The usage of vars for every plugin for instance makes the whole framework much more secure.
The Points of criticism:

Everything is a string (partially lack of types)
Lists are space-seperated not-escaped lists
There are too many ways to generate and modify function-strings (e.g. macros, the three braces)
There are too many ways to call function-strings (macros, as closures...)
Metaprogramming is just string-modification and can be applied everywhere
There is just a global namespace
There are no named arguments, no function signatures
No deallocation possible
Inefficient config file
Operators are functions, but the function names are symbols
No error handling
Lack of C++ documentation (how does it work internally?)

Why this is bad:

Everything is a string means that everything is executable, which can enable an attacker to execute code in some cases. Although it is easily possible to write forkbombs and other malware for cbs, this is probably not really an horror scenario, because masterlist-providers can inject code anyway. There other scenarios, where this can be dangerous: It can lead to data(=>code,state) corruption if random data is executed (just imagine a bug where someone executes a long string of human language). Such a corrupted block might even spread…corrupted code generated more corrupted code with metaprogramming. (I call this disease cubic cancer ;) ). Also it makes debugging a lot harder and even can hide bugs, this of course goes hand in hand with error handling: No error handling => no error on code corruption.
The problems I just described could be contained a bit if there where types and function signatures anyway (line with 8 words, can not be called for function that requires 3 args; can not call a function that requires lists for a line of human language) and again…error handling.
Now there is a lot of problems with the seperation between data and code, but there is an additional problem: The usage of complicated string manipulation methods: You can use multiple Macros of different levels, macros are hard to distinguish from actual variables and their usage varys depending on the level of rect brackets. Calling a function seems to be equivalent with accessing the string one macro level deeper. Then there are two kinds of string defining symbols: [...] and "..." witch both output a string (or you can just use none of them), there are also round braces witch evaluate the code immediately. This is apperantly still a little buggy, because some strings are not recognized as entire commands and in some cases the macro modifier is not recognized (I remember, that I tried to fill a bug report about this/talk to the devs about this, I also remember that I have been somewhat unsuccessful).

The next big block of criticism is the available variable space: Ther is only the global namespace. Not a local one, no packages/namespaces, only one. In other words: You iterate over a list using I as iterator and one other function you call does the same: You are screwed. If someone else in a completely different script decides to call his var 'roster' too...you are screwed. But not only is the cbs-namespace a mess, cubescript is also one single memory leak. no RAM at all is being deallocated, try this:

testnum = 0
testmax = 2048

buildup = [ if (*smaller* $i $m) [ s = (concatword $s $s $s $s $s $s $s $s $s $s); i = (* $i 10); sleep 1 [ buildup ] ] ]
test = [
if (*smaller* $testnum $testmax) [
s = a
i = 0
m = (pow 1024 2)
buildup

sleep 1 [ test ]
]
]

The code above builds string with the size of 1M and deletes it. It does that 2048 times. The memory consumption here should not be higher than 4M (this is generous). Actually it needed about a second to fill my entire RAM.
The next thing is that the configuration is done by writing the entire state => corrupted data and functions written.
The lists are bad for the obvious reason (lets append "mapc is stupid" to the end of a list ;) ).
Operators are just badly designed, using symbols but the arithmetic of functions is inconsistent.
And at last: There are about 5 lines of comment in the entire cube engine, maybe one in the cbs code. This makes it very hard to understand the internals, even if you can read C++.

Well, I am pretty exhausted. There are some ways how you can work around this problems, I'll write them down tomorrow :) .
You said you think cbs is perfect for it's purpose, what makes you think that?
Cheers,
mapc
reply to mapc

skiingpenguins | 2011-12-15 20:38



cube script isnt supposed to be as fancy as you seem to want it. i think you should chill out, and maybe go to a different game if you want something with all these feature things. cube script serves it's purpose very well. don't mess with it.
reply to 3starskiingpenguins

mapc | 2011-12-16 01:06



@skiingpenguins

Excuse me? Do you have the faintest idea what my essay meant, have you ever spent a single thought on programming language design, have you ever thought a second about application design? Please, do not waste my time! If you did not understand what I said, that's ok. I'll even explain it to you (somewhere else), but a statement like yours is not worthy an answer and I won't feed the trolls again…
reply to mapc

Chaos | 2011-12-16 02:29



Cubescript is a low-level language; hence, it's applications don't really go beyond those for which it was designed. However, in my opinion, cubescript really servers it's purpose well, accommodating a wide range of uses that relate to the game.
reply to 1starChaos

Suicizer | 2011-12-16 08:30



? This maybe has nothing to do with your content, but CubeScript doesn't seems like a low-level programming language to me. I would rather take OpenGL as example for a low-level programming language as CubeScript.

FrenchBadPing | 2011-11-06 00:17

Is it still dévoleppement ? Will there be a new version ? Do you know if PlatiniumArtSandBox is still in development ?
What does Eihrul in real life ? He works on another open source project like this ?
What do you think is the future of CubeEngine2 ?

nothing | 2011-10-31 09:05

Some of you might know the "maplounge". As sometimes errors occured like texture errors and missing mapmodels, which is due to the implementation of content in the download, we decided to make an own SVN download of mappackage, which we hope will make things easier. You can get detailed information on www.maplounge.net
Installation instructions are given there. Download of SVN version of Sauerbraten is not neccessary at the moment, but can be done as well, as it is not included in the mappackage.
We hope you enjoy playing on maplounge, and are looking forward to constructive critics, you can always send to "nothing" as a pm on www.nooblounge.net
If you want to give maps you made to the mappackage you are also welcome.
Hope to see you in game, sincerely yours nothing.

Chaos | 2011-10-05 19:38

All About Loops

Introduction
I know a few people who are trying to learn the basics of cubescript (and I'm sure there are many more out there), and so I thought I'd write a tutorial on loops - a fundamental part of any computer language. In essence, a loop is a sequence of instructions that is repeated until or while a particular condition is satisfied. I'll be discussing a few ways that loops can be utilized in cubescript.

The Basic Loop
The basic 'loop' command is quite easy to understand at its fundamental level. It goes like this,

loop i N [ body ]

This will exec body N times (i always starts at 0) increasing the value of i by 1 for each iteration. So if you wanted to quickly say the numbers 0, 1, 2… 9, you could use:

loop i 10 [ say $i ]

Also worth noting is that there is nothing special about 'i', you can just as easily use any other letter (or even strings of letters). Here's a quick exercise; see if you can find a way to quickly say all of the odd numbers from 0 to 10. Once you've had a minute to think about it, compare your answer with this,

loop i 6 [ say (* 2 $i) ]

What we're doing here is multiplying 'i' by 2 before we say it, resulting in an even number.

If you haven't played around with them to already know, sleeps in loops just don't work the way you want them to. For example, if you tried,

loop i 5 [ sleep 1000 [ echo $i ] ]

you'll notice that there is a one second pause after which the whole loop is carried out as if there was no sleep involved. And not only that, the value of 'i' seems to be off. This happens because the loop continues on while the sleeps are in progress (this might be hard to understand at first) and so, in the end, all the iterations seem to be executed as if there was one sleep in front of the entire loop. This can be fixed by increasing the sleep time for every iteration. As for the 'i', we need to refer to its value outside of the sleep, therefore we should use '@i' instead of '$i'. Putting it all together, we have:

loop i 5 [ sleep (* $i 1000) [ echo @i ] ]

This is does what we wanted the previous line of code to do; echo the numbers 0, 1, 2, 3 with a 1 second sleep between consecutive echoes.

Here's an interesting challenge: try to find a way to quickly echo the following; "0 0", "0 1", "0 2" … "0 4", "1 0", "1 1" … "1 4" … … "4 4", in other terms, a way to echo every possible way in which 2 not necessarily distinct numbers can be selected from the set {0 1 2 3 4}. After some thought, it becomes evident that we'll need to embed one loop inside of another as such,

loop i 5 [ loop k 5 [ echo (concat @i $k) ] ]

Again, we use the '@' because we are referring to the value of 'i' at a different level in the code.

Looping Through Lists
Lets say we had the list "2 3 5 7 11" and we wanted to quickly echo each element of that list in order, we could either use the normal 'loop' command and include (at "2 3 4 7 11" $i), or we could use 'looplist'. This command works as such,

looplist i L [ body ]

This is similar to loop, except now 'i' takes on each element of the list L. So, returning to the previous example, we can echo each element like this,

looplist i "2 3 5 7 11" [ echo $i ]

Pretty simple. Another exercise: find a way to quickly echo all of the names of the clients connected to a particular server. Here's how I would do it,

looplist i (listclients 1) [ echo (getclientname $i) ]

It's not hard to see that this would loop through the list of client numbers and echo the name that corresponds to each number.

Looping Through Files
Whether you knew it or not, it is in fact possible to loop through files in the sauerbraten folder using a command called 'loopfiles'. The format is like this,

loopfiles f dir ext [ body ]

This loops through the files in directory 'dir' with extension 'ext', executing 'body' for each iteration. As expected, 'f' gets assigned to the file name each iteration as well. So if we wanted to echo the names of all the screenshots in the 'screenshots' folder we could use,

loopfiles f screenshots png [ echo $f ]

Again, nothing too complicated. If we ever wanted to loop through all of the files in a certain directory with their extensions, we would simply leave 'ext' blank. So if you happen to have images that are not png files in the screenshots folder, you could use,

loopfiles f screenshots "" [ echo $f ]

You can see 'loopfiles' used in this Screenshot Script.

Looping Under a Given Condition
To loop under a certain condition we use 'while'. This command checks a condition, if it's true it executes the body of the loop, it it's false it terminates the loop. It's formatted like this,

while [ cond ] [ body ]

So if we wanted a different way to echo the numbers 0, 1, 2… 9 we could use,

var1 = 0
while [ (< $var1 10) ] [ echo $var1; var1 = (+ $var1 1) ]

The condition does indeed need to be placed into square brackets or you may encounter problems. This really isn't used that much because often times a simple 'loop' will do the job; it's still a useful tool, however.

Infinite Loops
There isn't a specific command for infinite loops, but rather a method that can be used to create them. Lets say we wanted to continuously echo "Hello World" every 3 seconds, we could do the following:

hwecho = [ echo "Hello World"; sleep 3000 [ hwecho ] ]

We are assigning a function that calls itself, and will therefore do so continuously. Issuing the command /hwecho will result in this continuous echoing. This is yet another tool that quite often comes in handy.

Loops within GUI Menus
Loops can also be used within GUI menus. For example, if we wanted 10 GUI buttons that would echo 0, 2, 3… 9 if pressed, we could create the GUI as follows,


newgui looptest [
loop i 10 [ guibutton $i [ echo @i ] ]
]

We simply have a loop within the definition of the GUI. Here you would have 10 buttons labeled 0 - 9 that would echo the number they are labeled with. This is a very basic example, you can see more sophisticated uses of loops within GUIs if you look at the ClanWar Script.

Well there you have it, loops in a nutshell. Hope you enjoyed reading it!

RaZgRiZ | 2011-10-04 19:38
Eihrul - Respect
127
points ]
 (19 votes)

I think we owe him that much.

Ok maybe this is a bit exaggerated, but when your bug report is verified and rectified, you just have to say "I told ya" !

---

Eihrul said it needed moar pony action, so there ya go buddy:

No, that's not a horse. It's a pony on steroids. Shut up.
It's also wearing a horn hat. Really!

Chaos | 2011-09-27 00:45
Bitwise Operators - A Brief Tutorial
10
points ]
 (1 vote)

Bitwise Operators

Introduction
Unfortunately, bitwise operators are rarely utilized in the scripts that I’ve been seeing on Quadropolis. Whether this is because their use is scarcely needed or because people just don’t know how to use them, I don’t know. However, I’d like to take this opportunity to inform you on the magic of bitwise operators. I’ll focus on cubescript, but this can sort of be expanded to many other computer languages; bitwise operators are fairly universal.

Binary System
To understand how bitwise operators work, you’ll first need to understand how a computer interprets numbers – in base-2. If you input a number in our normal base-10 system, the computer will translate it into base-2 and work with it that way. Converting numbers to and from binary (i.e. base-2) is easy, but here are the first few to give you a feel of how the system works,

0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000

Note that if you have a zero at the start of the number, it can be omitted - I just included it to have everything line up. So, let’s say we wanted to convert 13 to a binary number, there are many algorithms to do this but essentially what we must do is write 13 as a sum of powers of 2, and then ‘concatenate’ the coefficients to obtain a base-2 number. This is what I mean,

13 = 1*(8) + 1*(4) + 0*(2) + 1*(1) = 1*(2^3) + 1*(2^2) + 0*(2^1) + 1*(2^0)

We can better visualize this by writing the right-hand side of the equality above vertically,

1*(2^3)
1*(2^2)
0*(2^1)
1*(2^0)

The vertical column of 0s and 1s tells us the value of each bits (a bit is either a 0 or a 1; binary numbers are composed of these) in the base-2 number,

13 in binary = 1101

Essentially, we are determining which powers of two are ‘turned on or off’ and expressing that by writing out a string of 1s and 0s. Now that we have that sorted, we can move on to actual bitwise operators.

‘And’ Operator: &
Not to be confused with ‘&&’, the ‘and’ bitwise operator, denoted by the single ampersand ‘&’, is the first bitwise operator that we will consider. This operator essentially determines whether both bits are 1. For example, if we wanted to use this operator on the numbers 3 and 5, we would determine the result by converting both 3 and 5 to binary and determining each bit of the result.

3 = 011
5 = 101

Working bit by bit,

0 and 1 are not both 1, so the first bit is 0,
1 and 0 are not both 1, so the second bit is 0,
1 and 1 are both 1, so the third bit is 1.

So the result is 001, which is 1 in base-10. You can try it out in cubescript, just type /echo (& 3 5), in the cubescript language the bitwise operator comes first and is followed by the two numbers, much like the ways in which addition and subtraction are done. We will return to this operator later to show how it can be used to perform some nifty tricks.

‘Or’ Operator: |
Again, not to be confused with ‘||’, the single vertical line ‘|’ is used to signify the ‘or’ operator. Unlike the ‘and’ operator, this operator will determine whether either of the bits are 1. For example, again using 3 and 5:

3 = 011
5 = 101

Working bit by bit,

Either 0 and 1 are 1, so the first bit is 1,
Either 1 and 0 are 1, so the second bit is 1,
Either 1 and 1 are 1, so the third bit is also 1.

So the result is 111, which is 7 in base-10. Again, you can try it in cubescript by issuing the command /echo (| 3 5).

'Xor' Operator: ^
Here’s yet another one. This will determine whether both bits are different. Lets try it with 3 and 5:

3 = 011
5 = 101

Working bit by bit,

0 and 1 are different, so the first bit is 1,
1 and 0 are different, so the second bit is 1,
1 and 1 are not different, so the third bit is 0.

And so we have 110, or 6 in base-10. You can verify this with /echo (^ 3 5).

'Not' Operator: ~

Don’t confuse this with ‘!’. This operator simply switches the value of each bit; it’s only used on one number as opposed to the other bitwise operators we’ve looked at which involve two numbers. Lets try it with the 3:

3 = 011

Bit by bit,

Not 0 is 1, so the first bit is 1,
Not 1 is 0, so the second bit is 0,
Not 1 is 0, so the third bit is 0.

So we would expect to get 100 or 4 in base-10. BUT, this is clearly not what we receive if you try /echo (~ 3), in fact, we actually get -4! Why? Because one bit is allocated to a +/- sign before the number, and this operator switches ALL of the bits, therefore the number changes sign as well. Here’s a fancy trick for adding 1 to the value of a variable (I used x in this case):


x = (* -1 (~ $x))

This can always be replaced with the simpler x = (+ 1 $x), but the above example is included to illustrate that these operators are far from useless, as can be seen below.

GUI Bit Fields
Arguably one of the most eloquent uses of bitwise operators in cubescript, the GUI bit field allows us to create complex scripts in which very few variables are used. These GUI elements have the following format:

guibitfield [name of bitfield] [v - variable to effect] [power of 2]

So how does it work? Well, when the bit field is turned on, the bit it corresponds to is also turned on in the variable v (above). Here’s an example:


var1 = 0;
newgui gbf [
guibitfield “GBF1” var1 1
guibitfield “GBF2” var1 2
guibitfield “GBF3” var1 4
guibitfield “GBF4” var1 8
]

We initially set var1 to 0, as you can see from above. Lets say we activate GBF2, this would in turn activate the ‘2’ bit on in var1 and so var1 would equal 2. Now, if we have GBF2 and GBF3 on, we would have turned on the ‘2’ bit and the ‘4’ bit, so var1 would equal 6. Simple enough, right? Now how can we extract this information from the value of var1? We use the ‘and’ operator. If we have GBF2 and GBF3 activated, then var1 in binary would be 110 (6 in base-10). What we really care about is finding a way to determine whether various bit fields are indeed turned on, and we can do this in the following manner:


if (& $var1 2) [echo “GBF2 is on!”]
if (& $var1 4) [echo “GBF3 is on!”]

Pretty cool, huh? Take a look at what we’re really doing (consider the first ‘if’ statement), we’re using the ‘and’ operator on var1 and 2 (number 2, not var2):

$var1 = 110
2 = 010

Notice that the '2' bit is on in both of the binary numbers above.

The only way for GBF2 to be on is if the ‘2’ bit is on in var1, and therefore (& $var1 2) is non-zero! A similar argument goes for GBF1, 3 and 4. With this, you can ‘squeeze’ many variables into one all-inclusive variable.

Well that’s my little tutorial, hope you enjoyed reading it as much as I did writing it. Please let me know if there’s anything that you want me to make more clear or elaborate on.

Chaos | 2011-09-24 13:46

I just wanted to let everyone know that, if you ever need help with cubescript idents, syntax etc., you can join the irc channel #sauer-scripts on gamesurge and type .[cubescript ident] for information on that particular command. I'm sure that there's still stuff thats not included (and if you happen to find one, you can let an op know so he can bind that command to the bot), but for all practical purposes its hopefully pretty darn comprehensive. Anyway just thought I'd give you all the heads up.

- Chaos

RaZgRiZ | 2011-09-05 23:57
Blabberbox
16
points ]
 (7 votes)

Given how this place has a (god make it) forum, i assumed a node to discuss whatever pops into mind could prove entertaining. So i'll make a start.

This is a dot. You DO NOT mess with dots. Or THEY will mess YOU up.

User login
Users on Quadropolis
1 guest & no users online
nopnotme
12
points ]
 (2 votes)
Created 2017-09-29 21:52
6 years 25 weeks ago
7YearBitch
22
points ]
 (3 votes)
Created 2018-03-30 17:47
5 years 51 weeks ago
7YearBitch
28
points ]
 (4 votes)
Created 2018-02-28 00:20
6 years 3 weeks ago
7
points ]
 (1 vote)
Created 2018-04-20 14:42
5 years 48 weeks ago
18
points ]
 (3 votes)
Created 2018-03-02 09:43
6 years 3 weeks ago
sevnnseven
15
points ]
 (2 votes)
Created 2018-03-02 09:41
6 years 3 weeks ago
42
points ]
 (5 votes)
Created 2015-06-11 00:04
8 years 41 weeks ago
sevnnseven
25
points ]
 (3 votes)
Created 2018-03-01 19:26
6 years 3 weeks ago
49
points ]
 (5 votes)
Created 2017-06-22 03:17
6 years 39 weeks ago
39
points ]
 (4 votes)
Created 2018-01-11 11:11
6 years 10 weeks ago
12
points ]
 (2 votes)
Created 2017-09-29 22:03
6 years 25 weeks ago
25
points ]
 (3 votes)
Created 2017-11-20 13:55
6 years 17 weeks ago
35
points ]
 (4 votes)
Created 2017-11-23 23:59
6 years 17 weeks ago
nopnotme
1
 point ]
 (1 vote)
Created 2017-09-29 21:59
6 years 25 weeks ago
nopnotme
25
points ]
 (3 votes)
Created 2017-09-29 21:56
6 years 25 weeks ago
28
points ]
 (4 votes)
Created 2017-09-17 12:33
6 years 27 weeks ago
DeathStarPC
Created 2017-09-11 03:47
6 years 27 weeks ago
10
points ]
 (1 vote)
Created 2017-09-12 03:37
6 years 27 weeks ago
20
points ]
 (3 votes)
Created 2010-03-04 23:30
14 years 3 weeks ago
Created 2017-04-24 15:32
6 years 47 weeks ago
Who's new
  • ColdIV
  • Aidan
  • Hunk
  • letic86
  • BATMAN