Use listeners for abstract conditional hp effect.

This commit is contained in:
MobiusDev 2018-11-25 22:07:51 +00:00
parent b702b56954
commit 16ac14976f
40 changed files with 660 additions and 330 deletions

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6290,6 +6290,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6290,6 +6290,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6290,6 +6290,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6318,6 +6318,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6318,6 +6318,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6318,6 +6318,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6478,6 +6478,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6478,6 +6478,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6995,6 +6995,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())

View File

@ -16,27 +16,85 @@
*/ */
package handlers.effecthandlers; package handlers.effecthandlers;
import java.util.concurrent.atomic.AtomicBoolean;
import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenersContainer;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
/** /**
* @author UnAfraid * @author Mobius
*/ */
abstract class AbstractConditionalHpEffect extends AbstractStatEffect abstract class AbstractConditionalHpEffect extends AbstractStatEffect
{ {
private final int _hpPercent; private final int _hpPercent;
private final AtomicBoolean _actived = new AtomicBoolean();
private final AtomicBoolean _updated = new AtomicBoolean();
protected AbstractConditionalHpEffect(StatsSet params, Stats stat) protected AbstractConditionalHpEffect(StatsSet params, Stats stat)
{ {
super(params, stat); super(params, stat);
_hpPercent = params.getInt("hpPercent", -1); _hpPercent = params.getInt("hpPercent", 0);
}
@Override
public void onStart(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
// Register listeners
if ((_hpPercent > 0) && !_actived.get())
{
_actived.set(true);
_updated.set(canPump(effector, effected, skill));
final ListenersContainer container = effected;
container.addListener(new ConsumerEventListener(container, EventType.ON_CREATURE_HP_CHANGE, (OnCreatureHpChange event) -> onHpChange(event), this));
}
}
@Override
public void onExit(L2Character effector, L2Character effected, Skill skill)
{
// Augmentation option
if (skill == null)
{
return;
}
effected.removeListenerIf(listener -> listener.getOwner() == this);
_actived.set(false);
} }
@Override @Override
public boolean canPump(L2Character effector, L2Character effected, Skill skill) public boolean canPump(L2Character effector, L2Character effected, Skill skill)
{ {
return ((_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent)); return (_hpPercent <= 0) || (effected.getCurrentHpPercent() <= _hpPercent);
}
private void onHpChange(OnCreatureHpChange event)
{
final L2Character activeChar = event.getCreature();
if (canPump(null, activeChar, null))
{
if (_updated.get())
{
_updated.set(false);
activeChar.getStat().recalculateStats(true);
}
}
else if (!_updated.get())
{
_updated.set(true);
activeChar.getStat().recalculateStats(true);
}
} }
} }

View File

@ -6970,6 +6970,7 @@
<value level="14">129.3</value> <value level="14">129.3</value>
</amount> </amount>
<mode>DIFF</mode> <mode>DIFF</mode>
<hpPercent>30</hpPercent>
</effect> </effect>
</effects> </effects>
</skill> </skill>

View File

@ -19,7 +19,6 @@ package com.l2jmobius.gameserver.model.actor.status;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.l2jmobius.commons.concurrent.ThreadPool; import com.l2jmobius.commons.concurrent.ThreadPool;
@ -51,8 +50,6 @@ public class CharStatus
private static final byte REGEN_FLAG_HP = 1; private static final byte REGEN_FLAG_HP = 1;
private static final byte REGEN_FLAG_MP = 2; private static final byte REGEN_FLAG_MP = 2;
private final AtomicInteger _previousHpPercent = new AtomicInteger();
public CharStatus(L2Character activeChar) public CharStatus(L2Character activeChar)
{ {
_activeChar = activeChar; _activeChar = activeChar;
@ -175,10 +172,7 @@ public class CharStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = _currentHp; setCurrentHp(Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0));
final double newHp = Math.max(_currentHp - value, activeChar.isUndying() ? 1 : 0);
setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(activeChar, oldHp, newHp), activeChar);
} }
if ((activeChar.getCurrentHp() < 0.5)) // Die if ((activeChar.getCurrentHp() < 0.5)) // Die
@ -247,7 +241,6 @@ public class CharStatus
// place holder, only PcStatus has CP // place holder, only PcStatus has CP
public void setCurrentCp(double newCp, boolean broadcastPacket) public void setCurrentCp(double newCp, boolean broadcastPacket)
{ {
} }
public final double getCurrentHp() public final double getCurrentHp()
@ -269,7 +262,7 @@ public class CharStatus
public boolean setCurrentHp(double newHp, boolean broadcastPacket) public boolean setCurrentHp(double newHp, boolean broadcastPacket)
{ {
// Get the Max HP of the L2Character // Get the Max HP of the L2Character
final int currentHp = (int) _currentHp; final int oldHp = (int) _currentHp;
final double maxHp = _activeChar.getStat().getMaxHp(); final double maxHp = _activeChar.getStat().getMaxHp();
synchronized (this) synchronized (this)
@ -302,30 +295,16 @@ public class CharStatus
} }
} }
final boolean hpWasChanged = currentHp != _currentHp; final boolean hpWasChanged = oldHp != _currentHp;
// Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform // Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform
if (hpWasChanged) if (hpWasChanged)
{ {
final int lastHpPercent = _previousHpPercent.get();
final int currentHpPercent = (int) ((_currentHp * 100) / maxHp);
//@formatter:off
if (((lastHpPercent >= 60) && (currentHpPercent <= 60))
|| ((currentHpPercent >= 60) && (lastHpPercent <= 60))
|| ((lastHpPercent >= 30) && (currentHpPercent <= 30))
|| ((currentHpPercent >= 30) && (lastHpPercent <= 30)))
//@formatter:on
{
if (_previousHpPercent.compareAndSet(lastHpPercent, currentHpPercent))
{
_activeChar.getStat().recalculateStats(broadcastPacket);
}
}
if (broadcastPacket) if (broadcastPacket)
{ {
_activeChar.broadcastStatusUpdate(); _activeChar.broadcastStatusUpdate();
} }
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, _currentHp), getActiveChar());
} }
return hpWasChanged; return hpWasChanged;

View File

@ -26,8 +26,6 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat; import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.effects.EffectFlag; import com.l2jmobius.gameserver.model.effects.EffectFlag;
import com.l2jmobius.gameserver.model.entity.Duel; import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.OnCreatureHpChange;
import com.l2jmobius.gameserver.model.skills.AbnormalType; import com.l2jmobius.gameserver.model.skills.AbnormalType;
import com.l2jmobius.gameserver.model.stats.Formulas; import com.l2jmobius.gameserver.model.stats.Formulas;
import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.stats.Stats;
@ -272,7 +270,6 @@ public class PcStatus extends PlayableStatus
if (value > 0) if (value > 0)
{ {
final double oldHp = getCurrentHp();
double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0); double newHp = Math.max(getCurrentHp() - value, getActiveChar().isUndying() ? 1 : 0);
if (newHp <= 0) if (newHp <= 0)
{ {
@ -295,8 +292,6 @@ public class PcStatus extends PlayableStatus
} }
} }
setCurrentHp(newHp); setCurrentHp(newHp);
EventDispatcher.getInstance().notifyEventAsync(new OnCreatureHpChange(getActiveChar(), oldHp, newHp), getActiveChar());
} }
if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying()) if ((getActiveChar().getCurrentHp() < 0.5) && !isHPConsumption && !getActiveChar().isUndying())