It makes easier to maintain and read all the scripts related code and gives us more control over the code.
In some cases it will be a safe guard against errors.
We only accept code that is written according to our developing standards.
A properly written patch goes faster to core than unordered ones and makes the maintainers lifes easier.
Code never contain tabs, instead we use spaces.
By tab size, we mean 4x spaces. Not 5, not 3.
Most sane development-tools have options to replace tabs with 4 spaces.
Visual Studio:
Tools -> Options: Text Editor -> C++ -> Tabs
Smart, 4, 4, Insert spaces.
Notepad++:
Settings -> Preferences -> Language
Tab size: 4, Replace by space: checked
Always comment code where it is not typical code repeated in many/all scripts and/or not self-explanatory what the code does.
A comment should either be placed directly above the code :
// My comment
if (something == MY_CONSTANT)
or at code line 61 if this fits more natural in the code :
if (something == MY_CONSTANT)
{
a = b; // My comment
Do not file source code containing white space in end of line. Generally a no-no.
Do not fill parenthesis with whitespace. Place space in front, not after.
Wrong :
if( attack )
if ( attack )
Correct :
if (attack)
We use symmetric brackets. One line blocks does not need brackets
if (attack)
{
me->DoA();
me->DoB();
}
else
{
me->SelectA(); me->SelectB();
}
or
if (attack)
{
me->DoA();
me->DoB();
}
else
me->SelectA();
Similar to if () blocks, one line statements do not need brackets
for (uint32 i = 0; i < loopEnd; ++i)
{
DoSomething();
DoSomethingElse();
}
uint32 i = 0;
while (i < 10)
{
DoSomething();
DoSomethingElse();
++i;
}
do
{
DoSomething();
DoSomethingElse();
--i;
}
while (i > 0);
Constants makes code easier to read and does also provide a degree of fail safe.
Wrong :
if (player->GetQuestStatus(10090) == 1)
me->RemoveFlag(58, 2);
Correct :
if (player->GetQuestStatus(QUEST_BEAT_UP) == QUEST_STATUS_INCOMPLETE)
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
Constants are either set as #define, or most preferred in a enum. If it does not exist, make one.
It is strongly advised to avoid using #defines for constants, use either a const variable or an enum, if multiple variables can be grouped together
Enums must have a name. Separate constant on different enums depending on their type.
Correct :
enum Spells
{
SPELL_1 = 23444,
SPELL_2 = 23233,
H_SPELL_3 = 28345
};
Constant names have standardized prefixes :
Prefix | Usage |
---|---|
SPELL_ | Spell id |
NPC_ | Creature_template.entry |
ITEM_ | Item_template.entry |
GO_ | Gameobject_template.entry |
QUEST_ | Quest_template.entry |
SAY_ | Script_texts.entry (yell/normal say) |
EMOTE_ | Same as above, just different prefix to clearly see its emote |
EQUIP_ | Typically a item id(id from dbc, not _template) |
MODEL_ | A creature model |
H_XX | Heroic mode prefix (goes before the other prefix) XX is max man amount from mode. (OBSOLETE AS OF PATCH 3.2 WITH SpellDifficulty.dbc) |
RAID_XX | Raid mode prefix (goes before the other prefix) XX is max man amount from mode. (OBSOLETE AS OF PATCH 3.2 WITH SpellDifficulty.dbc) |
EVENT_ | Event/Encounter identifier for instances |
DATA_ | Identifiers in instance used for GUIDs/data not being event/encounter |
ACHIEV_ | Achievement id |
Correct :
SPELL_ENRAGE
H_XX_SPELL_ENRAGE
EVENT_ILLIDAN
DATA_ILLIDAN
ACHIEV_OH_NOVOS
No matter what, DO NOT USE HUNGARIAN NOTATION IN VARIABLE NAMES
for public/protected members or global variables:
uint64 SomeGuid;
uint32 ShadowBoltTimer;
uint8 ShadowBoltCount;
bool IsEnraged;
float HeightData;
for private members:
uint64 _someGuid;
uint32 _mapEntry;
uint8 _count;
bool _isDead;
float _heightData;
Methods are always UpperCamelCase and their parameters in lowerCamelCase, just like local variables
void DoSomething(uint32 someNumber)
{
uint32 someOtherNumber = 5;
}
Remember to use ' f ' after float values when declaring them to avoid compile warnings
float posX = 234.3456f;
Defining an array of structs:
Position const PosMobs[5] =
{
{-724.12f, -176.64f, 430.03f, 2.543f},
{-766.70f, -225.03f, 430.50f, 1.710f},
{-729.54f, -186.26f, 430.12f, 1.902f},
{-756.01f, -219.23f, 430.50f, 2.369f},
{-798.01f, -227.24f, 429.84f ,1.446f},
};
We are used to defining WorldObjects in this way :
GameObject* go;
Creature* creature;
Item* item;
Player* player;
Unit* unit;
Keep in mind we never use multiple declarations with pointers
Something* obj1, *obj2;
The proper way to do this is
Something* obj1;
Something* obj2;
References are defined in a similar way (& must be stuck to the type)
Creature& creature;
Never define Creature* me; in a creature script!
'me' is the pointer to the scripted creature
const keyword should always go after type name
Player const* player; // player object is constant
Unit* const unit; // pointer to the unit is constant
SpellEntry const* const spell; // both spell and pointer to spell are constant
static keyword always should be put as first
static uint32 someVar = 5;
static float const otherVar = 1.0f;
TODO