Partial sync with L2jServer HighFive Nov 6th 2015.
This commit is contained in:
@ -124,7 +124,6 @@ public final class Config
|
||||
public static double RESPAWN_RESTORE_CP;
|
||||
public static double RESPAWN_RESTORE_HP;
|
||||
public static double RESPAWN_RESTORE_MP;
|
||||
public static boolean ALT_GAME_TIREDNESS;
|
||||
public static boolean ENABLE_MODIFY_SKILL_DURATION;
|
||||
public static Map<Integer, Integer> SKILL_DURATION_LIST;
|
||||
public static boolean ENABLE_MODIFY_SKILL_REUSE;
|
||||
@ -1407,7 +1406,6 @@ public final class Config
|
||||
HP_REGEN_MULTIPLIER = character.getDouble("HpRegenMultiplier", 100) / 100;
|
||||
MP_REGEN_MULTIPLIER = character.getDouble("MpRegenMultiplier", 100) / 100;
|
||||
CP_REGEN_MULTIPLIER = character.getDouble("CpRegenMultiplier", 100) / 100;
|
||||
ALT_GAME_TIREDNESS = character.getBoolean("AltGameTiredness", false);
|
||||
ENABLE_MODIFY_SKILL_DURATION = character.getBoolean("EnableModifySkillDuration", false);
|
||||
|
||||
// Create Map only if enabled
|
||||
@ -3427,9 +3425,6 @@ public final class Config
|
||||
case "announcemammonspawn":
|
||||
ANNOUNCE_MAMMON_SPAWN = Boolean.parseBoolean(pValue);
|
||||
break;
|
||||
case "altgametiredness":
|
||||
ALT_GAME_TIREDNESS = Boolean.parseBoolean(pValue);
|
||||
break;
|
||||
case "enablefallingdamage":
|
||||
ENABLE_FALLING_DAMAGE = Boolean.parseBoolean(pValue);
|
||||
break;
|
||||
|
@ -35,7 +35,6 @@ import com.l2jserver.gameserver.data.xml.impl.AdminData;
|
||||
import com.l2jserver.gameserver.model.actor.L2Playable;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
|
||||
import com.l2jserver.util.StringUtil;
|
||||
|
||||
public final class L2World
|
||||
{
|
||||
@ -79,8 +78,6 @@ public final class L2World
|
||||
private final static Map<Integer, L2PcInstance> _allEvilPlayers = new ConcurrentHashMap<>();
|
||||
/** Map containing all visible objects. */
|
||||
private final Map<Integer, L2Object> _allObjects = new ConcurrentHashMap<>();
|
||||
/** Map used for debug. */
|
||||
private final Map<Integer, String> _allObjectsDebug = new ConcurrentHashMap<>();
|
||||
/** Map with the pets instances and their owner ID. */
|
||||
private final Map<Integer, L2PetInstance> _petsInstance = new ConcurrentHashMap<>();
|
||||
|
||||
@ -106,15 +103,11 @@ public final class L2World
|
||||
if (_allObjects.containsKey(object.getObjectId()))
|
||||
{
|
||||
_log.log(Level.WARNING, getClass().getSimpleName() + ": Current object: " + object + " already exist in OID map!");
|
||||
_log.log(Level.WARNING, StringUtil.getTraceString(Thread.currentThread().getStackTrace()));
|
||||
_log.log(Level.WARNING, getClass().getSimpleName() + ": Previous object: " + _allObjects.get(object.getObjectId()) + " already exist in OID map!");
|
||||
_log.log(Level.WARNING, _allObjectsDebug.get(object.getObjectId()));
|
||||
_log.log(Level.WARNING, "---------------------- End ---------------------");
|
||||
return;
|
||||
}
|
||||
|
||||
_allObjects.put(object.getObjectId(), object);
|
||||
_allObjectsDebug.put(object.getObjectId(), StringUtil.getTraceString(Thread.currentThread().getStackTrace()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,7 +123,6 @@ public final class L2World
|
||||
public void removeObject(L2Object object)
|
||||
{
|
||||
_allObjects.remove(object.getObjectId());
|
||||
_allObjectsDebug.remove(object.getObjectId());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,24 +273,6 @@ public final class L2World
|
||||
*/
|
||||
public void addVisibleObject(L2Object object, L2WorldRegion newRegion)
|
||||
{
|
||||
// TODO: this code should be obsoleted by protection in putObject func...
|
||||
if (object.isPlayer())
|
||||
{
|
||||
L2PcInstance player = object.getActingPlayer();
|
||||
if (!player.isTeleporting())
|
||||
{
|
||||
final L2PcInstance old = getPlayer(player.getObjectId());
|
||||
if (old != null)
|
||||
{
|
||||
_log.warning("Duplicate character!? Closing both characters (" + player.getName() + ")");
|
||||
player.logout();
|
||||
old.logout();
|
||||
return;
|
||||
}
|
||||
addPlayerToWorld(player);
|
||||
}
|
||||
}
|
||||
|
||||
if (!newRegion.isActive())
|
||||
{
|
||||
return;
|
||||
@ -419,16 +393,6 @@ public final class L2World
|
||||
// Remove all L2Object from L2ObjectHashSet(L2Object) containing all L2Object detected by the L2Character
|
||||
// Remove all L2PcInstance from L2ObjectHashSet(L2PcInstance) containing all player ingame detected by the L2Character
|
||||
object.getKnownList().removeAllKnownObjects();
|
||||
|
||||
// If selected L2Object is a L2PcIntance, remove it from L2ObjectHashSet(L2PcInstance) _allPlayers of L2World
|
||||
if (object.isPlayer())
|
||||
{
|
||||
final L2PcInstance player = object.getActingPlayer();
|
||||
if (!player.isTeleporting())
|
||||
{
|
||||
removeFromAllPlayers(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,6 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
||||
/** Represents the time where the attack should end, in nanoseconds. */
|
||||
private volatile long _attackEndTime;
|
||||
private int _disableBowAttackEndTime;
|
||||
private int _disableCrossBowAttackEndTime;
|
||||
|
||||
private int _castInterruptTime;
|
||||
|
||||
@ -812,6 +811,78 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
||||
teleToLocation(MapRegionManager.getInstance().getTeleToLocation(this, teleportWhere), true);
|
||||
}
|
||||
|
||||
private boolean canUseRangeWeapon()
|
||||
{
|
||||
if (isTransformed())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
L2Weapon weaponItem = getActiveWeaponItem();
|
||||
|
||||
if ((weaponItem == null) || !weaponItem.isRange())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check for arrows and MP
|
||||
if (isPlayer())
|
||||
{
|
||||
// Equip arrows needed in left hand and send a Server->Client packet ItemList to the L2PcInstance then return True
|
||||
if (!checkAndEquipArrows())
|
||||
{
|
||||
// Cancel the action because the L2PcInstance have no arrow
|
||||
getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
sendPacket(weaponItem.isBow() ? SystemMessageId.YOU_HAVE_RUN_OUT_OF_ARROWS : SystemMessageId.NOT_ENOUGH_BOLTS);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify if the bow can be use
|
||||
if (_disableBowAttackEndTime <= GameTimeController.getInstance().getGameTicks())
|
||||
{
|
||||
// Verify if L2PcInstance owns enough MP
|
||||
int mpConsume = weaponItem.getMpConsume();
|
||||
if ((weaponItem.getReducedMpConsume() > 0) && (Rnd.get(100) < weaponItem.getReducedMpConsumeChance()))
|
||||
{
|
||||
mpConsume = weaponItem.getReducedMpConsume();
|
||||
}
|
||||
mpConsume = (int) calcStat(Stats.BOW_MP_CONSUME_RATE, mpConsume, null, null);
|
||||
|
||||
if (getCurrentMp() < mpConsume)
|
||||
{
|
||||
// If L2PcInstance doesn't have enough MP, stop the attack
|
||||
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), 1000);
|
||||
sendPacket(SystemMessageId.NOT_ENOUGH_MP);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If L2PcInstance have enough MP, the bow consumes it
|
||||
if (mpConsume > 0)
|
||||
{
|
||||
getStatus().reduceMp(mpConsume);
|
||||
}
|
||||
|
||||
// Set the period of bow no re-use
|
||||
_disableBowAttackEndTime = (5 * GameTimeController.TICKS_PER_SECOND) + GameTimeController.getInstance().getGameTicks();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cancel the action because the bow can't be re-use at this moment
|
||||
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), 1000);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (isNpc())
|
||||
{
|
||||
if (_disableBowAttackEndTime > GameTimeController.getInstance().getGameTicks())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch a physical attack against a target (Simple, Bow, Pole or Dual).<br>
|
||||
* <B><U>Actions</U>:</B>
|
||||
@ -941,186 +1012,42 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
||||
return;
|
||||
}
|
||||
|
||||
// BOW and CROSSBOW checks
|
||||
// Get the active weapon item corresponding to the active weapon instance (always equipped in the right hand)
|
||||
L2Weapon weaponItem = getActiveWeaponItem();
|
||||
if ((weaponItem != null) && !isTransformed())
|
||||
{
|
||||
if (weaponItem.getItemType() == WeaponType.BOW)
|
||||
{
|
||||
// Check for arrows and MP
|
||||
if (isPlayer())
|
||||
{
|
||||
// Checking if target has moved to peace zone - only for player-bow attacks at the moment
|
||||
// Other melee is checked in movement code and for offensive spells a check is done every time
|
||||
if (target.isInsidePeaceZone(getActingPlayer()))
|
||||
{
|
||||
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return;
|
||||
}
|
||||
|
||||
// Equip arrows needed in left hand and send a Server->Client packet ItemList to the L2PcInstance then return True
|
||||
if (!checkAndEquipArrows())
|
||||
{
|
||||
// Cancel the action because the L2PcInstance have no arrow
|
||||
getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
sendPacket(SystemMessageId.YOU_HAVE_RUN_OUT_OF_ARROWS);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify if the bow can be use
|
||||
if (_disableBowAttackEndTime <= GameTimeController.getInstance().getGameTicks())
|
||||
{
|
||||
// Verify if L2PcInstance owns enough MP
|
||||
int mpConsume = weaponItem.getMpConsume();
|
||||
if ((weaponItem.getReducedMpConsume() > 0) && (Rnd.get(100) < weaponItem.getReducedMpConsumeChance()))
|
||||
{
|
||||
mpConsume = weaponItem.getReducedMpConsume();
|
||||
}
|
||||
mpConsume = (int) calcStat(Stats.BOW_MP_CONSUME_RATE, mpConsume, null, null);
|
||||
|
||||
if (getCurrentMp() < mpConsume)
|
||||
{
|
||||
// If L2PcInstance doesn't have enough MP, stop the attack
|
||||
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), 1000);
|
||||
sendPacket(SystemMessageId.NOT_ENOUGH_MP);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return;
|
||||
}
|
||||
|
||||
// If L2PcInstance have enough MP, the bow consumes it
|
||||
if (mpConsume > 0)
|
||||
{
|
||||
getStatus().reduceMp(mpConsume);
|
||||
}
|
||||
|
||||
// Set the period of bow no re-use
|
||||
_disableBowAttackEndTime = (5 * GameTimeController.TICKS_PER_SECOND) + GameTimeController.getInstance().getGameTicks();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cancel the action because the bow can't be re-use at this moment
|
||||
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), 1000);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (weaponItem.getItemType() == WeaponType.CROSSBOW)
|
||||
{
|
||||
// Check for bolts
|
||||
if (isPlayer())
|
||||
{
|
||||
// Checking if target has moved to peace zone - only for player-crossbow attacks at the moment
|
||||
// Other melee is checked in movement code and for offensive spells a check is done every time
|
||||
if (target.isInsidePeaceZone(getActingPlayer()))
|
||||
{
|
||||
getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return;
|
||||
}
|
||||
|
||||
// Equip bolts needed in left hand and send a Server->Client packet ItemList to the L2PcINstance then return True
|
||||
if (!checkAndEquipBolts())
|
||||
{
|
||||
// Cancel the action because the L2PcInstance have no arrow
|
||||
getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
sendPacket(SystemMessageId.NOT_ENOUGH_BOLTS);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify if the crossbow can be use
|
||||
if (_disableCrossBowAttackEndTime <= GameTimeController.getInstance().getGameTicks())
|
||||
{
|
||||
// Verify if L2PcInstance owns enough MP
|
||||
int mpConsume = weaponItem.getMpConsume();
|
||||
if ((weaponItem.getReducedMpConsume() > 0) && (Rnd.get(100) < weaponItem.getReducedMpConsumeChance()))
|
||||
{
|
||||
mpConsume = weaponItem.getReducedMpConsume();
|
||||
}
|
||||
mpConsume = (int) calcStat(Stats.BOW_MP_CONSUME_RATE, mpConsume, null, null);
|
||||
|
||||
if (getCurrentMp() < mpConsume)
|
||||
{
|
||||
// If L2PcInstance doesn't have enough MP, stop the attack
|
||||
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), 1000);
|
||||
sendPacket(SystemMessageId.NOT_ENOUGH_MP);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return;
|
||||
}
|
||||
|
||||
// If L2PcInstance have enough MP, the bow consumes it
|
||||
if (mpConsume > 0)
|
||||
{
|
||||
getStatus().reduceMp(mpConsume);
|
||||
}
|
||||
|
||||
// Set the period of crossbow no re-use
|
||||
_disableCrossBowAttackEndTime = (5 * GameTimeController.TICKS_PER_SECOND) + GameTimeController.getInstance().getGameTicks();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cancel the action because the crossbow can't be re-use at this moment
|
||||
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), 1000);
|
||||
sendPacket(ActionFailed.STATIC_PACKET);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (isNpc())
|
||||
{
|
||||
if (_disableCrossBowAttackEndTime > GameTimeController.getInstance().getGameTicks())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the L2PcInstance to _knownObjects and _knownPlayer of the target
|
||||
target.getKnownList().addKnownObject(this);
|
||||
|
||||
// Reduce the current CP if TIREDNESS configuration is activated
|
||||
if (Config.ALT_GAME_TIREDNESS)
|
||||
{
|
||||
setCurrentCp(getCurrentCp() - 10);
|
||||
}
|
||||
|
||||
// Verify if soulshots are charged.
|
||||
final boolean wasSSCharged = isChargedShot(ShotType.SOULSHOTS);
|
||||
// Get the Attack Speed of the L2Character (delay (in milliseconds) before next attack)
|
||||
final int timeAtk = calculateTimeBetweenAttacks(target, weaponItem);
|
||||
// the hit is calculated to happen halfway to the animation - might need further tuning e.g. in bow case
|
||||
L2Weapon weaponItem = getActiveWeaponItem();
|
||||
final int timeAtk = calculateTimeBetweenAttacks();
|
||||
final int timeToHit = timeAtk / 2;
|
||||
_attackEndTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeAtk, TimeUnit.MILLISECONDS);
|
||||
final int ssGrade = (weaponItem != null) ? weaponItem.getItemGrade().ordinal() : 0;
|
||||
// Create a Server->Client packet Attack
|
||||
Attack attack = new Attack(this, target, wasSSCharged, ssGrade);
|
||||
|
||||
// Make sure that char is facing selected target
|
||||
// also works: setHeading(Util.convertDegreeToClientHeading(Util.calculateAngleFrom(this, target)));
|
||||
Attack attack = new Attack(this, target, isChargedShot(ShotType.SOULSHOTS), (weaponItem != null) ? weaponItem.getItemGrade().ordinal() : 0);
|
||||
setHeading(Util.calculateHeadingFrom(this, target));
|
||||
|
||||
// Get the Attack Reuse Delay of the L2Weapon
|
||||
int reuse = calculateReuseTime(target, weaponItem);
|
||||
int reuse = calculateReuseTime(weaponItem);
|
||||
|
||||
boolean hitted = false;
|
||||
switch (getAttackType())
|
||||
{
|
||||
case BOW:
|
||||
{
|
||||
if (!canUseRangeWeapon())
|
||||
{
|
||||
return;
|
||||
}
|
||||
_attackEndTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeToHit + (reuse / 2), TimeUnit.MILLISECONDS);
|
||||
hitted = doAttackHitByBow(attack, target, timeAtk, reuse);
|
||||
break;
|
||||
}
|
||||
case CROSSBOW:
|
||||
{
|
||||
if (!canUseRangeWeapon())
|
||||
{
|
||||
return;
|
||||
}
|
||||
_attackEndTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeToHit + (reuse / 2), TimeUnit.MILLISECONDS);
|
||||
hitted = doAttackHitByCrossBow(attack, target, timeAtk, reuse);
|
||||
break;
|
||||
}
|
||||
case POLE:
|
||||
{
|
||||
_attackEndTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeAtk, TimeUnit.MILLISECONDS);
|
||||
hitted = doAttackHitByPole(attack, target, timeToHit);
|
||||
break;
|
||||
}
|
||||
@ -1136,11 +1063,13 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
||||
case DUALFIST:
|
||||
case DUALDAGGER:
|
||||
{
|
||||
_attackEndTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeAtk, TimeUnit.MILLISECONDS);
|
||||
hitted = doAttackHitByDual(attack, target, timeToHit);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
_attackEndTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeAtk, TimeUnit.MILLISECONDS);
|
||||
hitted = doAttackHitSimple(attack, target, timeToHit);
|
||||
break;
|
||||
}
|
||||
@ -1193,9 +1122,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
||||
}
|
||||
|
||||
// Notify AI with EVT_READY_TO_ACT
|
||||
// Old method - use in case of bow reuse issues occur.
|
||||
// ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), timeAtk + reuse);
|
||||
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), timeAtk);
|
||||
ThreadPoolManager.getInstance().scheduleAi(new NotifyAITask(this, CtrlEvent.EVT_READY_TO_ACT), timeAtk + reuse);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -1334,7 +1261,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
||||
ThreadPoolManager.getInstance().scheduleAi(new HitTask(this, target, damage1, crit1, miss1, attack.hasSoulshot(), shld1), sAtk);
|
||||
|
||||
// Calculate and set the disable delay of the bow in function of the Attack Speed
|
||||
_disableCrossBowAttackEndTime = ((sAtk + reuse) / GameTimeController.MILLIS_IN_TICK) + GameTimeController.getInstance().getGameTicks();
|
||||
_disableBowAttackEndTime = ((sAtk + reuse) / GameTimeController.MILLIS_IN_TICK) + GameTimeController.getInstance().getGameTicks();
|
||||
|
||||
// Add this hit to the Server-Client packet Attack
|
||||
attack.addHit(target, damage1, miss1, crit1, shld1);
|
||||
@ -5311,61 +5238,36 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
||||
}
|
||||
|
||||
/**
|
||||
* @param target
|
||||
* @param weapon
|
||||
* @return the Attack Speed of the L2Character (delay (in milliseconds) before next attack).
|
||||
*/
|
||||
public int calculateTimeBetweenAttacks(L2Character target, L2Weapon weapon)
|
||||
public int calculateTimeBetweenAttacks()
|
||||
{
|
||||
if ((weapon != null) && !isTransformed())
|
||||
{
|
||||
switch (weapon.getItemType())
|
||||
{
|
||||
case BOW:
|
||||
return (int) ((1500 * 345) / getPAtkSpd());
|
||||
case CROSSBOW:
|
||||
return (int) ((1200 * 345) / getPAtkSpd());
|
||||
case DAGGER:
|
||||
// atkSpd /= 1.15;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Formulas.calcPAtkSpd(this, target, getPAtkSpd());
|
||||
return (int) (500000 / getPAtkSpd());
|
||||
}
|
||||
|
||||
public int calculateReuseTime(L2Character target, L2Weapon weapon)
|
||||
/**
|
||||
* @param weapon
|
||||
* @return the Reuse Time of Attack (used for bow delay)
|
||||
*/
|
||||
public int calculateReuseTime(final L2Weapon weapon)
|
||||
{
|
||||
if (isTransformed())
|
||||
{
|
||||
switch (getAttackType())
|
||||
{
|
||||
case BOW:
|
||||
return (int) ((1500 * 333 * getStat().getWeaponReuseModifier(null)) / getStat().getPAtkSpd());
|
||||
case CROSSBOW:
|
||||
return (int) ((517500 * getStat().getWeaponReuseModifier(null)) / getStat().getPAtkSpd());
|
||||
return (int) ((1200 * 333 * getStat().getWeaponReuseModifier(null)) / getStat().getPAtkSpd());
|
||||
}
|
||||
}
|
||||
if ((weapon == null))
|
||||
|
||||
if ((weapon == null) || (weapon.getReuseDelay() == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reuse = weapon.getReuseDelay();
|
||||
|
||||
// only bows should continue for now
|
||||
if (reuse == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
reuse *= getStat().getWeaponReuseModifier(null);
|
||||
double atkSpd = getStat().getPAtkSpd();
|
||||
switch (weapon.getItemType())
|
||||
{
|
||||
case BOW:
|
||||
case CROSSBOW:
|
||||
return (int) ((reuse * 345) / atkSpd);
|
||||
default:
|
||||
return (int) ((reuse * 312) / atkSpd);
|
||||
}
|
||||
return (int) ((weapon.getReuseDelay() * 333) / getPAtkSpd());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,6 +320,7 @@ public abstract class ItemContainer
|
||||
item.setOwnerId(getOwnerId());
|
||||
item.setItemLocation(getBaseLocation());
|
||||
item.setLastChange(L2ItemInstance.ADDED);
|
||||
item.setEnchantLevel(template.getDefaultEnchantLevel());
|
||||
|
||||
// Add item in inventory
|
||||
addItem(item);
|
||||
|
@ -556,7 +556,7 @@ public class PcInventory extends Inventory
|
||||
actor.sendPacket(new ExAdenaInvenCount(actor));
|
||||
|
||||
// Notify to scripts
|
||||
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemAdd(actor, item), item.getItem());
|
||||
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemAdd(actor, item), actor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ public class PcInventory extends Inventory
|
||||
actor.sendPacket(new ExAdenaInvenCount(actor));
|
||||
|
||||
// Notify to scripts
|
||||
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemAdd(actor, item), item.getItem());
|
||||
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerItemAdd(actor, item), actor);
|
||||
}
|
||||
|
||||
return item;
|
||||
|
@ -454,4 +454,19 @@ public final class L2Weapon extends L2Item
|
||||
caster.sendPacket(sm);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRange()
|
||||
{
|
||||
return isBow() || isCrossBow();
|
||||
}
|
||||
|
||||
public boolean isBow()
|
||||
{
|
||||
return _type == WeaponType.BOW;
|
||||
}
|
||||
|
||||
public boolean isCrossBow()
|
||||
{
|
||||
return _type == WeaponType.CROSSBOW;
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,11 @@ public class PreparedEntry extends Entry
|
||||
{
|
||||
newProduct.setItemInfo(info);
|
||||
}
|
||||
else if (ing.isArmorOrWeapon() && (ing.getTemplate().getDefaultEnchantLevel() > 0))
|
||||
{
|
||||
info = new ItemInfo(ing.getTemplate().getDefaultEnchantLevel());
|
||||
newProduct.setItemInfo(info);
|
||||
}
|
||||
_products.add(newProduct);
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ public class CharacterSelect extends L2GameClientPacket
|
||||
{
|
||||
return; // handled in L2GameClient
|
||||
}
|
||||
|
||||
L2World.getInstance().addPlayerToWorld(cha);
|
||||
CharNameTable.getInstance().addName(cha);
|
||||
|
||||
cha.setClient(client);
|
||||
|
Reference in New Issue
Block a user