Lets you write skill logic in scripts without touching core. All custom logic goes into separate classes in scripts/handler/skills/
Where to put handlers:
scripts/handler/skills/MyHandler.java
Three effect types:
i_call_handler - onStart only. One-shot effects.
p_call_handler - onStart + onExit. Buffs with cleanup logic.
t_call_handler - onStart + onExit + onActionTime. Periodic effects.
Connecting in skill XML
One-shot effect:
Persistent buff:
Periodic tick every 3 seconds, 10 times:
The value of def name="handler" must match the handler class name exactly.
Basic handler template:
Override only the methods you need. All methods have no-op defaults.
Example 1 - one-shot effect
XML:
Handler:
Example 2 - persistent buff
XML:
Handler:
Example 3 - periodic tick
XML:
Handler:
Example 4 - blocking application
What is available inside a handler:
effect.getEffected() - effect target (Creature)
effect.getEffector() - caster (Creature)
effect.getSkill() - skill object
effect.getSkill().getId() - skill ID
effect.getSkill().getLevel() - skill level
effect.calc() - the val value from the effect XML
effect.getTimeLeft() - remaining duration in seconds
Where to put handlers:
scripts/handler/skills/MyHandler.java
Three effect types:
i_call_handler - onStart only. One-shot effects.
p_call_handler - onStart + onExit. Buffs with cleanup logic.
t_call_handler - onStart + onExit + onActionTime. Periodic effects.
Connecting in skill XML
One-shot effect:
Code:
<effect name="i_call_handler" time="0" val="0">
<def name="handler" val="MyHandler"/>
</effect>
Persistent buff:
Code:
<effect name="p_call_handler" time="60" val="0">
<def name="handler" val="MyHandler"/>
</effect>
Periodic tick every 3 seconds, 10 times:
Code:
<effect name="t_call_handler" time="3" count="10" val="0">
<def name="handler" val="MyHandler"/>
</effect>
The value of def name="handler" must match the handler class name exactly.
Basic handler template:
Code:
public class MyHandler extends AbstractSkillEffect
{
@Override
public void onStart(Effect effect)
{
Creature effected = effect.getEffected();
Creature effector = effect.getEffector();
// your logic
}
}
Override only the methods you need. All methods have no-op defaults.
Example 1 - one-shot effect
XML:
Code:
<effect name="i_call_handler" time="0" val="0">
<def name="handler" val="SummonCubic"/>
</effect>
Handler:
Code:
public class SummonCubic extends AbstractSkillEffect
{
@Override
public void onStart(Effect effect)
{
Creature effected = effect.getEffected();
if (effected == null || effected.isDead())
return;
// logic
}
}
Example 2 - persistent buff
XML:
Code:
<effect name="p_call_handler" time="60" val="0">
<def name="handler" val="MyBuff"/>
</effect>
Handler:
Code:
public class MyBuff extends AbstractSkillEffect
{
@Override
public void onStart(Effect effect)
{
if (!effect.getEffected().isPlayer())
return;
// logic on application
}
@Override
public void onExit(Effect effect)
{
if (!effect.getEffected().isPlayer())
return;
// cleanup on removal
}
}
Example 3 - periodic tick
XML:
Code:
<effect name="t_call_handler" time="3" count="10" val="0">
<def name="handler" val="MyDoT"/>
</effect>
Handler:
Code:
public class MyDoT extends AbstractSkillEffect
{
@Override
public boolean onActionTime(Effect effect)
{
if (effect.getEffected().isDead())
return false; // false = cancel early
// periodic logic
return true; // true = keep ticking
}
@Override
public void onExit(Effect effect)
{
// called once on removal
}
}
Example 4 - blocking application
Code:
@Override
public boolean checkCondition(Effect effect)
{
if (!effect.getEffected().isPlayer())
return false;
if (effect.getEffected().isDead())
return false;
return true;
}
What is available inside a handler:
effect.getEffected() - effect target (Creature)
effect.getEffector() - caster (Creature)
effect.getSkill() - skill object
effect.getSkill().getId() - skill ID
effect.getSkill().getLevel() - skill level
effect.calc() - the val value from the effect XML
effect.getTimeLeft() - remaining duration in seconds