RPG Xdocumentation About RPG X

Levels and skills

XP, the level curve formula, the skill tree, and writing skills as addons.

Players have a level, from 1 up to rpgx_level_max (100), and XP towards the next one. The bottom left of the HUD shows them: the level, with an XP bar next to it. Health and suit sit on top of those, with stamina, mana and buffs above them. XP comes from:

  • killing a spawn point's enemy: by its level, from the kill XP formula (default 10 * level: a level 3 enemy is 30 XP). Whoever kills it gets it.
  • turning in a quest with an XP reward (see Interactable NPCs).
  • addons: GAMEMODE:PlayerAddXP( ply, amount ) (server).

"+30 XP" shows next to the bar as it comes in. A level up shows LEVEL UP in the middle of the screen, refills stamina and mana (which grow by their per_level each level, see Stamina and mana) and gives rpgx_skill_points_per_level (1) skill point to spend on skills. At the highest level XP stops counting. Quests' minimum player level goes by it.

The level curve #

How much XP each level takes is a formula, set with a command in the console: by an owner in the game, or from the server console / RCON. It's saved in the database, so it survives restarts (and is the same on every server sharing a MySQL database, from their next restart).

rpgx_level_formula "100 * level ^ 1.5"

level is the level the player is at, and the result is the XP it takes to get from it to the next one: here 100 for level 1 to 2, 283 for 2 to 3, 3,162 for 10 to 11. It's rounded to whole XP, at least 1. With nothing after it, the command prints the current formula, what it comes out to for a few levels, and the total XP from level 1 to the highest. rpgx_level_formula default puts the default back. A formula that doesn't work is refused with the reason, and the old one stays. Changing it never takes levels away, and a cheaper curve levels players up right away if they already have the XP.

rpgx_kill_xp_formula "10 * level" works the same way for XP per kill, where level is the enemy's level (0 or less = no XP).

Put the formula in quotes. What a formula can have:

Write Means Example
+ - * / add, subtract, multiply, divide 50 * level + 100
^ to the power of level ^ 2 (level squared), 1.1 ^ level (10% more every level)
( ) work this part out first (level + 1) * 50
sqrt(x) square root 100 * sqrt(level)
cbrt(x) cube root 100 * cbrt(level)
root(x, n) nth root 100 * root(level, 4)
% remainder after dividing level % 5 (0 every 5th level)
min(a, b, ...), max(a, b, ...) the smallest / biggest of them max(100, 25 * level) (never under 100)
floor(x), ceil(x), round(x), abs(x) round down / up / to nearest, without the minus floor(level / 10)
ln(x), log(x), log(x, b), exp(x) natural log, log base 10, log base b, e to the power of x 100 * ln(level) + 50
pi, e, numbers like 1.5, .5, 2e3 constants (2e3 = 2000) pi * level

The order things are worked out in, and the mistakes it saves you from:

  • Parentheses first, then ^, then * / %, then + -. So level + 1 * 50 is level + 50; write (level + 1) * 50 for 50 times level plus one. 2 * 3 ^ 2 is 18, not 36.
  • Always write the *: 2 * level, not 2level; 2 * (level + 1), not 2(level + 1); (level + 1) * (level + 2), not (level + 1)(level + 2). The command tells you where it's missing.
  • Powers go right to left: 2 ^ 3 ^ 2 is 2 ^ 9 (512). Write (2 ^ 3) ^ 2 for 64.
  • A minus in front comes after the power: -2 ^ 2 is -4, (-2) ^ 2 is 4. A negative power works: 2 ^ -1 is 0.5.
  • Roots as powers need parentheses around the fraction: level ^ (1/2) is the square root (same as sqrt(level)), level ^ (1/3) the cube root. level ^ 1/2 is (level ^ 1) / 2, half the level.
  • Every level has to come out as a number. A root of something negative (sqrt(level - 5) below level 5) or dividing by zero (100 / (level - 3) at level 3) doesn't, so the formula is refused and the command says at which level.
  • Spaces don't matter, and neither do capitals (LEVEL). Only numbers, level, pi, e, the functions above and + - * / % ^ ( ) , are allowed; a formula is worked out, never run as code.

Some curves, as XP for level 1, 2, 5 and 10:

Formula 1 2 5 10
100 * level ^ 1.5 100 283 1,118 3,162 The default: steeper every level
50 * level ^ 2 + 100 150 300 1,350 5,100 Steeper still
1000 * 1.1 ^ level 1,100 1,210 1,611 2,594 10% more each level: gentle at first, very steep much later
100 * sqrt(level) 100 141 224 316 Flattens out
(level + 1) * 50 100 150 300 550 The same step every level
max(100, 25 * level) 100 100 125 250 Flat 100 until level 4, then rising

Skills #

The inventory's Skills tab is the skill tree. It builds itself from whatever skills are installed: skills that need nothing are the top row, and every other skill sits below the skills it needs, with a line from each one labelled with the level it needs (green once you have it). Rows wider than the window wrap. Each box shows the skill's icon and its level out of its cap. The edge is gold at the cap, green if you can raise it now, blue if you have some of it, and grey otherwise. Hovering shows what it does, what the next level costs and what it needs (✔ / ✘), or why it can't be raised. Click to put points into it. The top of the tab shows your level, XP and unspent skill points.

  • Every skill has its own level cap and skill points per level (usually 1). A skill with 0 points per level can't be bought at all: only quest rewards raise it.
  • A skill can need a player level, and other skills at a level ("Bonus stamina at level 3"). One that needs a skill that isn't installed stays in the tree but can't be learned.
  • Quest rewards can give levels of a skill (see Interactable NPCs): for free, whatever it needs, up to its cap. Given levels are kept apart from bought ones.
  • Built in: Bonus stamina and Bonus mana, each +rpgx_skill_bonus_stamina / rpgx_skill_bonus_mana (10) max per level, up to level 10, 1 point per level.
  • Skills are saved as they change. A skill whose addon has been removed from the server is deleted from players when they join, and its points come back. If a skill's cap goes down, bought levels come off first and their points come back. If a player has spent more points than they have (their level was lowered, or rpgx_skill_points_per_level was), their bought levels are reset and they spend the points again. Given levels always stay.

Commands, for owners (permission levels) and the server console:

Command Does
rpgx_level_formula ["formula" | default] Shows or sets the level curve (see The level curve)
rpgx_kill_xp_formula ["formula" | default] Shows or sets the XP per kill
rpgx_xp <player> <amount> Gives XP (level ups included)
rpgx_setlevel <player> <level> Sets the level, XP towards the next at 0
rpgx_skill_give <player> <skill> [levels] Gives levels of a skill, like a quest reward
rpgx_skills_reset <player> Gives back every point they spent; given levels stay

<player> is part of an online player's name, or their SteamID.

Skills from addons #

Skills are scripted like SWEPs (but aren't SWEPs): one file per skill, and the file name is its id. The gamemode's own are in gamemode/skills/. Any addon's go in lua/rpgx/skills/*.lua (loaded on both sides) and show up in the tree by themselves. For example lua/rpgx/skills/iron_lungs.lua:

SKILL.Name = "Iron lungs"
SKILL.Icon = "icon16/heart.png"         -- any icon16/... (https://wiki.facepunch.com/gmod/Silkicons) or your own material
SKILL.MaxLevel = 5                      -- its level cap
SKILL.Cost = 2                          -- skill points per level; 0 = only quest rewards raise it
SKILL.PlayerLevel = 5                   -- player level needed first
SKILL.Requires = { bonus_stamina = 3 }  -- Bonus stamina at level 3 first
SKILL.Resources = { stamina = 15 }      -- +15 max stamina per level

function SKILL:GetDescription( ply, level ) return "+15 max stamina per level. Now +" .. 15 * level .. "." end
function SKILL:OnLevelChanged( ply, level, old ) end   -- server

Whatever a skill leaves out comes from its base: SKILL.Base, "base" when not set (gamemode/skills/base.lua lists every value with its default). Any skill can be a base, and self.BaseClass is the base, like with SWEPs. SKILL.Abstract = true makes one that isn't in the tree.

Value Default
Name, Icon, Description "Skill", icon16/star.png, none What the tree shows (tooltip: Description or GetDescription)
MaxLevel 1 Its level cap
Cost 1 Skill points per level. 0 = can't be bought, only given. Or function( self, ply, level ) returning what raising it to level costs
PlayerLevel 1 Player level it needs
Requires none Other skills at a level: { bonus_stamina = 3, other_skill = 1 }
Resources none Added to resource pools per level: { stamina = 10, mana = 5 }, or function( self, ply, level ) returning that

Functions: GetDescription( ply, level ) (both; level 0 = not learned yet), OnLevelChanged( ply, level, old ) (server: learned, given, reset, and when the player joins with old 0), PlayerSpawn( ply, level ) (server, every spawn while it's above 0).

Also, both sides: GAMEMODE:PlayerLevel( ply ), GAMEMODE:PlayerXP( ply ) (XP, XP needed), GAMEMODE:SkillLevel( ply, id ) or ply:GetSkillLevel( id ), GAMEMODE:SkillPoints( ply ), GAMEMODE:SkillCanLearn( ply, id ), GAMEMODE:SkillList(), GAMEMODE:RegisterSkill( id, table ). Server: GAMEMODE:PlayerAddXP( ply, amount ), GAMEMODE:SkillGrant( ply, id, levels ), GAMEMODE:SkillLearn( ply, id ), GAMEMODE:SkillsReset( ply ), GAMEMODE:PlayerSetLevel( ply, level ), and the hooks RPGXLevelUp( ply, level, old ), RPGXGainedXP( ply, amount, why ), RPGXSkillChanged( ply, id, level, old ) and RPGXLevelsLoaded( ply ).