1. if(iPlayer ~= -1) then
Basically we are doing this to confirm it is a player and not a barbarian or city state?
No, those will still have actual player values. If you want to exclude barbarians or city-states, you need to do a check on pPlayer:IsBarbarian() or pPlayer:IsMinorCiv(), both of which are boolean values. In this case I didn't bother, but you can easily slide another IF check in there after the iPlayer check and before the iUnit check. Honestly, I'm not sure what pPlayer:GetLeaderType() does for barbarians or minor civs, so it'd probably be good to put that If check in, regardless.
The reason for the -1 check is that it's possible, on some occasions, for these events to get called without valid arguments. If that happens, you don't want to go any further, because there's no player with ID of -1 and so the pPlayer generation would fail. You should always sanitize your inputs this way to avoid crashing the functions.
2. pPlayer:GetUnitByID(iUnit);
We are doing this because the function returns a unit ID only and not a specific unit?
No, we're doing it because IDs are not unique; two players can each have a unit with ID of 42, so the iUnit argument by itself isn't enough to identify the unit. It's the combination of player ID and unit ID that uniquely identifies the unit structure.
GetUnitByID does return a unit structure (which I named pUnit), but you have to access it through that command on the pPlayer structure. It's just how it works.
1. GameInfo.Units[pType].CombatClass
Why are we using a bracket here and not parenthesis?
Brackets are for array indices. Parentheses are for function arguments. GetUnitByID() is a function, with iUnit as its argument; GameInfo.Units is an array (well, technically it's a two-tier structure, but no big difference), with pType as its index; the CombatClass part just tells it which part of the structure for that specific unit to use. While they look similar, they're not the same thing, so you have to be sure to use the right one.
2. condition = "LeaderType = '" .. GameInfo.Leaders[iLeader].Type .. "'";
What are the brackets, dots and quotations for?
The brackets are, again, because it's an array index. A ".." is a string append command, so that you can insert a variable inside a string. Effectively, what we're trying to create is a string that looks like
LeaderType = 'LEADER_ALEXANDER'
for the string variable named "condition", with the LEADER_ part changing depending on your civ. The strange double-quoting is because we need to have our string (the part inside the double "s) include a set of quotes of its own (the single quotes), while still dynamically assigning the leader type. It's a bit messy to read, but it's how you do programming like this.
3.
Code:
for row in GameInfo.Leader_Traits(condition) do
iTrait = row.TraitType;
end
Why is this a loop? Can non-array variables store more than value?
They can (although not without changing it to iTrait[index] and adding an index increment command), but that's not actually what it's doing. There's no way to explicitly say "go get me the trait for leader X" in a single command; all of those minor tables that crosslink the major ones require this sort of access. So what you do is set the condition variable to something that only matches one single table entry; then, you loop over the table, using that condition, knowing that it'll only execute once because no other entry will be valid.
I could have just as easily written it as
Code:
for row in GameInfo.Leader_Traits() do
if row.LeaderType == GameInfo.Leaders[iLeader].Type then
iTrait = row.TraitType;
end
end
and it'd have done the same thing, although it would take longer since it'd now be loading each entry in the Leader_Traits table into memory before checking. It's better to do it the way I did, even though it's harder to read.
Of course, this assumes that there's only one entry in the Leader_Traits table for each leader. If you allow multiple traits to be assigned to each leader, then you'll need to change iTrait to an array and add an index variable as well.
4. function Remove_Mounted_Penalty(iPlayer,iUnit,hexVec,unitType,cultureType,civID,primaryColor,secondaryColor,unitFlagIndex,fogState,selected,military,notInvisible)
Why are we calling so many arguments in this function?
You don't have a choice. SerialEventUnitCreated (like any other Lua event) has a very specific argument list; you can't just arbitrarily list a few of them and drop the rest. You see, it doesn't ACTUALLY know that iPlayer means player ID and so would put that in the appropriate variable; the function's first argument just happens to be player ID, the second just happens to be unit ID, and so on, and you can use whatever names you want for the variables.
The wiki has the argument lists for some of the events. Others, you can find by looking through the existing game's Lua; that argument list I gave was taken directly from one of the UI functions (UnitPanel, I think). And if all else fails, there's a trick for creating a "listener" function, using the unpack{...} command, but I don't have the syntax for that available offhand (I'm at work).