[0.8.9][NK] Buff system

johnycilohoklajohnycilohokla REGISTERED Posts: 283 Developer
edited December 2015 in Modding Tutorials
There are 3 types of buffs:
  • Timed
    • Buff will be applied for a specific amount of time
  • Reference counted
    • Buff will be applied until reference counter reaches 0
  • Constant
    • Buff will be applied until it is removed

Buffs can be used to:
  • Apply damage over time
  • Apply effect over time
  • Apply stat modifier
  • Create custom tick based effects on target

When a buff is applied it will tick until it is removed from the target.

Creating buff (instance)

local buffArgs = {}
local buffInstance = EternusEngine.BuffManager:CreateBuff(buffClass, buffArgs)
if (buffInstance == nil) then
NKWarn("Failed to create buff of class: " .. buffClass)
return
end

Applying buff

Once a buff instance is created it can be applied to a valid target (Buffable). Each instance of a buff should only be applied to one target.

Applying buff to an object:
obj:ApplyBuff(buffInstance)

Valid targets

Valid targets must mixin Buffable ("Scripts/Buffs/Buffable.lua").

List of valid targets:
  • Players (BasePlayer)
  • Characters (AICharacter)
    • Goat
    • Cat
    • BearRam
    • ...

Applying Buffable mixin to a class:
function MyClass:Constructor( args )
self:Mixin(Buffable, args)
end

Defining new buffs

All of the buff files have to be in "[MOD]/Scripts/Buffs/".
The name of the buff has to be the same as the name of the lua file.
("[MOD]/Scripts/Buffs/"..name..".lua")

Example buff:
include("Scripts/Buffs/Buff.lua")

-------------------------------------------------------------------------------
if ExampleBuff == nil then
ExampleBuff = Buff.Subclass("ExampleBuff")
EternusEngine.BuffManager:RegisterBuff("ExampleBuff", ExampleBuff)
end

ExampleBuff.Name = "ExampleBuff"

return ExampleBuff

Harmful buffs

Defining if a buff is harmful or not, is very important, it is used in Creative to prevent harmful buffs from being applied to the player.

There are 2 ways to define a harmful buff.

If the buff if always harmful, you can set a static variable Harmful on the class:
ExampleBuff.Harmful = true
If the buff can harmful, you can use the IsHarmful function:
function ExampleBuff:IsHarmful()
-- if the action is "Multiply" and the value is below 1, the buff is harmful
if self.m_modAction == StatModifier.EStatModAction.eMultiply and self.m_modValue < 1 then
return true
end
-- if the action is "Add" and the value is below 0, the buff is harmful
if self.m_modAction == StatModifier.EStatModAction.eAdd and self.m_modValue < 0 then
return true
end
return ExampleBuff.__super.IsHarmful(self)
end

Events

When a buff is applied the OnStart function will be called.
Defining OnStart:
function ExampleBuff:OnStart()
ExampleBuff.__super.OnStart(self)
-- ...
end


When matching buff is applied the Reapply function will be called, by default it will reset the timer on the buff.
Defining Reapply:
function ExampleBuff:Reapply()
ExampleBuff.__super.Reapply(self)
-- ...
end


Before a buff is stopped the TryRemove function will be called, returning false will prevent the buff from being removed.
Defining TryRemove:
function ExampleBuff:TryRemove()
-- ...
return ExampleBuff.__super.TryRemove(self)
end


When a buff is stopped the OnStop function will be called.
Defining OnStop:
function ExampleBuff:OnStop()
ExampleBuff.__super.OnStop(self)
-- ...
end


Ticking buffs will need to define an Update function, this function will be called when the target ticks(usually 60 ticks per second).
Defining Update:
-- dt = delta time [time since last update in seconds]
-- ex. 0.0167 (when tick per second is 60)
function ExampleBuff:Update( dt, finished )
-- tick the timer
ExampleBuff.__super.Update(self, dt, finished)

-- end the buff when target dies (server side only)
if (Eternus.IsServer and self.m_object:IsDead()) then
finished.val = true
end
end

StatModifier

When defining a buff that modifies stats you should use StatModifier mixin, it will handle all of the logic.

Defining default values:
ExampleBuff.StatToModify = "SpeedMultiplier"
ExampleBuff.DefaultModification = 1.0
ExampleBuff.DefaultModificationAction = StatModifier.EStatModAction.eMultiply
Mixin StatModifier needs to be mixed-in in the Constructor:
function ExampleBuff:Constructor( args )
-- Mixin StatModifier
if (args.value ~= nil and Eternus.IsServer) then
-- Mix in StatModifier and pass args along.
self:Mixin(StatModifier, args)
-- Initialize the StatModifier
self:InitModifier(args)
end
-- ...
end
My Blog
jc.png
  yt.png  t.png  
Sign In or Register to comment.