 Rules FAQ Members List Search Register Login Raised This Month: \$158 Target: \$400 39%  Author Message
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA  10-06-2010 , 22:25   [TUT] Bits, Bit-fields, and Bit-wise Operators #1 This tutorial covers the basics of bits, bit-fields, and bit-wise operators and is written on a very basic level that everyone should be able to understand. I know a similar tutorial already exists but in my opinion it isn't very clear if the reader does not have any experience with the topic. I've also included basic examples of how bit-fields can be used in plugins. Please let me know of any errors\typos or recommendations. Also, if you've read this and are still unsure of something, please tell me so I can explain further. What is a bit-field? A bit-field is a series of contiguous bits within a memory cell (non-array). The number of bits in a given bit-field is determined by the number of bytes allocated for the data-type being used. By default, all bits in a bit-field are 0. When no bits are 1 in a given bit-field, the resulting value will be 0. If one or more bits are 1 within a bit-field, the resulting number will be non-zero. AMX-X has only 1 data-type which is a 4-byte cell so it is limited to 32-bits in a single bit-field. If you need to manipulate bits above 32, see the bit-field array example below. Example of bit-field sizes:1-bytes = 8 bits == 0000 0000 2-bytes = 16 bits = 0000 0000 0000 0000 4-bytes = 32 bits = 0000 0000 0000 0000 0000 0000 0000 0000 How are numbers stored on a computer? All information on a computer is stored in memory (RAM, ROM, hard-disc, flash memory, etc). At the lowest level, memory consists of many many many on-off switches (known as bits). An integer value is a result of a combination of bit(s) that are set to 1 or 0. If you see me refer to a binary number, this means the bit-representation of an integer. Each bit cooresponds to a power of 2. For this example I will use 8 bits just as a quick example of how bits form a number. Bit-ordering (I'm not getting into endianness) is as follows: 7654 3210 The below values correspond to each of those bits. As you can see, if a given bit is 1 in a bitfield, the integer value will increased by the corresponding value for the respective power of 2. 1 === 2 power of 0 -- Stored in bits: 0000 0001 (binary representation) 2 === 2 power of 1 -- Stored in bits: 0000 0010 4 === 2 power of 2 -- Stored in bits: 0000 0100 8 === 2 power of 3 -- Stored in bits: 0000 1000 16 == 2 power of 4 -- Stored in bits: 0001 0000 32 == 2 power of 5 -- Stored in bits: 0010 0000 64 == 2 power of 6 -- Stored in bits: 0100 0000 128 = 2 power of 7 -- Stored in bits: 1000 0000 Suppose we have a variable holding the number 97, our bit-field would appear as: 0110 0001 Notice bits 1, 6, and 7 are set. We can then add each corresponding number (or 2 power of bit#) to our resulting number. 1 == 2 power of 0 -- 1 2 3 4 5 6 == 2 power of 5 -- 32 7 == 2 power of 6 -- 64 8 = Or 2^0 + 2^6 + 2^7 = 1 + 32 + 64 = 97 What are the bit-wise operators and how do I use them? & - And | - Or ^ - Xor (Exclusive Or) ~ - Not (Or Ones-complement) << - Left bit-shift >> - Right bit-shift Operator: & Function: And Description: This operator is used to check if and only if both of the corresponding bits in both operands are 1. The resulting bit-field will consist of bits (1's) that were present at the same location within both operands. 15 & 3 = 3 15 = 0000 1111 03 = 0000 0011 03 = 0000 0011 _________________ 145 & 97 = 1 145 = 1001 0001 097 = 0110 0001 001 = 0000 0001 _________________ 255 & 234 = 234 255 = 1111 1111 234 = 1110 1010 234 = 1110 1010 Operator: | Function: Or Description: This operator is used to check if one or both bits are 1 in the corresponding bit positions of the two operands. The resulting bit-field will consist of bits (1's) that were present in either of the operands for each bit location. 15 | 3 = 15 15 = 0000 1111 03 = 0000 0011 15 = 0000 1111 _________________ 145 | 97 = 241 145 = 1001 0001 097 = 0110 0001 241 = 1111 0001 _________________ 255 | 234 = 255 255 = 1111 1111 234 = 1110 1010 255 = 1111 1111 Operator: ^ Function: Xor (Exclusive Or) Description: This operator is used to check where the corresponding bits in the two operands are different. The resulting bit-field will consist of bits (1's) that were opposite (0 & 1 or 1 & 0) at the same location within both operands. 15 ^ 3 = 12 15 = 0000 1111 03 = 0000 0011 12 = 0000 1100 _________________ 145 ^ 97 = 240 145 = 1001 0001 097 = 0110 0001 240 = 1111 0000 _________________ 255 ^ 234 = 21 255 = 1111 1111 234 = 1110 1010 021 = 0001 0101 Operator: ~ Function: Not Description: Not takes the binary representation of a number, and turns all zeros into ones, and ones into zeros. Unlike the previous 3 bitwise operators [AND, OR, XOR], NOT takes just one operand 0000 1111 = 15 1111 0000 = ~15 = 240 _________________ 1010 1010 = 170 0101 0101 = ~170 = 85 _________________ Operator: << Function: Left bit-shift Description: Shift bits in operand to the left by specified bit positions. X << Y This will shift bits in the X operand Y bits to the left. Any bits to the left that fall out of the bit-range will be dropped. Any bits added to the right due to the shift are 0. This example assumes a 1-byte memory cell so any bits shifted left past the 8th bit are dropped; if you are using a larger memory cell (in AMXX, a cell is 4-bytes or 32-bits) these bits will not be dropped but moved past the 8th bit to bits 9-32). 15 << 4 015 = 0000 1111 030 = 0001 1110 [All bits shifted 1 position] 060 = 0011 1100 [All bits shifted 2 positions] 120 = 0111 1000 [All bits shifted 3 positions] 240 = 1111 0000 [All bits shifted 4 positions] _________________ 209 << 2 209 = 1101 0001 162 = 1010 0010 [All bits shifted 1 position] 068 = 0100 0100 [All bits shifted 2 positions] Operator: >> Function: Right bit-shift Description: Shift bits in operand to the right by specified bit positions. X >> Y This will shift bits in the X operand Y bits to the right. Any bits to the right that fall out of the bit-range will be dropped. Any bits added to the left due to the shift are 0. 15 >> 4 015 = 0000 1111 007 = 0000 0111 [All bits right-shifted 1 position] 003 = 0000 0011 [All bits right-shifted 2 positions] 001 = 0000 0001 [All bits right-shifted 3 positions] 000 = 0000 0000 [All bits right-shifted 4 positions] _________________ 209 >> 2 209 = 1101 0001 104 = 0110 1000 [All bits right-shifted 1 position] 052 = 0011 0100 [All bits right-shifted 2 positions] Common bit-field operations Setting bit(s) to 1\true in a bit-field This is done using the bit-wise OR operator |. As explained above, this will set the bit to true if it exists in either operand. Assume an empty variable which we want to set bit 4 to true. Set a single bit iVariable = iVariable | ( 1 << 4 ); 0000 0000 = iVariable (freshly declared, no value set) 0001 0000 = 1 << 4 0001 0000 = iVariable | ( 1 << 4 ) Set multiple bits in the same expression iVariable = iVariable | ( ( 1 << 4 ) | ( 1 << 5 ) ) 0000 0000 = iVariable 0001 0000 = 1 << 4 0010 0000 = 1 << 5 0011 0000 = iVariable | ( ( 1 << 4 ) | ( 1 << 5 ) ) Setting bit(s) to 0\false in a bit-field This is done using a combination of bit-wise AND & and the NOT ~ operator. Assume a bit-field with bits 4 and 5 set. iVariable = ( ( 1 << 4 ) | ( 1 << 5 ) ) Suppose we need to set bit 4 to 0\false. iVariable = iVariable & ~( 1 << 4 ) 0011 0000 = ( ( 1 << 4 ) | ( 1 << 5 ) ) 1110 1111 = ~( 1 << 4 ) 0010 0000 = ( ( 1 << 4 ) | ( 1 << 5 ) ) & ~( 1 << 4 ) The same can be done for setting multiple bits to 0\false in a single expression. You only need to bit-wise OR the bits you want set to 0. iVariable = iVariable & ~( ( 1 << 4 ) | ( 1 << 5 ) ) Using bit-fields In a bit-field you can set bit(s) to 1, set bit(s) to 0, check if a particular bit(s) is 0/1, and utilize the integer that results from the bit-field. This makes bit-fields very useful and efficient. Example 1, using bit-fields as a boolean A useful application is if you want to store if a player is admin when he connects to the server. Common practice is to create an array of cells, using one cell for each player's true\false value. Boolean array method: PHP Code: ``` new bool: g_IsAdmin;public client_putinserver( id ){    g_IsAdmin[ id ] = bool: is_user_admin( id );}public client_disconnect( id ){    g_IsAdmin[ id ] = false;}  ``` If player id's 2 and 6 are admins, elements g_IsAdmin and g_IsAdmin will be true. A cell is 4-bytes so using an array for this purpose requires 132 bytes of memory (33-cells times 4-bytes). If a bit-field is used instead, you will only declare a single cell and that can store the same info but using only 4 bytes! Bit-field method PHP Code: ``` new g_IsAdmin; //Only need a single cell of memorypublic client_putinserver( id ){    if ( is_user_admin( id ) )             g_IsAdmin |= ( 1 << ( id & 31 ) );}public client_disconnect( id ){    g_IsAdmin &= ~( 1 << ( id & 31 ) );}  ``` You may be wondering why 1 is being shifted left by ( id & 31 ). This is because a 4-byte data-type is limited to 32 bits which means the maximum shift left that can be done without losing data is 31. Since player-ids in Half-Life can range from 1-32, we can not do 1 << 32 so doing a ( id & 31 ) will give us a usable value. When ( # & 31 ) is used, the value will be equal to the player id except when id == 32, when id == 32, the resulting value is 0. In a nutshell, player-id's 1-31 are returned as normal but when the player id is 32, 0 is returned so we are essentially using 0-31 instead of 1-32 which is exactly what we need. In the situation explained above where player id's 2 and 6 are online admins, our bit-field would look like the below. If you are wondering why the bits are not at the shift position based on player id, refer to the ( id & 31 ) explained above. 0000 0000 0000 0000 0000 0000 0100 0100 A bonus for using bit-fields for storing boolean values is you can quickly check if any bits are set, or in this case, if any admins are online. Remember, if no bits are 1 in a given bit-field, the resulting value is 0; like-wise, if there are 1 or more bits set to 1 in the bit-field, the resulting number is non-zero. PHP Code: ``` if ( g_IsAdmin )    //there are 1 or more admins onlineelse    //there are no admins  ``` If an array was used, you would need to use a loop to iterate through all elements in the array to check if each value is 1. This is what makes bit-fields not only more memory efficient but also CPU efficient and easier (less code). Example 2, boolean for weapon index(s) For this example I will show how you can flag various weapons in a bit-field. This can be used in a weapon restriction plugin or any plugin that needs a true\false value for each weapon. This is possible because weapons in CS have indexes that range from 1-32. In this example we will be creating a bit-field to represent weapons CSW_SG550 , CSW_AWP , & CSW_G3SG1 . The highest index for a weapon (primary\secondary) is 30 (P90) so you do not need to worry about using ( # & 31) or anything like that. g_Weapons = ( 1 << CSW_SG550 ) | ( 1 << CSW_AWP ) | ( 1 << CSW_G3SG1 ); This is what will occur with the above operation 0000 0000 0000 0000 0000 0000 0000 0001 = 1 (How 1 is represented on the bit-level. We are going to shift this bit to each weapon index bit position) 0000 0000 0000 0000 0010 0000 0000 0000 = 1 << CSW_SG550 (1 left-shifted by CSW_SG550 ) 0000 0000 0000 0100 0000 0000 0000 0000 = 1 << CSW_AWP (1 left-shifted by CSW_AWP ) 0000 0001 0000 0000 0000 0000 0000 0000 = 1 << CSW_G3SG1 (1 left-shifted by CSW_G3SG1 ) 0000 0001 0000 0100 0010 0000 0000 0000 = g_Weapons (The result) Remember, we are using Or for the above operation which will set each bit-position to 1 if it exists in either operand. This is why g_Weapons now has each bit set in the appropriate bit-position. Now that we have a bit-field with our desired weapons, we can then check the weapon bit with the following: PHP Code: ``` if ( g_Weapons & ( 1 << CSW_AWP ) )    //weapon is in bitfield  ``` What is occurring with this statement is we are taking 1 and pushing the bit to the left by CSW_AWP  bits. This will set the 18th bit to 1 so we will be able to check it against g_Weapons to see if both bits exist in the position. Remember that the & operator checks if the bit is 1 at both cooresponding bit positions in each operand. 0000 0000 0000 0000 0000 0000 0000 0001 = 1 (Number 1 represented in bits) 0000 0000 0000 0100 0000 0000 0000 0000 = 1 << CSW_AWP (Left bit-shift of 18 bits) 0000 0001 0000 0100 0010 0000 0000 0000 = g_Weapons 0000 0000 0000 0100 0000 0000 0000 0000 = Bits in the CSW_AWP  position do both exist so this would return true Suppose we want to check if scout is in our bit-field. CSW_SCOUT = index 3 PHP Code: ``` if ( g_Weapons & ( 1 << CSW_SCOUT ) )    //That weapon is NOT in bitfield  ``` 0000 0000 0000 0000 0000 0000 0000 0001 = 1 0000 0000 0000 0000 0000 0000 0000 1000 = 1 << CSW_SCOUT (Left bit-shift of 3 bits) 0000 0001 0000 0100 0010 0000 0000 0000 = g_Weapons 0000 0000 0000 0000 0000 0000 0000 0000 = Bits in the 4th bit (1<<3) position do not both exist so this would return false Example 3, using a bit-field for your plugins flags\options. PHP Code: ``` #define MAX_PLAYERS    32//Create a list of options that are supported by the pluginenum ( <<=1 ) _: Options{    Speed=1, // 1 << 0 or 1     AutoAim,  // 1 << 1 or 1 << 1 (as value is calculated by enum)            HighJump, // 1 << 2 or 2 << 1    ExtraHP,   // 1 << 3 or 4 << 1    ExtraArmor // 1 << 4 or 8 << 1}//Define an array that will keep track of each option a player currently hasnew g_Options[ MAX_PLAYERS+1 ];//Examples of how to apply option for playerg_Options[ id ] |= Speed;g_Options[ id ] |= HighJump;g_Options[ id ] |= ExtraArmor;//Example how to check if a player has an optionif ( g_Options[ id ] & Speed )    //player has speed  ``` If you were to do the above with an array of booleans you would need to create a 2-dimension array as demonstrated below: PHP Code: ``` #define MAX_PLAYERS    32//Create options as normal enum (no bitshift)enum _:Options{    Speed,   //0    AutoAim,   //1    HighJump,  //2    ExtraHP,   //3    ExtraArmor //4}new g_bOptions[ MAX_PLAYERS+1 ][ Options ];//Examples of how to apply option for playerg_Options[ id ][ Speed ] = true;g_Options[ id ][ HighJump ] = true;g_Options[ id ][ ExtraArmor ]  true;//Example how to check if a player has an optionif ( g_Options[ id ][ Speed ] )    //player has speed  ``` Useful Macros To easily manipulate bits in your plugin to work with players (or any 1-32 indexes) without having to re-write the bit operations each time, here are some macros. Remember, the max bit you can manipulate is 32 in AMX-X since the only data-type available is a 4-byte cell [32 bits]. PHP Code: ``` //If you are storing a player index or anything that has an index up to 32.//Example: SetPlayerBit( BitFieldVar , # )#define SetPlayerBit(%1,%2)      (%1 |= (1<<(%2&31)))#define ClearPlayerBit(%1,%2)    (%1 &= ~(1 <<(%2&31)))#define CheckPlayerBit(%1,%2)    (%1 & (1<<(%2&31)))//Safe for using values 0-31.//Example: SetBit( BitFieldVar , # )#define SetBit(%1,%2)      (%1 |= (1<<%2))#define ClearBit(%1,%2)    (%1 &= ~(1<<%2))#define CheckBit(%1,%2)    (%1 & (1<<%2))  ``` The benefits of using bit-fields A major benefit is conserving memory and CPU but IMO they are, in most cases, easier than using an array of bools. As you saw towards the beginning of this tutorial, you save 131 bytes of memory by using a bit-field over an array for storing player boolean (true\false) values. It also can result in less code because you can quickly check if bits exist or not with a simple if-statement; using an array you would need some type of loop to check each element. Manipulating bits outside of the bit-range of a memory cell This can be done through the usage of a bit array. This will simply use the first array element for bits 1-32, the second element for bits 33-64, and so on. There is not max-bit limitation on a bit-array as there is with a normal bit-field. PHP Code: ``` g_BitField //bits 1-32g_BitField //bits 33-64g_BitField //bits 65-96  ``` Here's an example on how to setup your plugin to work with unlimited bits: PHP Code: ``` #define SetBit(%1,%2)      (%1[%2>>5] |= (1<<(%2 & 31)))#define ClearBit(%1,%2)    (%1[%2>>5] &= ~(1<<(%2 & 31)))#define CheckBit(%1,%2)    (%1[%2>>5] & (1<<(%2 & 31)))  ``` PHP Code: ``` //Set the highest bit that we need to access#define MAX_BIT    515//Define an array large enough to contain all of the needed bits (1 -> MAX_BIT)new iBitfieldArray[ ( MAX_BIT / 32 ) + 1 ];//or you can donew iBitfieldArray[ ( MAX_BIT >> 5 ) + 1 ];//Set some random bitsSetBit( iBitfieldArray , 256 );SetBit( iBitfieldArray , 500 );//Check if the above worked successfullyif ( CheckBit( iBitfieldArray , 256 ) )    ClearBit( iBitfieldArray , 256 );if ( CheckBit( iBitfieldArray , 20 ) )//falseClearBit( iBitfieldArray , 256 );  ``` If you want to practice your knowledge, you can do bit-operations with calculators that exist on the net, here's one, many others exist. Also, the calculator that ships with Windows can do bit operations and even convert an integer value to its binary representation. To access it, click View->Scientific. Enter a number, and towards the top left, under the white number display box, click the Bin option and it will display the bits representing that integer number. You can also do all of the explained bit operators with the exception of bit-shifting (can be done mathematically, though). Experimenting with binary numbers Pawn has a constant (0b) that allows you to work with values in binary directly. To use it, prefix a set of bits with 0b; the number 10 in bits is represented by 1010 so to store this value in a variable, you would do iVar = 0b1010. You can practice your knowledge using this if you are still uncomfortable after reading this tut. This functions identically to the hexadecimal prefix 0x that you may have seen used elsewhere. A few more examples: PHP Code: ``` i1 = 0b1;i2 = 0b10;i10 = 0b1010;i15 = 0b1111;i255 = 0b11111111;  ``` Operation example: PHP Code: ``` new iNum1 = 0b1011; //11new iNum2 = 0b1111; //15iResult = iNum1 & iNum2;0b1011 = iNum1; //110b1111 = iNum2; //150b1011 = iResult; //15  ``` Interesting reading once you have an understanding of bits: Link __________________ Last edited by Bugsy; 06-22-2015 at 22:08. Reason: Fixed link at bottom of thread  Exolent[jNr]
Veteran Member
Join Date: Feb 2007
Location: Tennessee  10-06-2010 , 22:43   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #2

First. tl;dr. Will read when I get home.
__________________
No private work or selling mods.
Quote:
 Originally Posted by xPaw I love you exolent!  wrecked_
Veteran Member
Join Date: Jan 2010
Location: New York (GMT-5)  10-06-2010 , 23:23   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #3 Fan-fucking-tastic job, I learned a lot. Your work is appreciated, sir. __________________ [ Paid Requests ] DO NOT PM ME ABOUT BLOCKMAKER NO PRIVATE SUPPORT  fysiks
Veteran Member
Join Date: Sep 2007
Location: Flatland, USA  10-06-2010 , 23:44   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #4 Great tutorial! Concerning bits+array: Code: `#define SetBit(%1,%2) (%1[%2>>5] |= (1<<(%2 & 31)))` Wouldn't SetBit(g_BitField, 32) actually be the first bit in the second cell? If yes, the first cell would only use 1 - 31 (the 0th bit remains unused). EDIT: oh wait, You can use SetBit(g_BitField, 0). Everything is based on 0 here like arrays. Was it confusing for anyone else? Or was I just confusing myself thinking too hard? __________________ Last edited by fysiks; 10-06-2010 at 23:51.  Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA  10-06-2010 , 23:46   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #5 SetBit( g_BitField , 32 ) would set the 0 ( 1 << 0 ) bit. 32 & 31 = 0 __________________  fysiks
Veteran Member
Join Date: Sep 2007
Location: Flatland, USA  10-06-2010 , 23:52   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #6 But, what I was saying is that 32>>5 is 1 right? Which puts it in the the second cell of the array. There are still 32 bits used in each cell I realize now (see my edit) since you can set SetBit(array, 0). __________________ Last edited by fysiks; 10-06-2010 at 23:54.  Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA  10-06-2010 , 23:54   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #7

Quote:
 Originally Posted by fysiks But, what I was saying is that 32>>5 is 1 right? Which puts it in the the second cell of the array.
Yes you're right
__________________  fysiks
Veteran Member
Join Date: Sep 2007
Location: Flatland, USA  10-06-2010 , 23:56   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #8

Quote:
 Originally Posted by Bugsy Yes you're right
I was just making it more confusing for myself.

Just using it is easier than trying to understand it lol .
__________________  Exolent[jNr]
Veteran Member
Join Date: Feb 2007
Location: Tennessee  10-07-2010 , 01:19   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #9

Okay, so I've read it and it's very detailed and explained well.

I have one thought though.
Shouldn't this:
Code:
`new iBitfieldArray[ ( MAX_BIT / 32 ) + 1 ];`
be this:
Code:
`new iBitfieldArray[ ( MAX_BIT >> 5 ) + 1 ];`
Not that the first is wrong, but 1. we are talking about bits, and 2. it was proved in the other thread that the latter was quicker than the former.
__________________
No private work or selling mods.
Quote:
 Originally Posted by xPaw I love you exolent!  Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA  10-07-2010 , 02:11   Re: [TUT] Bits, Bit-fields, and Bit-wise Operators #10

Quote:
 Originally Posted by Exolent[jNr] Okay, so I've read it and it's very detailed and explained well. I have one thought though. Shouldn't this: Code: `new iBitfieldArray[ ( MAX_BIT / 32 ) + 1 ];` be this: Code: `new iBitfieldArray[ ( MAX_BIT >> 5 ) + 1 ];` Not that the first is wrong, but 1. we are talking about bits, and 2. it was proved in the other thread that the latter was quicker than the former.
Either will do the same but I think it may just confuse readers more than help them having MAX_BIT >> 5. IMO, the latter method serves a better purpose in the macros because they will be used much more frequently whereas in the variable declaration it is probably only called once per map change (assuming a global var).
__________________  Thread Tools Show Printable Version Email this Page Display Modes Linear Mode Switch to Hybrid Mode Switch to Threaded Mode Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is Off Forum Rules
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home Server Discussion     Source Servers (SRCDS)     HL1 Servers (HLDS) AMX Mod X     News     Bug Reports     General     Off-Topic     Plugins         Suggestions / Requests         Approved Plugins         New Plugin Submissions         Unapproved/Old Plugins         Translation Request         High-Traffic Plugins             GunGame             UAIO (Ultimate All-In-One Plugin)             xREDIRECT             CSDM             AMX Super             RuneMod             Zombie Plague Mod             SuperHero Mod                 News                 Tech Support                 Scripting Help                 Off-Topic / General Chat                 Heroes                     Suggestions / Requests                     Approved Heroes                     New Submissions                     Unapproved/Old Heroes                         Module Heroes                     SuperHero Mod Stats - By 123                 (OLD) Bug Reports     Scripting         Scripting Help         Code Snippets/Tutorials         Module Coding     Donor Access SourceMod     News     General     Plugins         Plugins         Unapproved Plugins         Plugin/Gameplay Ideas and Requests         High-Traffic Plugins             SourceMod Anti-Cheat             Zombie:Reloaded             SourceBans / SourceBans++             VSH / Freak Fortress             Store             SM_Hosties             HLstatsX:CE     Scripting     Extensions     Snippets and Tutorials     Donor Access     Metamod: Source         Metamod:Source Plugins         Metamod:Source Questions         Coding MM:S Plugins & SM Extensions Hosted Stuff     Asherkin's Plugins         TF2Items         TFDodgeball         SteamTools     Bail's Plugins         CSDM         CS:S DM Off-Topic & Trash     Off-Topic     Trash

All times are GMT -4. The time now is 05:40.

 DMCA - Archive - Top