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.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
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.fishing.Fishing;
|
||||
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.ItemHolder;
|
||||
import org.l2jmobius.gameserver.model.holders.ItemSkillHolder;
|
||||
import org.l2jmobius.gameserver.model.holders.MonsterBookCardHolder;
|
||||
import org.l2jmobius.gameserver.model.holders.MonsterBookRewardHolder;
|
||||
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.SkillCaster;
|
||||
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.stats.BaseStat;
|
||||
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.UserInfo;
|
||||
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.friend.FriendStatus;
|
||||
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 ScheduledFuture<?> _autoPlayTask = null;
|
||||
private ScheduledFuture<?> _autoUseTask = null;
|
||||
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 final AutoPlaySettingsHolder _autoPlaySettings = new AutoPlaySettingsHolder();
|
||||
private final AutoUseSettingsHolder _autoUseSettings = new AutoUseSettingsHolder();
|
||||
|
||||
private ScheduledFuture<?> _timedHuntingZoneFinishTask = null;
|
||||
|
||||
@ -13863,16 +13854,6 @@ public class PlayerInstance extends Playable
|
||||
_autoSaveTask.cancel(false);
|
||||
_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())
|
||||
{
|
||||
_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())
|
||||
{
|
||||
_autoPlayTask.cancel(true);
|
||||
_autoPlayTask = null;
|
||||
}
|
||||
return _autoPlaySettings;
|
||||
}
|
||||
|
||||
public void startAutoPlayTask(boolean pickup, boolean longRange, boolean respectfulHunting)
|
||||
public AutoUseSettingsHolder getAutoUseSettings()
|
||||
{
|
||||
_pickup.set(pickup);
|
||||
_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();
|
||||
return _autoUseSettings;
|
||||
}
|
||||
|
||||
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.gameserver.model.actor.instance.PlayerInstance;
|
||||
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 $
|
||||
@ -57,11 +58,11 @@ public class RequestShortCutDel implements IClientIncomingPacket
|
||||
// Remove auto used ids.
|
||||
if (_slot > 263)
|
||||
{
|
||||
player.removeAutoSupplyItem(_id);
|
||||
AutoUseTaskManager.getInstance().removeAutoSupplyItem(player, _id);
|
||||
}
|
||||
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.clientpackets.IClientIncomingPacket;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySettingSend;
|
||||
import org.l2jmobius.gameserver.taskmanager.AutoPlayTaskManager;
|
||||
|
||||
/**
|
||||
* @author Mobius
|
||||
@ -59,7 +60,7 @@ public class ExAutoPlaySetting implements IClientIncomingPacket
|
||||
}
|
||||
|
||||
player.sendPacket(new ExAutoPlaySettingSend(_options, _active, _pickUp, _nextTargetMode, _longRange, _potionPercent, _respectfulHunting));
|
||||
player.setAutoPotionPercent(_potionPercent);
|
||||
player.getAutoPlaySettings().setAutoPotionPercent(_potionPercent);
|
||||
|
||||
if (!Config.ENABLE_AUTO_PLAY)
|
||||
{
|
||||
@ -68,11 +69,11 @@ public class ExAutoPlaySetting implements IClientIncomingPacket
|
||||
|
||||
if (_active)
|
||||
{
|
||||
player.startAutoPlayTask(_pickUp, _longRange, _respectfulHunting);
|
||||
AutoPlayTaskManager.getInstance().doAutoPlay(player, _pickUp, _longRange, _respectfulHunting);
|
||||
}
|
||||
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.clientpackets.IClientIncomingPacket;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExActivateAutoShortcut;
|
||||
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
|
||||
|
||||
/**
|
||||
* @author JoeAlisson, Mobius
|
||||
@ -75,17 +76,17 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
||||
// auto supply
|
||||
if (_room > 263)
|
||||
{
|
||||
player.removeAutoSupplyItem(item.getId());
|
||||
AutoUseTaskManager.getInstance().removeAutoSupplyItem(player, item.getId());
|
||||
}
|
||||
else // auto potion
|
||||
{
|
||||
player.removeAutoPotionItem(item.getId());
|
||||
AutoUseTaskManager.getInstance().removeAutoPotionItem(player, item.getId());
|
||||
}
|
||||
}
|
||||
// auto skill
|
||||
if (skill != null)
|
||||
{
|
||||
player.removeAutoSkill(skill.getId());
|
||||
AutoUseTaskManager.getInstance().removeAutoSkill(player, skill.getId());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -96,7 +97,7 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
||||
// auto supply
|
||||
if (Config.ENABLE_AUTO_ITEM && (item != null))
|
||||
{
|
||||
player.addAutoSupplyItem(item.getId());
|
||||
AutoUseTaskManager.getInstance().addAutoSupplyItem(player, item.getId());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -106,14 +107,14 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
||||
{
|
||||
if (Config.ENABLE_AUTO_POTION && (item != null) && item.isPotion())
|
||||
{
|
||||
player.addAutoPotionItem(item.getId());
|
||||
AutoUseTaskManager.getInstance().addAutoPotionItem(player, item.getId());
|
||||
return;
|
||||
}
|
||||
}
|
||||
// auto skill
|
||||
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.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
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.fishing.Fishing;
|
||||
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.ElementalSpiritDataHolder;
|
||||
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.PlayerEventHolder;
|
||||
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.SkillCaster;
|
||||
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.stats.BaseStat;
|
||||
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.UserInfo;
|
||||
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.friend.FriendStatus;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.sessionzones.TimedHuntingZoneExit;
|
||||
@ -866,15 +864,8 @@ public class PlayerInstance extends Playable
|
||||
private ElementalSpirit[] _spirits;
|
||||
private ElementalType _activeElementalSpiritType;
|
||||
|
||||
private ScheduledFuture<?> _autoPlayTask = null;
|
||||
private ScheduledFuture<?> _autoUseTask = null;
|
||||
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 final AutoPlaySettingsHolder _autoPlaySettings = new AutoPlaySettingsHolder();
|
||||
private final AutoUseSettingsHolder _autoUseSettings = new AutoUseSettingsHolder();
|
||||
|
||||
private ScheduledFuture<?> _timedHuntingZoneFinishTask = null;
|
||||
|
||||
@ -13714,16 +13705,6 @@ public class PlayerInstance extends Playable
|
||||
_autoSaveTask.cancel(false);
|
||||
_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())
|
||||
{
|
||||
_timedHuntingZoneFinishTask.cancel(false);
|
||||
@ -14117,274 +14098,14 @@ public class PlayerInstance extends Playable
|
||||
return AttackStanceTaskManager.getInstance().hasAttackStanceTask(this);
|
||||
}
|
||||
|
||||
public void stopAutoPlayTask()
|
||||
public AutoPlaySettingsHolder getAutoPlaySettings()
|
||||
{
|
||||
if ((_autoPlayTask != null) && !_autoPlayTask.isCancelled() && !_autoPlayTask.isDone())
|
||||
{
|
||||
_autoPlayTask.cancel(true);
|
||||
_autoPlayTask = null;
|
||||
}
|
||||
return _autoPlaySettings;
|
||||
}
|
||||
|
||||
public void startAutoPlayTask(boolean pickup, boolean longRange, boolean respectfulHunting)
|
||||
public AutoUseSettingsHolder getAutoUseSettings()
|
||||
{
|
||||
_pickup.set(pickup);
|
||||
_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();
|
||||
return _autoUseSettings;
|
||||
}
|
||||
|
||||
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.gameserver.model.actor.instance.PlayerInstance;
|
||||
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 $
|
||||
@ -57,11 +58,11 @@ public class RequestShortCutDel implements IClientIncomingPacket
|
||||
// Remove auto used ids.
|
||||
if (_slot > 263)
|
||||
{
|
||||
player.removeAutoSupplyItem(_id);
|
||||
AutoUseTaskManager.getInstance().removeAutoSupplyItem(player, _id);
|
||||
}
|
||||
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.clientpackets.IClientIncomingPacket;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySettingSend;
|
||||
import org.l2jmobius.gameserver.taskmanager.AutoPlayTaskManager;
|
||||
|
||||
/**
|
||||
* @author Mobius
|
||||
@ -59,7 +60,7 @@ public class ExAutoPlaySetting implements IClientIncomingPacket
|
||||
}
|
||||
|
||||
player.sendPacket(new ExAutoPlaySettingSend(_options, _active, _pickUp, _nextTargetMode, _longRange, _potionPercent, _respectfulHunting));
|
||||
player.setAutoPotionPercent(_potionPercent);
|
||||
player.getAutoPlaySettings().setAutoPotionPercent(_potionPercent);
|
||||
|
||||
if (!Config.ENABLE_AUTO_PLAY)
|
||||
{
|
||||
@ -68,11 +69,11 @@ public class ExAutoPlaySetting implements IClientIncomingPacket
|
||||
|
||||
if (_active)
|
||||
{
|
||||
player.startAutoPlayTask(_pickUp, _longRange, _respectfulHunting);
|
||||
AutoPlayTaskManager.getInstance().doAutoPlay(player, _pickUp, _longRange, _respectfulHunting);
|
||||
}
|
||||
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.clientpackets.IClientIncomingPacket;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExActivateAutoShortcut;
|
||||
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
|
||||
|
||||
/**
|
||||
* @author JoeAlisson, Mobius
|
||||
@ -75,17 +76,17 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
||||
// auto supply
|
||||
if (_room > 263)
|
||||
{
|
||||
player.removeAutoSupplyItem(item.getId());
|
||||
AutoUseTaskManager.getInstance().removeAutoSupplyItem(player, item.getId());
|
||||
}
|
||||
else // auto potion
|
||||
{
|
||||
player.removeAutoPotionItem(item.getId());
|
||||
AutoUseTaskManager.getInstance().removeAutoPotionItem(player, item.getId());
|
||||
}
|
||||
}
|
||||
// auto skill
|
||||
if (skill != null)
|
||||
{
|
||||
player.removeAutoSkill(skill.getId());
|
||||
AutoUseTaskManager.getInstance().removeAutoSkill(player, skill.getId());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -96,7 +97,7 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
||||
// auto supply
|
||||
if (Config.ENABLE_AUTO_ITEM && (item != null))
|
||||
{
|
||||
player.addAutoSupplyItem(item.getId());
|
||||
AutoUseTaskManager.getInstance().addAutoSupplyItem(player, item.getId());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -106,14 +107,14 @@ public class ExRequestActivateAutoShortcut implements IClientIncomingPacket
|
||||
{
|
||||
if (Config.ENABLE_AUTO_POTION && (item != null) && item.isPotion())
|
||||
{
|
||||
player.addAutoPotionItem(item.getId());
|
||||
AutoUseTaskManager.getInstance().addAutoPotionItem(player, item.getId());
|
||||
return;
|
||||
}
|
||||
}
|
||||
// auto skill
|
||||
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