Added AIs for grandbosses.
This commit is contained in:
3
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862-01.html
vendored
Normal file
3
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862-01.html
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<html><head><body>Angelic Vortex:<br>
|
||||
The Angelic Vortex emits a faint light which twinkles out. The vortex becomes inactive. It seems like, in order to go to the place where the Angelic Vortex is leading, you will need some special object.
|
||||
</body></html>
|
5
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862-02.html
vendored
Normal file
5
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862-02.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Angelic Vortex:<br>
|
||||
The Angelic Vortex emits a faint light, in the midst of which an image appears. A giant that normally appears as a stone statue has come alive and is fighting with many people. Even angels have joined the fray. It seems that the angels are angry at the humans who have broken the seal of the stone statue.<br>
|
||||
It appears impossible to cross over to that place right now. You have no choice but to wait until the fight is over.<br>
|
||||
<a action="bypass -h npc_%objectId%_Quest Baium 31862-04.html">Ask about the stone statue that has come alive.</a>
|
||||
</body></html>
|
5
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862-03.html
vendored
Normal file
5
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862-03.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<html><body>Angelic Vortex:<br>
|
||||
The Angelic Vortex emits a faint light, in the midst of which an image appears. A large, open space... but the gigantic, human-like stone statue is no longer there.<br>
|
||||
It seems that while the statue is not visible, one could cross over to that place.<br>
|
||||
<a action="bypass -h npc_%objectId%_Quest Baium 31862-04.html">Ask about the stone statue.</a>
|
||||
</body></html>
|
7
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862-04.html
vendored
Normal file
7
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862-04.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html><body>Angelic Vortex:<br>
|
||||
In ancient times a mighty emperor named Baium became so enamored of his own power that he began to fancy himself a god. He conscripted all of his people to build an awesome tower that reached almost to heaven.<br>
|
||||
The gods were not amused. They struck him down, cursed him with immortality and imprisoned him in his own tower for eternity! A statue of the foolish emperor stands there to this day.<br>
|
||||
Occasionally, the old emperor himself is woken up by those who seek his power. Unfortunately, when Baium is disturbed, so are the angels who guard him.<br>
|
||||
Although the angels are certainly no friend of Baium, they regard Humans with equal disdain.<font color="LEVEL"> Ultimate success against Baium depends upon the defeat of the guardian angels.</font><br>
|
||||
This is all I can tell you. Good luck!
|
||||
</body></html>
|
4
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862.html
vendored
Normal file
4
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/31862.html
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<html><body>Angelic Vortex:<br>
|
||||
The Angelic Vortex emits a faint light, and in the midst of the light an image appears. In the deepest part of a spacious area, a gigantic stone statue is visible. The statue has a human-like appearance and is in a seated position, as though it was being held by some invisible force against its will.<br>
|
||||
<a action="bypass -h npc_%objectId%_Quest Baium enter">Go where the Angelic Vortex leads.</a>
|
||||
</body></html>
|
791
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/Baium.java
vendored
Normal file
791
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Baium/Baium.java
vendored
Normal file
@@ -0,0 +1,791 @@
|
||||
/*
|
||||
* 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 ai.bosses.Baium;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.commons.util.CommonUtil;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.enums.CategoryType;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.enums.MountType;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||
import com.l2jmobius.gameserver.model.L2World;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Playable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.skills.SkillCaster;
|
||||
import com.l2jmobius.gameserver.model.variables.NpcVariables;
|
||||
import com.l2jmobius.gameserver.model.zone.type.L2NoRestartZone;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.Earthquake;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Baium AI.
|
||||
* @author St3eT
|
||||
*/
|
||||
public final class Baium extends AbstractNpcAI
|
||||
{
|
||||
// NPCs
|
||||
private static final int BAIUM = 29020; // Baium
|
||||
private static final int BAIUM_STONE = 29025; // Baium
|
||||
private static final int ANG_VORTEX = 31862; // Angelic Vortex
|
||||
private static final int ARCHANGEL = 29021; // Archangel
|
||||
private static final int TELE_CUBE = 31842; // Teleportation Cubic
|
||||
// Skills
|
||||
private static final SkillHolder BAIUM_ATTACK = new SkillHolder(4127, 1); // Baium: General Attack
|
||||
private static final SkillHolder ENERGY_WAVE = new SkillHolder(4128, 1); // Wind Of Force
|
||||
private static final SkillHolder EARTH_QUAKE = new SkillHolder(4129, 1); // Earthquake
|
||||
private static final SkillHolder THUNDERBOLT = new SkillHolder(4130, 1); // Striking of Thunderbolt
|
||||
private static final SkillHolder GROUP_HOLD = new SkillHolder(4131, 1); // Stun
|
||||
private static final SkillHolder SPEAR_ATTACK = new SkillHolder(4132, 1); // Spear: Pound the Ground
|
||||
private static final SkillHolder ANGEL_HEAL = new SkillHolder(4133, 1); // Angel Heal
|
||||
private static final SkillHolder HEAL_OF_BAIUM = new SkillHolder(4135, 1); // Baium Heal
|
||||
private static final SkillHolder BAIUM_PRESENT = new SkillHolder(4136, 1); // Baium's Gift
|
||||
private static final SkillHolder ANTI_STRIDER = new SkillHolder(4258, 1); // Hinder Strider
|
||||
// Items
|
||||
private static final int FABRIC = 4295; // Blooded Fabric
|
||||
// Zone
|
||||
private static final L2NoRestartZone zone = ZoneManager.getInstance().getZoneById(70051, L2NoRestartZone.class); // Baium zone
|
||||
// Status
|
||||
private static final int ALIVE = 0;
|
||||
private static final int WAITING = 1;
|
||||
private static final int IN_FIGHT = 2;
|
||||
private static final int DEAD = 3;
|
||||
// Locations
|
||||
private static final Location BAIUM_GIFT_LOC = new Location(115910, 17337, 10105);
|
||||
private static final Location BAIUM_LOC = new Location(116033, 17447, 10107, -25348);
|
||||
private static final Location TELEPORT_CUBIC_LOC = new Location(115017, 15549, 10090);
|
||||
private static final Location TELEPORT_IN_LOC = new Location(114077, 15882, 10078);
|
||||
private static final Location[] TELEPORT_OUT_LOC =
|
||||
{
|
||||
new Location(108784, 16000, -4928),
|
||||
new Location(113824, 10448, -5164),
|
||||
new Location(115488, 22096, -5168),
|
||||
};
|
||||
private static final Location[] ARCHANGEL_LOC =
|
||||
{
|
||||
new Location(115792, 16608, 10136, 0),
|
||||
new Location(115168, 17200, 10136, 0),
|
||||
new Location(115780, 15564, 10136, 13620),
|
||||
new Location(114880, 16236, 10136, 5400),
|
||||
new Location(114239, 17168, 10136, -1992)
|
||||
};
|
||||
// Misc
|
||||
private L2GrandBossInstance _baium = null;
|
||||
private static long _lastAttack = 0;
|
||||
private static L2PcInstance _standbyPlayer = null;
|
||||
|
||||
private Baium()
|
||||
{
|
||||
addFirstTalkId(ANG_VORTEX);
|
||||
addTalkId(ANG_VORTEX, TELE_CUBE, BAIUM_STONE);
|
||||
addStartNpc(ANG_VORTEX, TELE_CUBE, BAIUM_STONE);
|
||||
addAttackId(BAIUM, ARCHANGEL);
|
||||
addKillId(BAIUM);
|
||||
addSeeCreatureId(BAIUM);
|
||||
addSpellFinishedId(BAIUM);
|
||||
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(BAIUM);
|
||||
|
||||
switch (getStatus())
|
||||
{
|
||||
case WAITING:
|
||||
{
|
||||
setStatus(ALIVE);
|
||||
}
|
||||
case ALIVE:
|
||||
{
|
||||
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
|
||||
break;
|
||||
}
|
||||
case IN_FIGHT:
|
||||
{
|
||||
final double curr_hp = info.getDouble("currentHP");
|
||||
final double curr_mp = info.getDouble("currentMP");
|
||||
final int loc_x = info.getInt("loc_x");
|
||||
final int loc_y = info.getInt("loc_y");
|
||||
final int loc_z = info.getInt("loc_z");
|
||||
final int heading = info.getInt("heading");
|
||||
|
||||
_baium = (L2GrandBossInstance) addSpawn(BAIUM, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
_baium.setCurrentHpMp(curr_hp, curr_mp);
|
||||
_lastAttack = System.currentTimeMillis();
|
||||
addBoss(_baium);
|
||||
|
||||
for (Location loc : ARCHANGEL_LOC)
|
||||
{
|
||||
final L2Npc archangel = addSpawn(ARCHANGEL, loc, false, 0, true);
|
||||
startQuestTimer("SELECT_TARGET", 5000, archangel, null);
|
||||
}
|
||||
startQuestTimer("CHECK_ATTACK", 60000, _baium, null);
|
||||
break;
|
||||
}
|
||||
case DEAD:
|
||||
{
|
||||
final long remain = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
if (remain > 0)
|
||||
{
|
||||
startQuestTimer("CLEAR_STATUS", remain, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
notifyEvent("CLEAR_STATUS", null, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case "31862-04.html":
|
||||
{
|
||||
return event;
|
||||
}
|
||||
case "enter":
|
||||
{
|
||||
String htmltext = null;
|
||||
if (getStatus() == DEAD)
|
||||
{
|
||||
htmltext = "31862-03.html";
|
||||
}
|
||||
else if (getStatus() == IN_FIGHT)
|
||||
{
|
||||
htmltext = "31862-02.html";
|
||||
}
|
||||
else if (!hasQuestItems(player, FABRIC))
|
||||
{
|
||||
htmltext = "31862-01.html";
|
||||
}
|
||||
else
|
||||
{
|
||||
takeItems(player, FABRIC, 1);
|
||||
player.teleToLocation(TELEPORT_IN_LOC);
|
||||
}
|
||||
return htmltext;
|
||||
}
|
||||
case "teleportOut":
|
||||
{
|
||||
final Location destination = TELEPORT_OUT_LOC[getRandom(TELEPORT_OUT_LOC.length)];
|
||||
player.teleToLocation(destination.getX() + getRandom(100), destination.getY() + getRandom(100), destination.getZ());
|
||||
break;
|
||||
}
|
||||
case "wakeUp":
|
||||
{
|
||||
if (getStatus() == ALIVE)
|
||||
{
|
||||
npc.deleteMe();
|
||||
setStatus(IN_FIGHT);
|
||||
_baium = (L2GrandBossInstance) addSpawn(BAIUM, BAIUM_LOC, false, 0);
|
||||
_baium.disableCoreAI(true);
|
||||
addBoss(_baium);
|
||||
_lastAttack = System.currentTimeMillis();
|
||||
startQuestTimer("WAKEUP_ACTION", 50, _baium, null);
|
||||
startQuestTimer("MANAGE_EARTHQUAKE", 2000, _baium, player);
|
||||
startQuestTimer("CHECK_ATTACK", 60000, _baium, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "WAKEUP_ACTION":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
zone.broadcastPacket(new SocialAction(_baium.getObjectId(), 2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "MANAGE_EARTHQUAKE":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
zone.broadcastPacket(new Earthquake(npc.getX(), npc.getY(), npc.getZ(), 40, 10));
|
||||
zone.broadcastPacket(new PlaySound("BS02_A"));
|
||||
startQuestTimer("SOCIAL_ACTION", 8000, npc, player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SOCIAL_ACTION":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
zone.broadcastPacket(new SocialAction(npc.getObjectId(), 3));
|
||||
startQuestTimer("PLAYER_PORT", 6000, npc, player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "PLAYER_PORT":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
if ((player != null) && player.isInsideRadius(npc, 16000, true, false))
|
||||
{
|
||||
player.teleToLocation(BAIUM_GIFT_LOC);
|
||||
startQuestTimer("PLAYER_KILL", 3000, npc, player);
|
||||
}
|
||||
else if ((_standbyPlayer != null) && _standbyPlayer.isInsideRadius(npc, 16000, true, false))
|
||||
{
|
||||
_standbyPlayer.teleToLocation(BAIUM_GIFT_LOC);
|
||||
startQuestTimer("PLAYER_KILL", 3000, npc, _standbyPlayer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "PLAYER_KILL":
|
||||
{
|
||||
if ((player != null) && player.isInsideRadius(npc, 16000, true, false))
|
||||
{
|
||||
zone.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, player.getName() + ", How dare you wake me! Now you shall die!"); // TODO: replace with NpcStringId when are done core support
|
||||
npc.setTarget(player);
|
||||
npc.doCast(BAIUM_PRESENT.getSkill());
|
||||
}
|
||||
|
||||
for (L2PcInstance players : zone.getPlayersInside())
|
||||
{
|
||||
if (players.isHero())
|
||||
{
|
||||
zone.broadcastPacket(new ExShowScreenMessage(NpcStringId.NOT_EVEN_THE_GODS_THEMSELVES_COULD_TOUCH_ME_BUT_YOU_S1_YOU_DARE_CHALLENGE_ME_IGNORANT_MORTAL, 2, 4000, players.getName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
startQuestTimer("SPAWN_ARCHANGEL", 8000, npc, null);
|
||||
break;
|
||||
}
|
||||
case "SPAWN_ARCHANGEL":
|
||||
{
|
||||
_baium.disableCoreAI(false);
|
||||
|
||||
for (Location loc : ARCHANGEL_LOC)
|
||||
{
|
||||
final L2Npc archangel = addSpawn(ARCHANGEL, loc, false, 0, true);
|
||||
startQuestTimer("SELECT_TARGET", 5000, archangel, null);
|
||||
}
|
||||
|
||||
if ((player != null) && !player.isDead())
|
||||
{
|
||||
addAttackPlayerDesire(npc, player);
|
||||
}
|
||||
else if ((_standbyPlayer != null) && !_standbyPlayer.isDead())
|
||||
{
|
||||
addAttackPlayerDesire(npc, _standbyPlayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (L2Character creature : L2World.getInstance().getVisibleObjects(npc, L2PcInstance.class, 2000))
|
||||
{
|
||||
if (zone.isInsideZone(creature) && !creature.isDead())
|
||||
{
|
||||
addAttackPlayerDesire(npc, (L2Playable) creature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SELECT_TARGET":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) npc;
|
||||
final L2Character mostHated = mob.getMostHated();
|
||||
|
||||
if ((_baium == null) || _baium.isDead())
|
||||
{
|
||||
mob.deleteMe();
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mostHated != null) && mostHated.isPlayer() && zone.isInsideZone(mostHated))
|
||||
{
|
||||
if (mob.getTarget() != mostHated)
|
||||
{
|
||||
mob.clearAggroList();
|
||||
}
|
||||
addAttackPlayerDesire(mob, (L2Playable) mostHated);
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean found = false;
|
||||
for (L2Playable creature : L2World.getInstance().getVisibleObjects(mob, L2Playable.class, 1000))
|
||||
{
|
||||
if (zone.isInsideZone(creature) && !creature.isDead())
|
||||
{
|
||||
if (mob.getTarget() != creature)
|
||||
{
|
||||
mob.clearAggroList();
|
||||
}
|
||||
addAttackPlayerDesire(mob, creature);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (mob.isInsideRadius(_baium, 40, true, false))
|
||||
{
|
||||
if (mob.getTarget() != _baium)
|
||||
{
|
||||
mob.clearAggroList();
|
||||
}
|
||||
mob.setIsRunning(true);
|
||||
mob.addDamageHate(_baium, 0, 999);
|
||||
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, _baium);
|
||||
}
|
||||
else
|
||||
{
|
||||
mob.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _baium);
|
||||
}
|
||||
}
|
||||
}
|
||||
startQuestTimer("SELECT_TARGET", 5000, npc, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CHECK_ATTACK":
|
||||
{
|
||||
if ((npc != null) && ((_lastAttack + 1800000) < System.currentTimeMillis()))
|
||||
{
|
||||
notifyEvent("CLEAR_ZONE", null, null);
|
||||
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
|
||||
setStatus(ALIVE);
|
||||
}
|
||||
else if (npc != null)
|
||||
{
|
||||
if (((_lastAttack + 300000) < System.currentTimeMillis()) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.75)))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(HEAL_OF_BAIUM.getSkill());
|
||||
}
|
||||
startQuestTimer("CHECK_ATTACK", 60000, npc, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CLEAR_STATUS":
|
||||
{
|
||||
setStatus(ALIVE);
|
||||
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
|
||||
break;
|
||||
}
|
||||
case "CLEAR_ZONE":
|
||||
{
|
||||
for (L2Character charInside : zone.getCharactersInside())
|
||||
{
|
||||
if (charInside != null)
|
||||
{
|
||||
if (charInside.isNpc())
|
||||
{
|
||||
charInside.deleteMe();
|
||||
}
|
||||
else if (charInside.isPlayer())
|
||||
{
|
||||
notifyEvent("teleportOut", null, (L2PcInstance) charInside);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "RESPAWN_BAIUM":
|
||||
{
|
||||
if (getStatus() == DEAD)
|
||||
{
|
||||
setRespawn(0);
|
||||
cancelQuestTimer("CLEAR_STATUS", null, null);
|
||||
notifyEvent("CLEAR_STATUS", null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendMessage(getClass().getSimpleName() + ": You cant respawn Baium while Baium is alive!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ABORT_FIGHT":
|
||||
{
|
||||
if (getStatus() == IN_FIGHT)
|
||||
{
|
||||
_baium = null;
|
||||
notifyEvent("CLEAR_ZONE", null, null);
|
||||
notifyEvent("CLEAR_STATUS", null, null);
|
||||
player.sendMessage(getClass().getSimpleName() + ": Aborting fight!");
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendMessage(getClass().getSimpleName() + ": You cant abort attack right now!");
|
||||
}
|
||||
cancelQuestTimers("CHECK_ATTACK");
|
||||
cancelQuestTimers("SELECT_TARGET");
|
||||
break;
|
||||
}
|
||||
case "DESPAWN_MINIONS":
|
||||
{
|
||||
if (getStatus() == IN_FIGHT)
|
||||
{
|
||||
for (L2Character charInside : zone.getCharactersInside())
|
||||
{
|
||||
if ((charInside != null) && charInside.isNpc() && (charInside.getId() == ARCHANGEL))
|
||||
{
|
||||
charInside.deleteMe();
|
||||
}
|
||||
}
|
||||
if (player != null)
|
||||
{
|
||||
player.sendMessage(getClass().getSimpleName() + ": All archangels has been deleted!");
|
||||
}
|
||||
}
|
||||
else if (player != null)
|
||||
{
|
||||
player.sendMessage(getClass().getSimpleName() + ": You cant despawn archangels right now!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "MANAGE_SKILLS":
|
||||
{
|
||||
if (npc != null)
|
||||
{
|
||||
manageSkills(npc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
|
||||
{
|
||||
_lastAttack = System.currentTimeMillis();
|
||||
|
||||
if (npc.getId() == BAIUM)
|
||||
{
|
||||
if ((attacker.getMountType() == MountType.STRIDER) && !attacker.isAffectedBySkill(ANTI_STRIDER.getSkillId()))
|
||||
{
|
||||
if (!npc.isSkillDisabled(ANTI_STRIDER.getSkill()))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(ANTI_STRIDER.getSkill());
|
||||
}
|
||||
}
|
||||
|
||||
if (skill == null)
|
||||
{
|
||||
refreshAiParams(attacker, npc, (damage * 1000));
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
|
||||
{
|
||||
refreshAiParams(attacker, npc, ((damage / 3) * 100));
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
|
||||
{
|
||||
refreshAiParams(attacker, npc, (damage * 20));
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
|
||||
{
|
||||
refreshAiParams(attacker, npc, (damage * 10));
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshAiParams(attacker, npc, ((damage / 3) * 20));
|
||||
}
|
||||
manageSkills(npc);
|
||||
}
|
||||
else
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) npc;
|
||||
final L2Character mostHated = mob.getMostHated();
|
||||
|
||||
if ((getRandom(100) < 10) && SkillCaster.checkUseConditions(mob, SPEAR_ATTACK.getSkill()))
|
||||
{
|
||||
if ((mostHated != null) && (npc.calculateDistance(mostHated, true, false) < 1000) && zone.isCharacterInZone(mostHated))
|
||||
{
|
||||
mob.setTarget(mostHated);
|
||||
mob.doCast(SPEAR_ATTACK.getSkill());
|
||||
}
|
||||
else if (zone.isCharacterInZone(attacker))
|
||||
{
|
||||
mob.setTarget(attacker);
|
||||
mob.doCast(SPEAR_ATTACK.getSkill());
|
||||
}
|
||||
}
|
||||
|
||||
if ((getRandom(100) < 5) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.5)) && SkillCaster.checkUseConditions(mob, ANGEL_HEAL.getSkill()))
|
||||
{
|
||||
npc.setTarget(npc);
|
||||
npc.doCast(ANGEL_HEAL.getSkill());
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (zone.isCharacterInZone(killer))
|
||||
{
|
||||
setStatus(DEAD);
|
||||
addSpawn(TELE_CUBE, TELEPORT_CUBIC_LOC, false, 900000);
|
||||
zone.broadcastPacket(new PlaySound("BS01_D"));
|
||||
final long respawnTime = (Config.BAIUM_SPAWN_INTERVAL + getRandom(-Config.BAIUM_SPAWN_RANDOM, Config.BAIUM_SPAWN_RANDOM)) * 3600000;
|
||||
setRespawn(respawnTime);
|
||||
startQuestTimer("CLEAR_STATUS", respawnTime, null, null);
|
||||
startQuestTimer("CLEAR_ZONE", 900000, null, null);
|
||||
cancelQuestTimer("CHECK_ATTACK", npc, null);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
|
||||
{
|
||||
if (!zone.isInsideZone(creature) || (creature.isNpc() && (creature.getId() == BAIUM_STONE)))
|
||||
{
|
||||
return super.onSeeCreature(npc, creature, isSummon);
|
||||
}
|
||||
|
||||
if (creature.isPlayer() && !creature.isDead() && (_standbyPlayer == null))
|
||||
{
|
||||
_standbyPlayer = (L2PcInstance) creature;
|
||||
}
|
||||
|
||||
if (creature.isInCategory(CategoryType.CLERIC_GROUP))
|
||||
{
|
||||
if (npc.getCurrentHp() < (npc.getMaxHp() * 0.25))
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000);
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.5))
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000, 6000);
|
||||
}
|
||||
else if (npc.getCurrentHp() < (npc.getMaxHp() * 0.75))
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000, 3000);
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000, 2000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
refreshAiParams(creature, npc, 10000, 1000);
|
||||
}
|
||||
manageSkills(npc);
|
||||
return super.onSeeCreature(npc, creature, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
|
||||
{
|
||||
startQuestTimer("MANAGE_SKILLS", 1000, npc, null);
|
||||
|
||||
if (!zone.isCharacterInZone(npc) && (_baium != null))
|
||||
{
|
||||
_baium.teleToLocation(BAIUM_LOC);
|
||||
}
|
||||
return super.onSpellFinished(npc, player, skill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unload(boolean removeFromList)
|
||||
{
|
||||
if (_baium != null)
|
||||
{
|
||||
_baium.deleteMe();
|
||||
}
|
||||
return super.unload(removeFromList);
|
||||
}
|
||||
|
||||
private final void refreshAiParams(L2Character attacker, L2Npc npc, int damage)
|
||||
{
|
||||
refreshAiParams(attacker, npc, damage, damage);
|
||||
}
|
||||
|
||||
private final void refreshAiParams(L2Character attacker, L2Npc npc, int damage, int aggro)
|
||||
{
|
||||
final int newAggroVal = damage + getRandom(3000);
|
||||
final int aggroVal = aggro + 1000;
|
||||
final NpcVariables vars = npc.getVariables();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (attacker == vars.getObject("c_quest" + i, L2Character.class))
|
||||
{
|
||||
if (vars.getInt("i_quest" + i) < aggroVal)
|
||||
{
|
||||
vars.set("i_quest" + i, newAggroVal);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
final int index = CommonUtil.getIndexOfMinValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
|
||||
vars.set("i_quest" + index, newAggroVal);
|
||||
vars.set("c_quest" + index, attacker);
|
||||
}
|
||||
|
||||
private int getStatus()
|
||||
{
|
||||
return GrandBossManager.getInstance().getBossStatus(BAIUM);
|
||||
}
|
||||
|
||||
private void addBoss(L2GrandBossInstance grandboss)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(grandboss);
|
||||
}
|
||||
|
||||
private void setStatus(int status)
|
||||
{
|
||||
GrandBossManager.getInstance().setBossStatus(BAIUM, status);
|
||||
}
|
||||
|
||||
private void setRespawn(long respawnTime)
|
||||
{
|
||||
GrandBossManager.getInstance().getStatsSet(BAIUM).set("respawn_time", (System.currentTimeMillis() + respawnTime));
|
||||
}
|
||||
|
||||
private void manageSkills(L2Npc npc)
|
||||
{
|
||||
if (npc.isCastingNow(SkillCaster::isAnyNormalType) || npc.isCoreAIDisabled() || !npc.isInCombat())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final NpcVariables vars = npc.getVariables();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
final L2Character attacker = vars.getObject("c_quest" + i, L2Character.class);
|
||||
if ((attacker == null) || ((npc.calculateDistance(attacker, true, false) > 9000) || attacker.isDead()))
|
||||
{
|
||||
vars.set("i_quest" + i, 0);
|
||||
}
|
||||
}
|
||||
final int index = CommonUtil.getIndexOfMaxValue(vars.getInt("i_quest0"), vars.getInt("i_quest1"), vars.getInt("i_quest2"));
|
||||
final L2Character player = vars.getObject("c_quest" + index, L2Character.class);
|
||||
final int i2 = vars.getInt("i_quest" + index);
|
||||
if ((i2 > 0) && (getRandom(100) < 70))
|
||||
{
|
||||
vars.set("i_quest" + index, 500);
|
||||
}
|
||||
|
||||
SkillHolder skillToCast = null;
|
||||
if ((player != null) && !player.isDead())
|
||||
{
|
||||
if (npc.getCurrentHp() > (npc.getMaxHp() * 0.75))
|
||||
{
|
||||
if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = ENERGY_WAVE;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = EARTH_QUAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
skillToCast = BAIUM_ATTACK;
|
||||
}
|
||||
}
|
||||
else if (npc.getCurrentHp() > (npc.getMaxHp() * 0.5))
|
||||
{
|
||||
if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = GROUP_HOLD;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = ENERGY_WAVE;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = EARTH_QUAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
skillToCast = BAIUM_ATTACK;
|
||||
}
|
||||
}
|
||||
else if (npc.getCurrentHp() > (npc.getMaxHp() * 0.25))
|
||||
{
|
||||
if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = THUNDERBOLT;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = GROUP_HOLD;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = ENERGY_WAVE;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = EARTH_QUAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
skillToCast = BAIUM_ATTACK;
|
||||
}
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = THUNDERBOLT;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = GROUP_HOLD;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = ENERGY_WAVE;
|
||||
}
|
||||
else if (getRandom(100) < 10)
|
||||
{
|
||||
skillToCast = EARTH_QUAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
skillToCast = BAIUM_ATTACK;
|
||||
}
|
||||
}
|
||||
|
||||
if ((skillToCast != null) && SkillCaster.checkUseConditions(npc, skillToCast.getSkill()))
|
||||
{
|
||||
npc.setTarget(player);
|
||||
npc.doCast(skillToCast.getSkill());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Baium();
|
||||
}
|
||||
}
|
228
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Core/Core.java
vendored
Normal file
228
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Core/Core.java
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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 ai.bosses.Core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Core AI.
|
||||
* @author DrLecter, Emperorc
|
||||
*/
|
||||
public final class Core extends AbstractNpcAI
|
||||
{
|
||||
private static final int CORE = 29006;
|
||||
private static final int DEATH_KNIGHT = 29007;
|
||||
private static final int DOOM_WRAITH = 29008;
|
||||
// private static final int DICOR = 29009;
|
||||
// private static final int VALIDUS = 29010;
|
||||
private static final int SUSCEPTOR = 29011;
|
||||
// private static final int PERUM = 29012;
|
||||
// private static final int PREMO = 29013;
|
||||
|
||||
// Core Status Tracking :
|
||||
private static final byte ALIVE = 0; // Core is spawned.
|
||||
private static final byte DEAD = 1; // Core has been killed.
|
||||
|
||||
private static boolean _firstAttacked;
|
||||
|
||||
private final List<L2Attackable> _minions = new CopyOnWriteArrayList<>();
|
||||
|
||||
private Core()
|
||||
{
|
||||
registerMobs(CORE, DEATH_KNIGHT, DOOM_WRAITH, SUSCEPTOR);
|
||||
|
||||
_firstAttacked = false;
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(CORE);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(CORE);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for Core from DB
|
||||
final long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
|
||||
// if Core is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("core_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn Core.
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, 17726, 108915, -6480, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
|
||||
spawnBoss(core);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final String test = loadGlobalQuestVar("Core_Attacked");
|
||||
if (test.equalsIgnoreCase("true"))
|
||||
{
|
||||
_firstAttacked = true;
|
||||
}
|
||||
final int loc_x = info.getInt("loc_x");
|
||||
final int loc_y = info.getInt("loc_y");
|
||||
final int loc_z = info.getInt("loc_z");
|
||||
final int heading = info.getInt("heading");
|
||||
final double hp = info.getDouble("currentHP");
|
||||
final double mp = info.getDouble("currentMP");
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
core.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(core);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSave()
|
||||
{
|
||||
saveGlobalQuestVar("Core_Attacked", Boolean.toString(_firstAttacked));
|
||||
}
|
||||
|
||||
public void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
// Spawn minions
|
||||
L2Attackable mob;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
final int x = 16800 + (i * 360);
|
||||
mob = (L2Attackable) addSpawn(DEATH_KNIGHT, x, 110000, npc.getZ(), 280 + getRandom(40), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
mob = (L2Attackable) addSpawn(DEATH_KNIGHT, x, 109000, npc.getZ(), 280 + getRandom(40), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
final int x2 = 16800 + (i * 600);
|
||||
mob = (L2Attackable) addSpawn(DOOM_WRAITH, x2, 109300, npc.getZ(), 280 + getRandom(40), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
final int x = 16800 + (i * 450);
|
||||
mob = (L2Attackable) addSpawn(SUSCEPTOR, x, 110300, npc.getZ(), 280 + getRandom(40), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("core_unlock"))
|
||||
{
|
||||
final L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, 17726, 108915, -6480, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
|
||||
spawnBoss(core);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_minion"))
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) addSpawn(npc.getId(), npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("despawn_minions"))
|
||||
{
|
||||
_minions.forEach(L2Attackable::decayMe);
|
||||
_minions.clear();
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == CORE)
|
||||
{
|
||||
if (_firstAttacked)
|
||||
{
|
||||
if (getRandom(100) == 0)
|
||||
{
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.REMOVING_INTRUDERS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_firstAttacked = true;
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.A_NON_PERMITTED_TARGET_HAS_BEEN_DISCOVERED);
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.INTRUDER_REMOVAL_SYSTEM_INITIATED);
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
if (npcId == CORE)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.A_FATAL_ERROR_HAS_OCCURRED);
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.SYSTEM_IS_BEING_SHUT_DOWN);
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, NpcStringId.EMPTY);
|
||||
_firstAttacked = false;
|
||||
GrandBossManager.getInstance().setBossStatus(CORE, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
long respawnTime = (Config.CORE_SPAWN_INTERVAL + getRandom(-Config.CORE_SPAWN_RANDOM, Config.CORE_SPAWN_RANDOM)) * 3600000;
|
||||
respawnTime *= 3600000;
|
||||
|
||||
startQuestTimer("core_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(CORE);
|
||||
info.set("respawn_time", (System.currentTimeMillis() + respawnTime));
|
||||
GrandBossManager.getInstance().setStatsSet(CORE, info);
|
||||
startQuestTimer("despawn_minions", 20000, null, null);
|
||||
cancelQuestTimers("spawn_minion");
|
||||
}
|
||||
else if ((GrandBossManager.getInstance().getBossStatus(CORE) == ALIVE) && (_minions != null) && _minions.contains(npc))
|
||||
{
|
||||
_minions.remove(npc);
|
||||
startQuestTimer("spawn_minion", 60000, npc, null);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
if (npc.getId() == CORE)
|
||||
{
|
||||
npc.setIsImmobilized(true);
|
||||
}
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Core();
|
||||
}
|
||||
}
|
350
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Orfen/Orfen.java
vendored
Normal file
350
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/Orfen/Orfen.java
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* 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 ai.bosses.Orfen;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.enums.ChatType;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.L2Spawn;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Character;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.skills.SkillCaster;
|
||||
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
|
||||
import com.l2jmobius.gameserver.network.NpcStringId;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Orfen's AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
public final class Orfen extends AbstractNpcAI
|
||||
{
|
||||
private static final Location[] POS =
|
||||
{
|
||||
new Location(43728, 17220, -4342),
|
||||
new Location(55024, 17368, -5412),
|
||||
new Location(53504, 21248, -5486),
|
||||
new Location(53248, 24576, -5262)
|
||||
};
|
||||
|
||||
private static final NpcStringId[] TEXT =
|
||||
{
|
||||
NpcStringId.S1_STOP_KIDDING_YOURSELF_ABOUT_YOUR_OWN_POWERLESSNESS,
|
||||
NpcStringId.S1_I_LL_MAKE_YOU_FEEL_WHAT_TRUE_FEAR_IS,
|
||||
NpcStringId.YOU_RE_REALLY_STUPID_TO_HAVE_CHALLENGED_ME_S1_GET_READY,
|
||||
NpcStringId.S1_DO_YOU_THINK_THAT_S_GOING_TO_WORK
|
||||
};
|
||||
|
||||
private static final int ORFEN = 29014;
|
||||
// private static final int RAIKEL = 29015;
|
||||
private static final int RAIKEL_LEOS = 29016;
|
||||
// private static final int RIBA = 29017;
|
||||
private static final int RIBA_IREN = 29018;
|
||||
|
||||
private static boolean _IsTeleported;
|
||||
private static Set<L2Attackable> _minions = ConcurrentHashMap.newKeySet();
|
||||
private static L2ZoneType ZONE;
|
||||
|
||||
private static final byte ALIVE = 0;
|
||||
private static final byte DEAD = 1;
|
||||
|
||||
private static final SkillHolder PARALYSIS = new SkillHolder(4064, 1);
|
||||
private static final SkillHolder BLOW = new SkillHolder(4067, 4);
|
||||
private static final SkillHolder ORFEN_HEAL = new SkillHolder(4516, 1);
|
||||
|
||||
private Orfen()
|
||||
{
|
||||
final int[] mobs =
|
||||
{
|
||||
ORFEN,
|
||||
RAIKEL_LEOS,
|
||||
RIBA_IREN
|
||||
};
|
||||
registerMobs(mobs);
|
||||
_IsTeleported = false;
|
||||
ZONE = ZoneManager.getInstance().getZoneById(12013);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(ORFEN);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for Orfen from DB
|
||||
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
// if Orfen is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("orfen_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn Orfen.
|
||||
final int i = getRandom(10);
|
||||
Location loc;
|
||||
if (i < 4)
|
||||
{
|
||||
loc = POS[1];
|
||||
}
|
||||
else if (i < 7)
|
||||
{
|
||||
loc = POS[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = POS[3];
|
||||
}
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int loc_x = info.getInt("loc_x");
|
||||
final int loc_y = info.getInt("loc_y");
|
||||
final int loc_z = info.getInt("loc_z");
|
||||
final int heading = info.getInt("heading");
|
||||
final double hp = info.getDouble("currentHP");
|
||||
final double mp = info.getDouble("currentMP");
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
orfen.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSpawnPoint(L2Npc npc, int index)
|
||||
{
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
final L2Spawn spawn = npc.getSpawn();
|
||||
spawn.setLocation(POS[index]);
|
||||
npc.teleToLocation(POS[index], false);
|
||||
}
|
||||
|
||||
public void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
startQuestTimer("check_orfen_pos", 10000, npc, null, true);
|
||||
// Spawn minions
|
||||
final int x = npc.getX();
|
||||
final int y = npc.getY();
|
||||
L2Attackable mob;
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y + 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x + 100, y - 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y + 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
mob = (L2Attackable) addSpawn(RAIKEL_LEOS, x - 100, y - 100, npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
startQuestTimer("check_minion_loc", 10000, npc, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("orfen_unlock"))
|
||||
{
|
||||
final int i = getRandom(10);
|
||||
Location loc;
|
||||
if (i < 4)
|
||||
{
|
||||
loc = POS[1];
|
||||
}
|
||||
else if (i < 7)
|
||||
{
|
||||
loc = POS[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = POS[3];
|
||||
}
|
||||
final L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
|
||||
spawnBoss(orfen);
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_orfen_pos"))
|
||||
{
|
||||
if ((_IsTeleported && (npc.getCurrentHp() > (npc.getMaxHp() * 0.95))) || (!ZONE.isInsideZone(npc) && !_IsTeleported))
|
||||
{
|
||||
setSpawnPoint(npc, getRandom(3) + 1);
|
||||
_IsTeleported = false;
|
||||
}
|
||||
else if (_IsTeleported && !ZONE.isInsideZone(npc))
|
||||
{
|
||||
setSpawnPoint(npc, 0);
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("check_minion_loc"))
|
||||
{
|
||||
for (L2Attackable mob : _minions)
|
||||
{
|
||||
if (!npc.isInsideRadius(mob, 3000, false, false))
|
||||
{
|
||||
mob.teleToLocation(npc.getLocation());
|
||||
((L2Attackable) npc).clearAggroList();
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("despawn_minions"))
|
||||
{
|
||||
for (L2Attackable mob : _minions)
|
||||
{
|
||||
mob.decayMe();
|
||||
}
|
||||
_minions.clear();
|
||||
}
|
||||
else if (event.equalsIgnoreCase("spawn_minion"))
|
||||
{
|
||||
final L2Attackable mob = (L2Attackable) addSpawn(RAIKEL_LEOS, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0);
|
||||
mob.setIsRaidMinion(true);
|
||||
_minions.add(mob);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == ORFEN)
|
||||
{
|
||||
final L2Character originalCaster = isSummon ? caster.getServitors().values().stream().findFirst().orElse(caster.getPet()) : caster;
|
||||
if ((skill.getEffectPoint() > 0) && (getRandom(5) == 0) && npc.isInsideRadius(originalCaster, 1000, false, false))
|
||||
{
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, TEXT[getRandom(4)], caster.getName());
|
||||
originalCaster.teleToLocation(npc.getLocation());
|
||||
npc.setTarget(originalCaster);
|
||||
npc.doCast(PARALYSIS.getSkill());
|
||||
}
|
||||
}
|
||||
return super.onSkillSee(npc, caster, skill, targets, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isSummon)
|
||||
{
|
||||
if ((caller == null) || (npc == null) || npc.isCastingNow(SkillCaster::isAnyNormalType))
|
||||
{
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
final int npcId = npc.getId();
|
||||
final int callerId = caller.getId();
|
||||
if ((npcId == RAIKEL_LEOS) && (getRandom(20) == 0))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(BLOW.getSkill());
|
||||
}
|
||||
else if (npcId == RIBA_IREN)
|
||||
{
|
||||
int chance = 1;
|
||||
if (callerId == ORFEN)
|
||||
{
|
||||
chance = 9;
|
||||
}
|
||||
if ((callerId != RIBA_IREN) && (caller.getCurrentHp() < (caller.getMaxHp() / 2.0)) && (getRandom(10) < chance))
|
||||
{
|
||||
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
|
||||
npc.setTarget(caller);
|
||||
npc.doCast(ORFEN_HEAL.getSkill());
|
||||
}
|
||||
}
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
if (npcId == ORFEN)
|
||||
{
|
||||
if (!_IsTeleported && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2)))
|
||||
{
|
||||
_IsTeleported = true;
|
||||
setSpawnPoint(npc, 0);
|
||||
}
|
||||
else if (npc.isInsideRadius(attacker, 1000, false, false) && !npc.isInsideRadius(attacker, 300, false, false) && (getRandom(10) == 0))
|
||||
{
|
||||
npc.broadcastSay(ChatType.NPC_GENERAL, TEXT[getRandom(3)], attacker.getName());
|
||||
attacker.teleToLocation(npc.getLocation());
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(PARALYSIS.getSkill());
|
||||
}
|
||||
}
|
||||
else if (npcId == RIBA_IREN)
|
||||
{
|
||||
if (!npc.isCastingNow(SkillCaster::isAnyNormalType) && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2.0)))
|
||||
{
|
||||
npc.setTarget(attacker);
|
||||
npc.doCast(ORFEN_HEAL.getSkill());
|
||||
}
|
||||
}
|
||||
return super.onAttack(npc, attacker, damage, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
if (npc.getId() == ORFEN)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
GrandBossManager.getInstance().setBossStatus(ORFEN, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
long respawnTime = Config.ORFEN_SPAWN_INTERVAL + getRandom(-Config.ORFEN_SPAWN_RANDOM, Config.ORFEN_SPAWN_RANDOM);
|
||||
respawnTime *= 3600000;
|
||||
startQuestTimer("orfen_unlock", respawnTime, null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(ORFEN, info);
|
||||
cancelQuestTimer("check_minion_loc", npc, null);
|
||||
cancelQuestTimer("check_orfen_pos", npc, null);
|
||||
startQuestTimer("despawn_minions", 20000, null, null);
|
||||
cancelQuestTimers("spawn_minion");
|
||||
}
|
||||
else if ((GrandBossManager.getInstance().getBossStatus(ORFEN) == ALIVE) && (npc.getId() == RAIKEL_LEOS))
|
||||
{
|
||||
_minions.remove(npc);
|
||||
startQuestTimer("spawn_minion", 360000, npc, null);
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new Orfen();
|
||||
}
|
||||
}
|
419
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/QueenAnt/QueenAnt.java
vendored
Normal file
419
L2J_Mobius_Classic/dist/game/data/scripts/ai/bosses/QueenAnt/QueenAnt.java
vendored
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* 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 ai.bosses.QueenAnt;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||
import com.l2jmobius.gameserver.ai.CtrlIntention;
|
||||
import com.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||
import com.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||
import com.l2jmobius.gameserver.model.Location;
|
||||
import com.l2jmobius.gameserver.model.StatsSet;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Attackable;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Npc;
|
||||
import com.l2jmobius.gameserver.model.actor.L2Playable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||
import com.l2jmobius.gameserver.model.skills.CommonSkill;
|
||||
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||
import com.l2jmobius.gameserver.model.skills.SkillCaster;
|
||||
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
|
||||
import ai.AbstractNpcAI;
|
||||
|
||||
/**
|
||||
* Queen Ant's AI
|
||||
* @author Emperorc
|
||||
*/
|
||||
public final class QueenAnt extends AbstractNpcAI
|
||||
{
|
||||
private static final int QUEEN = 29001;
|
||||
private static final int LARVA = 29002;
|
||||
private static final int NURSE = 29003;
|
||||
private static final int GUARD = 29004;
|
||||
private static final int ROYAL = 29005;
|
||||
|
||||
private static final int[] MOBS =
|
||||
{
|
||||
QUEEN,
|
||||
LARVA,
|
||||
NURSE,
|
||||
GUARD,
|
||||
ROYAL
|
||||
};
|
||||
|
||||
private static final Location OUST_LOC_1 = new Location(-19480, 187344, -5600);
|
||||
private static final Location OUST_LOC_2 = new Location(-17928, 180912, -5520);
|
||||
private static final Location OUST_LOC_3 = new Location(-23808, 182368, -5600);
|
||||
|
||||
private static final int QUEEN_X = -21610;
|
||||
private static final int QUEEN_Y = 181594;
|
||||
private static final int QUEEN_Z = -5734;
|
||||
|
||||
// QUEEN Status Tracking :
|
||||
private static final byte ALIVE = 0; // Queen Ant is spawned.
|
||||
private static final byte DEAD = 1; // Queen Ant has been killed.
|
||||
|
||||
private static L2ZoneType _zone;
|
||||
|
||||
private static SkillHolder HEAL1 = new SkillHolder(4020, 1);
|
||||
private static SkillHolder HEAL2 = new SkillHolder(4024, 1);
|
||||
|
||||
L2MonsterInstance _queen = null;
|
||||
private L2MonsterInstance _larva = null;
|
||||
private final Set<L2MonsterInstance> _nurses = ConcurrentHashMap.newKeySet();
|
||||
ScheduledFuture<?> _task = null;
|
||||
|
||||
private QueenAnt()
|
||||
{
|
||||
addSpawnId(MOBS);
|
||||
addKillId(MOBS);
|
||||
addAggroRangeEnterId(MOBS);
|
||||
addFactionCallId(NURSE);
|
||||
|
||||
_zone = ZoneManager.getInstance().getZoneById(12012);
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
|
||||
final int status = GrandBossManager.getInstance().getBossStatus(QUEEN);
|
||||
if (status == DEAD)
|
||||
{
|
||||
// load the unlock date and time for queen ant from DB
|
||||
final long temp = info.getLong("respawn_time") - System.currentTimeMillis();
|
||||
// if queen ant is locked until a certain time, mark it so and start the unlock timer
|
||||
// the unlock time has not yet expired.
|
||||
if (temp > 0)
|
||||
{
|
||||
startQuestTimer("queen_unlock", temp, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the time has already expired while the server was offline. Immediately spawn queen ant.
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, QUEEN_X, QUEEN_Y, QUEEN_Z, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int loc_x = info.getInt("loc_x");
|
||||
int loc_y = info.getInt("loc_y");
|
||||
int loc_z = info.getInt("loc_z");
|
||||
final int heading = info.getInt("heading");
|
||||
final double hp = info.getDouble("currentHP");
|
||||
final double mp = info.getDouble("currentMP");
|
||||
if (!_zone.isInsideZone(loc_x, loc_y, loc_z))
|
||||
{
|
||||
loc_x = QUEEN_X;
|
||||
loc_y = QUEEN_Y;
|
||||
loc_z = QUEEN_Z;
|
||||
}
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, loc_x, loc_y, loc_z, heading, false, 0);
|
||||
queen.setCurrentHpMp(hp, mp);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnBoss(L2GrandBossInstance npc)
|
||||
{
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
if (getRandom(100) < 33)
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_1);
|
||||
}
|
||||
else if (getRandom(100) < 50)
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_zone.movePlayersTo(OUST_LOC_3);
|
||||
}
|
||||
GrandBossManager.getInstance().addBoss(npc);
|
||||
startQuestTimer("action", 10000, npc, null, true);
|
||||
startQuestTimer("heal", 1000, null, null, true);
|
||||
npc.broadcastPacket(new PlaySound(1, "BS01_A", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
_queen = npc;
|
||||
_larva = (L2MonsterInstance) addSpawn(LARVA, -21600, 179482, -5846, getRandom(360), false, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
|
||||
{
|
||||
if (event.equalsIgnoreCase("heal"))
|
||||
{
|
||||
boolean notCasting;
|
||||
final boolean larvaNeedHeal = (_larva != null) && (_larva.getCurrentHp() < _larva.getMaxHp());
|
||||
final boolean queenNeedHeal = (_queen != null) && (_queen.getCurrentHp() < _queen.getMaxHp());
|
||||
for (L2MonsterInstance nurse : _nurses)
|
||||
{
|
||||
if ((nurse == null) || nurse.isDead() || nurse.isCastingNow(SkillCaster::isAnyNormalType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
notCasting = nurse.getAI().getIntention() != CtrlIntention.AI_INTENTION_CAST;
|
||||
if (larvaNeedHeal)
|
||||
{
|
||||
if ((nurse.getTarget() != _larva) || notCasting)
|
||||
{
|
||||
nurse.setTarget(_larva);
|
||||
nurse.useMagic(getRandomBoolean() ? HEAL1.getSkill() : HEAL2.getSkill());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (queenNeedHeal)
|
||||
{
|
||||
if (nurse.getLeader() == _larva)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((nurse.getTarget() != _queen) || notCasting)
|
||||
{
|
||||
nurse.setTarget(_queen);
|
||||
nurse.useMagic(HEAL1.getSkill());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// if nurse not casting - remove target
|
||||
if (notCasting && (nurse.getTarget() != null))
|
||||
{
|
||||
nurse.setTarget(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("action") && (npc != null))
|
||||
{
|
||||
if (getRandom(3) == 0)
|
||||
{
|
||||
if (getRandom(2) == 0)
|
||||
{
|
||||
npc.broadcastSocialAction(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
npc.broadcastSocialAction(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.equalsIgnoreCase("queen_unlock"))
|
||||
{
|
||||
final L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN, QUEEN_X, QUEEN_Y, QUEEN_Z, 0, false, 0);
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, ALIVE);
|
||||
spawnBoss(queen);
|
||||
}
|
||||
return super.onAdvEvent(event, npc, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onSpawn(L2Npc npc)
|
||||
{
|
||||
final L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
switch (npc.getId())
|
||||
{
|
||||
case LARVA:
|
||||
{
|
||||
mob.setIsImmobilized(true);
|
||||
mob.setUndying(true);
|
||||
mob.setIsRaidMinion(true);
|
||||
break;
|
||||
}
|
||||
case NURSE:
|
||||
{
|
||||
mob.disableCoreAI(true);
|
||||
mob.setIsRaidMinion(true);
|
||||
_nurses.add(mob);
|
||||
break;
|
||||
}
|
||||
case ROYAL:
|
||||
case GUARD:
|
||||
{
|
||||
mob.setIsRaidMinion(true);
|
||||
break;
|
||||
}
|
||||
case QUEEN:
|
||||
{
|
||||
if (mob.getMinionList().getSpawnedMinions().isEmpty())
|
||||
{
|
||||
((L2MonsterInstance) npc).getMinionList().spawnMinions(npc.getParameters().getMinionList("Privates"));
|
||||
}
|
||||
_task = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new QueenAntTask(), 5 * 1000, 5 * 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return super.onSpawn(npc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFactionCall(L2Npc npc, L2Npc caller, L2PcInstance attacker, boolean isSummon)
|
||||
{
|
||||
if ((caller == null) || (npc == null))
|
||||
{
|
||||
return super.onFactionCall(npc, caller, attacker, isSummon);
|
||||
}
|
||||
|
||||
if (!npc.isCastingNow(SkillCaster::isAnyNormalType) && (npc.getAI().getIntention() != CtrlIntention.AI_INTENTION_CAST))
|
||||
{
|
||||
if (caller.getCurrentHp() < caller.getMaxHp())
|
||||
{
|
||||
npc.setTarget(caller);
|
||||
((L2Attackable) npc).useMagic(HEAL1.getSkill());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
|
||||
{
|
||||
if ((npc == null) || (player.isGM() && player.isInvisible()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean isMage;
|
||||
final L2Playable character;
|
||||
if (isSummon)
|
||||
{
|
||||
isMage = false;
|
||||
character = player.getServitors().values().stream().findFirst().orElse(player.getPet());
|
||||
}
|
||||
else
|
||||
{
|
||||
isMage = player.isMageClass();
|
||||
character = player;
|
||||
}
|
||||
|
||||
if (character == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Config.RAID_DISABLE_CURSE && ((character.getLevel() - npc.getLevel()) > 8))
|
||||
{
|
||||
Skill curse = null;
|
||||
if (isMage)
|
||||
{
|
||||
if (!character.hasAbnormalType(CommonSkill.RAID_CURSE.getSkill().getAbnormalType()) && (getRandom(4) == 0))
|
||||
{
|
||||
curse = CommonSkill.RAID_CURSE.getSkill();
|
||||
}
|
||||
}
|
||||
else if (!character.hasAbnormalType(CommonSkill.RAID_CURSE2.getSkill().getAbnormalType()) && (getRandom(4) == 0))
|
||||
{
|
||||
curse = CommonSkill.RAID_CURSE2.getSkill();
|
||||
}
|
||||
|
||||
if (curse != null)
|
||||
{
|
||||
npc.broadcastPacket(new MagicSkillUse(npc, character, curse.getId(), curse.getLevel(), 300, 0));
|
||||
curse.applyEffects(npc, character);
|
||||
}
|
||||
|
||||
((L2Attackable) npc).stopHating(character); // for calling again
|
||||
return null;
|
||||
}
|
||||
|
||||
return super.onAggroRangeEnter(npc, player, isSummon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
|
||||
{
|
||||
final int npcId = npc.getId();
|
||||
if (npcId == QUEEN)
|
||||
{
|
||||
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
|
||||
GrandBossManager.getInstance().setBossStatus(QUEEN, DEAD);
|
||||
// Calculate Min and Max respawn times randomly.
|
||||
final long respawnTime = (Config.QUEEN_ANT_SPAWN_INTERVAL + getRandom(-Config.QUEEN_ANT_SPAWN_RANDOM, Config.QUEEN_ANT_SPAWN_RANDOM)) * 3600000;
|
||||
startQuestTimer("queen_unlock", respawnTime, null, null);
|
||||
cancelQuestTimer("action", npc, null);
|
||||
cancelQuestTimer("heal", null, null);
|
||||
// also save the respawn time so that the info is maintained past reboots
|
||||
final StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
|
||||
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
|
||||
GrandBossManager.getInstance().setStatsSet(QUEEN, info);
|
||||
_nurses.clear();
|
||||
_larva.deleteMe();
|
||||
_larva = null;
|
||||
_queen = null;
|
||||
if (_task != null)
|
||||
{
|
||||
_task.cancel(false);
|
||||
_task = null;
|
||||
}
|
||||
}
|
||||
else if ((_queen != null) && !_queen.isAlikeDead())
|
||||
{
|
||||
if (npcId == ROYAL)
|
||||
{
|
||||
final L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
if (mob.getLeader() != null)
|
||||
{
|
||||
mob.getLeader().getMinionList().onMinionDie(mob, (280 + getRandom(40)) * 1000);
|
||||
}
|
||||
}
|
||||
else if (npcId == NURSE)
|
||||
{
|
||||
final L2MonsterInstance mob = (L2MonsterInstance) npc;
|
||||
_nurses.remove(mob);
|
||||
if (mob.getLeader() != null)
|
||||
{
|
||||
mob.getLeader().getMinionList().onMinionDie(mob, 10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKill(npc, killer, isSummon);
|
||||
}
|
||||
|
||||
private class QueenAntTask implements Runnable
|
||||
{
|
||||
public QueenAntTask()
|
||||
{
|
||||
// Constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ((_queen == null) || _queen.isDead())
|
||||
{
|
||||
_task.cancel(false);
|
||||
_task = null;
|
||||
}
|
||||
else if (_queen.calculateDistance(QUEEN_X, QUEEN_Y, QUEEN_Z, false, false) > 2000.)
|
||||
{
|
||||
_queen.clearAggroList();
|
||||
_queen.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(QUEEN_X, QUEEN_Y, QUEEN_Z, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new QueenAnt();
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@
|
||||
</parameters>
|
||||
<race>BUG</race>
|
||||
<sex>FEMALE</sex>
|
||||
<acquire exp="2179535" sp="523" />
|
||||
<acquire exp="2179535" sp="65386" raidPoints="300" />
|
||||
<stats str="60" int="76" dex="73" wit="70" con="57" men="80">
|
||||
<vitals hp="96595.8" hpRegen="208" mp="300.8" mpRegen="2.1" />
|
||||
<attack physical="105" magical="8" random="30" critical="7" accuracy="40" attackSpeed="172" type="FIST" range="40" distance="80" width="120" />
|
||||
@@ -48,6 +48,110 @@
|
||||
<radius normal="45" />
|
||||
<height normal="53" />
|
||||
</collision>
|
||||
<drop_lists>
|
||||
<death>
|
||||
<item id="882" min="1" max="3" chance="34.9" /> <!-- Mithril Ring -->
|
||||
<item id="915" min="1" max="1" chance="34.38" /> <!-- Aquastone Necklace -->
|
||||
<item id="852" min="1" max="3" chance="34.33" /> <!-- Moonstone Earring -->
|
||||
<item id="851" min="1" max="3" chance="33.96" /> <!-- Onyx Beast's Eye Earring -->
|
||||
<item id="914" min="1" max="1" chance="33.56" /> <!-- Dark Necklace -->
|
||||
<item id="853" min="1" max="3" chance="32.84" /> <!-- Earring of Protection -->
|
||||
<item id="884" min="1" max="3" chance="32.64" /> <!-- Ring of Protection -->
|
||||
<item id="883" min="1" max="3" chance="32.48" /> <!-- Aquastone Ring -->
|
||||
<item id="2496" min="1" max="1" chance="32.26" /> <!-- Dwarven Chain Shield -->
|
||||
<item id="355" min="1" max="1" chance="31.92" /> <!-- Dwarven Chain Mail Shirt -->
|
||||
<item id="916" min="1" max="1" chance="31.87" /> <!-- Necklace of Protection -->
|
||||
<item id="382" min="1" max="1" chance="31.81" /> <!-- Dwarven Chain Gaiters -->
|
||||
<item id="399" min="1" max="1" chance="24.48" /> <!-- Rind Leather Armor -->
|
||||
<item id="440" min="1" max="1" chance="24.17" /> <!-- Robe of Seal -->
|
||||
<item id="500" min="1" max="1" chance="23.96" /> <!-- Great Helmet -->
|
||||
<item id="419" min="1" max="1" chance="23.87" /> <!-- Rind Leather Gaiters -->
|
||||
<item id="6660" min="1" max="1" chance="19.79" /> <!-- Queen Ant's Ring -->
|
||||
<item id="2455" min="1" max="3" chance="17.35" /> <!-- Plated Leather Gloves -->
|
||||
<item id="498" min="1" max="3" chance="17.17" /> <!-- Steel Plate Helmet -->
|
||||
<item id="418" min="1" max="1" chance="16.93" /> <!-- Plated Leather Gaiters -->
|
||||
<item id="1126" min="1" max="3" chance="16.91" /> <!-- Crimson Boots -->
|
||||
<item id="632" min="1" max="3" chance="16.61" /> <!-- Knight's Shield -->
|
||||
<item id="398" min="1" max="1" chance="16.56" /> <!-- Plated Leather Armor -->
|
||||
<item id="380" min="1" max="1" chance="7.217" /> <!-- Plate Gaiters -->
|
||||
<item id="187" min="1" max="1" chance="7.209" /> <!-- Atuba Hammer -->
|
||||
<item id="322" min="1" max="1" chance="7.208" /> <!-- Vajra Wand -->
|
||||
<item id="1125" min="1" max="3" chance="7.2" /> <!-- Assault Boots -->
|
||||
<item id="353" min="1" max="1" chance="7.197" /> <!-- Half Plate Armor -->
|
||||
<item id="396" min="1" max="1" chance="7.195" /> <!-- Salamander Skin Mail -->
|
||||
<item id="2427" min="1" max="3" chance="7.183" /> <!-- Salamander Skin Boots -->
|
||||
<item id="438" min="1" max="3" chance="7.183" /> <!-- Sage's Rags -->
|
||||
<item id="262" min="1" max="1" chance="7.161" /> <!-- Scallop Jamadhr -->
|
||||
<item id="321" min="1" max="1" chance="7.161" /> <!-- Demon's Fangs -->
|
||||
<item id="225" min="1" max="1" chance="7.16" /> <!-- Mithril Dagger -->
|
||||
<item id="2412" min="1" max="3" chance="7.156" /> <!-- Plate Helmet -->
|
||||
<item id="188" min="1" max="1" chance="7.141" /> <!-- Ghost Staff -->
|
||||
<item id="2451" min="1" max="3" chance="7.14" /> <!-- Sage's Worn Gloves -->
|
||||
<item id="297" min="1" max="1" chance="7.137" /> <!-- Glaive -->
|
||||
<item id="61" min="1" max="3" chance="7.129" /> <!-- Mithril Gloves -->
|
||||
<item id="159" min="1" max="1" chance="7.123" /> <!-- Bonebreaker -->
|
||||
<item id="2494" min="1" max="3" chance="7.103" /> <!-- Plate Shield -->
|
||||
<item id="607" min="1" max="3" chance="7.111" /> <!-- Ogre Power Gauntlets -->
|
||||
<item id="190" min="1" max="1" chance="7.109" /> <!-- Atuba Mace -->
|
||||
<item id="497" min="1" max="3" chance="7.107" /> <!-- Chain Helmet -->
|
||||
<item id="2428" min="1" max="3" chance="7.101" /> <!-- Plate Boots -->
|
||||
<item id="630" min="1" max="3" chance="7.098" /> <!-- Square Shield -->
|
||||
<item id="280" min="1" max="1" chance="7.093" /> <!-- Light Crossbow -->
|
||||
<item id="70" min="1" max="1" chance="7.091" /> <!-- Claymore -->
|
||||
<item id="189" min="1" max="1" chance="7.088" /> <!-- Staff of Life -->
|
||||
<item id="320" min="1" max="1" chance="7.086" /> <!-- Blue Crystal Skull -->
|
||||
<item id="2499" min="1" max="1" chance="7.006" /> <!-- Elven Long Sword -->
|
||||
<item id="131" min="1" max="1" chance="6.427" /> <!-- Spirit Sword -->
|
||||
<item id="227" min="1" max="1" chance="6.423" /> <!-- Stiletto -->
|
||||
<item id="133" min="1" max="1" chance="6.421" /> <!-- Raid Sword -->
|
||||
<item id="325" min="1" max="1" chance="6.407" /> <!-- Horn of Glory -->
|
||||
<item id="195" min="1" max="1" chance="6.406" /> <!-- Cursed Staff -->
|
||||
<item id="74" min="1" max="1" chance="6.368" /> <!-- Katana -->
|
||||
<item id="282" min="1" max="1" chance="6.347" /> <!-- Elemental Bow -->
|
||||
<item id="94" min="1" max="1" chance="6.334" /> <!-- Bec de Corbin -->
|
||||
<item id="285" min="1" max="1" chance="6.334" /> <!-- Noble Elven Bow -->
|
||||
<item id="242" min="1" max="1" chance="6.332" /> <!-- Soulfire Dirk -->
|
||||
<item id="73" min="1" max="1" chance="6.326" /> <!-- Shamshir -->
|
||||
<item id="302" min="1" max="1" chance="5.642" /> <!-- Body Slasher -->
|
||||
<item id="397" min="1" max="1" chance="5.62" /> <!-- Reinforced Mithril Shirt -->
|
||||
<item id="2413" min="1" max="3" chance="5.617" /> <!-- Chain Hood -->
|
||||
<item id="2495" min="1" max="3" chance="5.613" /> <!-- Chain Shield -->
|
||||
<item id="354" min="1" max="1" chance="5.613" /> <!-- Chain Mail Shirt -->
|
||||
<item id="194" min="1" max="1" chance="5.594" /> <!-- Heavy Doom Axe -->
|
||||
<item id="2453" min="1" max="3" chance="5.594" /> <!-- Chain Gloves -->
|
||||
<item id="281" min="1" max="1" chance="5.593" /> <!-- Crystallized Ice Bow -->
|
||||
<item id="631" min="1" max="3" chance="5.602" /> <!-- Eldarake -->
|
||||
<item id="439" min="1" max="1" chance="5.59" /> <!-- Karmian Tunic -->
|
||||
<item id="160" min="1" max="1" chance="5.588" /> <!-- Battle Axe -->
|
||||
<item id="71" min="1" max="1" chance="5.585" /> <!-- Flamberge -->
|
||||
<item id="226" min="1" max="1" chance="5.575" /> <!-- Cursed Dagger -->
|
||||
<item id="191" min="1" max="1" chance="5.567" /> <!-- Heavy Doom Hammer -->
|
||||
<item id="96" min="1" max="1" chance="5.563" /> <!-- Scythe -->
|
||||
<item id="298" min="1" max="1" chance="5.56" /> <!-- Orcish Glaive -->
|
||||
<item id="263" min="1" max="1" chance="5.56" /> <!-- Chakram -->
|
||||
<item id="2431" min="1" max="3" chance="5.547" /> <!-- Plated Leather Boots -->
|
||||
<item id="2433" min="1" max="3" chance="5.539" /> <!-- Boots of Seal -->
|
||||
<item id="2429" min="1" max="3" chance="5.537" /> <!-- Chain Boots -->
|
||||
<item id="72" min="1" max="1" chance="5.537" /> <!-- StormBringer -->
|
||||
<item id="192" min="1" max="1" chance="5.537" /> <!-- Crystal Staff -->
|
||||
<item id="232" min="1" max="1" chance="5.53" /> <!-- Dark Elven Dagger -->
|
||||
<item id="230" min="1" max="1" chance="5.521" /> <!-- Needle Wolverine -->
|
||||
<item id="2454" min="1" max="3" chance="5.516" /> <!-- Karmian Gloves -->
|
||||
<item id="381" min="1" max="1" chance="5.515" /> <!-- Chain Gaiters -->
|
||||
<item id="62" min="1" max="3" chance="5.511" /> <!-- Reinforced Mithril Boots -->
|
||||
<item id="173" min="1" max="1" chance="5.51" /> <!-- Skull Graver -->
|
||||
<item id="89" min="1" max="1" chance="5.503" /> <!-- Big Hammer -->
|
||||
<item id="471" min="1" max="1" chance="5.501" /> <!-- Karmian Stockings -->
|
||||
<item id="2432" min="1" max="3" chance="5.501" /> <!-- Dwarven Chain Boots -->
|
||||
<item id="161" min="1" max="1" chance="5.498" /> <!-- Silver Axe -->
|
||||
<item id="193" min="1" max="1" chance="5.497" /> <!-- Stick of Faith -->
|
||||
<item id="2452" min="1" max="3" chance="5.485" /> <!-- Reinforced Mithril Gloves -->
|
||||
<item id="2430" min="1" max="3" chance="5.483" /> <!-- Karmian Boots -->
|
||||
<item id="2387" min="1" max="1" chance="5.481" /> <!-- Reinforced Mithril Gaiters -->
|
||||
<item id="70000" min="76" max="228" chance="100" /> <!-- Sealed Rune - Stage 1 -->
|
||||
<!-- FIXME: Also drops herbs. -->
|
||||
</death>
|
||||
</drop_lists>
|
||||
</npc>
|
||||
<npc id="29002" level="29" type="L2Monster" name="Queen Ant Larva">
|
||||
<race>BUG</race>
|
||||
@@ -226,7 +330,7 @@
|
||||
</parameters>
|
||||
<race>CONSTRUCT</race>
|
||||
<sex>MALE</sex>
|
||||
<acquire exp="2041407" sp="489" />
|
||||
<acquire exp="2041407" sp="61242" raidPoints="300" />
|
||||
<stats str="60" int="76" dex="73" wit="70" con="57" men="80">
|
||||
<vitals hp="261551.68" hpRegen="273" mp="259.2" mpRegen="1.5" />
|
||||
<attack physical="158.48" magical="44.27" random="30" critical="7" accuracy="40" attackSpeed="172" type="FIST" range="40" distance="80" width="120" />
|
||||
@@ -261,6 +365,87 @@
|
||||
<radius normal="140" />
|
||||
<height normal="75" />
|
||||
</collision>
|
||||
<drop_lists>
|
||||
<death>
|
||||
<item id="854" min="1" max="3" chance="34.44" /> <!-- Earring of Seal -->
|
||||
<item id="1127" min="1" max="3" chance="34.14" /> <!-- Forgotten Boots -->
|
||||
<item id="1149" min="1" max="3" chance="33.75" /> <!-- Shining Circlet -->
|
||||
<item id="885" min="1" max="3" chance="33.25" /> <!-- Ring of Ages -->
|
||||
<item id="917" min="1" max="1" chance="32.58" /> <!-- Necklace of Mermaid -->
|
||||
<item id="608" min="1" max="3" chance="31.99" /> <!-- Mithril Gauntlets -->
|
||||
<item id="472" min="1" max="1" chance="25.78" /> <!-- Demon's Stockings -->
|
||||
<item id="2459" min="1" max="1" chance="25.62" /> <!-- Demon's Gloves -->
|
||||
<item id="2460" min="1" max="1" chance="25.22" /> <!-- Theca Leather Gloves -->
|
||||
<item id="420" min="1" max="1" chance="25.06" /> <!-- Theca Leather Gaiters -->
|
||||
<item id="2436" min="1" max="1" chance="24.98" /> <!-- Theca Leather Boots -->
|
||||
<item id="2435" min="1" max="1" chance="24.72" /> <!-- Demon's Boots -->
|
||||
<item id="441" min="1" max="1" chance="24.37" /> <!-- Demon's Tunic -->
|
||||
<item id="400" min="1" max="1" chance="24.01" /> <!-- Theca Leather Armor -->
|
||||
<item id="6662" min="1" max="1" chance="20.82" /> <!-- Ring of Core -->
|
||||
<item id="2462" min="1" max="1" chance="20.76" /> <!-- Full Plate Gauntlets -->
|
||||
<item id="401" min="1" max="1" chance="20.72" /> <!-- Drake Leather Armor -->
|
||||
<item id="2461" min="1" max="1" chance="20.58" /> <!-- Drake Leather Gloves -->
|
||||
<item id="2437" min="1" max="1" chance="20.28" /> <!-- Drake Leather Boots -->
|
||||
<item id="356" min="1" max="1" chance="20.12" /> <!-- Full Plate Armor -->
|
||||
<item id="517" min="1" max="3" chance="20.01" /> <!-- Compound Helmet -->
|
||||
<item id="2468" min="1" max="3" chance="19.97" /> <!-- Blessed Gloves -->
|
||||
<item id="2463" min="1" max="1" chance="19.87" /> <!-- Divine Gloves -->
|
||||
<item id="103" min="1" max="3" chance="19.79" /> <!-- Tower Shield -->
|
||||
<item id="2438" min="1" max="1" chance="19.69" /> <!-- Full Plate Boots -->
|
||||
<item id="442" min="1" max="1" chance="19.67" /> <!-- Divine Tunic -->
|
||||
<item id="2414" min="1" max="1" chance="19.65" /> <!-- Full Plate Helmet -->
|
||||
<item id="2497" min="1" max="1" chance="19.54" /> <!-- Full Plate Shield -->
|
||||
<item id="107" min="1" max="3" chance="19.48" /> <!-- Compound Shield -->
|
||||
<item id="64" min="1" max="1" chance="19.35" /> <!-- Compound Boots -->
|
||||
<item id="1128" min="1" max="3" chance="19.32" /> <!-- Adamantite Boots -->
|
||||
<item id="60" min="1" max="1" chance="19.31" /> <!-- Compound Armor -->
|
||||
<item id="603" min="1" max="3" chance="19.15" /> <!-- Divine Boots -->
|
||||
<item id="473" min="1" max="1" chance="19.13" /> <!-- Divine Stockings -->
|
||||
<item id="499" min="1" max="3" chance="19.09" /> <!-- Mithril Helmet -->
|
||||
<item id="888" min="1" max="3" chance="17.26" /> <!-- Blessed Ring -->
|
||||
<item id="857" min="1" max="3" chance="17.15" /> <!-- Holy Earring -->
|
||||
<item id="855" min="1" max="3" chance="17" /> <!-- Nassen's Earring -->
|
||||
<item id="119" min="1" max="1" chance="16.92" /> <!-- Necklace of Seal -->
|
||||
<item id="886" min="1" max="3" chance="15.98" /> <!-- Ring of Seal -->
|
||||
<item id="919" min="1" max="1" chance="15.93" /> <!-- Blessed Necklace -->
|
||||
<item id="266" min="1" max="1" chance="11.61" /> <!-- Great Pata -->
|
||||
<item id="2503" min="1" max="1" chance="11.56" /> <!-- Yaksa Mace -->
|
||||
<item id="286" min="1" max="1" chance="11.35" /> <!-- Eminence Bow -->
|
||||
<item id="299" min="1" max="1" chance="11.34" /> <!-- Orcish Poleaxe -->
|
||||
<item id="206" min="1" max="1" chance="11.16" /> <!-- Demon's Staff -->
|
||||
<item id="135" min="1" max="1" chance="11.1" /> <!-- Samurai Long Sword -->
|
||||
<item id="228" min="1" max="1" chance="11.06" /> <!-- Crystal Dagger -->
|
||||
<item id="205" min="1" max="1" chance="10.9" /> <!-- Ghoul's Staff -->
|
||||
<item id="204" min="1" max="1" chance="10.85" /> <!-- Deadman's Staff -->
|
||||
<item id="303" min="1" max="1" chance="4.311" /> <!-- Widow Maker -->
|
||||
<item id="84" min="1" max="1" chance="4.224" /> <!-- Homunkulus' Sword -->
|
||||
<item id="162" min="1" max="1" chance="4.221" /> <!-- War Axe -->
|
||||
<item id="197" min="1" max="1" chance="4.216" /> <!-- Paradia Staff -->
|
||||
<item id="174" min="1" max="1" chance="4.213" /> <!-- Nirvana Axe -->
|
||||
<item id="76" min="1" max="1" chance="4.212" /> <!-- Sword of Delusion -->
|
||||
<item id="134" min="1" max="1" chance="4.209" /> <!-- Sword of Nightmare -->
|
||||
<item id="132" min="1" max="1" chance="4.207" /> <!-- Ultimate Sword -->
|
||||
<item id="201" min="1" max="1" chance="4.2" /> <!-- Club of Nature -->
|
||||
<item id="95" min="1" max="1" chance="4.196" /> <!-- Poleaxe -->
|
||||
<item id="77" min="1" max="1" chance="4.195" /> <!-- Tsurugi -->
|
||||
<item id="265" min="1" max="1" chance="4.19" /> <!-- Fisted Blade -->
|
||||
<item id="196" min="1" max="1" chance="4.176" /> <!-- Stick of Eternity -->
|
||||
<item id="202" min="1" max="1" chance="4.176" /> <!-- Mace of Underworld -->
|
||||
<item id="200" min="1" max="1" chance="4.175" /> <!-- Sage's Staff -->
|
||||
<item id="198" min="1" max="1" chance="4.162" /> <!-- Inferno Staff -->
|
||||
<item id="283" min="1" max="1" chance="4.156" /> <!-- Akat Longbow -->
|
||||
<item id="203" min="1" max="1" chance="4.152" /> <!-- Pa'agrio Axe -->
|
||||
<item id="199" min="1" max="1" chance="4.143" /> <!-- Pa'agrio Hammer -->
|
||||
<item id="75" min="1" max="1" chance="4.131" /> <!-- Caliburs -->
|
||||
<item id="145" min="1" max="1" chance="4.126" /> <!-- Sword of Whispering Death -->
|
||||
<item id="231" min="1" max="1" chance="4.114" /> <!-- Grace Dagger -->
|
||||
<item id="233" min="1" max="1" chance="4.111" /> <!-- Dark Screamer -->
|
||||
<item id="301" min="1" max="1" chance="4.098" /> <!-- Scorpion -->
|
||||
<item id="70000" min="297" max="891" chance="100" /> <!-- Sealed Rune - Stage 1 -->
|
||||
<item id="8620" min="1" max="3" chance="49.66" /> <!-- Ancient Book: Divine Inspiration (Manuscript) -->
|
||||
<!-- FIXME: Also drops herbs. -->
|
||||
</death>
|
||||
</drop_lists>
|
||||
</npc>
|
||||
<npc id="29007" level="50" type="L2Monster" name="Death Knight">
|
||||
<parameters>
|
||||
@@ -598,7 +783,7 @@
|
||||
</parameters>
|
||||
<race>ELEMENTAL</race>
|
||||
<sex>FEMALE</sex>
|
||||
<acquire exp="12776400" sp="3066" />
|
||||
<acquire exp="8872500" sp="266175" raidPoints="300" />
|
||||
<stats str="60" int="76" dex="73" wit="70" con="57" men="80">
|
||||
<vitals hp="261551.68" hpRegen="273" mp="747.8" mpRegen="2.1" />
|
||||
<attack physical="164" magical="11" random="30" critical="7" accuracy="40" attackSpeed="172" type="FIST" range="40" distance="80" width="120" />
|
||||
@@ -637,6 +822,61 @@
|
||||
<radius normal="35" />
|
||||
<height normal="143" />
|
||||
</collision>
|
||||
<drop_lists>
|
||||
<death>
|
||||
<item id="887" min="1" max="3" chance="34.78" /> <!-- Adamantite Ring -->
|
||||
<item id="918" min="1" max="1" chance="34.06" /> <!-- Adamantite Necklace -->
|
||||
<item id="856" min="1" max="3" chance="33.27" /> <!-- Adamantite Earring -->
|
||||
<item id="2379" min="1" max="1" chance="25.82" /> <!-- Avadon Gaiters -->
|
||||
<item id="673" min="1" max="1" chance="25.7" /> <!-- Avadon Shield -->
|
||||
<item id="2415" min="1" max="1" chance="25.04" /> <!-- Sealed Avadon Circlet -->
|
||||
<item id="2376" min="1" max="1" chance="24.62" /> <!-- Avadon Breastplate -->
|
||||
<item id="2462" min="1" max="1" chance="20.96" /> <!-- Full Plate Gauntlets -->
|
||||
<item id="442" min="1" max="1" chance="20.93" /> <!-- Divine Tunic -->
|
||||
<item id="603" min="1" max="3" chance="20.79" /> <!-- Divine Boots -->
|
||||
<item id="473" min="1" max="1" chance="20.66" /> <!-- Divine Stockings -->
|
||||
<item id="1128" min="1" max="3" chance="20.64" /> <!-- Adamantite Boots -->
|
||||
<item id="2497" min="1" max="3" chance="20.45" /> <!-- Full Plate Shield -->
|
||||
<item id="2463" min="1" max="1" chance="20.25" /> <!-- Divine Gloves -->
|
||||
<item id="2438" min="1" max="1" chance="20.24" /> <!-- Full Plate Boots -->
|
||||
<item id="2414" min="1" max="1" chance="20.2" /> <!-- Full Plate Helmet -->
|
||||
<item id="499" min="1" max="3" chance="20.03" /> <!-- Mithril Helmet -->
|
||||
<item id="356" min="1" max="1" chance="19.54" /> <!-- Full Plate Armor -->
|
||||
<item id="2461" min="1" max="1" chance="19.5" /> <!-- Drake Leather Gloves -->
|
||||
<item id="401" min="1" max="1" chance="19.48" /> <!-- Drake Leather Armor -->
|
||||
<item id="2437" min="1" max="1" chance="19.41" /> <!-- Drake Leather Boots -->
|
||||
<item id="2468" min="1" max="3" chance="19.18" /> <!-- Blessed Gloves -->
|
||||
<item id="6661" min="1" max="1" chance="19.05" /> <!-- Orfen's Earring -->
|
||||
<item id="886" min="1" max="3" chance="17.44" /> <!-- Ring of Seal -->
|
||||
<item id="857" min="1" max="3" chance="17.38" /> <!-- Holy Earring -->
|
||||
<item id="919" min="1" max="1" chance="17.09" /> <!-- Blessed Necklace -->
|
||||
<item id="119" min="1" max="1" chance="17.02" /> <!-- Necklace of Seal -->
|
||||
<item id="855" min="1" max="3" chance="16.59" /> <!-- Nassen's Earring -->
|
||||
<item id="888" min="1" max="3" chance="15.88" /> <!-- Blessed Ring -->
|
||||
<item id="206" min="1" max="1" chance="11.64" /> <!-- Demon's Staff -->
|
||||
<item id="286" min="1" max="1" chance="11.55" /> <!-- Eminence Bow -->
|
||||
<item id="135" min="1" max="1" chance="11.53" /> <!-- Samurai Long Sword -->
|
||||
<item id="205" min="1" max="1" chance="11.44" /> <!-- Ghoul's Staff -->
|
||||
<item id="228" min="1" max="1" chance="11.42" /> <!-- Crystal Dagger -->
|
||||
<item id="204" min="1" max="1" chance="11.01" /> <!-- Deadman's Staff -->
|
||||
<item id="2503" min="1" max="1" chance="10.74" /> <!-- Yaksa Mace -->
|
||||
<item id="266" min="1" max="1" chance="10.62" /> <!-- Great Pata -->
|
||||
<item id="299" min="1" max="1" chance="10.61" /> <!-- Orcish Poleaxe -->
|
||||
<item id="947" min="2" max="8" chance="100" /> <!-- Scroll: Enchant Weapon (B-grade) -->
|
||||
<item id="70000" min="198" max="593" chance="100" /> <!-- Sealed Rune - Stage 1 -->
|
||||
<item id="948" min="10" max="30" chance="100" /> <!-- Scroll: Enchant Armor (B-grade) -->
|
||||
<item id="8620" min="1" max="3" chance="51.22" /> <!-- Ancient Book: Divine Inspiration (Manuscript) -->
|
||||
<item id="4072" min="20" max="80" chance="12.91" /> <!-- Sealed Avadon Circlet Pattern -->
|
||||
<item id="4064" min="20" max="80" chance="12.87" /> <!-- Avadon Breastplate Part -->
|
||||
<item id="4050" min="20" max="80" chance="12.85" /> <!-- Adamantite Ring Wire -->
|
||||
<item id="4049" min="20" max="80" chance="12.61" /> <!-- Adamantite Earring Gemstone -->
|
||||
<item id="4071" min="20" max="80" chance="12.26" /> <!-- Avadon Robe Fabric -->
|
||||
<item id="4051" min="20" max="80" chance="12.26" /> <!-- Adamantite Necklace Chain -->
|
||||
<item id="4439" min="20" max="80" chance="12.07" /> <!-- Avadon Shield Fragment -->
|
||||
<item id="4065" min="20" max="80" chance="12.07" /> <!-- Avadon Gaiter Material -->
|
||||
<!-- FIXME: Also drops herbs. -->
|
||||
</death>
|
||||
</drop_lists>
|
||||
</npc>
|
||||
<npc id="29015" level="48" type="L2Monster" name="Laikel">
|
||||
<parameters>
|
||||
@@ -896,78 +1136,78 @@
|
||||
</collision>
|
||||
<drop_lists>
|
||||
<death>
|
||||
<item id="6328" min="1" max="3" chance="51.12" /> <!-- Sealed Majestic Ring -->
|
||||
<item id="49580" min="1" max="1" chance="31.16" /> <!-- Baium's Ring -->
|
||||
<item id="6327" min="1" max="1" chance="20.48" /> <!-- Sealed Majestic Earring -->
|
||||
<item id="7900" min="1" max="1" chance="17.56" /> <!-- Ice Storm Hammer -->
|
||||
<item id="7892" min="1" max="1" chance="17.24" /> <!-- Spell Breaker -->
|
||||
<item id="7893" min="1" max="1" chance="16.68" /> <!-- Kaim Vanul's Bones -->
|
||||
<item id="7883" min="1" max="1" chance="16.27" /> <!-- Guardian's Sword -->
|
||||
<item id="7889" min="1" max="1" chance="15.97" /> <!-- Wizard's Tear -->
|
||||
<item id="6325" min="1" max="3" chance="15.56" /> <!-- Sealed Phoenix Ring -->
|
||||
<item id="7901" min="1" max="1" chance="15.55" /> <!-- Star Buster -->
|
||||
<item id="6326" min="1" max="1" chance="8.065" /> <!-- Sealed Majestic Necklace -->
|
||||
<item id="5292" min="1" max="3" chance="6.963" /> <!-- Sealed Dark Crystal Shield -->
|
||||
<item id="5315" min="1" max="1" chance="6.03" /> <!-- Sealed Shield of Nightmare -->
|
||||
<item id="5296" min="1" max="3" chance="5.068" /> <!-- Sealed Tallum Boots -->
|
||||
<item id="235" min="1" max="1" chance="5.067" /> <!-- Bloody Orchid -->
|
||||
<item id="288" min="1" max="1" chance="5.066" /> <!-- Carnage Bow -->
|
||||
<item id="5290" min="1" max="3" chance="5.065" /> <!-- Sealed Dark Crystal Gloves -->
|
||||
<item id="5295" min="1" max="3" chance="5.053" /> <!-- Sealed Tallum Gloves -->
|
||||
<item id="269" min="1" max="1" chance="5.053" /> <!-- Blood Tornado -->
|
||||
<item id="5294" min="1" max="3" chance="5.052" /> <!-- Sealed Tallum Helmet -->
|
||||
<item id="80" min="1" max="1" chance="5.04" /> <!-- Tallum Blade -->
|
||||
<item id="2504" min="1" max="1" chance="5.031" /> <!-- Meteor Shower -->
|
||||
<item id="7884" min="1" max="1" chance="5.025" /> <!-- Infernal Master -->
|
||||
<item id="7894" min="1" max="1" chance="5.019" /> <!-- Spiritual Eye -->
|
||||
<item id="7899" min="1" max="1" chance="4.982" /> <!-- Destroyer Hammer -->
|
||||
<item id="150" min="1" max="1" chance="4.982" /> <!-- Elemental Sword -->
|
||||
<item id="5291" min="1" max="3" chance="4.954" /> <!-- Sealed Dark Crystal Boots -->
|
||||
<item id="98" min="1" max="1" chance="4.949" /> <!-- Halberd -->
|
||||
<item id="5289" min="1" max="3" chance="4.946" /> <!-- Sealed Dark Crystal Helmet -->
|
||||
<item id="151" min="1" max="1" chance="4.933" /> <!-- Sword of Miracles -->
|
||||
<item id="289" min="1" max="1" chance="4.933" /> <!-- Soul Bow -->
|
||||
<item id="164" min="1" max="1" chance="4.064" /> <!-- Elysian -->
|
||||
<item id="213" min="1" max="1" chance="4.062" /> <!-- Branch of the Mother Tree -->
|
||||
<item id="236" min="1" max="1" chance="4.051" /> <!-- Soul Separator -->
|
||||
<item id="270" min="1" max="1" chance="4.026" /> <!-- Dragon Grinder -->
|
||||
<item id="81" min="1" max="1" chance="4.019" /> <!-- Dragon Slayer -->
|
||||
<item id="6324" min="1" max="1" chance="3.987" /> <!-- Sealed Phoenix Earring -->
|
||||
<item id="7895" min="1" max="1" chance="3.969" /> <!-- Flaming Dragon Skull -->
|
||||
<item id="2500" min="1" max="1" chance="3.962" /> <!-- Dark Legion's Edge -->
|
||||
<item id="305" min="1" max="1" chance="3.956" /> <!-- Tallum Glaive -->
|
||||
<item id="7902" min="1" max="1" chance="3.95" /> <!-- Doom Crusher -->
|
||||
<item id="212" min="1" max="1" chance="3.93" /> <!-- Dasparion's Staff -->
|
||||
<item id="5288" min="1" max="1" chance="3.055" /> <!-- Sealed Dark Crystal Gaiters -->
|
||||
<item id="5317" min="1" max="1" chance="3.028" /> <!-- Sealed Majestic Circlet -->
|
||||
<item id="5297" min="1" max="1" chance="3.017" /> <!-- Sealed Dark Crystal Leather Armor -->
|
||||
<item id="5312" min="1" max="1" chance="3.01" /> <!-- Sealed Helm of Nightmare -->
|
||||
<item id="5318" min="1" max="1" chance="3.005" /> <!-- Sealed Majestic Gauntlets -->
|
||||
<item id="5293" min="1" max="1" chance="2.999" /> <!-- Sealed Tallum Plate Armor -->
|
||||
<item id="5314" min="1" max="1" chance="2.995" /> <!-- Sealed Boots of Nightmare -->
|
||||
<item id="6328" min="1" max="3" chance="51.82" /> <!-- Sealed Majestic Ring -->
|
||||
<item id="49580" min="1" max="1" chance="30.47" /> <!-- Baium's Ring -->
|
||||
<item id="6327" min="1" max="1" chance="20.23" /> <!-- Sealed Majestic Earring -->
|
||||
<item id="7900" min="1" max="1" chance="17.78" /> <!-- Ice Storm Hammer -->
|
||||
<item id="7893" min="1" max="1" chance="17.72" /> <!-- Kaim Vanul's Bones -->
|
||||
<item id="7883" min="1" max="1" chance="17.42" /> <!-- Guardian's Sword -->
|
||||
<item id="7901" min="1" max="1" chance="16.71" /> <!-- Star Buster -->
|
||||
<item id="7892" min="1" max="1" chance="16.66" /> <!-- Spell Breaker -->
|
||||
<item id="7889" min="1" max="1" chance="15.69" /> <!-- Wizard's Tear -->
|
||||
<item id="6325" min="1" max="3" chance="14.68" /> <!-- Sealed Phoenix Ring -->
|
||||
<item id="6326" min="1" max="1" chance="8.035" /> <!-- Sealed Majestic Necklace -->
|
||||
<item id="5292" min="1" max="3" chance="6.95" /> <!-- Sealed Dark Crystal Shield -->
|
||||
<item id="5315" min="1" max="1" chance="5.979" /> <!-- Sealed Shield of Nightmare -->
|
||||
<item id="5295" min="1" max="3" chance="5.068" /> <!-- Sealed Tallum Gloves -->
|
||||
<item id="288" min="1" max="1" chance="5.063" /> <!-- Carnage Bow -->
|
||||
<item id="2504" min="1" max="1" chance="5.062" /> <!-- Meteor Shower -->
|
||||
<item id="235" min="1" max="1" chance="5.059" /> <!-- Bloody Orchid -->
|
||||
<item id="289" min="1" max="1" chance="5.052" /> <!-- Soul Bow -->
|
||||
<item id="7899" min="1" max="1" chance="5.028" /> <!-- Destroyer Hammer -->
|
||||
<item id="151" min="1" max="1" chance="5.023" /> <!-- Sword of Miracles -->
|
||||
<item id="7894" min="1" max="1" chance="5.016" /> <!-- Spiritual Eye -->
|
||||
<item id="5289" min="1" max="3" chance="5.011" /> <!-- Sealed Dark Crystal Helmet -->
|
||||
<item id="5296" min="1" max="3" chance="4.991" /> <!-- Sealed Tallum Boots -->
|
||||
<item id="5294" min="1" max="3" chance="4.99" /> <!-- Sealed Tallum Helmet -->
|
||||
<item id="80" min="1" max="1" chance="4.979" /> <!-- Tallum Blade -->
|
||||
<item id="150" min="1" max="1" chance="4.97" /> <!-- Elemental Sword -->
|
||||
<item id="269" min="1" max="1" chance="4.969" /> <!-- Blood Tornado -->
|
||||
<item id="5291" min="1" max="3" chance="4.964" /> <!-- Sealed Dark Crystal Boots -->
|
||||
<item id="98" min="1" max="1" chance="4.955" /> <!-- Halberd -->
|
||||
<item id="5290" min="1" max="3" chance="4.945" /> <!-- Sealed Dark Crystal Gloves -->
|
||||
<item id="7884" min="1" max="1" chance="4.937" /> <!-- Infernal Master -->
|
||||
<item id="7895" min="1" max="1" chance="4.059" /> <!-- Flaming Dragon Skull -->
|
||||
<item id="305" min="1" max="1" chance="4.031" /> <!-- Tallum Glaive -->
|
||||
<item id="270" min="1" max="1" chance="4.008" /> <!-- Dragon Grinder -->
|
||||
<item id="7902" min="1" max="1" chance="3.993" /> <!-- Doom Crusher -->
|
||||
<item id="212" min="1" max="1" chance="3.966" /> <!-- Dasparion's Staff -->
|
||||
<item id="164" min="1" max="1" chance="3.963" /> <!-- Elysian -->
|
||||
<item id="236" min="1" max="1" chance="3.963" /> <!-- Soul Separator -->
|
||||
<item id="2500" min="1" max="1" chance="3.961" /> <!-- Dark Legion's Edge -->
|
||||
<item id="6324" min="1" max="1" chance="3.954" /> <!-- Sealed Phoenix Earring -->
|
||||
<item id="81" min="1" max="1" chance="3.949" /> <!-- Dragon Slayer -->
|
||||
<item id="213" min="1" max="1" chance="3.934" /> <!-- Branch of the Mother Tree -->
|
||||
<item id="5305" min="1" max="1" chance="3.07" /> <!-- Sealed Tallum Stockings -->
|
||||
<item id="5318" min="1" max="1" chance="3.063" /> <!-- Sealed Majestic Gauntlets -->
|
||||
<item id="5319" min="1" max="1" chance="3.042" /> <!-- Sealed Majestic Boots -->
|
||||
<item id="5301" min="1" max="1" chance="3.029" /> <!-- Sealed Tallum Leather Armor -->
|
||||
<item id="5308" min="1" max="1" chance="3.022" /> <!-- Sealed Dark Crystal Robe -->
|
||||
<item id="5287" min="1" max="1" chance="3.017" /> <!-- Sealed Dark Crystal Breastplate -->
|
||||
<item id="5314" min="1" max="1" chance="2.998" /> <!-- Sealed Boots of Nightmare -->
|
||||
<item id="5304" min="1" max="1" chance="2.996" /> <!-- Sealed Tallum Tunic -->
|
||||
<item id="5297" min="1" max="1" chance="2.994" /> <!-- Sealed Dark Crystal Leather Armor -->
|
||||
<item id="5312" min="1" max="1" chance="2.981" /> <!-- Sealed Helm of Nightmare -->
|
||||
<item id="49683" min="1" max="1" chance="2.978" /> <!-- Talisman of Baium -->
|
||||
<item id="5301" min="1" max="1" chance="2.967" /> <!-- Sealed Tallum Leather Armor -->
|
||||
<item id="5319" min="1" max="1" chance="2.961" /> <!-- Sealed Majestic Boots -->
|
||||
<item id="5308" min="1" max="1" chance="2.959" /> <!-- Sealed Dark Crystal Robe -->
|
||||
<item id="5313" min="1" max="1" chance="2.955" /> <!-- Sealed Gauntlets of Nightmare -->
|
||||
<item id="5304" min="1" max="1" chance="2.955" /> <!-- Sealed Tallum Tunic -->
|
||||
<item id="5287" min="1" max="1" chance="2.944" /> <!-- Sealed Dark Crystal Breastplate -->
|
||||
<item id="5298" min="1" max="1" chance="2.94" /> <!-- Sealed Dark Crystal Leggings -->
|
||||
<item id="5305" min="1" max="1" chance="2.937" /> <!-- Sealed Tallum Stockings -->
|
||||
<item id="5329" min="1" max="1" chance="2.066" /> <!-- Sealed Majestic Robe -->
|
||||
<item id="5316" min="1" max="1" chance="2.05" /> <!-- Sealed Majestic Plate Armor -->
|
||||
<item id="5323" min="1" max="1" chance="1.992" /> <!-- Sealed Majestic Leather Armor -->
|
||||
<item id="5311" min="1" max="1" chance="1.983" /> <!-- Sealed Armor of Nightmare -->
|
||||
<item id="5320" min="1" max="1" chance="1.982" /> <!-- Sealed Leather Armor of Nightmare -->
|
||||
<item id="5326" min="1" max="1" chance="1.965" /> <!-- Sealed Robe of Nightmare -->
|
||||
<item id="5298" min="1" max="1" chance="2.974" /> <!-- Sealed Dark Crystal Leggings -->
|
||||
<item id="5317" min="1" max="1" chance="2.95" /> <!-- Sealed Majestic Circlet -->
|
||||
<item id="5288" min="1" max="1" chance="2.939" /> <!-- Sealed Dark Crystal Gaiters -->
|
||||
<item id="5313" min="1" max="1" chance="2.939" /> <!-- Sealed Gauntlets of Nightmare -->
|
||||
<item id="5293" min="1" max="1" chance="2.931" /> <!-- Sealed Tallum Plate Armor -->
|
||||
<item id="5323" min="1" max="1" chance="1.98" /> <!-- Sealed Majestic Leather Armor -->
|
||||
<item id="5316" min="1" max="1" chance="1.964" /> <!-- Sealed Majestic Plate Armor -->
|
||||
<item id="5311" min="1" max="1" chance="1.948" /> <!-- Sealed Armor of Nightmare -->
|
||||
<item id="5326" min="1" max="1" chance="1.945" /> <!-- Sealed Robe of Nightmare -->
|
||||
<item id="5329" min="1" max="1" chance="1.94" /> <!-- Sealed Majestic Robe -->
|
||||
<item id="5320" min="1" max="1" chance="1.931" /> <!-- Sealed Leather Armor of Nightmare -->
|
||||
<item id="6323" min="1" max="1" chance="0.75" /> <!-- Sealed Phoenix Necklace -->
|
||||
<item id="8621" min="1" max="3" chance="100" /> <!-- Ancient Book: Divine Inspiration (Original Version) -->
|
||||
<item id="70000" min="1356" max="4068" chance="100" /> <!-- Sealed Rune - Lv. 1 -->
|
||||
<item id="730" min="1" max="1" chance="51.23" /> <!-- Scroll: Enchant Armor (A-grade) -->
|
||||
<item id="729" min="1" max="1" chance="51.18" /> <!-- Scroll: Enchant Weapon (A-grade) -->
|
||||
<item id="33808" min="1" max="1" chance="51.11" /> <!-- Improved Scroll: Enchant Weapon (B-grade) -->
|
||||
<item id="33814" min="2" max="4" chance="50.87" /> <!-- Improved Scroll: Enchant Armor (B-grade) -->
|
||||
<item id="49682" min="1" max="1" chance="28.27" /> <!-- Baium’s Soul -->
|
||||
<item id="70000" min="1356" max="4068" chance="100" /> <!-- Sealed Rune - Stage 1 -->
|
||||
<item id="730" min="1" max="1" chance="51.19" /> <!-- Scroll: Enchant Armor (A-grade) -->
|
||||
<item id="33814" min="2" max="4" chance="50.94" /> <!-- Improved Scroll: Enchant Armor (B-grade) -->
|
||||
<item id="33808" min="1" max="1" chance="50.09" /> <!-- Improved Scroll: Enchant Weapon (B-grade) -->
|
||||
<item id="729" min="1" max="1" chance="50.04" /> <!-- Scroll: Enchant Weapon (A-grade) -->
|
||||
<item id="49682" min="1" max="1" chance="25.99" /> <!-- Baium’s Soul -->
|
||||
<!-- FIXME: Also drops herbs. -->
|
||||
</death>
|
||||
</drop_lists>
|
||||
|
@@ -32,6 +32,8 @@ What is done
|
||||
-Admin menu teleport and shop cleanups
|
||||
-Blacksmith NPC updates
|
||||
-New Race Track arena zone
|
||||
-Giran Luxury Shop updates
|
||||
-Grandboss scripts and stats
|
||||
|
||||
Custom work
|
||||
-Newbie Helper NPC location info
|
||||
@@ -43,7 +45,6 @@ TODO list
|
||||
-Retail NPC dialogs
|
||||
-Retail NPC buylists
|
||||
-Test quests and update rewards
|
||||
-Giran Luxury Shop updates
|
||||
-Floran Agricultural Area clan halls
|
||||
-Test castle sieges
|
||||
-Whisper of Dreams quests
|
||||
|
Reference in New Issue
Block a user