L2Character attack rework.
Adapted from: L2jUnity free files.
This commit is contained in:
@@ -78,7 +78,7 @@ public class DoppelgangerAI extends L2CharacterAI
|
||||
return;
|
||||
}
|
||||
clientStopMoving(null);
|
||||
_actor.doAttack(attackTarget);
|
||||
_actor.doAutoAttack(attackTarget);
|
||||
}
|
||||
|
||||
private void thinkCast()
|
||||
|
@@ -218,7 +218,7 @@ public class FriendlyNpcAI extends L2AttackableAI
|
||||
return;
|
||||
}
|
||||
|
||||
_actor.doAttack(originalAttackTarget);
|
||||
_actor.doAutoAttack(originalAttackTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -994,7 +994,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
||||
}
|
||||
|
||||
// Attacks target
|
||||
_actor.doAttack(target);
|
||||
_actor.doAutoAttack(target);
|
||||
}
|
||||
|
||||
private boolean checkSkillTarget(Skill skill, L2Object target)
|
||||
|
@@ -223,7 +223,7 @@ public final class L2ControllableMobAI extends L2AttackableAI
|
||||
|
||||
return;
|
||||
}
|
||||
_actor.doAttack(target);
|
||||
_actor.doAutoAttack(target);
|
||||
}
|
||||
|
||||
protected void thinkForceAttack()
|
||||
@@ -264,7 +264,7 @@ public final class L2ControllableMobAI extends L2AttackableAI
|
||||
return;
|
||||
}
|
||||
|
||||
_actor.doAttack(getForcedTarget());
|
||||
_actor.doAutoAttack(getForcedTarget());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -364,7 +364,7 @@ public final class L2ControllableMobAI extends L2AttackableAI
|
||||
}
|
||||
}
|
||||
|
||||
_actor.doAttack(target);
|
||||
_actor.doAutoAttack(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -262,7 +262,7 @@ public class L2PlayerAI extends L2PlayableAI
|
||||
return;
|
||||
}
|
||||
|
||||
_actor.doAttack((L2Character) target);
|
||||
_actor.doAutoAttack((L2Character) target);
|
||||
}
|
||||
|
||||
private void thinkCast()
|
||||
|
@@ -107,7 +107,7 @@ public class L2SummonAI extends L2PlayableAI implements Runnable
|
||||
return;
|
||||
}
|
||||
clientStopMoving(null);
|
||||
_actor.doAttack(attackTarget);
|
||||
_actor.doAutoAttack(attackTarget);
|
||||
}
|
||||
|
||||
private void thinkCast()
|
||||
@@ -276,7 +276,7 @@ public class L2SummonAI extends L2PlayableAI implements Runnable
|
||||
final L2Summon summon = getActor();
|
||||
if ((summon.getOwner() != null) && (summon.getOwner() != attacker) && !summon.isMoving() && summon.canAttack(attacker, false) && summon.getOwner().isInsideRadius(_actor, 2 * AVOID_RADIUS, true, false))
|
||||
{
|
||||
summon.doAttack(attacker);
|
||||
summon.doAutoAttack(attacker);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,8 @@
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import com.l2jmobius.gameserver.enums.AttackType;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
|
||||
@@ -24,6 +26,7 @@ import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
*/
|
||||
public class Hit
|
||||
{
|
||||
private final WeakReference<L2Object> _target;
|
||||
private final int _targetId;
|
||||
private final int _damage;
|
||||
private final int _ssGrade;
|
||||
@@ -31,6 +34,7 @@ public class Hit
|
||||
|
||||
public Hit(L2Object target, int damage, boolean miss, boolean crit, byte shld, boolean soulshot, int ssGrade)
|
||||
{
|
||||
_target = new WeakReference<>(target);
|
||||
_targetId = target.getObjectId();
|
||||
_damage = damage;
|
||||
_ssGrade = ssGrade;
|
||||
@@ -62,6 +66,11 @@ public class Hit
|
||||
_flags |= type.getMask();
|
||||
}
|
||||
|
||||
public L2Object getTarget()
|
||||
{
|
||||
return _target.get();
|
||||
}
|
||||
|
||||
public int getTargetId()
|
||||
{
|
||||
return _targetId;
|
||||
@@ -81,4 +90,24 @@ public class Hit
|
||||
{
|
||||
return _ssGrade;
|
||||
}
|
||||
|
||||
public boolean isMiss()
|
||||
{
|
||||
return (AttackType.MISSED.getMask() & _flags) != 0;
|
||||
}
|
||||
|
||||
public boolean isCritical()
|
||||
{
|
||||
return (AttackType.CRITICAL.getMask() & _flags) != 0;
|
||||
}
|
||||
|
||||
public boolean isShotUsed()
|
||||
{
|
||||
return (AttackType.SHOT_USED.getMask() & _flags) != 0;
|
||||
}
|
||||
|
||||
public boolean isBlocked()
|
||||
{
|
||||
return (AttackType.BLOCKED.getMask() & _flags) != 0;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -91,7 +91,7 @@ public final class L2DoorInstance extends L2Character
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAttack(L2Character target)
|
||||
public void doAutoAttack(L2Character target)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -4644,9 +4644,9 @@ public final class L2PcInstance extends L2Playable
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAttack(L2Character target)
|
||||
public void doAutoAttack(L2Character target)
|
||||
{
|
||||
super.doAttack(target);
|
||||
super.doAutoAttack(target);
|
||||
setRecentFakeDeath(false);
|
||||
if (target.isFakePlayer())
|
||||
{
|
||||
|
@@ -195,7 +195,7 @@ public final class L2StaticObjectInstance extends L2Character
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAttack(L2Character target)
|
||||
public void doAutoAttack(L2Character target)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.model.actor.tasks.character;
|
||||
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
|
||||
/**
|
||||
* Task launching the function onHitTimer().<br>
|
||||
* <B><U>Actions</U>:</B>
|
||||
* <ul>
|
||||
* <li>If the attacker/target is dead or use fake death, notify the AI with EVT_CANCEL and send a Server->Client packet ActionFailed (if attacker is a L2PcInstance)</li>
|
||||
* <li>If attack isn't aborted, send a message system (critical hit, missed...) to attacker/target if they are L2PcInstance</li>
|
||||
* <li>If attack isn't aborted and hit isn't missed, reduce HP of the target and calculate reflection damage to reduce HP of attacker if necessary</li>
|
||||
* <li>if attack isn't aborted and hit isn't missed, manage attack or cast break of the target (calculating rate, sending message...)</li>
|
||||
* </ul>
|
||||
* @author xban1x
|
||||
*/
|
||||
public final class HitTask implements Runnable
|
||||
{
|
||||
private final L2Character _character;
|
||||
private final L2Character _hitTarget;
|
||||
private final int _damage;
|
||||
private final boolean _crit;
|
||||
private final boolean _miss;
|
||||
private final byte _shld;
|
||||
private final boolean _soulshot;
|
||||
|
||||
public HitTask(L2Character character, L2Character target, int damage, boolean crit, boolean miss, boolean soulshot, byte shld)
|
||||
{
|
||||
_character = character;
|
||||
_hitTarget = target;
|
||||
_damage = damage;
|
||||
_crit = crit;
|
||||
_shld = shld;
|
||||
_miss = miss;
|
||||
_soulshot = soulshot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (_character != null)
|
||||
{
|
||||
_character.onHitTimer(_hitTarget, _damage, _crit, _miss, _soulshot, _shld);
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,6 +19,7 @@ package com.l2jmobius.gameserver.model.events.impl.character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.events.EventType;
|
||||
import com.l2jmobius.gameserver.model.events.impl.IBaseEvent;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
|
||||
/**
|
||||
* An instantly executed event when L2Character is attacked by L2Character.
|
||||
@@ -28,11 +29,13 @@ public class OnCreatureAttack implements IBaseEvent
|
||||
{
|
||||
private final L2Character _attacker;
|
||||
private final L2Character _target;
|
||||
private final Skill _skill;
|
||||
|
||||
public OnCreatureAttack(L2Character attacker, L2Character target)
|
||||
public OnCreatureAttack(L2Character attacker, L2Character target, Skill skill)
|
||||
{
|
||||
_attacker = attacker;
|
||||
_target = target;
|
||||
_skill = skill;
|
||||
}
|
||||
|
||||
public final L2Character getAttacker()
|
||||
@@ -45,6 +48,11 @@ public class OnCreatureAttack implements IBaseEvent
|
||||
return _target;
|
||||
}
|
||||
|
||||
public final Skill getSkill()
|
||||
{
|
||||
return _skill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventType getType()
|
||||
{
|
||||
|
@@ -37,6 +37,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2StaticObjectInstance;
|
||||
import com.l2jmobius.gameserver.model.cubic.CubicInstance;
|
||||
import com.l2jmobius.gameserver.model.effects.EffectFlag;
|
||||
import com.l2jmobius.gameserver.model.effects.L2EffectType;
|
||||
import com.l2jmobius.gameserver.model.interfaces.ILocational;
|
||||
import com.l2jmobius.gameserver.model.items.L2Armor;
|
||||
import com.l2jmobius.gameserver.model.items.L2Item;
|
||||
import com.l2jmobius.gameserver.model.items.L2Weapon;
|
||||
@@ -271,8 +272,12 @@ public final class Formulas
|
||||
}
|
||||
|
||||
// Autoattack critical rate.
|
||||
// It is capped to 500, but unbound by positional critical rate and level diff bonus.
|
||||
rate *= activeChar.getStat().getPositionTypeValue(Stats.CRITICAL_RATE, Position.getPosition(activeChar, target));
|
||||
// Even though, visible critical rate is capped to 500, you can reach higher than 50% chance with position and level modifiers.
|
||||
// TODO: Find retail-like calculation for criticalRateMod.
|
||||
final double criticalRateMod = (target.getStat().getValue(Stats.DEFENCE_CRITICAL_RATE, rate) + target.getStat().getValue(Stats.DEFENCE_CRITICAL_RATE_ADD, 0)) / 10;
|
||||
final double criticalLocBonus = calcCriticalPositionBonus(activeChar, target);
|
||||
final double criticalHeightBonus = calcCriticalHeightBonus(activeChar, target);
|
||||
rate = criticalLocBonus * criticalRateMod * criticalHeightBonus;
|
||||
|
||||
// In retail, it appears that when you are higher level attacking lower level mobs, your critical rate is much higher.
|
||||
// Level 91 attacking level 1 appear that nearly all hits are critical. Unconfirmed for skills and pvp.
|
||||
@@ -286,6 +291,37 @@ public final class Formulas
|
||||
return finalRate > Rnd.get(1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default (10% for side, 30% for back) positional critical rate bonus and multiplies it by any buffs that give positional critical rate bonus.
|
||||
* @param activeChar the attacker.
|
||||
* @param target the target.
|
||||
* @return a multiplier representing the positional critical rate bonus. Autoattacks for example get this bonus on top of the already capped critical rate of 500.
|
||||
*/
|
||||
public static double calcCriticalPositionBonus(L2Character activeChar, L2Character target)
|
||||
{
|
||||
final Position position = target.isAffected(EffectFlag.ATTACK_BEHIND) ? Position.BACK : Position.getPosition(activeChar, target);
|
||||
switch (position)
|
||||
{
|
||||
case SIDE: // 10% Critical Chance bonus when attacking from side.
|
||||
{
|
||||
return 1.1 * activeChar.getStat().getPositionTypeValue(Stats.CRITICAL_RATE, Position.SIDE);
|
||||
}
|
||||
case BACK: // 30% Critical Chance bonus when attacking from back.
|
||||
{
|
||||
return 1.3 * activeChar.getStat().getPositionTypeValue(Stats.CRITICAL_RATE, Position.BACK);
|
||||
}
|
||||
default: // No Critical Chance bonus when attacking from front.
|
||||
{
|
||||
return activeChar.getStat().getPositionTypeValue(Stats.CRITICAL_RATE, Position.FRONT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static double calcCriticalHeightBonus(ILocational from, ILocational target)
|
||||
{
|
||||
return ((((CommonUtil.constrain(from.getZ() - target.getZ(), -25, 25) * 4) / 5) + 10) / 100) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attacker
|
||||
* @param target
|
||||
@@ -403,16 +439,6 @@ public final class Formulas
|
||||
return Rnd.get(100) < rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attackSpeed the attack speed of the Creature.
|
||||
* @return {@code 500000 / attackSpeed}.
|
||||
*/
|
||||
public static int calculateTimeBetweenAttacks(int attackSpeed)
|
||||
{
|
||||
// Measured Nov 2015 by Nik. Formula: atk.spd/500 = hits per second.
|
||||
return Math.max(50, (500000 / attackSpeed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate delay (in milliseconds) for skills cast
|
||||
* @param attacker
|
||||
@@ -1023,7 +1049,7 @@ public final class Formulas
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static void calcDamageReflected(L2Character attacker, L2Character target, Skill skill, boolean crit)
|
||||
public static void calcCounterAttack(L2Character attacker, L2Character target, Skill skill, boolean crit)
|
||||
{
|
||||
// Only melee skills can be reflected
|
||||
if (skill.isMagic() || (skill.getCastRange() > MELEE_ATTACK_RANGE))
|
||||
@@ -1049,7 +1075,7 @@ public final class Formulas
|
||||
|
||||
double counterdmg = ((target.getPAtk() * 873) / attacker.getPDef()); // Old: (((target.getPAtk(attacker) * 10.0) * 70.0) / attacker.getPDef(target));
|
||||
counterdmg *= calcWeaponTraitBonus(attacker, target);
|
||||
counterdmg *= calcGeneralTraitBonus(attacker, target, skill.getTraitType(), false);
|
||||
counterdmg *= calcGeneralTraitBonus(attacker, target, skill.getTraitType(), true);
|
||||
counterdmg *= calcAttributeBonus(attacker, target, skill);
|
||||
|
||||
attacker.reduceCurrentHp(counterdmg, target, skill);
|
||||
@@ -1086,35 +1112,37 @@ public final class Formulas
|
||||
return cha.getStat().getValue(Stats.FALL, (fallHeight * cha.getMaxHp()) / 1000.0);
|
||||
}
|
||||
|
||||
public static boolean calcBlowSuccess(L2Character activeChar, L2Character target, Skill skill, double blowChance)
|
||||
/**
|
||||
* Basic chance formula:<br>
|
||||
* <ul>
|
||||
* <li>chance = weapon_critical * dex_bonus * crit_height_bonus * crit_pos_bonus * effect_bonus * fatal_blow_rate</li>
|
||||
* <li>weapon_critical = (12 for daggers)</li>
|
||||
* <li>dex_bonus = dex modifier bonus for current dex (Seems unused in GOD, so its not used in formula).</li>
|
||||
* <li>crit_height_bonus = (z_diff * 4 / 5 + 10) / 100 + 1 or alternatively (z_diff * 0.008) + 1.1. Be aware of z_diff constraint of -25 to 25.</li>
|
||||
* <li>crit_pos_bonus = crit_pos(front = 1, side = 1.1, back = 1.3) * p_critical_rate_position_bonus</li>
|
||||
* <li>effect_bonus = (p2 + 100) / 100, p2 - 2nd param of effect. Blow chance of effect.</li>
|
||||
* </ul>
|
||||
* Chance cannot be higher than 80%.
|
||||
* @param activeChar
|
||||
* @param target
|
||||
* @param skill
|
||||
* @param chanceBoost
|
||||
* @return
|
||||
*/
|
||||
public static boolean calcBlowSuccess(L2Character activeChar, L2Character target, Skill skill, double chanceBoost)
|
||||
{
|
||||
final double weaponCritical = 12; // Dagger weapon critical mod is 12... TODO: Make it work for other weapons.
|
||||
final L2Weapon weapon = activeChar.getActiveWeaponItem();
|
||||
final double weaponCritical = weapon != null ? weapon.getStats(Stats.CRITICAL_RATE, activeChar.getTemplate().getBaseCritRate()) : activeChar.getTemplate().getBaseCritRate();
|
||||
// double dexBonus = BaseStats.DEX.calcBonus(activeChar); Not used in GOD
|
||||
final double critHeightBonus = ((((CommonUtil.constrain(activeChar.getZ() - target.getZ(), -25, 25) * 4) / 5) + 10) / 100) + 1;
|
||||
final Position position = Position.getPosition(activeChar, target);
|
||||
final double criticalPosition = position == Position.BACK ? 1.3 : position == Position.SIDE ? 1.1 : 1; // 30% chance from back, 10% chance from side.
|
||||
final double criticalPositionMod = criticalPosition * activeChar.getStat().getPositionTypeValue(Stats.CRITICAL_RATE, position);
|
||||
final double critHeightBonus = calcCriticalHeightBonus(activeChar, target);
|
||||
final double criticalPosition = calcCriticalPositionBonus(activeChar, target); // 30% chance from back, 10% chance from side. Include buffs that give positional crit rate.
|
||||
final double chanceBoostMod = (100 + chanceBoost) / 100;
|
||||
final double blowRateMod = activeChar.getStat().getValue(Stats.BLOW_RATE, 1);
|
||||
blowChance = (weaponCritical + blowChance) * 10;
|
||||
|
||||
final double rate = blowChance * critHeightBonus * criticalPositionMod * blowRateMod;
|
||||
|
||||
// Debug
|
||||
if (activeChar.isDebug())
|
||||
{
|
||||
final StatsSet set = new StatsSet();
|
||||
set.set("weaponCritical", weaponCritical);
|
||||
set.set("critHeightBonus", critHeightBonus);
|
||||
set.set("criticalPosition", criticalPosition);
|
||||
set.set("criticalPositionMod", criticalPositionMod);
|
||||
set.set("blowRate", blowRateMod);
|
||||
set.set("blowChance", blowChance);
|
||||
set.set("rate(max 800 of 1000)", rate);
|
||||
Debug.sendSkillDebug(activeChar, target, skill, set);
|
||||
}
|
||||
final double rate = criticalPosition * critHeightBonus * weaponCritical * chanceBoostMod * blowRateMod;
|
||||
|
||||
// Blow rate is capped at 80%
|
||||
return Rnd.get(1000) < Math.min(rate, 800);
|
||||
return Rnd.get(100) < Math.min(rate, 80);
|
||||
}
|
||||
|
||||
public static List<BuffInfo> calcCancelStealEffects(L2Character activeChar, L2Character target, Skill skill, DispelSlotType slot, int rate, int max)
|
||||
@@ -1224,6 +1252,12 @@ public final class Formulas
|
||||
*/
|
||||
public static boolean calcProbability(double baseChance, L2Character attacker, L2Character target, Skill skill)
|
||||
{
|
||||
// Skills without set probability should only test against trait invulnerability.
|
||||
if (Double.isNaN(baseChance))
|
||||
{
|
||||
return calcGeneralTraitBonus(attacker, target, skill.getTraitType(), true) > 0;
|
||||
}
|
||||
|
||||
// Outdated formula: return Rnd.get(100) < ((((((skill.getMagicLevel() + baseChance) - target.getLevel()) + 30) - target.getINT()) * calcAttributeBonus(attacker, target, skill)) * calcGeneralTraitBonus(attacker, target, skill.getTraitType(), false));
|
||||
// TODO: Find more retail-like formula
|
||||
return Rnd.get(100) < (((((skill.getMagicLevel() + baseChance) - target.getLevel()) - getAbnormalResist(skill.getBasicProperty(), target)) * calcAttributeBonus(attacker, target, skill)) * calcGeneralTraitBonus(attacker, target, skill.getTraitType(), false));
|
||||
@@ -1486,7 +1520,7 @@ public final class Formulas
|
||||
*/
|
||||
public static boolean calcStunBreak(L2Character activeChar)
|
||||
{
|
||||
// Check if target is stunned and 10% chance.
|
||||
// Check if target is stunned and 10% chance (retail is 14% and 35% on crit?)
|
||||
if (activeChar.hasBlockActions() && (Rnd.get(10) == 0))
|
||||
{
|
||||
// Any stun that has double duration due to skill mastery, doesn't get removed until its time reaches the usual abnormal time.
|
||||
@@ -1497,8 +1531,18 @@ public final class Formulas
|
||||
|
||||
public static boolean calcRealTargetBreak()
|
||||
{
|
||||
// Real Target breaks at 5% probability.
|
||||
return Rnd.get(20) == 0;
|
||||
// Real Target breaks at 3% (Rnd > 3.0 doesn't break) probability.
|
||||
return Rnd.get(100) <= 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attackSpeed the attack speed of the Creature.
|
||||
* @return {@code 500000 / attackSpeed}.
|
||||
*/
|
||||
public static int calculateTimeBetweenAttacks(int attackSpeed)
|
||||
{
|
||||
// Measured Nov 2015 by Nik. Formula: atk.spd/500 = hits per second.
|
||||
return Math.max(50, (500000 / attackSpeed));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -143,6 +143,7 @@ public enum Stats
|
||||
PHYSICAL_ATTACK_RANGE("pAtkRange", new PRangeFinalizer()),
|
||||
MAGIC_ATTACK_RANGE("mAtkRange"),
|
||||
ATTACK_COUNT_MAX("atkCountMax"),
|
||||
PHYSICAL_POLEARM_TARGET_SINGLE("polearmSingleTarget"),
|
||||
// Run speed, walk & escape speed are calculated proportionally, magic speed is a buff
|
||||
MOVE_SPEED("moveSpeed"),
|
||||
RUN_SPEED("runSpd", new SpeedFinalizer()),
|
||||
@@ -266,7 +267,8 @@ public enum Stats
|
||||
// Which base stat ordinal should alter skill critical formula.
|
||||
STAT_BONUS_SKILL_CRITICAL("statSkillCritical"),
|
||||
STAT_BONUS_SPEED("statSpeed"),
|
||||
SHOTS_BONUS("shotBonus", new ShotsBonusFinalizer());
|
||||
SHOTS_BONUS("shotBonus", new ShotsBonusFinalizer()),
|
||||
ATTACK_DAMAGE("attackDamage");
|
||||
|
||||
static final Logger LOGGER = Logger.getLogger(Stats.class.getName());
|
||||
public static final int NUM_STATS = values().length;
|
||||
|
@@ -29,8 +29,6 @@ import com.l2jmobius.gameserver.network.OutgoingPackets;
|
||||
public class Attack implements IClientOutgoingPacket
|
||||
{
|
||||
private final int _attackerObjId;
|
||||
private final boolean _soulshot;
|
||||
private final int _ssGrade;
|
||||
private final Location _attackerLoc;
|
||||
private final Location _targetLoc;
|
||||
private final List<Hit> _hits = new ArrayList<>();
|
||||
@@ -38,29 +36,26 @@ public class Attack implements IClientOutgoingPacket
|
||||
/**
|
||||
* @param attacker
|
||||
* @param target
|
||||
* @param useShots
|
||||
* @param ssGrade
|
||||
*/
|
||||
public Attack(L2Character attacker, L2Character target, boolean useShots, int ssGrade)
|
||||
public Attack(L2Character attacker, L2Character target)
|
||||
{
|
||||
_attackerObjId = attacker.getObjectId();
|
||||
_soulshot = useShots;
|
||||
_ssGrade = Math.min(ssGrade, 6);
|
||||
_attackerLoc = new Location(attacker);
|
||||
_targetLoc = new Location(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds hit to the attack (Attacks such as dual dagger/sword/fist has two hits)
|
||||
* @param target
|
||||
* @param damage
|
||||
* @param miss
|
||||
* @param crit
|
||||
* @param shld
|
||||
* @param hit
|
||||
*/
|
||||
public void addHit(L2Character target, int damage, boolean miss, boolean crit, byte shld)
|
||||
public void addHit(Hit hit)
|
||||
{
|
||||
_hits.add(new Hit(target, damage, miss, crit, shld, _soulshot, _ssGrade));
|
||||
_hits.add(hit);
|
||||
}
|
||||
|
||||
public List<Hit> getHits()
|
||||
{
|
||||
return _hits;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,14 +66,6 @@ public class Attack implements IClientOutgoingPacket
|
||||
return !_hits.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if attack has soul shot charged.
|
||||
*/
|
||||
public boolean hasSoulshot()
|
||||
{
|
||||
return _soulshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes current hit
|
||||
* @param packet
|
||||
|
Reference in New Issue
Block a user