- Хроники
- Salvation
- Исходники
- Присутствуют
- Сборка
- мобиус
Не могу понять что не так. Почему-то не срабатывает.
Проверяю на шилке 788, 5564.
Полностью исправно работает, если перса будет бить другой перс, но не работает, если тебя бьет пачка мобов, не важно какого лвла.
Шанс выкручен в сотку для дебага.
Проверяю на шилке 788, 5564.
Полностью исправно работает, если перса будет бить другой перс, но не работает, если тебя бьет пачка мобов, не важно какого лвла.
Шанс выкручен в сотку для дебага.
Код:
[27/09 10:07:30] 🎯 TRIGGER SKILL BY DAMAGE RECEIVED - EVENT CAUGHT
[27/09 10:07:30] 🎯 Effect Skill ID: 5564
[27/09 10:07:30] 🎯 MinDamage: 1, Chance: 100
[27/09 10:07:30] 🎯 AttackerType: Creature
[27/09 10:07:30] 🎯 Actual Damage: 8.0
[27/09 10:07:30] ✅ ALL CHECKS PASSED for skill 5564
[27/09 10:07:30] ✅ Target acquired: Player:ШК[268492931]
[27/09 10:07:30] ✅ BuffInfo for skill 5564: null
[27/09 10:07:30] ✅ Using base skill level: 1
XML:
<skill id="788" toLevel="1" name="Pain of Shilen">
<icon>icon.skill0788</icon>
<operateType>A2</operateType>
<targetType>SELF</targetType>
<abnormalLevel>1</abnormalLevel>
<abnormalTime>60</abnormalTime>
<abnormalType>SEED_OF_KNIGHT</abnormalType>
<affectScope>SINGLE</affectScope>
<basicProperty>NONE</basicProperty>
<effectPoint>138</effectPoint>
<hitTime>2500</hitTime>
<isMagic>1</isMagic> <!-- Magic Skill -->
<magicCriticalRate>5</magicCriticalRate>
<magicLevel>83</magicLevel>
<mpConsume>29</mpConsume>
<mpInitialConsume>8</mpInitialConsume>
<reuseDelay>15000</reuseDelay>
<effects>
<effect name="TriggerSkillByDamageReceived">
<!-- Pain of Shillien -->
<attackerType>Creature</attackerType>
<chance>100</chance>
<targetType>SELF</targetType>
<minDamage>1</minDamage>
<skillId>5564</skillId> <!-- Pain of Shilen -->
<skillLevel>1</skillLevel>
</effect>
<effect name="CriticalDamage">
<amount>10</amount>
<mode>PER</mode>
</effect>
</effects>
</skill>
<skill id="5564" toLevel="3" name="Pain of Shilen">
<icon>
<value level="1">icon.skill0788</value>
<value level="2">icon.skill0788_2</value>
<value level="3">icon.skill0788_3</value>
</icon>
<operateType>A2</operateType>
<targetType>TARGET</targetType>
<abnormalLevel>
<value level="1">2</value>
<value level="2">3</value>
<value level="3">4</value>
</abnormalLevel>
<abnormalTime>20</abnormalTime>
<abnormalType>SEED_OF_KNIGHT</abnormalType>
<affectScope>SINGLE</affectScope>
<basicProperty>NONE</basicProperty>
<castRange>400</castRange>
<effectRange>900</effectRange>
<isMagic>4</isMagic> <!-- Item Skill -->
<isTriggeredSkill>true</isTriggeredSkill>
<magicCriticalRate>-5</magicCriticalRate>
<magicLevel>81</magicLevel>
<effects>
<effect name="TriggerSkillByDamageReceived">
<!-- Pain of Shillien -->
<attackerType>Creature</attackerType>
<chance>
<value level="1">10</value>
<value level="2">10</value>
<value level="3">0</value>
</chance>
<targetType>SELF</targetType>
<minDamage>1</minDamage>
<skillId>5564</skillId> <!-- Pain of Shilen -->
<skillLevel>
<value level="1">2</value>
<value level="2">3</value>
<value level="3">0</value>
</skillLevel>
</effect>
<effect name="VampiricAttack" fromLevel="3" toLevel="3">
<amount>8</amount>
<chance>30</chance>
</effect>
<effect name="CriticalDamage">
<amount>20</amount>
<mode>PER</mode>
</effect>
<effect name="AttackAttribute">
<amount>
<value level="1">0</value>
<value level="2">20</value>
<value level="3">20</value>
</amount>
<attribute>WIND</attribute>
</effect>
</effects>
</skill>
Java:
package handlers.effecthandlers;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import l2j.commons.util.Rnd;
import l2j.gameserver.data.xml.SkillData;
import l2j.gameserver.handler.TargetHandler;
import l2j.gameserver.model.StatSet;
import l2j.gameserver.model.WorldObject;
import l2j.gameserver.model.actor.Creature;
import l2j.gameserver.model.actor.enums.creature.InstanceType;
import l2j.gameserver.model.effects.AbstractEffect;
import l2j.gameserver.model.events.EventType;
import l2j.gameserver.model.events.holders.actor.creature.OnCreatureDamageReceived;
import l2j.gameserver.model.events.listeners.ConsumerEventListener;
import l2j.gameserver.model.item.instance.Item;
import l2j.gameserver.model.skill.BuffInfo;
import l2j.gameserver.model.skill.Skill;
import l2j.gameserver.model.skill.SkillCaster;
import l2j.gameserver.model.skill.enums.SkillFinishType;
import l2j.gameserver.model.skill.holders.SkillHolder;
import l2j.gameserver.model.skill.targets.TargetType;
/**
* Trigger skill by damage received effect implementation.
* @author UnAfraid
*/
public class TriggerSkillByDamageReceived extends AbstractEffect
{
private final int _minAttackerLevel;
private final int _maxAttackerLevel;
private final int _minDamage;
private final int _chance;
private final int _hpPercent;
private final SkillHolder _skill;
private final TargetType _targetType;
private final InstanceType _attackerType;
private final int _skillLevelScaleTo;
private final List<SkillHolder> _triggerSkills;
public TriggerSkillByDamageReceived(StatSet params)
{
_minAttackerLevel = params.getInt("minAttackerLevel", 1);
_maxAttackerLevel = params.getInt("maxAttackerLevel", Integer.MAX_VALUE);
_minDamage = params.getInt("minDamage", 1);
_chance = params.getInt("chance", 100);
_hpPercent = params.getInt("hpPercent", 100);
_skill = new SkillHolder(params.getInt("skillId", 0), params.getInt("skillLevel", 1));
_targetType = params.getEnum("targetType", TargetType.class, TargetType.SELF);
_attackerType = params.getEnum("attackerType", InstanceType.class, InstanceType.Creature);
_skillLevelScaleTo = params.getInt("skillLevelScaleTo", 0);
// Specific skills by level.
final String triggerSkills = params.getString("triggerSkills", "");
if (triggerSkills.isEmpty())
{
_triggerSkills = null;
}
else
{
final String[] split = triggerSkills.split(";");
_triggerSkills = new ArrayList<>(split.length);
for (String skill : split)
{
final String[] splitSkill = skill.split(",");
_triggerSkills.add(new SkillHolder(Integer.parseInt(splitSkill[0]), Integer.parseInt(splitSkill[1])));
}
}
}
private void onDamageReceivedEvent(OnCreatureDamageReceived event)
{
LOGGER.info("🎯 TRIGGER SKILL BY DAMAGE RECEIVED - EVENT CAUGHT");
LOGGER.info("🎯 Effect Skill ID: " + _skill.getSkillId());
LOGGER.info("🎯 MinDamage: " + _minDamage + ", Chance: " + _chance);
LOGGER.info("🎯 AttackerType: " + _attackerType);
LOGGER.info("🎯 Actual Damage: " + event.getDamage());
if (event.isDamageOverTime() || (_chance == 0) || ((_triggerSkills == null) && ((_skill.getSkillId() == 0) || (_skill.getSkillLevel() == 0))))
{
LOGGER.info("❌ FAIL: DOT or invalid chance/skill");
return;
}
if (event.getAttacker() == event.getTarget())
{
LOGGER.info("❌ FAIL: self damage");
return;
}
if ((event.getAttacker().getLevel() < _minAttackerLevel) || (event.getAttacker().getLevel() > _maxAttackerLevel))
{
LOGGER.info("❌ FAIL: attacker level mismatch");
return;
}
if (_minDamage > 0 && event.getDamage() < _minDamage)
{
LOGGER.info("❌ FAIL: Damage too low - " + event.getDamage() + " < " + _minDamage);
return;
}
if ((_chance < 100) && (Rnd.get(100) > _chance))
{
return;
}
if ((_hpPercent < 100) && (event.getTarget().getCurrentHpPercent() > _hpPercent))
{
return;
}
if (!event.getAttacker().getInstanceType().isType(_attackerType))
{
return;
}
LOGGER.info("✅ ALL CHECKS PASSED for skill " + _skill.getSkillId());
WorldObject target = null;
try
{
target = TargetHandler.getInstance().getHandler(_targetType).getTarget(event.getTarget(), event.getAttacker(), _triggerSkills == null ? _skill.getSkill() : _triggerSkills.get(0).getSkill(), false, false, false);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Exception in ITargetTypeHandler.getTarget(): " + e.getMessage(), e);
}
if ((target == null) || !target.isCreature())
{
LOGGER.info("❌ FAIL: target is null or not creature");
return;
}
Skill triggerSkill = null;
if (_triggerSkills == null)
{
final BuffInfo buffInfo = target.asCreature().getEffectList().getBuffInfoBySkillId(_skill.getSkillId());
if ((_skillLevelScaleTo <= 0) || (buffInfo == null))
{
triggerSkill = _skill.getSkill();
}
else
{
triggerSkill = SkillData.getInstance().getSkill(_skill.getSkillId(), Math.min(_skillLevelScaleTo, buffInfo.getSkill().getLevel() + 1));
}
if ((buffInfo == null) || (buffInfo.getSkill().getLevel() < triggerSkill.getLevel()))
{
SkillCaster.triggerCast(event.getAttacker(), target.asCreature(), triggerSkill);
}
}
else // Multiple trigger skills.
{
final Iterator<SkillHolder> iterator = _triggerSkills.iterator();
while (iterator.hasNext())
{
final Skill nextSkill = iterator.next().getSkill();
if (target.asCreature().isAffectedBySkill(nextSkill.getId()))
{
if (iterator.hasNext())
{
target.asCreature().stopSkillEffects(SkillFinishType.SILENT, nextSkill.getId());
triggerSkill = iterator.next().getSkill();
break;
}
// Already at last skill.
return;
}
}
if (triggerSkill == null)
{
triggerSkill = _triggerSkills.get(0).getSkill();
}
SkillCaster.triggerCast(event.getAttacker(), target.asCreature(), triggerSkill);
}
}
@Override
public void onExit(Creature effector, Creature effected, Skill skill)
{
effected.removeListenerIf(EventType.ON_CREATURE_DAMAGE_RECEIVED, listener -> listener.getOwner() == this);
}
@Override
public void onStart(Creature effector, Creature effected, Skill skill, Item item)
{
effected.addListener(new ConsumerEventListener(effected, EventType.ON_CREATURE_DAMAGE_RECEIVED, (OnCreatureDamageReceived event) -> onDamageReceivedEvent(event), this));
}
}