diff --git a/aCis_gs/java/net/sf/l2j/gameserver/handler/skillhandlers/SummonCreature.java b/aCis_gs/java/net/sf/l2j/gameserver/handler/skillhandlers/SummonCreature.java
index 4919749..18711bf 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/handler/skillhandlers/SummonCreature.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/handler/skillhandlers/SummonCreature.java
@@ -6,10 +6,12 @@
import net.sf.l2j.gameserver.enums.skills.SkillType;
import net.sf.l2j.gameserver.geoengine.GeoEngine;
import net.sf.l2j.gameserver.handler.ISkillHandler;
+import net.sf.l2j.gameserver.idfactory.IdFactory;
import net.sf.l2j.gameserver.model.World;
import net.sf.l2j.gameserver.model.WorldObject;
import net.sf.l2j.gameserver.model.actor.Creature;
import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.actor.instance.Agathion;
import net.sf.l2j.gameserver.model.actor.instance.Pet;
import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
import net.sf.l2j.gameserver.model.holder.IntIntHolder;
@@ -40,10 +42,6 @@
if (checkedItem.getOwnerId() != player.getObjectId() || checkedItem.getLocation() != ItemLocation.INVENTORY)
return;
- // Owner has a pet listed in world.
- if (World.getInstance().getPet(player.getObjectId()) != null)
- return;
-
// Check summon item validity.
final IntIntHolder summonItem = SummonItemData.getInstance().getSummonItem(checkedItem.getItemId());
if (summonItem == null)
@@ -54,6 +52,37 @@
if (npcTemplate == null)
return;
+ if (npcTemplate.getType().equalsIgnoreCase("Agathion"))
+ {
+ if (player.getAgathion() != null)
+ player.getAgathion().unSummon(player);
+
+ Agathion summon;
+ summon = new Agathion(IdFactory.getInstance().getNextId(), npcTemplate, player);
+// summon.setInstanceId(player.getInstanceId());
+ player.setAgathion(summon);
+
+ summon.setName(npcTemplate.getName());
+ summon.setTitle(player.getName());
+ summon.getStatus().setMaxHpMp();
+ summon.forceRunStance();
+
+ final SpawnLocation spawnLoc = creature.getPosition().clone();
+ spawnLoc.addStrictOffset(40);
+ spawnLoc.setHeadingTo(creature.getPosition());
+ spawnLoc.set(GeoEngine.getInstance().getValidLocation(creature, spawnLoc));
+
+ summon.spawnMe(spawnLoc);
+ summon.setInvul(true);
+ summon.getAI().setFollowStatus(true);
+ item.setAgathionItem(player);
+ return;
+ }
+
+ // Owner has a pet listed in world.
+ if (World.getInstance().getPet(player.getObjectId()) != null)
+ return;
+
// Add the pet instance to world.
final Pet pet = Pet.restore(checkedItem, npcTemplate, player);
if (pet == null)
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/model/actor/Player.java b/aCis_gs/java/net/sf/l2j/gameserver/model/actor/Player.java
index f5a1be5..2ab98f4 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/model/actor/Player.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/model/actor/Player.java
@@ -108,6 +108,7 @@
import net.sf.l2j.gameserver.model.actor.container.player.Request;
import net.sf.l2j.gameserver.model.actor.container.player.ShortcutList;
import net.sf.l2j.gameserver.model.actor.container.player.SubClass;
+import net.sf.l2j.gameserver.model.actor.instance.Agathion;
import net.sf.l2j.gameserver.model.actor.instance.Door;
import net.sf.l2j.gameserver.model.actor.instance.FestivalMonster;
import net.sf.l2j.gameserver.model.actor.instance.Folk;
@@ -368,6 +369,7 @@
private final QuestList _questList = new QuestList(this);
private Summon _summon;
+ private Agathion aga;
private TamedBeast _tamedBeast;
private int _partyRoom;
@@ -6282,6 +6284,9 @@
else if (_summon != null)
_summon.unSummon(this);
+ if (getAgathion() != null)
+ aga.unSummon(this);
+
// Stop all scheduled tasks.
stopChargeTask();
@@ -7152,4 +7157,14 @@
setTarget(null);
sendPacket(ActionFailed.STATIC_PACKET);
}
+
+ public void setAgathion(Agathion aga)
+ {
+ this.aga = aga;
+ }
+
+ public Agathion getAgathion()
+ {
+ return aga;
+ }
}
\ No newline at end of file
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/model/actor/cast/PlayerCast.java b/aCis_gs/java/net/sf/l2j/gameserver/model/actor/cast/PlayerCast.java
index 28abb8c..55cc846 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/model/actor/cast/PlayerCast.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/model/actor/cast/PlayerCast.java
@@ -268,7 +268,7 @@
switch (skill.getSkillType())
{
case SUMMON:
- if (!((L2SkillSummon) skill).isCubic())
+ if (!((L2SkillSummon) skill).isAgathion() && !((L2SkillSummon) skill).isCubic())
{
if (_actor.getSummon() != null || _actor.isMounted())
{
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/model/actor/instance/Agathion.java b/aCis_gs/java/net/sf/l2j/gameserver/model/actor/instance/Agathion.java
new file mode 100644
index 0000000..a818256
--- /dev/null
+++ b/aCis_gs/java/net/sf/l2j/gameserver/model/actor/instance/Agathion.java
@@ -0,0 +1,132 @@
+package net.sf.l2j.gameserver.model.actor.instance;
+
+import java.util.concurrent.Future;
+
+import net.sf.l2j.commons.pool.ThreadPool;
+import net.sf.l2j.commons.random.Rnd;
+
+import net.sf.l2j.gameserver.model.actor.Npc;
+import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
+import net.sf.l2j.gameserver.model.item.instance.ItemInstance;
+import net.sf.l2j.gameserver.model.location.Location;
+import net.sf.l2j.gameserver.network.serverpackets.PetDelete;
+
+/**
+ * @author maxi5
+ */
+public class Agathion extends Npc
+{
+ private Player owner;
+ private Future<?> _followTask;
+
+ private ItemInstance item;
+
+ public Agathion(int objectId, NpcTemplate template, Player owner)
+ {
+ super(objectId, template);
+
+ // Set the magical circle animation.
+ setShowSummonAnimation(true);
+
+ // Set the Player owner.
+ this.owner = owner;
+ }
+
+ @Override
+ public void onSpawn()
+ {
+ disableCoreAi(true);
+ setSpawnLocation(getPosition());
+ followToOwner();
+ super.onSpawn();
+ }
+
+ public void unSummon(Player owner)
+ {
+ // Abort attack, cast and move.
+ abortAll(true);
+
+ if (item != null)
+ item.setAgathion(owner, false);
+
+ owner.sendPacket(new PetDelete(2, getObjectId()));
+ owner.setAgathion(null);
+
+ if (owner.getSummon() != null)
+ owner.getSummon().sendInfo(owner);
+ owner.broadcastUserInfo();
+
+ if (_followTask != null)
+ _followTask.cancel(true);
+
+ decayMe();
+ deleteMe();
+
+ super.deleteMe();
+ }
+
+ public void followToOwner()
+ {
+ if (owner == null)
+ return;
+ setTarget(owner);
+
+ if (_followTask == null)
+ _followTask = ThreadPool.scheduleAtFixedRate(new Follow(this), 1000, 1000);
+
+ getPosition().setHeading(owner.getHeading());
+ int rnd = Rnd.get(-15, +15);
+ Location toMoveLoc = new Location(owner.getX(), owner.getY(), owner.getZ());
+
+ if (!isIn2DRadius(owner, 2000))
+ {
+ teleportTo(owner.getPosition().clone(), rnd);
+ return;
+ }
+ if (!isIn2DRadius(owner, 50) && !isMoving())
+ {
+ getMove().maybeMoveToLocation(toMoveLoc, rnd, true, false);
+ return;
+ }
+ if (isIn2DRadius(owner, 30))
+ {
+ getMove().stop();
+ getAI().thinkIdle();
+ return;
+ }
+ getMove().maybeMoveToLocation(toMoveLoc, rnd, true, false);
+ }
+
+ @Override
+ public boolean isInMyTerritory()
+ {
+ return false;
+ }
+
+ private static class Follow implements Runnable
+ {
+ private final Agathion agathion;
+
+ protected Follow(Agathion aga)
+ {
+ agathion = aga;
+ }
+
+ @Override
+ public void run()
+ {
+ agathion.followToOwner();
+ }
+ }
+
+ public void setAgathionItem(ItemInstance item)
+ {
+ this.item = item;
+ }
+
+ public Player getOwner()
+ {
+ return owner;
+ }
+}
\ No newline at end of file
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/model/item/instance/ItemInstance.java b/aCis_gs/java/net/sf/l2j/gameserver/model/item/instance/ItemInstance.java
index 652df79..7cb112f 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/model/item/instance/ItemInstance.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/model/item/instance/ItemInstance.java
@@ -5,6 +5,7 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
+import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;
import net.sf.l2j.commons.pool.ConnectionPool;
@@ -74,6 +75,8 @@
private boolean _destroyProtected;
private ScheduledFuture<?> _dropProtection;
+ private boolean isAgathion;
+ private Future<?> _protectedTask;
public ItemInstance(int objectId, int itemId)
{
@@ -501,7 +504,7 @@
*/
public boolean isDropable()
{
- return !isAugmented() && _item.isDropable();
+ return isAgathion || !isAugmented() && _item.isDropable();
}
/**
@@ -509,7 +512,7 @@
*/
public boolean isDestroyable()
{
- return !isQuestItem() && _item.isDestroyable();
+ return isAgathion || !isQuestItem() && _item.isDestroyable();
}
/**
@@ -517,7 +520,7 @@
*/
public boolean isTradable()
{
- return !isAugmented() && _item.isTradable();
+ return isAgathion || !isAugmented() && _item.isTradable();
}
/**
@@ -534,7 +537,7 @@
*/
public boolean isDepositable(boolean isPrivateWarehouse)
{
- return !(isEquipped() || !_item.isDepositable()) && (isPrivateWarehouse || (isTradable() && !isShadowItem()));
+ return !(isEquipped() || isAgathion || !_item.isDepositable()) && (isPrivateWarehouse || (isTradable() && !isShadowItem()));
}
/**
@@ -944,4 +947,47 @@
{
_shotsMask = 0;
}
+
+ public void setAgathion(Player player, boolean isAgathion)
+ {
+ this.isAgathion = isAgathion;
+ }
+
+ public void checkProtected(Player player)
+ {
+ if (_protectedTask != null)
+ _protectedTask.cancel(true);
+ _protectedTask = ThreadPool.schedule(new Protected(player), 5500);
+ }
+
+ public boolean isAgathion()
+ {
+ return isAgathion;
+ }
+
+ public void setAgathionItem(Player player)
+ {
+ player.getAgathion().setAgathionItem(this);
+ }
+
+ private class Protected implements Runnable
+ {
+ private final Player player;
+
+ protected Protected(Player player)
+ {
+ this.player = player;
+ }
+
+ @Override
+ public void run()
+ {
+ if (player.getAgathion() != null)
+ isAgathion = true;
+ else
+ isAgathion = false;
+ if (_protectedTask != null)
+ _protectedTask.cancel(true);
+ }
+ }
}
\ No newline at end of file
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/Action.java b/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/Action.java
index 1652483..7af1464 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/Action.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/Action.java
@@ -4,6 +4,7 @@
import net.sf.l2j.gameserver.model.World;
import net.sf.l2j.gameserver.model.WorldObject;
import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.actor.instance.Agathion;
import net.sf.l2j.gameserver.network.SystemMessageId;
import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
@@ -57,6 +58,12 @@
return;
}
+ if (target instanceof Agathion)
+ {
+ player.sendPacket(ActionFailed.STATIC_PACKET);
+ return;
+ }
+
target.onAction(player, false, _isShiftAction);
}
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/AttackRequest.java b/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/AttackRequest.java
index 5bbd7e8..e091a24 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/AttackRequest.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/AttackRequest.java
@@ -3,6 +3,7 @@
import net.sf.l2j.gameserver.model.World;
import net.sf.l2j.gameserver.model.WorldObject;
import net.sf.l2j.gameserver.model.actor.Player;
+import net.sf.l2j.gameserver.model.actor.instance.Agathion;
import net.sf.l2j.gameserver.network.SystemMessageId;
import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
@@ -54,6 +55,12 @@
return;
}
+ if (target instanceof Agathion)
+ {
+ player.sendPacket(ActionFailed.STATIC_PACKET);
+ return;
+ }
+
// (player.getTarget() == target) -> This happens when you control + click a target without having had it selected beforehand. Behaves as the Action packet and will NOT trigger an attack.
target.onAction(player, (player.getTarget() == target), _isShiftAction);
}
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/RequestDestroyItem.java b/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/RequestDestroyItem.java
index 5f3a046..d37be72 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/RequestDestroyItem.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/RequestDestroyItem.java
@@ -57,6 +57,12 @@
return;
}
+ if (itemToRemove.isAgathion())
+ {
+ player.sendPacket(SystemMessageId.CANNOT_DISCARD_THIS_ITEM);
+ return;
+ }
+
if (itemToRemove.isEquipped() && (!itemToRemove.isStackable() || (itemToRemove.isStackable() && _count >= itemToRemove.getCount())))
player.useEquippableItem(itemToRemove, false);
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/RequestDropItem.java b/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/RequestDropItem.java
index 8ff3f5c..6b443f0 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/RequestDropItem.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/network/clientpackets/RequestDropItem.java
@@ -46,7 +46,7 @@
if (item.isQuestItem())
return;
- if (_count > item.getCount())
+ if (_count > item.getCount() || item.isAgathion())
{
player.sendPacket(SystemMessageId.CANNOT_DISCARD_THIS_ITEM);
return;
diff --git a/aCis_gs/java/net/sf/l2j/gameserver/skills/l2skills/L2SkillSummon.java b/aCis_gs/java/net/sf/l2j/gameserver/skills/l2skills/L2SkillSummon.java
index 438f224..2fba8f4 100644
--- a/aCis_gs/java/net/sf/l2j/gameserver/skills/l2skills/L2SkillSummon.java
+++ b/aCis_gs/java/net/sf/l2j/gameserver/skills/l2skills/L2SkillSummon.java
@@ -12,6 +12,7 @@
import net.sf.l2j.gameserver.model.actor.Creature;
import net.sf.l2j.gameserver.model.actor.Player;
import net.sf.l2j.gameserver.model.actor.Summon;
+import net.sf.l2j.gameserver.model.actor.instance.Agathion;
import net.sf.l2j.gameserver.model.actor.instance.Servitor;
import net.sf.l2j.gameserver.model.actor.instance.SiegeSummon;
import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
@@ -24,6 +25,7 @@
private final int _npcId;
private final float _expPenalty;
private final boolean _isCubic;
+ private final boolean _isAgathion;
private final int _activationTime;
private final int _activationChance;
@@ -47,6 +49,7 @@
_npcId = set.getInteger("npcId", 0); // default for undescribed skills
_expPenalty = set.getFloat("expPenalty", 0.f);
_isCubic = set.getBool("isCubic", false);
+ _isAgathion = set.getBool("isAgathion", false);
_activationTime = set.getInteger("activationtime", 8);
_activationChance = set.getInteger("activationchance", 30);
@@ -82,7 +85,7 @@
if (player.isInObserverMode())
return false;
- if (player.getSummon() != null)
+ if (!_isAgathion && player.getSummon() != null)
{
player.sendPacket(SystemMessageId.SUMMON_ONLY_ONE);
return false;
@@ -140,6 +143,37 @@
}
else
{
+ if (_isAgathion)
+ {
+ NpcTemplate summonTemplate = NpcData.getInstance().getTemplate(_npcId);
+
+ if (summonTemplate == null)
+ {
+ LOGGER.warn("Couldn't properly spawn with id {} ; the template is missing.", _npcId);
+ return;
+ }
+ if (player.getAgathion() != null)
+ player.getAgathion().unSummon(player);
+ Agathion summon;
+ summon = new Agathion(IdFactory.getInstance().getNextId(), summonTemplate, player);
+ //summon.setInstanceId(player.getInstanceId());
+ player.setAgathion(summon);
+
+ summon.setName(summonTemplate.getName());
+ summon.setTitle(player.getName());
+ summon.getStatus().setMaxHpMp();
+ summon.forceRunStance();
+
+ final SpawnLocation spawnLoc = player.getPosition().clone();
+ spawnLoc.addStrictOffset(30);
+ spawnLoc.setHeadingTo(player.getPosition());
+ spawnLoc.set(GeoEngine.getInstance().getValidLocation(player, spawnLoc));
+
+ summon.spawnMe(spawnLoc);
+ summon.setInvul(true);
+ summon.getAI().setFollowStatus(true);
+ return;
+ }
if (player.getSummon() != null || player.isMounted())
return;
@@ -184,6 +218,11 @@
return _isCubic;
}
+ public final boolean isAgathion()
+ {
+ return _isAgathion;
+ }
+
public final int getTotalLifeTime()
{
return _summonTotalLifeTime;