Addition of auto play task managers.
This commit is contained in:
parent
561895582e
commit
8f80bb3a41
@ -39,7 +39,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -220,9 +219,10 @@ import org.l2jmobius.gameserver.model.events.returns.TerminateReturn;
|
|||||||
import org.l2jmobius.gameserver.model.events.timers.TimerHolder;
|
import org.l2jmobius.gameserver.model.events.timers.TimerHolder;
|
||||||
import org.l2jmobius.gameserver.model.fishing.Fishing;
|
import org.l2jmobius.gameserver.model.fishing.Fishing;
|
||||||
import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
|
import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.AutoPlaySettingsHolder;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.AutoUseSettingsHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.DamageTakenHolder;
|
import org.l2jmobius.gameserver.model.holders.DamageTakenHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.ItemHolder;
|
import org.l2jmobius.gameserver.model.holders.ItemHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.ItemSkillHolder;
|
|
||||||
import org.l2jmobius.gameserver.model.holders.MonsterBookCardHolder;
|
import org.l2jmobius.gameserver.model.holders.MonsterBookCardHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.MonsterBookRewardHolder;
|
import org.l2jmobius.gameserver.model.holders.MonsterBookRewardHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.MovieHolder;
|
import org.l2jmobius.gameserver.model.holders.MovieHolder;
|
||||||
@ -266,7 +266,6 @@ import org.l2jmobius.gameserver.model.skills.CommonSkill;
|
|||||||
import org.l2jmobius.gameserver.model.skills.Skill;
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.skills.SkillCaster;
|
import org.l2jmobius.gameserver.model.skills.SkillCaster;
|
||||||
import org.l2jmobius.gameserver.model.skills.SkillCastingType;
|
import org.l2jmobius.gameserver.model.skills.SkillCastingType;
|
||||||
import org.l2jmobius.gameserver.model.skills.targets.AffectScope;
|
|
||||||
import org.l2jmobius.gameserver.model.skills.targets.TargetType;
|
import org.l2jmobius.gameserver.model.skills.targets.TargetType;
|
||||||
import org.l2jmobius.gameserver.model.stats.BaseStat;
|
import org.l2jmobius.gameserver.model.stats.BaseStat;
|
||||||
import org.l2jmobius.gameserver.model.stats.Formulas;
|
import org.l2jmobius.gameserver.model.stats.Formulas;
|
||||||
@ -348,7 +347,6 @@ import org.l2jmobius.gameserver.network.serverpackets.TradeOtherDone;
|
|||||||
import org.l2jmobius.gameserver.network.serverpackets.TradeStart;
|
import org.l2jmobius.gameserver.network.serverpackets.TradeStart;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
|
import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
|
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlayDoMacro;
|
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
|
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
|
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.monsterbook.ExMonsterBook;
|
import org.l2jmobius.gameserver.network.serverpackets.monsterbook.ExMonsterBook;
|
||||||
@ -869,15 +867,8 @@ public class PlayerInstance extends Playable
|
|||||||
|
|
||||||
private final Set<Integer> _whisperers = ConcurrentHashMap.newKeySet();
|
private final Set<Integer> _whisperers = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
private ScheduledFuture<?> _autoPlayTask = null;
|
private final AutoPlaySettingsHolder _autoPlaySettings = new AutoPlaySettingsHolder();
|
||||||
private ScheduledFuture<?> _autoUseTask = null;
|
private final AutoUseSettingsHolder _autoUseSettings = new AutoUseSettingsHolder();
|
||||||
private final AtomicBoolean _pickup = new AtomicBoolean();
|
|
||||||
private final AtomicBoolean _longRange = new AtomicBoolean();
|
|
||||||
private final AtomicBoolean _respectfulHunting = new AtomicBoolean();
|
|
||||||
private final AtomicInteger _autoPotionPercent = new AtomicInteger();
|
|
||||||
private final Collection<Integer> _autoSupplyItems = ConcurrentHashMap.newKeySet();
|
|
||||||
private final Collection<Integer> _autoPotionItems = ConcurrentHashMap.newKeySet();
|
|
||||||
private final Collection<Integer> _autoSkills = ConcurrentHashMap.newKeySet();
|
|
||||||
|
|
||||||
private ScheduledFuture<?> _timedHuntingZoneFinishTask = null;
|
private ScheduledFuture<?> _timedHuntingZoneFinishTask = null;
|
||||||
|
|
||||||
@ -13863,16 +13854,6 @@ public class PlayerInstance extends Playable
|
|||||||
_autoSaveTask.cancel(false);
|
_autoSaveTask.cancel(false);
|
||||||
_autoSaveTask = null;
|
_autoSaveTask = null;
|
||||||
}
|
}
|
||||||
if ((_autoPlayTask != null) && !_autoPlayTask.isDone() && !_autoPlayTask.isCancelled())
|
|
||||||
{
|
|
||||||
_autoPlayTask.cancel(false);
|
|
||||||
_autoPlayTask = null;
|
|
||||||
}
|
|
||||||
if ((_autoUseTask != null) && !_autoUseTask.isDone() && !_autoUseTask.isCancelled())
|
|
||||||
{
|
|
||||||
_autoUseTask.cancel(false);
|
|
||||||
_autoUseTask = null;
|
|
||||||
}
|
|
||||||
if ((_timedHuntingZoneFinishTask != null) && !_timedHuntingZoneFinishTask.isDone() && !_timedHuntingZoneFinishTask.isCancelled())
|
if ((_timedHuntingZoneFinishTask != null) && !_timedHuntingZoneFinishTask.isDone() && !_timedHuntingZoneFinishTask.isCancelled())
|
||||||
{
|
{
|
||||||
_timedHuntingZoneFinishTask.cancel(false);
|
_timedHuntingZoneFinishTask.cancel(false);
|
||||||
@ -14170,274 +14151,14 @@ public class PlayerInstance extends Playable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopAutoPlayTask()
|
public AutoPlaySettingsHolder getAutoPlaySettings()
|
||||||
{
|
{
|
||||||
if ((_autoPlayTask != null) && !_autoPlayTask.isCancelled() && !_autoPlayTask.isDone())
|
return _autoPlaySettings;
|
||||||
{
|
|
||||||
_autoPlayTask.cancel(true);
|
|
||||||
_autoPlayTask = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startAutoPlayTask(boolean pickup, boolean longRange, boolean respectfulHunting)
|
public AutoUseSettingsHolder getAutoUseSettings()
|
||||||
{
|
{
|
||||||
_pickup.set(pickup);
|
return _autoUseSettings;
|
||||||
_longRange.set(longRange);
|
|
||||||
_respectfulHunting.set(respectfulHunting);
|
|
||||||
|
|
||||||
if (_autoPlayTask != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_autoPlayTask = ThreadPool.scheduleAtFixedRate(() ->
|
|
||||||
{
|
|
||||||
if (!Config.ENABLE_AUTO_PLAY)
|
|
||||||
{
|
|
||||||
stopAutoPlayTask();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip thinking.
|
|
||||||
final WorldObject target = getTarget();
|
|
||||||
if ((target != null) && target.isMonster())
|
|
||||||
{
|
|
||||||
final MonsterInstance monster = (MonsterInstance) target;
|
|
||||||
if ((monster.getTarget() == this) && !monster.isAlikeDead())
|
|
||||||
{
|
|
||||||
// Check if actually attacking.
|
|
||||||
if (hasAI() && getAI().isAutoAttacking() && !isAttackingNow() && !isCastingNow())
|
|
||||||
{
|
|
||||||
doAutoAttack(monster);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pickup.
|
|
||||||
if (_pickup.get())
|
|
||||||
{
|
|
||||||
for (ItemInstance droppedItem : World.getInstance().getVisibleObjectsInRange(this, ItemInstance.class, 200))
|
|
||||||
{
|
|
||||||
// Check if item is reachable.
|
|
||||||
if ((droppedItem == null) //
|
|
||||||
|| (!droppedItem.isSpawned()) //
|
|
||||||
|| !GeoEngine.getInstance().canMoveToTarget(getX(), getY(), getZ(), droppedItem.getX(), droppedItem.getY(), droppedItem.getZ(), getInstanceWorld()))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move to item.
|
|
||||||
if (calculateDistance2D(droppedItem) > 50)
|
|
||||||
{
|
|
||||||
moveToLocation(droppedItem.getX(), droppedItem.getY(), droppedItem.getZ(), 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to pick it up.
|
|
||||||
if (!droppedItem.isProtected() || (droppedItem.getOwnerId() == getObjectId()))
|
|
||||||
{
|
|
||||||
doPickupItem(droppedItem);
|
|
||||||
return; // Avoid pickup being skipped.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find target.
|
|
||||||
MonsterInstance monster = null;
|
|
||||||
double closestDistance = Double.MAX_VALUE;
|
|
||||||
for (MonsterInstance nearby : World.getInstance().getVisibleObjectsInRange(this, MonsterInstance.class, _longRange.get() ? 1400 : 600))
|
|
||||||
{
|
|
||||||
// Skip unavailable monsters.
|
|
||||||
if ((nearby == null) || nearby.isAlikeDead())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Check monster target.
|
|
||||||
if (_respectfulHunting.get() && (nearby.getTarget() != null) && (nearby.getTarget() != this))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Check if monster is reachable.
|
|
||||||
if (nearby.isAutoAttackable(this) //
|
|
||||||
&& GeoEngine.getInstance().canSeeTarget(this, nearby)//
|
|
||||||
&& GeoEngine.getInstance().canMoveToTarget(getX(), getY(), getZ(), nearby.getX(), nearby.getY(), nearby.getZ(), getInstanceWorld()))
|
|
||||||
{
|
|
||||||
final double monsterDistance = calculateDistance2D(nearby);
|
|
||||||
if (monsterDistance < closestDistance)
|
|
||||||
{
|
|
||||||
monster = nearby;
|
|
||||||
closestDistance = monsterDistance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New target was assigned.
|
|
||||||
if (monster != null)
|
|
||||||
{
|
|
||||||
setTarget(monster);
|
|
||||||
sendPacket(ExAutoPlayDoMacro.STATIC_PACKET);
|
|
||||||
}
|
|
||||||
}, 0, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopAutoUseTask()
|
|
||||||
{
|
|
||||||
if ((_autoUseTask != null) && !_autoUseTask.isCancelled() && !_autoUseTask.isDone())
|
|
||||||
{
|
|
||||||
_autoUseTask.cancel(true);
|
|
||||||
_autoUseTask = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startAutoUseTask()
|
|
||||||
{
|
|
||||||
if (_autoUseTask != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_autoUseTask = ThreadPool.scheduleAtFixedRate(() ->
|
|
||||||
{
|
|
||||||
if (hasBlockActions() || isControlBlocked() || isAlikeDead() || isInsideZone(ZoneId.PEACE))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.ENABLE_AUTO_ITEM)
|
|
||||||
{
|
|
||||||
ITEMS: for (int itemId : _autoSupplyItems)
|
|
||||||
{
|
|
||||||
final ItemInstance item = _inventory.getItemByItemId(itemId);
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
removeAutoSupplyItem(itemId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ItemSkillHolder itemSkillHolder : item.getItem().getAllSkills())
|
|
||||||
{
|
|
||||||
final Skill skill = itemSkillHolder.getSkill();
|
|
||||||
if (isAffectedBySkill(skill.getId()) || hasSkillReuse(skill.getReuseHashCode()) || !skill.checkCondition(this, this, false))
|
|
||||||
{
|
|
||||||
continue ITEMS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final int reuseDelay = item.getReuseDelay();
|
|
||||||
if ((reuseDelay <= 0) || (getItemRemainingReuseTime(item.getObjectId()) <= 0))
|
|
||||||
{
|
|
||||||
final EtcItem etcItem = item.getEtcItem();
|
|
||||||
final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem);
|
|
||||||
if ((handler != null) && handler.useItem(this, item, false) && (reuseDelay > 0))
|
|
||||||
{
|
|
||||||
addTimeStampItem(item, reuseDelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.ENABLE_AUTO_POTION && (getCurrentHpPercent() <= _autoPotionPercent.get()))
|
|
||||||
{
|
|
||||||
for (int itemId : _autoPotionItems)
|
|
||||||
{
|
|
||||||
final ItemInstance item = _inventory.getItemByItemId(itemId);
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
removeAutoPotionItem(itemId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final int reuseDelay = item.getReuseDelay();
|
|
||||||
if ((reuseDelay <= 0) || (getItemRemainingReuseTime(item.getObjectId()) <= 0))
|
|
||||||
{
|
|
||||||
final EtcItem etcItem = item.getEtcItem();
|
|
||||||
final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem);
|
|
||||||
if ((handler != null) && handler.useItem(this, item, false) && (reuseDelay > 0))
|
|
||||||
{
|
|
||||||
addTimeStampItem(item, reuseDelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.ENABLE_AUTO_BUFF)
|
|
||||||
{
|
|
||||||
for (int skillId : _autoSkills)
|
|
||||||
{
|
|
||||||
final Skill skill = getKnownSkill(skillId);
|
|
||||||
if (skill == null)
|
|
||||||
{
|
|
||||||
removeAutoSkill(skillId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!isAffectedBySkill(skillId) && !hasSkillReuse(skill.getReuseHashCode()) && skill.checkCondition(this, this, false))
|
|
||||||
{
|
|
||||||
// Summon check.
|
|
||||||
if (skill.getAffectScope() == AffectScope.SUMMON_EXCEPT_MASTER)
|
|
||||||
{
|
|
||||||
if (!hasServitors()) // Is this check truly needed?
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int occurrences = 0;
|
|
||||||
for (Summon servitor : _servitors.values())
|
|
||||||
{
|
|
||||||
if (servitor.isAffectedBySkill(skillId))
|
|
||||||
{
|
|
||||||
occurrences++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (occurrences == _servitors.size())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doCast(skill);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 0, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAutoPotionPercent(int value)
|
|
||||||
{
|
|
||||||
_autoPotionPercent.set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAutoSupplyItem(int itemId)
|
|
||||||
{
|
|
||||||
_autoSupplyItems.add(itemId);
|
|
||||||
startAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAutoSupplyItem(int itemId)
|
|
||||||
{
|
|
||||||
_autoSupplyItems.remove(itemId);
|
|
||||||
stopAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAutoPotionItem(int itemId)
|
|
||||||
{
|
|
||||||
_autoPotionItems.add(itemId);
|
|
||||||
startAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAutoPotionItem(int itemId)
|
|
||||||
{
|
|
||||||
_autoPotionItems.remove(itemId);
|
|
||||||
stopAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAutoSkill(int skillId)
|
|
||||||
{
|
|
||||||
_autoSkills.add(skillId);
|
|
||||||
startAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAutoSkill(int skillId)
|
|
||||||
{
|
|
||||||
_autoSkills.remove(skillId);
|
|
||||||
stopAutoUseTask();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInTimedHuntingZone()
|
public boolean isInTimedHuntingZone()
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.l2jmobius.gameserver.model.holders;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class AutoPlaySettingsHolder
|
||||||
|
{
|
||||||
|
private final AtomicBoolean _pickup = new AtomicBoolean();
|
||||||
|
private final AtomicBoolean _longRange = new AtomicBoolean();
|
||||||
|
private final AtomicBoolean _respectfulHunting = new AtomicBoolean();
|
||||||
|
private final AtomicInteger _autoPotionPercent = new AtomicInteger();
|
||||||
|
|
||||||
|
public AutoPlaySettingsHolder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean doPickup()
|
||||||
|
{
|
||||||
|
return _pickup.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPickup(boolean value)
|
||||||
|
{
|
||||||
|
_pickup.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLongRange()
|
||||||
|
{
|
||||||
|
return _longRange.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongRange(boolean value)
|
||||||
|
{
|
||||||
|
_longRange.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRespectfulHunting()
|
||||||
|
{
|
||||||
|
return _respectfulHunting.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRespectfulHunting(boolean value)
|
||||||
|
{
|
||||||
|
_respectfulHunting.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAutoPotionPercent()
|
||||||
|
{
|
||||||
|
return _autoPotionPercent.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoPotionPercent(int value)
|
||||||
|
{
|
||||||
|
_autoPotionPercent.set(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.l2jmobius.gameserver.model.holders;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class AutoUseSettingsHolder
|
||||||
|
{
|
||||||
|
private final Collection<Integer> _autoSupplyItems = ConcurrentHashMap.newKeySet();
|
||||||
|
private final Collection<Integer> _autoPotionItems = ConcurrentHashMap.newKeySet();
|
||||||
|
private final Collection<Integer> _autoSkills = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
|
public AutoUseSettingsHolder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Integer> getAutoSupplyItems()
|
||||||
|
{
|
||||||
|
return _autoSupplyItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Integer> getAutoPotionItems()
|
||||||
|
{
|
||||||
|
return _autoPotionItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Integer> getAutoSkills()
|
||||||
|
{
|
||||||
|
return _autoSkills;
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ package org.l2jmobius.gameserver.network.clientpackets;
|
|||||||
import org.l2jmobius.commons.network.PacketReader;
|
import org.l2jmobius.commons.network.PacketReader;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
import org.l2jmobius.gameserver.network.GameClient;
|
import org.l2jmobius.gameserver.network.GameClient;
|
||||||
|
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version $Revision: 1.3.4.2 $ $Date: 2005/03/27 15:29:30 $
|
* @version $Revision: 1.3.4.2 $ $Date: 2005/03/27 15:29:30 $
|
||||||
@ -57,11 +58,11 @@ public class RequestShortCutDel implements IClientIncomingPacket
|
|||||||
// Remove auto used ids.
|
// Remove auto used ids.
|
||||||
if (_slot > 263)
|
if (_slot > 263)
|
||||||
{
|
{
|
||||||
player.removeAutoSupplyItem(_id);
|
AutoUseTaskManager.getInstance().removeAutoSupplyItem(player, _id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player.removeAutoSkill(_id);
|
AutoUseTaskManager.getInstance().removeAutoSkill(player, _id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
|||||||
import org.l2jmobius.gameserver.network.GameClient;
|
import org.l2jmobius.gameserver.network.GameClient;
|
||||||
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
|
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySettingSend;
|
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySettingSend;
|
||||||
|
import org.l2jmobius.gameserver.taskmanager.AutoPlayTaskManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Mobius
|
* @author Mobius
|
||||||
@ -59,7 +60,7 @@ public class ExAutoPlaySetting implements IClientIncomingPacket
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.sendPacket(new ExAutoPlaySettingSend(_options, _active, _pickUp, _nextTargetMode, _longRange, _potionPercent, _respectfulHunting));
|
player.sendPacket(new ExAutoPlaySettingSend(_options, _active, _pickUp, _nextTargetMode, _longRange, _potionPercent, _respectfulHunting));
|
||||||
player.setAutoPotionPercent(_potionPercent);
|
player.getAutoPlaySettings().setAutoPotionPercent(_potionPercent);
|
||||||
|
|
||||||
if (!Config.ENABLE_AUTO_PLAY)
|
if (!Config.ENABLE_AUTO_PLAY)
|
||||||
{
|
{
|
||||||
@ -68,11 +69,11 @@ public class ExAutoPlaySetting implements IClientIncomingPacket
|
|||||||
|
|
||||||
if (_active)
|
if (_active)
|
||||||
{
|
{
|
||||||
player.startAutoPlayTask(_pickUp, _longRange, _respectfulHunting);
|
AutoPlayTaskManager.getInstance().doAutoPlay(player, _pickUp, _longRange, _respectfulHunting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player.stopAutoPlayTask();
|
AutoPlayTaskManager.getInstance().stopAutoPlay(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import org.l2jmobius.gameserver.model.skills.Skill;
|
|||||||
import org.l2jmobius.gameserver.network.GameClient;
|
import org.l2jmobius.gameserver.network.GameClient;
|
||||||
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
|
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExActivateAutoShortcut;
|
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExActivateAutoShortcut;
|
||||||
|
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author JoeAlisson, Mobius
|
* @author JoeAlisson, Mobius
|
||||||
@ -75,17 +76,17 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
|||||||
// auto supply
|
// auto supply
|
||||||
if (_room > 263)
|
if (_room > 263)
|
||||||
{
|
{
|
||||||
player.removeAutoSupplyItem(item.getId());
|
AutoUseTaskManager.getInstance().removeAutoSupplyItem(player, item.getId());
|
||||||
}
|
}
|
||||||
else // auto potion
|
else // auto potion
|
||||||
{
|
{
|
||||||
player.removeAutoPotionItem(item.getId());
|
AutoUseTaskManager.getInstance().removeAutoPotionItem(player, item.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// auto skill
|
// auto skill
|
||||||
if (skill != null)
|
if (skill != null)
|
||||||
{
|
{
|
||||||
player.removeAutoSkill(skill.getId());
|
AutoUseTaskManager.getInstance().removeAutoSkill(player, skill.getId());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -96,7 +97,7 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
|||||||
// auto supply
|
// auto supply
|
||||||
if (Config.ENABLE_AUTO_ITEM && (item != null))
|
if (Config.ENABLE_AUTO_ITEM && (item != null))
|
||||||
{
|
{
|
||||||
player.addAutoSupplyItem(item.getId());
|
AutoUseTaskManager.getInstance().addAutoSupplyItem(player, item.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -106,14 +107,14 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
|||||||
{
|
{
|
||||||
if (Config.ENABLE_AUTO_POTION && (item != null) && item.isPotion())
|
if (Config.ENABLE_AUTO_POTION && (item != null) && item.isPotion())
|
||||||
{
|
{
|
||||||
player.addAutoPotionItem(item.getId());
|
AutoUseTaskManager.getInstance().addAutoPotionItem(player, item.getId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// auto skill
|
// auto skill
|
||||||
if (Config.ENABLE_AUTO_BUFF && (skill != null))
|
if (Config.ENABLE_AUTO_BUFF && (skill != null))
|
||||||
{
|
{
|
||||||
player.addAutoSkill(skill.getId());
|
AutoUseTaskManager.getInstance().addAutoSkill(player, skill.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.l2jmobius.gameserver.taskmanager;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
|
||||||
|
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlayDoMacro;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class AutoPlayTaskManager
|
||||||
|
{
|
||||||
|
private static final Set<PlayerInstance> PLAYERS = ConcurrentHashMap.newKeySet();
|
||||||
|
private static boolean _working = false;
|
||||||
|
|
||||||
|
public AutoPlayTaskManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_working)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_working = true;
|
||||||
|
|
||||||
|
PLAY: for (PlayerInstance player : PLAYERS)
|
||||||
|
{
|
||||||
|
if (!player.isOnline() || player.isInOfflineMode() || !Config.ENABLE_AUTO_PLAY)
|
||||||
|
{
|
||||||
|
stopAutoPlay(player);
|
||||||
|
continue PLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip thinking.
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target != null) && target.isMonster())
|
||||||
|
{
|
||||||
|
final MonsterInstance monster = (MonsterInstance) target;
|
||||||
|
if ((monster.getTarget() == player) && !monster.isAlikeDead())
|
||||||
|
{
|
||||||
|
// Check if actually attacking.
|
||||||
|
if (player.hasAI() && player.getAI().isAutoAttacking() && !player.isAttackingNow() && !player.isCastingNow())
|
||||||
|
{
|
||||||
|
player.doAutoAttack(monster);
|
||||||
|
}
|
||||||
|
continue PLAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup.
|
||||||
|
if (player.getAutoPlaySettings().doPickup())
|
||||||
|
{
|
||||||
|
PICKUP: for (ItemInstance droppedItem : World.getInstance().getVisibleObjectsInRange(player, ItemInstance.class, 200))
|
||||||
|
{
|
||||||
|
// Check if item is reachable.
|
||||||
|
if ((droppedItem == null) //
|
||||||
|
|| (!droppedItem.isSpawned()) //
|
||||||
|
|| !GeoEngine.getInstance().canMoveToTarget(player.getX(), player.getY(), player.getZ(), droppedItem.getX(), droppedItem.getY(), droppedItem.getZ(), player.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
continue PICKUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to item.
|
||||||
|
if (player.calculateDistance2D(droppedItem) > 50)
|
||||||
|
{
|
||||||
|
player.moveToLocation(droppedItem.getX(), droppedItem.getY(), droppedItem.getZ(), 0);
|
||||||
|
continue PLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to pick it up.
|
||||||
|
if (!droppedItem.isProtected() || (droppedItem.getOwnerId() == player.getObjectId()))
|
||||||
|
{
|
||||||
|
player.doPickupItem(droppedItem);
|
||||||
|
continue PLAY; // Avoid pickup being skipped.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find target.
|
||||||
|
MonsterInstance monster = null;
|
||||||
|
double closestDistance = Double.MAX_VALUE;
|
||||||
|
TARGET: for (MonsterInstance nearby : World.getInstance().getVisibleObjectsInRange(player, MonsterInstance.class, player.getAutoPlaySettings().isLongRange() ? 1400 : 600))
|
||||||
|
{
|
||||||
|
// Skip unavailable monsters.
|
||||||
|
if ((nearby == null) || nearby.isAlikeDead())
|
||||||
|
{
|
||||||
|
continue TARGET;
|
||||||
|
}
|
||||||
|
// Check monster target.
|
||||||
|
if (player.getAutoPlaySettings().isRespectfulHunting() && (nearby.getTarget() != null) && (nearby.getTarget() != player))
|
||||||
|
{
|
||||||
|
continue TARGET;
|
||||||
|
}
|
||||||
|
// Check if monster is reachable.
|
||||||
|
if (nearby.isAutoAttackable(player) //
|
||||||
|
&& GeoEngine.getInstance().canSeeTarget(player, nearby)//
|
||||||
|
&& GeoEngine.getInstance().canMoveToTarget(player.getX(), player.getY(), player.getZ(), nearby.getX(), nearby.getY(), nearby.getZ(), player.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
final double monsterDistance = player.calculateDistance2D(nearby);
|
||||||
|
if (monsterDistance < closestDistance)
|
||||||
|
{
|
||||||
|
monster = nearby;
|
||||||
|
closestDistance = monsterDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New target was assigned.
|
||||||
|
if (monster != null)
|
||||||
|
{
|
||||||
|
player.setTarget(monster);
|
||||||
|
player.sendPacket(ExAutoPlayDoMacro.STATIC_PACKET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_working = false;
|
||||||
|
}, 1000, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doAutoPlay(PlayerInstance player, boolean pickup, boolean longRange, boolean respectfulHunting)
|
||||||
|
{
|
||||||
|
player.getAutoPlaySettings().setPickup(pickup);
|
||||||
|
player.getAutoPlaySettings().setLongRange(longRange);
|
||||||
|
player.getAutoPlaySettings().setRespectfulHunting(respectfulHunting);
|
||||||
|
|
||||||
|
if (!PLAYERS.contains(player))
|
||||||
|
{
|
||||||
|
PLAYERS.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopAutoPlay(PlayerInstance player)
|
||||||
|
{
|
||||||
|
PLAYERS.remove(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AutoPlayTaskManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final AutoPlayTaskManager INSTANCE = new AutoPlayTaskManager();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.l2jmobius.gameserver.taskmanager;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.handler.IItemHandler;
|
||||||
|
import org.l2jmobius.gameserver.handler.ItemHandler;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Summon;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.ItemSkillHolder;
|
||||||
|
import org.l2jmobius.gameserver.model.items.EtcItem;
|
||||||
|
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.targets.AffectScope;
|
||||||
|
import org.l2jmobius.gameserver.model.zone.ZoneId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class AutoUseTaskManager
|
||||||
|
{
|
||||||
|
private static final Set<PlayerInstance> PLAYERS = ConcurrentHashMap.newKeySet();
|
||||||
|
private static boolean _working = false;
|
||||||
|
|
||||||
|
public AutoUseTaskManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_working)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_working = true;
|
||||||
|
|
||||||
|
for (PlayerInstance player : PLAYERS)
|
||||||
|
{
|
||||||
|
if (!player.isOnline() || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
stopAutoUseTask(player);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.hasBlockActions() || player.isControlBlocked() || player.isAlikeDead() || player.isInsideZone(ZoneId.PEACE))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.ENABLE_AUTO_ITEM)
|
||||||
|
{
|
||||||
|
ITEMS: for (int itemId : player.getAutoUseSettings().getAutoSupplyItems())
|
||||||
|
{
|
||||||
|
final ItemInstance item = player.getInventory().getItemByItemId(itemId);
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSupplyItems().remove(itemId);
|
||||||
|
continue ITEMS; // TODO: break?
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ItemSkillHolder itemSkillHolder : item.getItem().getAllSkills())
|
||||||
|
{
|
||||||
|
final Skill skill = itemSkillHolder.getSkill();
|
||||||
|
if (player.isAffectedBySkill(skill.getId()) || player.hasSkillReuse(skill.getReuseHashCode()) || !skill.checkCondition(player, player, false))
|
||||||
|
{
|
||||||
|
continue ITEMS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final int reuseDelay = item.getReuseDelay();
|
||||||
|
if ((reuseDelay <= 0) || (player.getItemRemainingReuseTime(item.getObjectId()) <= 0))
|
||||||
|
{
|
||||||
|
final EtcItem etcItem = item.getEtcItem();
|
||||||
|
final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem);
|
||||||
|
if ((handler != null) && handler.useItem(player, item, false) && (reuseDelay > 0))
|
||||||
|
{
|
||||||
|
player.addTimeStampItem(item, reuseDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.ENABLE_AUTO_POTION && (player.getCurrentHpPercent() <= player.getAutoPlaySettings().getAutoPotionPercent()))
|
||||||
|
{
|
||||||
|
POTIONS: for (int itemId : player.getAutoUseSettings().getAutoPotionItems())
|
||||||
|
{
|
||||||
|
final ItemInstance item = player.getInventory().getItemByItemId(itemId);
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoPotionItems().remove(itemId);
|
||||||
|
continue POTIONS; // TODO: break?
|
||||||
|
}
|
||||||
|
final int reuseDelay = item.getReuseDelay();
|
||||||
|
if ((reuseDelay <= 0) || (player.getItemRemainingReuseTime(item.getObjectId()) <= 0))
|
||||||
|
{
|
||||||
|
final EtcItem etcItem = item.getEtcItem();
|
||||||
|
final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem);
|
||||||
|
if ((handler != null) && handler.useItem(player, item, false) && (reuseDelay > 0))
|
||||||
|
{
|
||||||
|
player.addTimeStampItem(item, reuseDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.ENABLE_AUTO_BUFF)
|
||||||
|
{
|
||||||
|
BUFFS: for (int skillId : player.getAutoUseSettings().getAutoSkills())
|
||||||
|
{
|
||||||
|
final Skill skill = player.getKnownSkill(skillId);
|
||||||
|
if (skill == null)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSkills().remove(skillId);
|
||||||
|
continue BUFFS; // TODO: break?
|
||||||
|
}
|
||||||
|
if (!player.isAffectedBySkill(skillId) && !player.hasSkillReuse(skill.getReuseHashCode()) && skill.checkCondition(player, player, false))
|
||||||
|
{
|
||||||
|
// Summon check.
|
||||||
|
if (skill.getAffectScope() == AffectScope.SUMMON_EXCEPT_MASTER)
|
||||||
|
{
|
||||||
|
if (!player.hasServitors()) // Is this check truly needed?
|
||||||
|
{
|
||||||
|
continue BUFFS;
|
||||||
|
}
|
||||||
|
int occurrences = 0;
|
||||||
|
for (Summon servitor : player.getServitors().values())
|
||||||
|
{
|
||||||
|
if (servitor.isAffectedBySkill(skillId))
|
||||||
|
{
|
||||||
|
occurrences++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (occurrences == player.getServitors().size())
|
||||||
|
{
|
||||||
|
continue BUFFS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.doCast(skill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_working = false;
|
||||||
|
}, 1000, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startAutoUseTask(PlayerInstance player)
|
||||||
|
{
|
||||||
|
if (!PLAYERS.contains(player))
|
||||||
|
{
|
||||||
|
PLAYERS.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopAutoUseTask(PlayerInstance player)
|
||||||
|
{
|
||||||
|
PLAYERS.remove(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAutoSupplyItem(PlayerInstance player, int itemId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSupplyItems().add(itemId);
|
||||||
|
startAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAutoSupplyItem(PlayerInstance player, int itemId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSupplyItems().remove(itemId);
|
||||||
|
stopAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAutoPotionItem(PlayerInstance player, int itemId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoPotionItems().add(itemId);
|
||||||
|
startAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAutoPotionItem(PlayerInstance player, int itemId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoPotionItems().remove(itemId);
|
||||||
|
stopAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAutoSkill(PlayerInstance player, int skillId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSkills().add(skillId);
|
||||||
|
startAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAutoSkill(PlayerInstance player, int skillId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSkills().remove(skillId);
|
||||||
|
stopAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AutoUseTaskManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final AutoUseTaskManager INSTANCE = new AutoUseTaskManager();
|
||||||
|
}
|
||||||
|
}
|
@ -40,7 +40,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -223,10 +222,11 @@ import org.l2jmobius.gameserver.model.events.returns.TerminateReturn;
|
|||||||
import org.l2jmobius.gameserver.model.events.timers.TimerHolder;
|
import org.l2jmobius.gameserver.model.events.timers.TimerHolder;
|
||||||
import org.l2jmobius.gameserver.model.fishing.Fishing;
|
import org.l2jmobius.gameserver.model.fishing.Fishing;
|
||||||
import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
|
import org.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.AutoPlaySettingsHolder;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.AutoUseSettingsHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.DamageTakenHolder;
|
import org.l2jmobius.gameserver.model.holders.DamageTakenHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
|
import org.l2jmobius.gameserver.model.holders.ElementalSpiritDataHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.ItemHolder;
|
import org.l2jmobius.gameserver.model.holders.ItemHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.ItemSkillHolder;
|
|
||||||
import org.l2jmobius.gameserver.model.holders.MovieHolder;
|
import org.l2jmobius.gameserver.model.holders.MovieHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.PlayerEventHolder;
|
import org.l2jmobius.gameserver.model.holders.PlayerEventHolder;
|
||||||
import org.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder;
|
import org.l2jmobius.gameserver.model.holders.PreparedMultisellListHolder;
|
||||||
@ -267,7 +267,6 @@ import org.l2jmobius.gameserver.model.skills.CommonSkill;
|
|||||||
import org.l2jmobius.gameserver.model.skills.Skill;
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.skills.SkillCaster;
|
import org.l2jmobius.gameserver.model.skills.SkillCaster;
|
||||||
import org.l2jmobius.gameserver.model.skills.SkillCastingType;
|
import org.l2jmobius.gameserver.model.skills.SkillCastingType;
|
||||||
import org.l2jmobius.gameserver.model.skills.targets.AffectScope;
|
|
||||||
import org.l2jmobius.gameserver.model.skills.targets.TargetType;
|
import org.l2jmobius.gameserver.model.skills.targets.TargetType;
|
||||||
import org.l2jmobius.gameserver.model.stats.BaseStat;
|
import org.l2jmobius.gameserver.model.stats.BaseStat;
|
||||||
import org.l2jmobius.gameserver.model.stats.Formulas;
|
import org.l2jmobius.gameserver.model.stats.Formulas;
|
||||||
@ -348,7 +347,6 @@ import org.l2jmobius.gameserver.network.serverpackets.TradeOtherDone;
|
|||||||
import org.l2jmobius.gameserver.network.serverpackets.TradeStart;
|
import org.l2jmobius.gameserver.network.serverpackets.TradeStart;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
|
import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
|
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlayDoMacro;
|
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
|
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
|
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.sessionzones.TimedHuntingZoneExit;
|
import org.l2jmobius.gameserver.network.serverpackets.sessionzones.TimedHuntingZoneExit;
|
||||||
@ -866,15 +864,8 @@ public class PlayerInstance extends Playable
|
|||||||
private ElementalSpirit[] _spirits;
|
private ElementalSpirit[] _spirits;
|
||||||
private ElementalType _activeElementalSpiritType;
|
private ElementalType _activeElementalSpiritType;
|
||||||
|
|
||||||
private ScheduledFuture<?> _autoPlayTask = null;
|
private final AutoPlaySettingsHolder _autoPlaySettings = new AutoPlaySettingsHolder();
|
||||||
private ScheduledFuture<?> _autoUseTask = null;
|
private final AutoUseSettingsHolder _autoUseSettings = new AutoUseSettingsHolder();
|
||||||
private final AtomicBoolean _pickup = new AtomicBoolean();
|
|
||||||
private final AtomicBoolean _longRange = new AtomicBoolean();
|
|
||||||
private final AtomicBoolean _respectfulHunting = new AtomicBoolean();
|
|
||||||
private final AtomicInteger _autoPotionPercent = new AtomicInteger();
|
|
||||||
private final Collection<Integer> _autoSupplyItems = ConcurrentHashMap.newKeySet();
|
|
||||||
private final Collection<Integer> _autoPotionItems = ConcurrentHashMap.newKeySet();
|
|
||||||
private final Collection<Integer> _autoSkills = ConcurrentHashMap.newKeySet();
|
|
||||||
|
|
||||||
private ScheduledFuture<?> _timedHuntingZoneFinishTask = null;
|
private ScheduledFuture<?> _timedHuntingZoneFinishTask = null;
|
||||||
|
|
||||||
@ -13714,16 +13705,6 @@ public class PlayerInstance extends Playable
|
|||||||
_autoSaveTask.cancel(false);
|
_autoSaveTask.cancel(false);
|
||||||
_autoSaveTask = null;
|
_autoSaveTask = null;
|
||||||
}
|
}
|
||||||
if ((_autoPlayTask != null) && !_autoPlayTask.isDone() && !_autoPlayTask.isCancelled())
|
|
||||||
{
|
|
||||||
_autoPlayTask.cancel(false);
|
|
||||||
_autoPlayTask = null;
|
|
||||||
}
|
|
||||||
if ((_autoUseTask != null) && !_autoUseTask.isDone() && !_autoUseTask.isCancelled())
|
|
||||||
{
|
|
||||||
_autoUseTask.cancel(false);
|
|
||||||
_autoUseTask = null;
|
|
||||||
}
|
|
||||||
if ((_timedHuntingZoneFinishTask != null) && !_timedHuntingZoneFinishTask.isDone() && !_timedHuntingZoneFinishTask.isCancelled())
|
if ((_timedHuntingZoneFinishTask != null) && !_timedHuntingZoneFinishTask.isDone() && !_timedHuntingZoneFinishTask.isCancelled())
|
||||||
{
|
{
|
||||||
_timedHuntingZoneFinishTask.cancel(false);
|
_timedHuntingZoneFinishTask.cancel(false);
|
||||||
@ -14117,274 +14098,14 @@ public class PlayerInstance extends Playable
|
|||||||
return AttackStanceTaskManager.getInstance().hasAttackStanceTask(this);
|
return AttackStanceTaskManager.getInstance().hasAttackStanceTask(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopAutoPlayTask()
|
public AutoPlaySettingsHolder getAutoPlaySettings()
|
||||||
{
|
{
|
||||||
if ((_autoPlayTask != null) && !_autoPlayTask.isCancelled() && !_autoPlayTask.isDone())
|
return _autoPlaySettings;
|
||||||
{
|
|
||||||
_autoPlayTask.cancel(true);
|
|
||||||
_autoPlayTask = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startAutoPlayTask(boolean pickup, boolean longRange, boolean respectfulHunting)
|
public AutoUseSettingsHolder getAutoUseSettings()
|
||||||
{
|
{
|
||||||
_pickup.set(pickup);
|
return _autoUseSettings;
|
||||||
_longRange.set(longRange);
|
|
||||||
_respectfulHunting.set(respectfulHunting);
|
|
||||||
|
|
||||||
if (_autoPlayTask != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_autoPlayTask = ThreadPool.scheduleAtFixedRate(() ->
|
|
||||||
{
|
|
||||||
if (!Config.ENABLE_AUTO_PLAY)
|
|
||||||
{
|
|
||||||
stopAutoPlayTask();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip thinking.
|
|
||||||
final WorldObject target = getTarget();
|
|
||||||
if ((target != null) && target.isMonster())
|
|
||||||
{
|
|
||||||
final MonsterInstance monster = (MonsterInstance) target;
|
|
||||||
if ((monster.getTarget() == this) && !monster.isAlikeDead())
|
|
||||||
{
|
|
||||||
// Check if actually attacking.
|
|
||||||
if (hasAI() && getAI().isAutoAttacking() && !isAttackingNow() && !isCastingNow())
|
|
||||||
{
|
|
||||||
doAutoAttack(monster);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pickup.
|
|
||||||
if (_pickup.get())
|
|
||||||
{
|
|
||||||
for (ItemInstance droppedItem : World.getInstance().getVisibleObjectsInRange(this, ItemInstance.class, 200))
|
|
||||||
{
|
|
||||||
// Check if item is reachable.
|
|
||||||
if ((droppedItem == null) //
|
|
||||||
|| (!droppedItem.isSpawned()) //
|
|
||||||
|| !GeoEngine.getInstance().canMoveToTarget(getX(), getY(), getZ(), droppedItem.getX(), droppedItem.getY(), droppedItem.getZ(), getInstanceWorld()))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move to item.
|
|
||||||
if (calculateDistance2D(droppedItem) > 50)
|
|
||||||
{
|
|
||||||
moveToLocation(droppedItem.getX(), droppedItem.getY(), droppedItem.getZ(), 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to pick it up.
|
|
||||||
if (!droppedItem.isProtected() || (droppedItem.getOwnerId() == getObjectId()))
|
|
||||||
{
|
|
||||||
doPickupItem(droppedItem);
|
|
||||||
return; // Avoid pickup being skipped.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find target.
|
|
||||||
MonsterInstance monster = null;
|
|
||||||
double closestDistance = Double.MAX_VALUE;
|
|
||||||
for (MonsterInstance nearby : World.getInstance().getVisibleObjectsInRange(this, MonsterInstance.class, _longRange.get() ? 1400 : 600))
|
|
||||||
{
|
|
||||||
// Skip unavailable monsters.
|
|
||||||
if ((nearby == null) || nearby.isAlikeDead())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Check monster target.
|
|
||||||
if (_respectfulHunting.get() && (nearby.getTarget() != null) && (nearby.getTarget() != this))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Check if monster is reachable.
|
|
||||||
if (nearby.isAutoAttackable(this) //
|
|
||||||
&& GeoEngine.getInstance().canSeeTarget(this, nearby)//
|
|
||||||
&& GeoEngine.getInstance().canMoveToTarget(getX(), getY(), getZ(), nearby.getX(), nearby.getY(), nearby.getZ(), getInstanceWorld()))
|
|
||||||
{
|
|
||||||
final double monsterDistance = calculateDistance2D(nearby);
|
|
||||||
if (monsterDistance < closestDistance)
|
|
||||||
{
|
|
||||||
monster = nearby;
|
|
||||||
closestDistance = monsterDistance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New target was assigned.
|
|
||||||
if (monster != null)
|
|
||||||
{
|
|
||||||
setTarget(monster);
|
|
||||||
sendPacket(ExAutoPlayDoMacro.STATIC_PACKET);
|
|
||||||
}
|
|
||||||
}, 0, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopAutoUseTask()
|
|
||||||
{
|
|
||||||
if ((_autoUseTask != null) && !_autoUseTask.isCancelled() && !_autoUseTask.isDone())
|
|
||||||
{
|
|
||||||
_autoUseTask.cancel(true);
|
|
||||||
_autoUseTask = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startAutoUseTask()
|
|
||||||
{
|
|
||||||
if (_autoUseTask != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_autoUseTask = ThreadPool.scheduleAtFixedRate(() ->
|
|
||||||
{
|
|
||||||
if (hasBlockActions() || isControlBlocked() || isAlikeDead() || isInsideZone(ZoneId.PEACE))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.ENABLE_AUTO_ITEM)
|
|
||||||
{
|
|
||||||
ITEMS: for (int itemId : _autoSupplyItems)
|
|
||||||
{
|
|
||||||
final ItemInstance item = _inventory.getItemByItemId(itemId);
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
removeAutoSupplyItem(itemId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ItemSkillHolder itemSkillHolder : item.getItem().getAllSkills())
|
|
||||||
{
|
|
||||||
final Skill skill = itemSkillHolder.getSkill();
|
|
||||||
if (isAffectedBySkill(skill.getId()) || hasSkillReuse(skill.getReuseHashCode()) || !skill.checkCondition(this, this, false))
|
|
||||||
{
|
|
||||||
continue ITEMS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final int reuseDelay = item.getReuseDelay();
|
|
||||||
if ((reuseDelay <= 0) || (getItemRemainingReuseTime(item.getObjectId()) <= 0))
|
|
||||||
{
|
|
||||||
final EtcItem etcItem = item.getEtcItem();
|
|
||||||
final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem);
|
|
||||||
if ((handler != null) && handler.useItem(this, item, false) && (reuseDelay > 0))
|
|
||||||
{
|
|
||||||
addTimeStampItem(item, reuseDelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.ENABLE_AUTO_POTION && (getCurrentHpPercent() <= _autoPotionPercent.get()))
|
|
||||||
{
|
|
||||||
for (int itemId : _autoPotionItems)
|
|
||||||
{
|
|
||||||
final ItemInstance item = _inventory.getItemByItemId(itemId);
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
removeAutoPotionItem(itemId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final int reuseDelay = item.getReuseDelay();
|
|
||||||
if ((reuseDelay <= 0) || (getItemRemainingReuseTime(item.getObjectId()) <= 0))
|
|
||||||
{
|
|
||||||
final EtcItem etcItem = item.getEtcItem();
|
|
||||||
final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem);
|
|
||||||
if ((handler != null) && handler.useItem(this, item, false) && (reuseDelay > 0))
|
|
||||||
{
|
|
||||||
addTimeStampItem(item, reuseDelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.ENABLE_AUTO_BUFF)
|
|
||||||
{
|
|
||||||
for (int skillId : _autoSkills)
|
|
||||||
{
|
|
||||||
final Skill skill = getKnownSkill(skillId);
|
|
||||||
if (skill == null)
|
|
||||||
{
|
|
||||||
removeAutoSkill(skillId);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!isAffectedBySkill(skillId) && !hasSkillReuse(skill.getReuseHashCode()) && skill.checkCondition(this, this, false))
|
|
||||||
{
|
|
||||||
// Summon check.
|
|
||||||
if (skill.getAffectScope() == AffectScope.SUMMON_EXCEPT_MASTER)
|
|
||||||
{
|
|
||||||
if (!hasServitors()) // Is this check truly needed?
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int occurrences = 0;
|
|
||||||
for (Summon servitor : _servitors.values())
|
|
||||||
{
|
|
||||||
if (servitor.isAffectedBySkill(skillId))
|
|
||||||
{
|
|
||||||
occurrences++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (occurrences == _servitors.size())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doCast(skill);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 0, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAutoPotionPercent(int value)
|
|
||||||
{
|
|
||||||
_autoPotionPercent.set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAutoSupplyItem(int itemId)
|
|
||||||
{
|
|
||||||
_autoSupplyItems.add(itemId);
|
|
||||||
startAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAutoSupplyItem(int itemId)
|
|
||||||
{
|
|
||||||
_autoSupplyItems.remove(itemId);
|
|
||||||
stopAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAutoPotionItem(int itemId)
|
|
||||||
{
|
|
||||||
_autoPotionItems.add(itemId);
|
|
||||||
startAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAutoPotionItem(int itemId)
|
|
||||||
{
|
|
||||||
_autoPotionItems.remove(itemId);
|
|
||||||
stopAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAutoSkill(int skillId)
|
|
||||||
{
|
|
||||||
_autoSkills.add(skillId);
|
|
||||||
startAutoUseTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAutoSkill(int skillId)
|
|
||||||
{
|
|
||||||
_autoSkills.remove(skillId);
|
|
||||||
stopAutoUseTask();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInTimedHuntingZone()
|
public boolean isInTimedHuntingZone()
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.l2jmobius.gameserver.model.holders;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class AutoPlaySettingsHolder
|
||||||
|
{
|
||||||
|
private final AtomicBoolean _pickup = new AtomicBoolean();
|
||||||
|
private final AtomicBoolean _longRange = new AtomicBoolean();
|
||||||
|
private final AtomicBoolean _respectfulHunting = new AtomicBoolean();
|
||||||
|
private final AtomicInteger _autoPotionPercent = new AtomicInteger();
|
||||||
|
|
||||||
|
public AutoPlaySettingsHolder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean doPickup()
|
||||||
|
{
|
||||||
|
return _pickup.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPickup(boolean value)
|
||||||
|
{
|
||||||
|
_pickup.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLongRange()
|
||||||
|
{
|
||||||
|
return _longRange.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongRange(boolean value)
|
||||||
|
{
|
||||||
|
_longRange.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRespectfulHunting()
|
||||||
|
{
|
||||||
|
return _respectfulHunting.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRespectfulHunting(boolean value)
|
||||||
|
{
|
||||||
|
_respectfulHunting.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAutoPotionPercent()
|
||||||
|
{
|
||||||
|
return _autoPotionPercent.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoPotionPercent(int value)
|
||||||
|
{
|
||||||
|
_autoPotionPercent.set(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.l2jmobius.gameserver.model.holders;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class AutoUseSettingsHolder
|
||||||
|
{
|
||||||
|
private final Collection<Integer> _autoSupplyItems = ConcurrentHashMap.newKeySet();
|
||||||
|
private final Collection<Integer> _autoPotionItems = ConcurrentHashMap.newKeySet();
|
||||||
|
private final Collection<Integer> _autoSkills = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
|
public AutoUseSettingsHolder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Integer> getAutoSupplyItems()
|
||||||
|
{
|
||||||
|
return _autoSupplyItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Integer> getAutoPotionItems()
|
||||||
|
{
|
||||||
|
return _autoPotionItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Integer> getAutoSkills()
|
||||||
|
{
|
||||||
|
return _autoSkills;
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ package org.l2jmobius.gameserver.network.clientpackets;
|
|||||||
import org.l2jmobius.commons.network.PacketReader;
|
import org.l2jmobius.commons.network.PacketReader;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
import org.l2jmobius.gameserver.network.GameClient;
|
import org.l2jmobius.gameserver.network.GameClient;
|
||||||
|
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version $Revision: 1.3.4.2 $ $Date: 2005/03/27 15:29:30 $
|
* @version $Revision: 1.3.4.2 $ $Date: 2005/03/27 15:29:30 $
|
||||||
@ -57,11 +58,11 @@ public class RequestShortCutDel implements IClientIncomingPacket
|
|||||||
// Remove auto used ids.
|
// Remove auto used ids.
|
||||||
if (_slot > 263)
|
if (_slot > 263)
|
||||||
{
|
{
|
||||||
player.removeAutoSupplyItem(_id);
|
AutoUseTaskManager.getInstance().removeAutoSupplyItem(player, _id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player.removeAutoSkill(_id);
|
AutoUseTaskManager.getInstance().removeAutoSkill(player, _id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
|||||||
import org.l2jmobius.gameserver.network.GameClient;
|
import org.l2jmobius.gameserver.network.GameClient;
|
||||||
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
|
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySettingSend;
|
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySettingSend;
|
||||||
|
import org.l2jmobius.gameserver.taskmanager.AutoPlayTaskManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Mobius
|
* @author Mobius
|
||||||
@ -59,7 +60,7 @@ public class ExAutoPlaySetting implements IClientIncomingPacket
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.sendPacket(new ExAutoPlaySettingSend(_options, _active, _pickUp, _nextTargetMode, _longRange, _potionPercent, _respectfulHunting));
|
player.sendPacket(new ExAutoPlaySettingSend(_options, _active, _pickUp, _nextTargetMode, _longRange, _potionPercent, _respectfulHunting));
|
||||||
player.setAutoPotionPercent(_potionPercent);
|
player.getAutoPlaySettings().setAutoPotionPercent(_potionPercent);
|
||||||
|
|
||||||
if (!Config.ENABLE_AUTO_PLAY)
|
if (!Config.ENABLE_AUTO_PLAY)
|
||||||
{
|
{
|
||||||
@ -68,11 +69,11 @@ public class ExAutoPlaySetting implements IClientIncomingPacket
|
|||||||
|
|
||||||
if (_active)
|
if (_active)
|
||||||
{
|
{
|
||||||
player.startAutoPlayTask(_pickUp, _longRange, _respectfulHunting);
|
AutoPlayTaskManager.getInstance().doAutoPlay(player, _pickUp, _longRange, _respectfulHunting);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
player.stopAutoPlayTask();
|
AutoPlayTaskManager.getInstance().stopAutoPlay(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import org.l2jmobius.gameserver.model.skills.Skill;
|
|||||||
import org.l2jmobius.gameserver.network.GameClient;
|
import org.l2jmobius.gameserver.network.GameClient;
|
||||||
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
|
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExActivateAutoShortcut;
|
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExActivateAutoShortcut;
|
||||||
|
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author JoeAlisson, Mobius
|
* @author JoeAlisson, Mobius
|
||||||
@ -75,17 +76,17 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
|||||||
// auto supply
|
// auto supply
|
||||||
if (_room > 263)
|
if (_room > 263)
|
||||||
{
|
{
|
||||||
player.removeAutoSupplyItem(item.getId());
|
AutoUseTaskManager.getInstance().removeAutoSupplyItem(player, item.getId());
|
||||||
}
|
}
|
||||||
else // auto potion
|
else // auto potion
|
||||||
{
|
{
|
||||||
player.removeAutoPotionItem(item.getId());
|
AutoUseTaskManager.getInstance().removeAutoPotionItem(player, item.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// auto skill
|
// auto skill
|
||||||
if (skill != null)
|
if (skill != null)
|
||||||
{
|
{
|
||||||
player.removeAutoSkill(skill.getId());
|
AutoUseTaskManager.getInstance().removeAutoSkill(player, skill.getId());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -96,7 +97,7 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
|||||||
// auto supply
|
// auto supply
|
||||||
if (Config.ENABLE_AUTO_ITEM && (item != null))
|
if (Config.ENABLE_AUTO_ITEM && (item != null))
|
||||||
{
|
{
|
||||||
player.addAutoSupplyItem(item.getId());
|
AutoUseTaskManager.getInstance().addAutoSupplyItem(player, item.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -106,14 +107,14 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
|||||||
{
|
{
|
||||||
if (Config.ENABLE_AUTO_POTION && (item != null) && item.isPotion())
|
if (Config.ENABLE_AUTO_POTION && (item != null) && item.isPotion())
|
||||||
{
|
{
|
||||||
player.addAutoPotionItem(item.getId());
|
AutoUseTaskManager.getInstance().addAutoPotionItem(player, item.getId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// auto skill
|
// auto skill
|
||||||
if (Config.ENABLE_AUTO_BUFF && (skill != null))
|
if (Config.ENABLE_AUTO_BUFF && (skill != null))
|
||||||
{
|
{
|
||||||
player.addAutoSkill(skill.getId());
|
AutoUseTaskManager.getInstance().addAutoSkill(player, skill.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.l2jmobius.gameserver.taskmanager;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
|
||||||
|
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlayDoMacro;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class AutoPlayTaskManager
|
||||||
|
{
|
||||||
|
private static final Set<PlayerInstance> PLAYERS = ConcurrentHashMap.newKeySet();
|
||||||
|
private static boolean _working = false;
|
||||||
|
|
||||||
|
public AutoPlayTaskManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_working)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_working = true;
|
||||||
|
|
||||||
|
PLAY: for (PlayerInstance player : PLAYERS)
|
||||||
|
{
|
||||||
|
if (!player.isOnline() || player.isInOfflineMode() || !Config.ENABLE_AUTO_PLAY)
|
||||||
|
{
|
||||||
|
stopAutoPlay(player);
|
||||||
|
continue PLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip thinking.
|
||||||
|
final WorldObject target = player.getTarget();
|
||||||
|
if ((target != null) && target.isMonster())
|
||||||
|
{
|
||||||
|
final MonsterInstance monster = (MonsterInstance) target;
|
||||||
|
if ((monster.getTarget() == player) && !monster.isAlikeDead())
|
||||||
|
{
|
||||||
|
// Check if actually attacking.
|
||||||
|
if (player.hasAI() && player.getAI().isAutoAttacking() && !player.isAttackingNow() && !player.isCastingNow())
|
||||||
|
{
|
||||||
|
player.doAutoAttack(monster);
|
||||||
|
}
|
||||||
|
continue PLAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup.
|
||||||
|
if (player.getAutoPlaySettings().doPickup())
|
||||||
|
{
|
||||||
|
PICKUP: for (ItemInstance droppedItem : World.getInstance().getVisibleObjectsInRange(player, ItemInstance.class, 200))
|
||||||
|
{
|
||||||
|
// Check if item is reachable.
|
||||||
|
if ((droppedItem == null) //
|
||||||
|
|| (!droppedItem.isSpawned()) //
|
||||||
|
|| !GeoEngine.getInstance().canMoveToTarget(player.getX(), player.getY(), player.getZ(), droppedItem.getX(), droppedItem.getY(), droppedItem.getZ(), player.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
continue PICKUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to item.
|
||||||
|
if (player.calculateDistance2D(droppedItem) > 50)
|
||||||
|
{
|
||||||
|
player.moveToLocation(droppedItem.getX(), droppedItem.getY(), droppedItem.getZ(), 0);
|
||||||
|
continue PLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to pick it up.
|
||||||
|
if (!droppedItem.isProtected() || (droppedItem.getOwnerId() == player.getObjectId()))
|
||||||
|
{
|
||||||
|
player.doPickupItem(droppedItem);
|
||||||
|
continue PLAY; // Avoid pickup being skipped.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find target.
|
||||||
|
MonsterInstance monster = null;
|
||||||
|
double closestDistance = Double.MAX_VALUE;
|
||||||
|
TARGET: for (MonsterInstance nearby : World.getInstance().getVisibleObjectsInRange(player, MonsterInstance.class, player.getAutoPlaySettings().isLongRange() ? 1400 : 600))
|
||||||
|
{
|
||||||
|
// Skip unavailable monsters.
|
||||||
|
if ((nearby == null) || nearby.isAlikeDead())
|
||||||
|
{
|
||||||
|
continue TARGET;
|
||||||
|
}
|
||||||
|
// Check monster target.
|
||||||
|
if (player.getAutoPlaySettings().isRespectfulHunting() && (nearby.getTarget() != null) && (nearby.getTarget() != player))
|
||||||
|
{
|
||||||
|
continue TARGET;
|
||||||
|
}
|
||||||
|
// Check if monster is reachable.
|
||||||
|
if (nearby.isAutoAttackable(player) //
|
||||||
|
&& GeoEngine.getInstance().canSeeTarget(player, nearby)//
|
||||||
|
&& GeoEngine.getInstance().canMoveToTarget(player.getX(), player.getY(), player.getZ(), nearby.getX(), nearby.getY(), nearby.getZ(), player.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
final double monsterDistance = player.calculateDistance2D(nearby);
|
||||||
|
if (monsterDistance < closestDistance)
|
||||||
|
{
|
||||||
|
monster = nearby;
|
||||||
|
closestDistance = monsterDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New target was assigned.
|
||||||
|
if (monster != null)
|
||||||
|
{
|
||||||
|
player.setTarget(monster);
|
||||||
|
player.sendPacket(ExAutoPlayDoMacro.STATIC_PACKET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_working = false;
|
||||||
|
}, 1000, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doAutoPlay(PlayerInstance player, boolean pickup, boolean longRange, boolean respectfulHunting)
|
||||||
|
{
|
||||||
|
player.getAutoPlaySettings().setPickup(pickup);
|
||||||
|
player.getAutoPlaySettings().setLongRange(longRange);
|
||||||
|
player.getAutoPlaySettings().setRespectfulHunting(respectfulHunting);
|
||||||
|
|
||||||
|
if (!PLAYERS.contains(player))
|
||||||
|
{
|
||||||
|
PLAYERS.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopAutoPlay(PlayerInstance player)
|
||||||
|
{
|
||||||
|
PLAYERS.remove(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AutoPlayTaskManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final AutoPlayTaskManager INSTANCE = new AutoPlayTaskManager();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.l2jmobius.gameserver.taskmanager;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.l2jmobius.Config;
|
||||||
|
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||||
|
import org.l2jmobius.gameserver.handler.IItemHandler;
|
||||||
|
import org.l2jmobius.gameserver.handler.ItemHandler;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Summon;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.ItemSkillHolder;
|
||||||
|
import org.l2jmobius.gameserver.model.items.EtcItem;
|
||||||
|
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.targets.AffectScope;
|
||||||
|
import org.l2jmobius.gameserver.model.zone.ZoneId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class AutoUseTaskManager
|
||||||
|
{
|
||||||
|
private static final Set<PlayerInstance> PLAYERS = ConcurrentHashMap.newKeySet();
|
||||||
|
private static boolean _working = false;
|
||||||
|
|
||||||
|
public AutoUseTaskManager()
|
||||||
|
{
|
||||||
|
ThreadPool.scheduleAtFixedRate(() ->
|
||||||
|
{
|
||||||
|
if (_working)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_working = true;
|
||||||
|
|
||||||
|
for (PlayerInstance player : PLAYERS)
|
||||||
|
{
|
||||||
|
if (!player.isOnline() || player.isInOfflineMode())
|
||||||
|
{
|
||||||
|
stopAutoUseTask(player);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.hasBlockActions() || player.isControlBlocked() || player.isAlikeDead() || player.isInsideZone(ZoneId.PEACE))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.ENABLE_AUTO_ITEM)
|
||||||
|
{
|
||||||
|
ITEMS: for (int itemId : player.getAutoUseSettings().getAutoSupplyItems())
|
||||||
|
{
|
||||||
|
final ItemInstance item = player.getInventory().getItemByItemId(itemId);
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSupplyItems().remove(itemId);
|
||||||
|
continue ITEMS; // TODO: break?
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ItemSkillHolder itemSkillHolder : item.getItem().getAllSkills())
|
||||||
|
{
|
||||||
|
final Skill skill = itemSkillHolder.getSkill();
|
||||||
|
if (player.isAffectedBySkill(skill.getId()) || player.hasSkillReuse(skill.getReuseHashCode()) || !skill.checkCondition(player, player, false))
|
||||||
|
{
|
||||||
|
continue ITEMS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final int reuseDelay = item.getReuseDelay();
|
||||||
|
if ((reuseDelay <= 0) || (player.getItemRemainingReuseTime(item.getObjectId()) <= 0))
|
||||||
|
{
|
||||||
|
final EtcItem etcItem = item.getEtcItem();
|
||||||
|
final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem);
|
||||||
|
if ((handler != null) && handler.useItem(player, item, false) && (reuseDelay > 0))
|
||||||
|
{
|
||||||
|
player.addTimeStampItem(item, reuseDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.ENABLE_AUTO_POTION && (player.getCurrentHpPercent() <= player.getAutoPlaySettings().getAutoPotionPercent()))
|
||||||
|
{
|
||||||
|
POTIONS: for (int itemId : player.getAutoUseSettings().getAutoPotionItems())
|
||||||
|
{
|
||||||
|
final ItemInstance item = player.getInventory().getItemByItemId(itemId);
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoPotionItems().remove(itemId);
|
||||||
|
continue POTIONS; // TODO: break?
|
||||||
|
}
|
||||||
|
final int reuseDelay = item.getReuseDelay();
|
||||||
|
if ((reuseDelay <= 0) || (player.getItemRemainingReuseTime(item.getObjectId()) <= 0))
|
||||||
|
{
|
||||||
|
final EtcItem etcItem = item.getEtcItem();
|
||||||
|
final IItemHandler handler = ItemHandler.getInstance().getHandler(etcItem);
|
||||||
|
if ((handler != null) && handler.useItem(player, item, false) && (reuseDelay > 0))
|
||||||
|
{
|
||||||
|
player.addTimeStampItem(item, reuseDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.ENABLE_AUTO_BUFF)
|
||||||
|
{
|
||||||
|
BUFFS: for (int skillId : player.getAutoUseSettings().getAutoSkills())
|
||||||
|
{
|
||||||
|
final Skill skill = player.getKnownSkill(skillId);
|
||||||
|
if (skill == null)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSkills().remove(skillId);
|
||||||
|
continue BUFFS; // TODO: break?
|
||||||
|
}
|
||||||
|
if (!player.isAffectedBySkill(skillId) && !player.hasSkillReuse(skill.getReuseHashCode()) && skill.checkCondition(player, player, false))
|
||||||
|
{
|
||||||
|
// Summon check.
|
||||||
|
if (skill.getAffectScope() == AffectScope.SUMMON_EXCEPT_MASTER)
|
||||||
|
{
|
||||||
|
if (!player.hasServitors()) // Is this check truly needed?
|
||||||
|
{
|
||||||
|
continue BUFFS;
|
||||||
|
}
|
||||||
|
int occurrences = 0;
|
||||||
|
for (Summon servitor : player.getServitors().values())
|
||||||
|
{
|
||||||
|
if (servitor.isAffectedBySkill(skillId))
|
||||||
|
{
|
||||||
|
occurrences++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (occurrences == player.getServitors().size())
|
||||||
|
{
|
||||||
|
continue BUFFS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.doCast(skill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_working = false;
|
||||||
|
}, 1000, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startAutoUseTask(PlayerInstance player)
|
||||||
|
{
|
||||||
|
if (!PLAYERS.contains(player))
|
||||||
|
{
|
||||||
|
PLAYERS.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopAutoUseTask(PlayerInstance player)
|
||||||
|
{
|
||||||
|
PLAYERS.remove(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAutoSupplyItem(PlayerInstance player, int itemId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSupplyItems().add(itemId);
|
||||||
|
startAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAutoSupplyItem(PlayerInstance player, int itemId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSupplyItems().remove(itemId);
|
||||||
|
stopAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAutoPotionItem(PlayerInstance player, int itemId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoPotionItems().add(itemId);
|
||||||
|
startAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAutoPotionItem(PlayerInstance player, int itemId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoPotionItems().remove(itemId);
|
||||||
|
stopAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAutoSkill(PlayerInstance player, int skillId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSkills().add(skillId);
|
||||||
|
startAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAutoSkill(PlayerInstance player, int skillId)
|
||||||
|
{
|
||||||
|
player.getAutoUseSettings().getAutoSkills().remove(skillId);
|
||||||
|
stopAutoUseTask(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AutoUseTaskManager getInstance()
|
||||||
|
{
|
||||||
|
return SingletonHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SingletonHolder
|
||||||
|
{
|
||||||
|
protected static final AutoUseTaskManager INSTANCE = new AutoUseTaskManager();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user