I use these primitives for crating races and adding skills (which I call upgrades):
/**
* Registers a race with the SourceCraft plugin
* @param name: The name of the race. (max 64)
* @param short: The short name of the race. (max 16)
* @param switchmessage_instant: The message displayed to the player when they are switched to a new race. (max 192)
* @param switchmessage_dead: The message displayed to the play when they try to switch to the race,
* but they are alive so they need to wait until they die or the new round. (max 192)
* @param required_level: The overeall level the player must obtain before changing to this race. (default is 0)
* @param tech_level: The "tech" level the player must obtain in the race's faction before changing to this race.
* (default is 0)
* @param max_level: The maximum level the race can attain. (default is 16)
* @param initial_energy: The amount of energy players of this race are given on spawn. (default is 30)
* @param energy_limit: The maximum energy players of this race can attain, <0 is unlimited. (default is 100)
* @param energy_rate: The rate at which this race gains energy per second, (default is 1)
* @param faction: What faction the race is a member of, found in faction.inc. (default is Generic)
* @param type: What unit type the race is, found in faction.inc. (default is GenericUnit)
* @param parent: Parent race, for summoned races. (default is "" for none).
* @param description: The description of the race. (max 16)
* @param image: The image of the race.
* @return The return value will be the race index or -1 if there was a problem.
*/
native CreateRace(const String:name[],const String:short[],const String:switchmessage_instant[],
const String:switchmessage_dead[],required_level=0,tech_level=0,max_level=16,
initial_energy=30,energy_limit=100,energy_rate=1,Faction:faction=Generic,
UnitType:type=GenericUnit,const String:parent[]="",
const String:description[]="", const String:image[]="");
/**
* Adds an upgrade to a race
* @param race: The race ID returned from CreateRace()
* @param name: The name of the upgrade. (max 64)
* @param short: The short name of the upgrade. (max 16)
* @param desc: The description of the upgrade. (max 192)
* @param upgrade_category: Set to 0 for a "Normal" Upgrade or a category number for an ultimate. (default is 0)
* @param required_level: The race level required before this upgrade becomes available.
* (default is the minumum ultimate level {usually 8} and 1 for all others)
* @param max_level: The maximum level the upgrade can attain. (default is 4)
* @param energy: Amount of energy required to invoke upgrade. (default is 0)
* @param recurring_energy: Recurring amount of energy required the while upgrade is active,
* such as energy per shot. (default is 0)
* @param vespene: Amount of vespene required to purchase or invoke upgrade. (default is 0)
* @param crystals: Amount of crystals required to purchase or invoke upgrade. (default is 0)
* @param cost_flag: If 0, resources will be used to invoke.
* If 1, resources will be used to purchase.
* If 2, resources will be used to purchase and refunded when reset. (default is 0)
* @return The return value will be the upgrade index or -1 if there was a problem.
*/
native AddUpgrade(race,const String:name[],const String:short[],const String:desc[],
upgrade_category=0,required_level=-1,max_level=4,energy=0,
recurring_energy=0,vespene=0,crystals=0,cost_flag=0);
Which allows for an unlimited number of skills/upgrades and an unlimited number of ultimate (although currently I only use up to 4).
Which is then used to create a race thusly:
{
raceID = CreateRace("Terran SCV", "scv",
"You are now a Terran SCV.",
"You will be a Terran SCV when you die or respawn.",
48, 0, 37, .faction=Terran, .type=BioMechanical,
.description="The SCV is used to construct and maintain everything from remote outposts to space platforms as well as harvest resources...",
.image="/sc/images/Terran/SCV.png");
supplyID = AddUpgrade(raceID, "Supply Depot", "supply", "Provides additional ammo or metal.");
if (GetGameType() == tf2)
{
supplyBunkerID = AddUpgrade(raceID,"Research Supply Bunkers", "supply_bunker",
"Your structures become supply bunkers that regenerates the Health, Ammo/Metal and Energy of Teammates near them.", 0, 0);
}
else
{
supplyBunkerID = AddUpgrade(raceID,"Research Supply Bunkers", "supply_bunker",
"Not Available", false, 99, 0);
}
if (GetGameType() == tf2 && (m_AmmopacksAvailable || LibraryExists("ammopacks")))
{
ammopackID = AddUpgrade(raceID,"Ammopack", "ammopack",
"Drop Ammopacks on death. At level 2 and above, Ammopacks can be dropped with alt fire of the wrench (or +ultimate 4, if battlecruiser has not been researched).\nEngineers use metal instead of energy to drop Ammopacks.",
false, 0, .energy=GetConVarInt(cvarAmmopackEnergy));
if (!m_AmmopacksAvailable)
{
ControlAmmopacks(true);
m_AmmopacksAvailable = true;
}
}
else if (GetGameType() == dod && (m_DodAmmoAvailable || LibraryExists("dodammo")))
{
ammopackID = AddUpgrade(raceID,"Ammopack", "ammopack",
"Drop Ammopacks on death. At level 2 and above, extra ammopacks can be dropped using the dropammo command (usually h).");
if (!m_DodAmmoAvailable)
{
ControlDodAmmo(true);
m_DodAmmoAvailable = true;
}
}
else
{
LogMessage("Ammopacks are not available");
ammopackID = AddUpgrade(raceID,"Ammopack", "ammopack",
"Not Available", false, 99, 0);
}
if (GetGameType() == tf2 && (m_TeleporterAvailable || LibraryExists("tf2teleporter")))
{
teleporterID = AddUpgrade(raceID,"Teleportation", "teleporter",
"Decreases the recharge rate of your teleporters.");
if (!m_TeleporterAvailable)
{
ControlTeleporter(true);
m_TeleporterAvailable = true;
}
}
else
{
LogMessage("tf2teleporter is not available");
teleporterID = AddUpgrade(raceID,"Teleportation", "teleporter",
"Not Available", false, 99, 0);
}
immunityID = AddUpgrade(raceID, "Immunity", "immunity",
"Makes you Immune to: Theft at Level 1,\nUltimates at Level 2,\nMotion Taking at Level 3,\nand Blindness at level 4.");
armorID = AddUpgrade(raceID, "Armor", "armor", "A suit of Light Armor that takes damage up to 60\% until it is depleted.");
cvarAllowGravgun = FindConVar("sc_allow_gravgun");
new allowGravGun = GetConVarInt(cvarAllowGravgun);
if (allowGravGun >= 1 && (m_GravgunAvailable || LibraryExists("ztf2grab")))
{
if (GetGameType() != tf2)
{
gravgunID = AddUpgrade(raceID,"Gravity Gun", "gravgun",
"Allows you to pick up objects and move them around.\nAverages 1 energy per second while in use.",
true, 10, 1, .energy=GetConVarInt(cvarGravgunEnergy)); // Ultimate
}
else
{
cvarAllowRepair = FindConVar("sc_allow_gravgun_repair");
if (cvarAllowRepair && GetConVarBool(cvarAllowRepair))
{
gravgunID = AddUpgrade(raceID,"Gravity Gun", "gravgun",
(allowGravGun >= 2) ? "Allows you pick to up and move your objects around.\nLevel 2 allows you to pickup other players objects, which can be repaired at Level 3 (while being held) and thrown at Level 4.\nAverages 1 energy per second while in use." :
"Allows Engineers to pick up and move thier objects around..\nLevel 2 allows Engineers to pickup other players objects, which can be repaired at Level 3 (while being held) and thrown at Level 4.\nAverages 1 energy per second while in use.",
true, 10, .energy=GetConVarInt(cvarGravgunEnergy)); // Ultimate
}
else
{
gravgunID = AddUpgrade(raceID,"Gravity Gun", "gravgun",
(allowGravGun >= 2) ? "Allows you pick to up and move your objects around.\nLevel 2 allows you to pickup other players objects, which can be thrown at Level 4.\nAverages 1 energy per second while in use." :
"Allows Engineers to pick up and move thier objects around..\nLevel 2 allows Engineers to pickup other players objects, which can be thrown at Level 4.\nAverages 1 energy per second while in use.",
true, 10, .energy=GetConVarInt(cvarGravgunEnergy)); // Ultimate
}
}
if (!m_GravgunAvailable)
{
ControlZtf2grab(true);
m_GravgunAvailable = true;
}
}
else
{
gravgunID = AddUpgrade(raceID,"Gravity Gun", "gravgun",
"Not Available", true, 99, 0); // Ultimate
if (m_GravgunAvailable || LibraryExists("ztf2grab"))
ControlZtf2grab(true);
else if (allowGravGun)
LogMessage("ztf2grab is not available");
else
{
LogMessage("Disabling Terran SCV:Gravity Gun due to configuration: sc_allow_gravgun=%d",
allowGravGun);
}
}
bunkerID = AddUpgrade(raceID,"Enter Bunker", "bunker",
"Enter the Bunker, which provides addional armor (20-160%) that takes 100\% damage at the cost of becoming immoble while in the bunker",
2, .energy=GetConVarInt(cvarBunkerEnergy)); // Ultimate 2
if (m_TripminesAvailable || LibraryExists("tripmines"))
{
tripmineID = AddUpgrade(raceID,"Tripmine", "tripmine",
"You will be given a tripmine to plant for every level.",
2); // Ultimate 2
if (!m_TripminesAvailable)
{
ControlTripmines(true);
m_TripminesAvailable = true;
}
}
else
{
LogMessage("Tripmines are not available");
tripmineID = AddUpgrade(raceID,"Tripmine", "tripmine",
"Not Available", 2, 99,0); // Ultimate 2
}
if (m_NadesAvailable || LibraryExists("ztf2nades"))
{
nadeID = AddUpgrade(raceID,"Grenade", "nade", "You will be given a frag grenade and a special grenade to use for every level.\nThrow a frag nade with +ultimate 2 and a special nade with +ultimate 3\nType !nade for more information.", 3); // Ultimate 2 & 3
if (!m_NadesAvailable)
{
ControlNades(true);
m_NadesAvailable = true;
}
}
else
{
LogMessage("ztf2nades are not available");
nadeID = AddUpgrade(raceID,"Grenade", "nade",
"Not Available", true, 99,0); // Ultimate
}
battlecruiserID = AddUpgrade(raceID,"Build Battlecruiser", "battlecruiser",
"You become a Battlecruiser until you die.\n+ultimate 3 can also be used if nades aren't leveled",
4, 16,1, .energy=GetConVarInt(cvarBattlecruiserEnergy)); // Ultimate 4
if (GameType == tf2 && (m_AmplifierAvailable || LibraryExists("Amplifier")))
{
amplifierID = AddUpgrade(raceID,"Research Amplifier", "amplifier",
"Construct Amplifiers instead of Dispensers",
0, 1, 1);
if (!m_AmplifierAvailable)
{
ControlAmplifier(true);
m_AmplifierAvailable = true;
}
}
else
{
LogError("Amplifier is not available");
amplifierID = AddUpgrade(raceID,"Research Amplifier", "amplifier",
"Not Available", false, 99, 0);
}
}