Scripted buffs
Buffs and debuffs as files, like SWEPs: putting them on players and NPCs, and writing your own.
Buffs and debuffs are scripted like SWEPs: one file per buff, and the file name is its id. The
gamemode's own are in gamemode/buffs/; any addon's go in lua/rpgx/buffs/*.lua (loaded on both
sides). Applying one is a single line (server), on players and NPCs alike:
ent:AddBuff( "slowed" ) -- for its own Duration; again = one more stack, time restarts
ent:AddBuff( "frozen", 5 ) -- 5 seconds (0 = until removed)
ent:AddBuff( "slowed", nil, 3 ) -- 3 stacks at once (up to its MaxStacks)
ent:RemoveBuff( "slowed" )
ent:ClearBuffs()
-- both sides:
ent:HasBuff( "frozen" ) ent:GetBuffStacks( "slowed" ) ent:GetBuffs() -- id -> { stacks, ends, duration, data, ... }
A buff file, e.g. lua/rpgx/buffs/poisoned.lua:
BUFF.Name = "Poisoned"
BUFF.Icon = "icon16/bug.png" -- any icon16/... (https://wiki.facepunch.com/gmod/Silkicons) or your own material
BUFF.Debuff = true
BUFF.Duration = 8
BUFF.MaxStacks = 3
BUFF.Regen = { stamina = 0.5 } -- stamina refills at half speed
BUFF.DamageTaken = function( self, ent, inst ) return 1 + 0.1 * inst.stacks end
function BUFF:GetDescription( ent, inst ) return "Stamina refills at half speed, and you take more damage." end
function BUFF:Think( ent, inst ) end -- server, every tick
Whatever a buff leaves out comes from its base: BUFF.Base, "base" when not set
(gamemode/buffs/base.lua lists every value and function with its default). Any buff can be a base:
Frozen is BUFF.Base = "slowed". self.BaseClass is the base, like with SWEPs, and
BUFF.Abstract = true makes one that can't be applied or picked anywhere (buffs deriving from it
aren't abstract).
| Value | Default | |
|---|---|---|
Name, Icon, Description |
"Buff", icon16/star.png, none |
What the HUD shows (tooltip: Description or GetDescription) |
Debuff |
false | Red edge instead of green |
Hidden |
false | Not on the HUD |
Duration |
10 | Seconds when applied without saying; 0 = until removed |
MaxStacks |
1 | Applying it again adds a stack, up to this |
RemoveOnDeath |
true | |
Speed |
Players: movement speed times this (0 = can't move) | |
NoJump, NoAttack |
Players: true = can't jump / neither attack button does anything | |
Regen |
Refilling times this, per resource: { stamina = 0.5, mana = 2 } |
|
DamageTaken, DamageDealt |
Damage times this |
The effects can also be a function( self, ent, inst ) returning the value (inst.stacks for
stacking ones); several buffs multiply. Functions: OnApply( ent, inst ), OnStack( ent, inst ),
OnRemove( ent, inst, reason ) (expired / removed / death / gone), Think( ent, inst ),
EntityTakeDamage( ent, dmg, inst ) (server); SetupMove( ply, mv, cmd, inst ),
GetDescription( ent, inst ) (both). inst.data is a table for the buff's own use.
Built in: Slowed (-20% speed per stack, up to 3, 5 s) and Frozen (can't move, jump or
attack for 3 s; NPCs stop and turn blue). Buffs show on the HUD with the others (see Buffs and
debuffs); death clears them unless RemoveOnDeath = false.
Also: GAMEMODE:RegisterBuff( id, table ) registers one from code (both sides),
GAMEMODE:BuffList() is every appliable one, and the server hooks RPGXBuffAdded( ent, id, inst )
and RPGXBuffRemoved( ent, id, inst, reason ). To try one out: rpgx_buff <id> [seconds] [stacks]
puts it on the player or NPC you look at (else yourself), rpgx_buff clear removes them all
(permission buff_debug).