completed fix
--- a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/actor/Creature.java
+++ b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/gameserver/model/actor/Creature.java
@@ -671,7 +671,7 @@ public abstract class Creature extends WorldObject
final WorldObject target = ((intention == Intention.ATTACK) || (intention == Intention.FOLLOW)) ? _target : null;
if (target != null)
{
- if (target != this)
+ if ((target != this) && !isOnGeodataPath(move))
{
broadcastPacket(new MoveToPawn(this, target, getAI().getClientMovingToPawnOffset()));
}
@@ -1943,18 +1943,24 @@ public abstract class Creature extends WorldObject
// Get the Base Casting Time of the Skills.
int skillTime = (skill.getHitTime() + skill.getCoolTime());
+ int animationTime = skill.getHitTime(); // Use only hitTime for animation
+ int hitTime = skill.getHitTime(); // Calculate hitTime separately for damage timing
if (!skill.isChanneling() || (skill.getChannelingSkillId() == 0))
{
// Calculate the Casting Time of the "Non-Static" Skills (with caster PAtk/MAtkSpd).
if (!skill.isStatic())
{
skillTime = Formulas.calcAtkSpd(this, skill, skillTime);
+ animationTime = Formulas.calcAtkSpd(this, skill, animationTime);
+ hitTime = Formulas.calcAtkSpd(this, skill, hitTime);
}
// Calculate the Casting Time of Magic Skills (reduced in 40% if using SPS/BSPS)
if (skill.isMagic() && (isChargedShot(ShotType.SPIRITSHOTS) || isChargedShot(ShotType.BLESSED_SPIRITSHOTS)))
{
skillTime = (int) (0.6 * skillTime);
+ animationTime = (int) (0.6 * animationTime);
+ hitTime = (int) (0.6 * hitTime);
}
}
@@ -1970,6 +1976,9 @@ public abstract class Creature extends WorldObject
skillTime = 500;
}
+ // Calculate coolTime after all adjustments
+ int coolTime = skillTime - hitTime;
+
// queue herbs and potions
if (_isCastingSimultaneouslyNow && simultaneously)
{
@@ -2100,7 +2109,7 @@ public abstract class Creature extends WorldObject
{
// Send a Server->Client packet MagicSkillUser with target, displayId, level, skillTime, reuseDelay
// to the Creature AND to all Player in the _KnownPlayers of the Creature
- broadcastSkillPacket(new MagicSkillUse(this, target, skill.getDisplayId(), skill.getDisplayLevel(), skillTime, reuseDelay), target);
+ broadcastSkillPacket(new MagicSkillUse(this, target, skill.getDisplayId(), skill.getDisplayLevel(), animationTime, reuseDelay), target);
broadcastSkillPacket(new MagicSkillLaunched(this, skill.getDisplayId(), skill.getDisplayLevel(), targets), targets);
}
@@ -2140,6 +2149,7 @@ public abstract class Creature extends WorldObject
}
final MagicUseTask mut = new MagicUseTask(this, targets, skill, skillTime, simultaneously);
+ mut.setCoolTime(coolTime);
// launch the magic in skillTime milliseconds
if (skillTime > 0)
@@ -2164,9 +2174,9 @@ public abstract class Creature extends WorldObject
_skillCast2 = null;
}
- // Create a task MagicUseTask to launch the MagicSkill at the end of the casting time (skillTime)
+ // Create a task MagicUseTask to launch the MagicSkill at hitTime (for damage) instead of skillTime
// For client animation reasons (party buffs especially) 400 ms before!
- _skillCast2 = ThreadPool.schedule(mut, Math.max(0, skillTime - 400));
+ _skillCast2 = ThreadPool.schedule(mut, Math.max(0, hitTime - 400));
}
else
{
@@ -2177,9 +2187,9 @@ public abstract class Creature extends WorldObject
_skillCast = null;
}
- // Create a task MagicUseTask to launch the MagicSkill at the end of the casting time (skillTime)
+ // Create a task MagicUseTask to launch the MagicSkill at hitTime (for damage) instead of skillTime
// For client animation reasons (party buffs especially) 400 ms before!
- _skillCast = ThreadPool.schedule(mut, Math.max(0, skillTime - 400));
+ _skillCast = ThreadPool.schedule(mut, Math.max(0, hitTime - 400));
}
}
else
@@ -6061,13 +6071,34 @@ public abstract class Creature extends WorldObject
LOGGER.log(Level.WARNING, "", e);
}
+ // Clear casting state immediately after damage if creature is dead
+ // This allows death processing to proceed normally
+ if (isAlikeDead())
+ {
+ if (!mut.isSimultaneous())
+ {
+ _skillCast = null;
+ _castInterruptTime = 0;
+ setCastingNow(false);
+ }
+ else
+ {
+ _skillCast2 = null;
+ setCastingSimultaneouslyNow(false);
+ }
+ // Don't schedule finalizer if dead, death processing will handle cleanup
+ return;
+ }
+
if (mut.getSkillTime() > 0)
{
mut.setCount(mut.getCount() + 1);
}
mut.setPhase(3);
- if (mut.getSkillTime() == 0)
+ // Schedule finalizer at the end of skillTime (after coolTime from hitTime)
+ int finalizerDelay = mut.getCoolTime();
+ if (finalizerDelay <= 0)
{
onMagicFinalizer(mut);
}
@@ -6075,11 +6106,11 @@ public abstract class Creature extends WorldObject
{
if (mut.isSimultaneous())
{
- _skillCast2 = ThreadPool.schedule(mut, 0);
+ _skillCast2 = ThreadPool.schedule(mut, finalizerDelay);
}
else
{
- _skillCast = ThreadPool.schedule(mut, 0);
+ _skillCast = ThreadPool.schedule(mut, finalizerDelay);
}
}
}
@@ -6094,7 +6125,7 @@ public abstract class Creature extends WorldObject
return;
}
- // Cleanup
+ // Cleanup - ensure casting state is cleared even if creature is dead
_skillCast = null;
_castInterruptTime = 0;