DotP 2014: Cleaning Code
Creating clean code is the difference between code that you can fix later when something needs changed and chose that you have rewrite from scratch. It's also the difference between code that you need to fix because there are simple errors and code that you never need to look at again. Coding cleanly isn't a new concept at all, but here are some things to keep in mind as you go.
Whenever you make a variable, give it a useful name. Often, it's okay to simply name a target pointer "target", but if you've got two targets, or you'll be dealing with lots of pointers, then you'd be much better off naming them something a little more descriptive. If they're interchangeable, then this isn't as important, such as with teh ability "destroy two target creatures". But, if the ability is something like The Mimeoplasm, where you've got two different pointers to creature cards, and the pointers will do different things, naming them differently is a good idea. If they're different types, such as a player and a creature, then name them "oPlayer" and "oCreature" or "oTargetPlayer" and "oTargetCreature".
You'll notice I add "o" before a lot of variables. Other times it's "i", or something like that. These prefixes denote the type of data the variable contains. "o" is for object, and "i" is for int. You'll also see "s" for string, "b" for boolean, and filters are variously "f" or "o" (they are, internally, objects; i.e., something you can call functions on). Data chests also get "o", because, again, they're internally objects, since you can call functions on them. (When I say "call functions on them, I mean EffectDC():Get_Int(0). The colon after EffectDC() means Get_Int(0) is being called on the data chest returned by EffectDC()).
This is a really good habit to get into, and it'll allow you to more easily recognize what a variable contains without having to backtrace where it came from. When you're coding, you might not think it'll matter much since you can easily remember where the variable came from, but it's also very important for other coders who may come in to fix the code at some point. With clean code, it's much easier for them to fix it and takes a lot less time. It also means they're less likely to need to.
Another thing to keep in mind is to use a function call whenever possible to eliminate large sections of repetetive code. This isn't always viable, but it's often applicable. For instance, consider this code, which is on many cards.
<AUTO_SKIP> local effectController = EffectController() if effectController:GetTeam():IsSharedLifeTotal() == true then if effectController:GetLifeTotal() >= 30 then return true end else if effectController:GetLifeTotal() >= 20 then return true end end return false </AUTO_SKIP>
If you take the time to parse through this code, it simply returns true if your current life total is >= to your starting life total. This can be accomplished with a single line of code, which is not only much easier to read and understand, but can also be updated in the future on every card that uses it (such as when Commander was introduced).
return EffectController():GetLifeTotal() >= CW_General_GetStartingLifeTotal()
Now, it's very easy to read (especially once you get used to reading "CW_General_" as a prefix and not part of the function name).
For the record, IsSharedLifeTotal() is one way to tell if you're in a two-headed giant game.
Anyway, now the EDH is out, the starting life total has changed for 2, 3, and 4 player games. In 2 player games, it's now 30. In 3 and 4 player games, it's now 40. But all of those cards need updated to reflect that. When code is repeated too often on different cards in ways like this, it makes it very hard to change things in the future. In order to change one thing, you have to edit hundreds of cards.
