This commit is contained in:
mobius
2015-01-01 20:02:50 +00:00
parent eeae660458
commit a6a3718849
17894 changed files with 2818932 additions and 0 deletions

View File

@@ -0,0 +1,200 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.ArrayList;
import java.util.Map;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.quest.QuestTimer;
/**
* Anais AI.
* @author nonom
*/
public final class Anais extends AbstractNpcAI
{
// NPCs
private static final int ANAIS = 25701;
private static final int DIVINE_BURNER = 18915;
private static final int GRAIL_WARD = 18929;
// Skill
private static SkillHolder DIVINE_NOVA = new SkillHolder(6326, 1);
// Instances
ArrayList<L2Npc> _divineBurners = new ArrayList<>(4);
private L2PcInstance _nextTarget = null;
private L2Npc _current = null;
private int _pot = 0;
private Anais()
{
super(Anais.class.getSimpleName(), "ai/individual");
addAttackId(ANAIS);
addSpawnId(DIVINE_BURNER);
addKillId(GRAIL_WARD);
}
private void burnerOnAttack(int pot, L2Npc anais)
{
L2Npc npc = _divineBurners.get(pot);
npc.setDisplayEffect(1);
npc.setIsRunning(false);
if (pot < 4)
{
_current = npc;
QuestTimer checkAround = getQuestTimer("CHECK", anais, null);
if (checkAround == null) // || !checkAround.getIsActive()
{
startQuestTimer("CHECK", 3000, anais, null);
}
}
else
{
cancelQuestTimer("CHECK", anais, null);
}
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "CHECK":
{
if (!npc.isAttackingNow())
{
cancelQuestTimer("CHECK", npc, null);
}
if ((_current != null) || (_pot < 4))
{
final Map<Integer, L2PcInstance> players = npc.getKnownList().getKnownPlayers();
final L2PcInstance target = players.get(getRandom(players.size() - 1));
_nextTarget = target;
if (_nextTarget == null)
{
_nextTarget = (L2PcInstance) npc.getTarget();
}
final L2Npc b = _divineBurners.get(_pot);
_pot = _pot + 1;
b.setDisplayEffect(1);
b.setIsRunning(false);
L2Npc ward = addSpawn(GRAIL_WARD, new Location(b.getX(), b.getY(), b.getZ()), true, 0);
((L2Attackable) ward).addDamageHate(_nextTarget, 0, 999);
ward.setIsRunning(true);
ward.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, _nextTarget, null);
startQuestTimer("GUARD_ATTACK", 1000, ward, _nextTarget, true);
startQuestTimer("SUICIDE", 20000, ward, null);
ward.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, _nextTarget);
}
break;
}
case "GUARD_ATTACK":
{
if (_nextTarget != null)
{
final double distance = npc.calculateDistance(_nextTarget, false, false);
if (distance < 100)
{
npc.doCast(DIVINE_NOVA.getSkill());
}
else if (distance > 2000)
{
npc.doDie(null);
cancelQuestTimer("GUARD_ATTACK", npc, player);
}
}
break;
}
case "SUICIDE":
{
npc.doCast(DIVINE_NOVA.getSkill());
cancelQuestTimer("GUARD_ATTACK", npc, _nextTarget);
if (_current != null)
{
_current.setDisplayEffect(2);
_current.setIsRunning(false);
_current = null;
}
npc.doDie(null);
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (_pot == 0)
{
burnerOnAttack(0, npc);
}
else if ((npc.getCurrentHp() <= (npc.getMaxRecoverableHp() * 0.75)) && (_pot == 1))
{
burnerOnAttack(1, npc);
}
else if ((npc.getCurrentHp() <= (npc.getMaxRecoverableHp() * 0.5)) && (_pot == 2))
{
burnerOnAttack(2, npc);
}
else if ((npc.getCurrentHp() <= (npc.getMaxRecoverableHp() * 0.25)) && (_pot == 3))
{
burnerOnAttack(3, npc);
}
return super.onAttack(npc, attacker, damage, isSummon);
}
/*
* (non-Javadoc)
* @see com.l2jserver.gameserver.model.quest.Quest#onSpawn(com.l2jserver.gameserver.model.actor.L2Npc)
*/
@Override
public String onSpawn(L2Npc npc)
{
_divineBurners.add(npc);
return super.onSpawn(npc);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
npc.doCast(DIVINE_NOVA.getSkill());
cancelQuestTimer("GUARD_ATTACK", npc, _nextTarget);
cancelQuestTimer("CHECK", npc, null);
if (_current != null)
{
_current.setDisplayEffect(2);
_current.setIsRunning(false);
_current = null;
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new Anais();
}
}

View File

@@ -0,0 +1,8 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks.<br>
<font color="LEVEL">Do not expect Shilen's authority will diminish<br>
while false gods freely roam.<br>
Leave, and<br>
prepare to face the return of Antharas.</font><br>
(Challenging Antharas is not currently available.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
<font color="LEVEL">Do not expect that you might challenge Antharas at your own convenience.<br>
When the time is right, Shilen's authority will judge you.</font><br>
(Currently, other members are challenging Antharas.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Heart of Warding:<br>
A voice that can shatter your entire body is resonating in your head:<br>
<font color="LEVEL">Do not dare to face Shilen's authority<br>
without the most determined preparation.</font><br>
(Only those who have the Portal Stone can challenge Antharas.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
<font color="LEVEL">No matter how many gather to follow false gods,<br>
Shilen's authority is too great.</font><br>
(The number of participants are above the allowed number in challenging Antharas.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
<font color="LEVEL">You seek death and defeat by coming here without your leader! You appear before Shilen's authority<br>
and you tempt Shilen's wrath!</font><br>
(The players who belong to an association can only enter through the Association Leader.)
</body></html>

View File

@@ -0,0 +1,12 @@
<html><body>Heart of Warding:<br>
You are overcome by a voice, a voice so powerful you are helpless as it speaks:<br>
<font color="LEVEL">A terrible creature <br>
fell to the earth from above <br>
in order to vent a mother's spite,<br>
cursed and forsaken by her own children.<br>
Dark Pilgrim of the Holy Land,<br>
Do you dare face the Land Dragon Antharas?</font><br>
(A maximum of 200 people can challenge Antharas.)<br>
<a action="bypass -h npc_%objectId%_Quest Antharas enter">Move to Antharas' Nest</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

File diff suppressed because it is too large Load Diff

View 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>

View 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>

View 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>

View 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>

View 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>

View File

@@ -0,0 +1,792 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual.Baium;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.enums.CategoryType;
import com.l2jserver.gameserver.enums.MountType;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.variables.NpcVariables;
import com.l2jserver.gameserver.model.zone.type.L2NoRestartZone;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.Earthquake;
import com.l2jserver.gameserver.network.serverpackets.ExShowScreenMessage;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.util.Util;
/**
* 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()
{
super(Baium.class.getSimpleName(), "ai/individual");
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);
final int curr_hp = info.getInt("currentHP");
final int curr_mp = info.getInt("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");
final long respawnTime = info.getLong("respawn_time");
switch (getStatus())
{
case WAITING:
{
setStatus(ALIVE);
}
case ALIVE:
{
addSpawn(BAIUM_STONE, BAIUM_LOC, false, 0);
break;
}
case IN_FIGHT:
{
_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 = respawnTime - 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, null);
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));
broadcastNpcSay(npc, Say2.NPC_ALL, 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 : npc.getKnownList().getKnownCharactersInRadius(2000))
{
if ((creature != null) && creature.isPlayer() && 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 (L2Character creature : mob.getKnownList().getKnownCharactersInRadius(1000))
{
if ((creature != null) && creature.isPlayable() && zone.isInsideZone(creature) && !creature.isDead())
{
if (mob.getTarget() != creature)
{
mob.clearAggroList();
}
addAttackPlayerDesire(mob, (L2Playable) 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) && mob.checkDoCastConditions(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)) && mob.checkDoCastConditions(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"));
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 = Util.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() || 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 = Util.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) && npc.checkDoCastConditions(skillToCast.getSkill()))
{
npc.setTarget(player);
npc.doCast(skillToCast.getSkill());
}
}
public static void main(String[] args)
{
new Baium();
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.SystemMessageId;
/**
* Ballista AI.
* @author St3eT
*/
public final class Ballista extends AbstractNpcAI
{
// NPCs
private static final int[] BALLISTA =
{
35685, // Shanty Fortress
35723, // Southern Fortress
35754, // Hive Fortress
35792, // Valley Fortress
35823, // Ivory Fortress
35854, // Narsell Fortress
35892, // Bayou Fortress
35923, // White Sands Fortress
35961, // Borderland Fortress
35999, // Swamp Fortress
36030, // Archaic Fortress
36068, // Floran Fortress
36106, // Cloud Mountain)
36137, // Tanor Fortress
36168, // Dragonspine Fortress
36206, // Antharas's Fortress
36244, // Western Fortress
36282, // Hunter's Fortress
36313, // Aaru Fortress
36351, // Demon Fortress
36389, // Monastic Fortress
};
// Skill
private static final SkillHolder BOMB = new SkillHolder(2342, 1); // Ballista Bomb
// Misc
private static final int MIN_CLAN_LV = 5;
private Ballista()
{
super(Ballista.class.getSimpleName(), "ai/individual");
addSkillSeeId(BALLISTA);
addSpawnId(BALLISTA);
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance caster, Skill skill, L2Object[] targets, boolean isSummon)
{
if ((skill != null) && (caster.getTarget() == npc) && (getRandom(100) < 40) && (skill == BOMB.getSkill()))
{
if (npc.getFort().getSiege().isInProgress())
{
if ((caster.getClan() != null) && (caster.getClan().getLevel() >= MIN_CLAN_LV))
{
caster.getClan().addReputationScore(Config.BALLISTA_POINTS, true);
caster.sendPacket(SystemMessageId.THE_BALLISTA_HAS_BEEN_SUCCESSFULLY_DESTROYED_THE_CLAN_REPUTATION_WILL_BE_INCREASED);
}
}
npc.doDie(caster);
}
return super.onSkillSee(npc, caster, skill, targets, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
npc.disableCoreAI(true);
npc.setIsMortal(false);
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new Ballista();
}
}

View File

@@ -0,0 +1,782 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.ArrayList;
import java.util.concurrent.ScheduledFuture;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.datatables.DoorTable;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.effects.L2EffectType;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
import com.l2jserver.gameserver.network.serverpackets.DoorStatusUpdate;
import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.network.serverpackets.SpecialCamera;
import com.l2jserver.gameserver.network.serverpackets.StaticObject;
import com.l2jserver.gameserver.util.Util;
/**
* Beleth's AI.
* @author Treat
*/
public final class Beleth extends AbstractNpcAI
{
protected static L2Npc CAMERA;
protected static L2Npc CAMERA2;
protected static L2Npc CAMERA3;
protected static L2Npc CAMERA4;
protected static L2Npc BELETH;
protected static L2Npc PRIEST;
protected static L2ZoneType ZONE = null;
private static L2PcInstance BELETH_KILLER;
private static boolean DEBUG = false;
protected static boolean MOVIE = false;
private static boolean ATTACKED = false;
private static int ALLOW_OBJECT_ID = 0;
private static int KILLED = 0;
protected static ScheduledFuture<?> SPAWN_TIMER = null;
protected static ArrayList<L2Npc> MINIONS = new ArrayList<>();
private static SkillHolder BLEED = new SkillHolder(5495, 1);
private static SkillHolder FIREBALL = new SkillHolder(5496, 1);
private static SkillHolder HORN_OF_RISING = new SkillHolder(5497, 1);
private static SkillHolder LIGHTENING = new SkillHolder(5499, 1);
protected static final Location BELETH_SPAWN = new Location(16323, 213059, -9357, 49152);
private Beleth()
{
super(Beleth.class.getSimpleName(), "ai/individual");
ZONE = ZoneManager.getInstance().getZoneById(12018);
addEnterZoneId(12018);
registerMobs(29118, 29119);
addStartNpc(32470);
addTalkId(32470);
addFirstTalkId(29128);
StatsSet info = GrandBossManager.getInstance().getStatsSet(29118);
int status = GrandBossManager.getInstance().getBossStatus(29118);
if (status == 3)
{
long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
if (temp > 0)
{
ThreadPoolManager.getInstance().scheduleGeneral(new unlock(), temp);
}
else
{
GrandBossManager.getInstance().setBossStatus(29118, 0);
}
}
else if (status != 0)
{
GrandBossManager.getInstance().setBossStatus(29118, 0);
}
DoorTable.getInstance().getDoor(20240001).openMe();
}
protected static L2Npc spawn(int npcId, Location loc)
{
try
{
L2NpcTemplate template = NpcData.getInstance().getTemplate(npcId);
if (template != null)
{
L2Spawn spawn = new L2Spawn(template);
spawn.setInstanceId(loc.getInstanceId());
spawn.setLocation(loc);
spawn.setAmount(spawn.getAmount() + 1);
return spawn.doSpawn();
}
}
catch (Exception ignored)
{
}
return null;
}
public static void startSpawnTask()
{
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(1), DEBUG ? 10000 : 300000);
}
protected static class unlock implements Runnable
{
@Override
public void run()
{
GrandBossManager.getInstance().setBossStatus(29118, 0);
DoorTable.getInstance().getDoor(20240001).openMe();
}
}
private static class Cast implements Runnable
{
SkillHolder _skill;
L2Npc _npc;
public Cast(SkillHolder skill, L2Npc npc)
{
_skill = skill;
_npc = npc;
}
@Override
public void run()
{
if ((_npc != null) && !_npc.isDead() && !_npc.isCastingNow())
{
_npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
_npc.doCast(_skill.getSkill());
}
}
}
private static class Spawn implements Runnable
{
private int _taskId = 0;
public Spawn(int taskId)
{
_taskId = taskId;
}
@Override
public void run()
{
try
{
int instanceId = 0;
switch (_taskId)
{
case 1:
MOVIE = true;
for (L2Character npc : ZONE.getCharactersInside())
{
if (npc.isNpc())
{
npc.deleteMe();
}
}
CAMERA = spawn(29120, new Location(16323, 213142, -9357, 0, instanceId));
CAMERA2 = spawn(29121, new Location(16323, 210741, -9357, 0, instanceId));
CAMERA3 = spawn(29122, new Location(16323, 213170, -9357, 0, instanceId));
CAMERA4 = spawn(29123, new Location(16323, 214917, -9356, 0, instanceId));
ZONE.broadcastPacket(new PlaySound(1, "BS07_A", 1, CAMERA.getObjectId(), CAMERA.getX(), CAMERA.getY(), CAMERA.getZ()));
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 400, 75, -25, 0, 2500, 0, 0, 1, 0, 0));
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 400, 75, -25, 0, 2500, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(2), 300);
break;
case 2:
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 1800, -45, -45, 5000, 5000, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(3), 4900);
break;
case 3:
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 2500, -120, -45, 5000, 5000, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(4), 4900);
break;
case 4:
ZONE.broadcastPacket(new SpecialCamera(CAMERA2, 2200, 130, 0, 0, 1500, -20, 15, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(5), 1400);
break;
case 5:
ZONE.broadcastPacket(new SpecialCamera(CAMERA2, 2300, 100, 0, 2000, 4500, 0, 10, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(6), 2500);
break;
case 6:
L2DoorInstance door = DoorTable.getInstance().getDoor(20240001);
door.closeMe();
ZONE.broadcastPacket(new StaticObject(door, false));
ZONE.broadcastPacket(new DoorStatusUpdate(door));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(7), 1700);
break;
case 7:
ZONE.broadcastPacket(new SpecialCamera(CAMERA4, 1500, 210, 0, 0, 1500, 0, 0, 1, 0, 0));
ZONE.broadcastPacket(new SpecialCamera(CAMERA4, 900, 255, 0, 5000, 6500, 0, 10, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(8), 6000);
break;
case 8:
spawn(29125, new Location(16323, 214917, -9356, 0, instanceId));
ZONE.broadcastPacket(new SpecialCamera(CAMERA4, 900, 255, 0, 0, 1500, 0, 10, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(9), 1000);
break;
case 9:
ZONE.broadcastPacket(new SpecialCamera(CAMERA4, 1000, 255, 0, 7000, 17000, 0, 25, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(10), 3000);
break;
case 10:
BELETH = spawn(29118, new Location(16321, 214211, -9352, 49369, instanceId));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(11), 200);
break;
case 11:
ZONE.broadcastPacket(new SocialAction(BELETH.getObjectId(), 1));
for (int i = 0; i < 6; i++)
{
int x = (int) ((150 * Math.cos(i * 1.046666667)) + 16323);
int y = (int) ((150 * Math.sin(i * 1.046666667)) + 213059);
L2Npc minion = spawn(29119, new Location(x, y, -9357, 49152, BELETH.getInstanceId()));
minion.setShowSummonAnimation(true);
minion.decayMe();
MINIONS.add(minion);
}
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(12), 6800);
break;
case 12:
ZONE.broadcastPacket(new SpecialCamera(BELETH, 0, 270, -5, 0, 4000, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(13), 3500);
break;
case 13:
ZONE.broadcastPacket(new SpecialCamera(BELETH, 800, 270, 10, 3000, 6000, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(14), 5000);
break;
case 14:
ZONE.broadcastPacket(new SpecialCamera(CAMERA3, 100, 270, 15, 0, 5000, 0, 0, 1, 0, 0));
ZONE.broadcastPacket(new SpecialCamera(CAMERA3, 100, 270, 15, 0, 5000, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(15), 100);
break;
case 15:
ZONE.broadcastPacket(new SpecialCamera(CAMERA3, 100, 270, 15, 3000, 6000, 0, 5, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(16), 1400);
break;
case 16:
BELETH.teleToLocation(BELETH_SPAWN);
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(17), 200);
break;
case 17:
ZONE.broadcastPacket(new MagicSkillUse(BELETH, BELETH, 5532, 1, 2000, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(18), 2000);
break;
case 18:
ZONE.broadcastPacket(new SpecialCamera(CAMERA3, 700, 270, 20, 1500, 8000, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(19), 6900);
break;
case 19:
ZONE.broadcastPacket(new SpecialCamera(CAMERA3, 40, 260, 0, 0, 4000, 0, 0, 1, 0, 0));
for (L2Npc blth : MINIONS)
{
blth.spawnMe();
}
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(20), 3000);
break;
case 20:
ZONE.broadcastPacket(new SpecialCamera(CAMERA3, 40, 280, 0, 0, 4000, 5, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(21), 3000);
break;
case 21:
ZONE.broadcastPacket(new SpecialCamera(CAMERA3, 5, 250, 5, 0, 13000, 20, 15, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(22), 1000);
break;
case 22:
ZONE.broadcastPacket(new SocialAction(BELETH.getObjectId(), 3));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(23), 4000);
break;
case 23:
ZONE.broadcastPacket(new MagicSkillUse(BELETH, BELETH, 5533, 1, 2000, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(24), 6800);
break;
case 24:
BELETH.deleteMe();
for (L2Npc bel : MINIONS)
{
bel.deleteMe();
}
MINIONS.clear();
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(25), 1000);
break;
case 25:
CAMERA.deleteMe();
CAMERA2.deleteMe();
CAMERA3.deleteMe();
CAMERA4.deleteMe();
MOVIE = false;
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(26), 60000);
break;
case 26:
if (SPAWN_TIMER != null)
{
SPAWN_TIMER.cancel(false);
setSpawnTimer(0);
}
SpawnBeleths();
break;
case 27:
BELETH.doDie(null);
CAMERA = spawn(29122, new Location(16323, 213170, -9357, 0, instanceId));
CAMERA.broadcastPacket(new PlaySound(1, "BS07_D", 1, CAMERA.getObjectId(), CAMERA.getX(), CAMERA.getY(), CAMERA.getZ()));
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 400, 290, 25, 0, 10000, 0, 0, 1, 0, 0));
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 400, 290, 25, 0, 10000, 0, 0, 1, 0, 0));
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 400, 110, 25, 4000, 10000, 0, 0, 1, 0, 0));
ZONE.broadcastPacket(new SocialAction(BELETH.getObjectId(), 5));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(28), 4000);
break;
case 28:
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 400, 295, 25, 4000, 5000, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(29), 4500);
break;
case 29:
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 400, 295, 10, 4000, 11000, 0, 25, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(30), 9000);
break;
case 30:
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 250, 90, 25, 0, 1000, 0, 0, 1, 0, 0));
ZONE.broadcastPacket(new SpecialCamera(CAMERA, 250, 90, 25, 0, 10000, 0, 0, 1, 0, 0));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(31), 2000);
break;
case 31:
PRIEST.spawnMe();
BELETH.deleteMe();
CAMERA2 = spawn(29121, new Location(14056, 213170, -9357, 0, instanceId));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(32), 3500);
break;
case 32:
ZONE.broadcastPacket(new SpecialCamera(CAMERA2, 800, 180, 0, 0, 4000, 0, 10, 1, 0, 0));
ZONE.broadcastPacket(new SpecialCamera(CAMERA2, 800, 180, 0, 0, 4000, 0, 10, 1, 0, 0));
L2DoorInstance door2 = DoorTable.getInstance().getDoor(20240002);
door2.openMe();
ZONE.broadcastPacket(new StaticObject(door2, false));
ZONE.broadcastPacket(new DoorStatusUpdate(door2));
DoorTable.getInstance().getDoor(20240003).openMe();
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(33), 4000);
break;
case 33:
CAMERA.deleteMe();
CAMERA2.deleteMe();
MOVIE = false;
break;
case 333:
BELETH = spawn(29118, new Location(16323, 213170, -9357, 49152));
break;
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
@Override
public String onEnterZone(L2Character character, L2ZoneType zone)
{
if (((character.isPlayer()) && (GrandBossManager.getInstance().getBossStatus(29118) == 1)) || (DEBUG && (GrandBossManager.getInstance().getBossStatus(29118) != 2) && (character.isPlayer())))
{
startSpawnTask();
GrandBossManager.getInstance().setBossStatus(29118, 2);
}
return null;
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (npc == null)
{
return super.onKill(npc, killer, isSummon);
}
if ((npc.getId() == 29118) && (killer != null))
{
setBelethKiller(1, killer);
GrandBossManager.getInstance().setBossStatus(29118, 3);
// Calculate Min and Max respawn times randomly.
long respawnTime = Config.BELETH_SPAWN_INTERVAL + getRandom(-Config.BELETH_SPAWN_RANDOM, Config.BELETH_SPAWN_RANDOM);
respawnTime *= 3600000;
StatsSet info = GrandBossManager.getInstance().getStatsSet(29118);
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
GrandBossManager.getInstance().setStatsSet(29118, info);
ThreadPoolManager.getInstance().scheduleGeneral(new unlock(), respawnTime);
deleteAll();
npc.deleteMe();
MOVIE = true;
BELETH = spawn(29118, new Location(16323, 213170, -9357, 49152));
BELETH.setIsInvul(true);
BELETH.setIsImmobilized(true);
BELETH.disableAllSkills();
PRIEST = spawn(29128, new Location(BELETH));
PRIEST.setShowSummonAnimation(true);
PRIEST.decayMe();
spawn(32470, new Location(12470, 215607, -9381, 49152));
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(27), 1000);
}
else if (npc.getId() == 29119)
{
if (npc.getObjectId() == ALLOW_OBJECT_ID)
{
MINIONS.remove(npc);
KILLED++;
if (KILLED >= 5)
{
deleteAll();
setSpawnTimer(1);
}
else
{
ALLOW_OBJECT_ID = MINIONS.get(getRandom(MINIONS.size())).getObjectId();
ATTACKED = false;
}
}
else if (SPAWN_TIMER == null)
{
deleteAll();
setSpawnTimer(2);
KILLED = 0;
}
npc.abortCast();
npc.setTarget(null);
npc.deleteMe();
}
return null;
}
@Override
public String onSkillSee(L2Npc npc, L2PcInstance player, Skill skill, L2Object[] targets, boolean isSummon)
{
if ((npc != null) && !npc.isDead() && ((npc.getId() == 29118) || (npc.getId() == 29119)) && !npc.isCastingNow() && skill.hasEffectType(L2EffectType.HEAL) && (getRandom(100) < 80))
{
npc.setTarget(player);
npc.doCast(HORN_OF_RISING.getSkill());
}
return null;
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (npc == null)
{
return super.onAttack(npc, attacker, damage, isSummon);
}
if ((npc.getId() == 29118) || (npc.getId() == 29119))
{
if ((npc.getObjectId() == ALLOW_OBJECT_ID) && !ATTACKED)
{
ATTACKED = true;
L2Npc fakeBeleth = MINIONS.get(getRandom(MINIONS.size()));
while (fakeBeleth.getObjectId() == ALLOW_OBJECT_ID)
{
fakeBeleth = MINIONS.get(getRandom(MINIONS.size()));
}
ZONE.broadcastPacket(new CreatureSay(fakeBeleth.getObjectId(), 0, fakeBeleth.getName(), "Miss text."));
}
if (getRandom(100) < 40)
{
return null;
}
final double distance = npc.calculateDistance(attacker, false, false);
if ((distance > 500) || (getRandom(100) < 80))
{
for (L2Npc beleth : MINIONS)
{
if ((beleth != null) && !beleth.isDead() && Util.checkIfInRange(900, beleth, attacker, false) && !beleth.isCastingNow())
{
beleth.setTarget(attacker);
beleth.doCast(FIREBALL.getSkill());
}
}
if ((BELETH != null) && !BELETH.isDead() && Util.checkIfInRange(900, BELETH, attacker, false) && !BELETH.isCastingNow())
{
BELETH.setTarget(attacker);
BELETH.doCast(FIREBALL.getSkill());
}
}
else if (!npc.isDead() && !npc.isCastingNow())
{
if (!npc.getKnownList().getKnownPlayersInRadius(200).isEmpty())
{
npc.doCast(LIGHTENING.getSkill());
return null;
}
((L2Attackable) npc).clearAggroList();
}
}
return null;
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
if ((npc != null) && !npc.isDead() && ((npc.getId() == 29118) || (npc.getId() == 29119)) && !npc.isCastingNow())
{
if ((player != null) && !player.isDead())
{
final double distance2 = npc.calculateDistance(player, false, false);
if ((distance2 > 890) && !npc.isMovementDisabled())
{
npc.setTarget(player);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, player);
double speed = npc.isRunning() ? npc.getRunSpeed() : npc.getWalkSpeed();
int time = (int) (((distance2 - 890) / speed) * 1000);
ThreadPoolManager.getInstance().scheduleGeneral(new Cast(FIREBALL, npc), time);
}
else if (distance2 < 890)
{
npc.setTarget(player);
npc.doCast(FIREBALL.getSkill());
}
return null;
}
if (getRandom(100) < 40)
{
if (!npc.getKnownList().getKnownPlayersInRadius(200).isEmpty())
{
npc.doCast(LIGHTENING.getSkill());
return null;
}
}
for (L2PcInstance plr : npc.getKnownList().getKnownPlayersInRadius(950))
{
npc.setTarget(plr);
npc.doCast(FIREBALL.getSkill());
return null;
}
((L2Attackable) npc).clearAggroList();
}
return null;
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
if ((npc != null) && !npc.isDead() && ((npc.getId() == 29118) || (npc.getId() == 29119)) && !npc.isCastingNow() && !MOVIE)
{
if (getRandom(100) < 40)
{
if (!npc.getKnownList().getKnownPlayersInRadius(200).isEmpty())
{
npc.doCast(BLEED.getSkill());
return null;
}
}
npc.setTarget(player);
npc.doCast(FIREBALL.getSkill());
}
return null;
}
@Override
public String onSpawn(L2Npc npc)
{
if ((npc.getId() == 29118) || (npc.getId() == 29119))
{
npc.setRunning();
if (!MOVIE && !npc.getKnownList().getKnownPlayersInRadius(300).isEmpty() && (getRandom(100) < 60))
{
npc.doCast(BLEED.getSkill());
}
if (npc.getId() == 29118)
{
npc.getSpawn().setRespawnDelay(0);// setOnKillDelay
}
}
return null;
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player)
{
final String html;
if ((BELETH_KILLER != null) && (player.getObjectId() == BELETH_KILLER.getObjectId()))
{
player.addItem("Kill Beleth", 10314, 1, null, true);// giveItems(10314, 1, 0)
setBelethKiller(0, player);
html = "32470a.htm";
}
else
{
html = "32470b.htm";
}
return HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/default/" + html);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
return null;
}
private static void setBelethKiller(int event, L2PcInstance killer)
{
if (event == 0)
{
BELETH_KILLER = null;
}
else if (event == 1)
{
if (killer.getParty() != null)
{
if (killer.getParty().getCommandChannel() != null)
{
BELETH_KILLER = killer.getParty().getCommandChannel().getLeader();
}
else
{
BELETH_KILLER = killer.getParty().getLeader();
}
}
else
{
BELETH_KILLER = killer;
}
}
}
protected static void setSpawnTimer(int event)
{
switch (event)
{
case 0:
SPAWN_TIMER = null;
break;
case 1:
SPAWN_TIMER = ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(333), 60000);
break;
case 2:
SPAWN_TIMER = ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(26), 60000);
break;
default:
break;
}
}
private static void deleteAll()
{
if ((MINIONS != null) && !MINIONS.isEmpty())
{
for (L2Npc npc : MINIONS)
{
if ((npc == null) || npc.isDead())
{
continue;
}
npc.abortCast();
npc.setTarget(null);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
npc.deleteMe();
}
MINIONS.clear();
}
ALLOW_OBJECT_ID = 0;
ATTACKED = false;
}
protected static void SpawnBeleths()
{
int a = 0;
L2Npc npc;
for (int i = 0; i < 16; i++)
{
a++;
int x = (int) ((650 * Math.cos(i * 0.39)) + 16323);
int y = (int) ((650 * Math.sin(i * 0.39)) + 213170);
npc = spawn(29119, new Location(x, y, -9357, 49152));
MINIONS.add(npc);
if (a >= 2)
{
npc.setIsOverloaded(true);
a = 0;
}
}
int[] xm = new int[16];
int[] ym = new int[16];
for (int i = 0; i < 4; i++)
{
xm[i] = (int) ((1700 * Math.cos((i * 1.57) + 0.78)) + 16323);
ym[i] = (int) ((1700 * Math.sin((i * 1.57) + 0.78)) + 213170);
npc = spawn(29119, new Location(xm[i], ym[i], -9357, 49152));
npc.setIsOverloaded(true);
MINIONS.add(npc);
}
xm[4] = (xm[0] + xm[1]) / 2;
ym[4] = (ym[0] + ym[1]) / 2;
npc = spawn(29119, new Location(xm[4], ym[4], -9357, 49152));
npc.setIsOverloaded(true);
MINIONS.add(npc);
xm[5] = (xm[1] + xm[2]) / 2;
ym[5] = (ym[1] + ym[2]) / 2;
npc = spawn(29119, new Location(xm[5], ym[5], -9357, 49152));
npc.setIsOverloaded(true);
MINIONS.add(npc);
xm[6] = (xm[2] + xm[3]) / 2;
ym[6] = (ym[2] + ym[3]) / 2;
npc = spawn(29119, new Location(xm[6], ym[6], -9357, 49152));
npc.setIsOverloaded(true);
MINIONS.add(npc);
xm[7] = (xm[3] + xm[0]) / 2;
ym[7] = (ym[3] + ym[0]) / 2;
npc = spawn(29119, new Location(xm[7], ym[7], -9357, 49152));
npc.setIsOverloaded(true);
MINIONS.add(npc);
xm[8] = (xm[0] + xm[4]) / 2;
ym[8] = (ym[0] + ym[4]) / 2;
MINIONS.add(spawn(29119, new Location(xm[8], ym[8], -9357, 49152)));
xm[9] = (xm[4] + xm[1]) / 2;
ym[9] = (ym[4] + ym[1]) / 2;
MINIONS.add(spawn(29119, new Location(xm[9], ym[9], -9357, 49152)));
xm[10] = (xm[1] + xm[5]) / 2;
ym[10] = (ym[1] + ym[5]) / 2;
MINIONS.add(spawn(29119, new Location(xm[10], ym[10], -9357, 49152)));
xm[11] = (xm[5] + xm[2]) / 2;
ym[11] = (ym[5] + ym[2]) / 2;
MINIONS.add(spawn(29119, new Location(xm[11], ym[11], -9357, 49152)));
xm[12] = (xm[2] + xm[6]) / 2;
ym[12] = (ym[2] + ym[6]) / 2;
MINIONS.add(spawn(29119, new Location(xm[12], ym[12], -9357, 49152)));
xm[13] = (xm[6] + xm[3]) / 2;
ym[13] = (ym[6] + ym[3]) / 2;
MINIONS.add(spawn(29119, new Location(xm[13], ym[13], -9357, 49152)));
xm[14] = (xm[3] + xm[7]) / 2;
ym[14] = (ym[3] + ym[7]) / 2;
MINIONS.add(spawn(29119, new Location(xm[14], ym[14], -9357, 49152)));
xm[15] = (xm[7] + xm[0]) / 2;
ym[15] = (ym[7] + ym[0]) / 2;
MINIONS.add(spawn(29119, new Location(xm[15], ym[15], -9357, 49152)));
ALLOW_OBJECT_ID = MINIONS.get(getRandom(MINIONS.size())).getObjectId();
ATTACKED = false;
}
public static void main(String[] args)
{
new Beleth();
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* Cat's Eye Bandit (Quest Monster) AI.
* @author Gladicek
*/
public final class CatsEyeBandit extends AbstractNpcAI
{
// NPC ID
private static final int MOB_ID = 27038;
// Weapons
private static final int BOW = 1181;
private static final int DAGGER = 1182;
private CatsEyeBandit()
{
super(CatsEyeBandit.class.getSimpleName(), "ai/individual");
addAttackId(MOB_ID);
addKillId(MOB_ID);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
final QuestState qs = attacker.getQuestState("403_PathToRogue"); // TODO: Replace with class name.
if (npc.isScriptValue(0) && (qs != null) && ((qs.getItemEquipped(Inventory.PAPERDOLL_RHAND) == BOW) || (qs.getItemEquipped(Inventory.PAPERDOLL_RHAND) == DAGGER)))
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.YOU_CHILDISH_FOOL_DO_YOU_THINK_YOU_CAN_CATCH_ME);
npc.setScriptValue(1);
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
final QuestState qs = killer.getQuestState("403_PathToRogue"); // TODO: Replace with class name.
if (qs != null)
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.I_MUST_DO_SOMETHING_ABOUT_THIS_SHAMEFUL_INCIDENT);
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new CatsEyeBandit();
}
}

View File

@@ -0,0 +1,230 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.List;
import javolution.util.FastList;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
/**
* Core AI
* @author DrLecter Revised By 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 FastList<>();
private Core()
{
super(Core.class.getSimpleName(), "ai/individual");
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
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.
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 int hp = info.getInt("currentHP");
final int mp = info.getInt("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 saveGlobalData()
{
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++)
{
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"))
{
L2GrandBossInstance core = (L2GrandBossInstance) addSpawn(CORE, 17726, 108915, -6480, 0, false, 0);
GrandBossManager.getInstance().setBossStatus(CORE, ALIVE);
spawnBoss(core);
}
else if (event.equalsIgnoreCase("spawn_minion"))
{
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"))
{
for (int i = 0; i < Minions.size(); i++)
{
L2Attackable mob = Minions.get(i);
if (mob != null)
{
mob.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.broadcastPacket(new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), NpcStringId.REMOVING_INTRUDERS));
}
}
else
{
_FirstAttacked = true;
npc.broadcastPacket(new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), NpcStringId.A_NON_PERMITTED_TARGET_HAS_BEEN_DISCOVERED));
npc.broadcastPacket(new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), 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)
{
int objId = npc.getObjectId();
npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, objId, npc.getX(), npc.getY(), npc.getZ()));
npc.broadcastPacket(new NpcSay(objId, Say2.NPC_ALL, npcId, NpcStringId.A_FATAL_ERROR_HAS_OCCURRED));
npc.broadcastPacket(new NpcSay(objId, Say2.NPC_ALL, npcId, NpcStringId.SYSTEM_IS_BEING_SHUT_DOWN));
npc.broadcastPacket(new NpcSay(objId, Say2.NPC_ALL, npcId, 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);
respawnTime *= 3600000;
startQuestTimer("core_unlock", respawnTime, null, null);
// also save the respawn time so that the info is maintained past reboots
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);
}
public static void main(String[] args)
{
new Core();
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* AI for Kamaloka (33) - Crimson Hatu Otis
* @author Gladicek
*/
public final class CrimsonHatuOtis extends AbstractNpcAI
{
// Npc
private static final int CRIMSON_HATU_OTIS = 18558;
// Skills
private static SkillHolder BOSS_SPINING_SLASH = new SkillHolder(4737, 1);
private static SkillHolder BOSS_HASTE = new SkillHolder(4175, 1);
private CrimsonHatuOtis()
{
super(CrimsonHatuOtis.class.getSimpleName(), "ai/individual");
addAttackId(CRIMSON_HATU_OTIS);
addKillId(CRIMSON_HATU_OTIS);
}
@Override
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "SKILL":
{
if (npc.isDead())
{
cancelQuestTimer("SKILL", npc, null);
return null;
}
npc.setTarget(player);
npc.doCast(BOSS_SPINING_SLASH.getSkill());
startQuestTimer("SKILL", 60000, npc, null);
break;
}
case "BUFF":
{
if (npc.isScriptValue(2))
{
npc.setTarget(npc);
npc.doCast(BOSS_HASTE.getSkill());
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (npc.isScriptValue(0))
{
npc.setScriptValue(1);
startQuestTimer("SKILL", 5000, npc, null);
}
else if (npc.isScriptValue(1) && (npc.getCurrentHp() < (npc.getMaxHp() * 0.3)))
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.I_VE_HAD_IT_UP_TO_HERE_WITH_YOU_I_LL_TAKE_CARE_OF_YOU);
npc.setScriptValue(2);
startQuestTimer("BUFF", 1000, npc, null);
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
cancelQuestTimer("SKILL", npc, null);
cancelQuestTimer("BUFF", npc, null);
return super.onKill(npc, player, isSummon);
}
public static void main(String[] args)
{
new CrimsonHatuOtis();
}
}

View File

@@ -0,0 +1,248 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javolution.util.FastSet;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
/**
* Dark Water Dragon's AI.
*/
public final class DarkWaterDragon extends AbstractNpcAI
{
private static final int DRAGON = 22267;
private static final int SHADE1 = 22268;
private static final int SHADE2 = 22269;
private static final int FAFURION = 18482;
private static final int DETRACTOR1 = 22270;
private static final int DETRACTOR2 = 22271;
private static Set<Integer> SECOND_SPAWN = new FastSet<>(); // Used to track if second Shades were already spawned
private static Set<Integer> MY_TRACKING_SET = new FastSet<>(); // Used to track instances of npcs
private static Map<Integer, L2PcInstance> ID_MAP = new ConcurrentHashMap<>(); // Used to track instances of npcs
private DarkWaterDragon()
{
super(DarkWaterDragon.class.getSimpleName(), "ai/individual");
int[] mobs =
{
DRAGON,
SHADE1,
SHADE2,
FAFURION,
DETRACTOR1,
DETRACTOR2
};
addKillId(mobs);
addAttackId(mobs);
addSpawnId(mobs);
MY_TRACKING_SET.clear();
SECOND_SPAWN.clear();
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (npc != null)
{
if (event.equalsIgnoreCase("first_spawn")) // timer to start timer "1"
{
startQuestTimer("1", 40000, npc, null, true); // spawns detractor every 40 seconds
}
else if (event.equalsIgnoreCase("second_spawn")) // timer to start timer "2"
{
startQuestTimer("2", 40000, npc, null, true); // spawns detractor every 40 seconds
}
else if (event.equalsIgnoreCase("third_spawn")) // timer to start timer "3"
{
startQuestTimer("3", 40000, npc, null, true); // spawns detractor every 40 seconds
}
else if (event.equalsIgnoreCase("fourth_spawn")) // timer to start timer "4"
{
startQuestTimer("4", 40000, npc, null, true); // spawns detractor every 40 seconds
}
else if (event.equalsIgnoreCase("1")) // spawns a detractor
{
addSpawn(DETRACTOR1, (npc.getX() + 100), (npc.getY() + 100), npc.getZ(), 0, false, 40000);
}
else if (event.equalsIgnoreCase("2")) // spawns a detractor
{
addSpawn(DETRACTOR2, (npc.getX() + 100), (npc.getY() - 100), npc.getZ(), 0, false, 40000);
}
else if (event.equalsIgnoreCase("3")) // spawns a detractor
{
addSpawn(DETRACTOR1, (npc.getX() - 100), (npc.getY() + 100), npc.getZ(), 0, false, 40000);
}
else if (event.equalsIgnoreCase("4")) // spawns a detractor
{
addSpawn(DETRACTOR2, (npc.getX() - 100), (npc.getY() - 100), npc.getZ(), 0, false, 40000);
}
else if (event.equalsIgnoreCase("fafurion_despawn")) // Fafurion Kindred disappears and drops reward
{
cancelQuestTimer("fafurion_poison", npc, null);
cancelQuestTimer("1", npc, null);
cancelQuestTimer("2", npc, null);
cancelQuestTimer("3", npc, null);
cancelQuestTimer("4", npc, null);
MY_TRACKING_SET.remove(npc.getObjectId());
player = ID_MAP.remove(npc.getObjectId());
if (player != null)
{
((L2Attackable) npc).doItemDrop(NpcData.getInstance().getTemplate(18485), player);
}
npc.deleteMe();
}
else if (event.equalsIgnoreCase("fafurion_poison")) // Reduces Fafurions hp like it is poisoned
{
if (npc.getCurrentHp() <= 500)
{
cancelQuestTimer("fafurion_despawn", npc, null);
cancelQuestTimer("first_spawn", npc, null);
cancelQuestTimer("second_spawn", npc, null);
cancelQuestTimer("third_spawn", npc, null);
cancelQuestTimer("fourth_spawn", npc, null);
cancelQuestTimer("1", npc, null);
cancelQuestTimer("2", npc, null);
cancelQuestTimer("3", npc, null);
cancelQuestTimer("4", npc, null);
MY_TRACKING_SET.remove(npc.getObjectId());
ID_MAP.remove(npc.getObjectId());
}
npc.reduceCurrentHp(500, npc, null); // poison kills Fafurion if he is not healed
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
int npcId = npc.getId();
int npcObjId = npc.getObjectId();
if (npcId == DRAGON)
{
if (!MY_TRACKING_SET.contains(npcObjId)) // this allows to handle multiple instances of npc
{
MY_TRACKING_SET.add(npcObjId);
// Spawn first 5 shades on first attack on Dark Water Dragon
L2Character originalAttacker = isSummon ? attacker.getSummon() : attacker;
spawnShade(originalAttacker, SHADE1, npc.getX() + 100, npc.getY() + 100, npc.getZ());
spawnShade(originalAttacker, SHADE2, npc.getX() + 100, npc.getY() - 100, npc.getZ());
spawnShade(originalAttacker, SHADE1, npc.getX() - 100, npc.getY() + 100, npc.getZ());
spawnShade(originalAttacker, SHADE2, npc.getX() - 100, npc.getY() - 100, npc.getZ());
spawnShade(originalAttacker, SHADE1, npc.getX() - 150, npc.getY() + 150, npc.getZ());
}
else if ((npc.getCurrentHp() < (npc.getMaxHp() / 2.0)) && !(SECOND_SPAWN.contains(npcObjId)))
{
SECOND_SPAWN.add(npcObjId);
// Spawn second 5 shades on half hp of on Dark Water Dragon
L2Character originalAttacker = isSummon ? attacker.getSummon() : attacker;
spawnShade(originalAttacker, SHADE2, npc.getX() + 100, npc.getY() + 100, npc.getZ());
spawnShade(originalAttacker, SHADE1, npc.getX() + 100, npc.getY() - 100, npc.getZ());
spawnShade(originalAttacker, SHADE2, npc.getX() - 100, npc.getY() + 100, npc.getZ());
spawnShade(originalAttacker, SHADE1, npc.getX() - 100, npc.getY() - 100, npc.getZ());
spawnShade(originalAttacker, SHADE2, npc.getX() - 150, npc.getY() + 150, npc.getZ());
}
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
int npcId = npc.getId();
int npcObjId = npc.getObjectId();
if (npcId == DRAGON)
{
MY_TRACKING_SET.remove(npcObjId);
SECOND_SPAWN.remove(npcObjId);
L2Attackable faf = (L2Attackable) addSpawn(FAFURION, npc.getX(), npc.getY(), npc.getZ(), 0, false, 0); // spawns Fafurion Kindred when Dard Water Dragon is dead
ID_MAP.put(faf.getObjectId(), killer);
}
else if (npcId == FAFURION)
{
cancelQuestTimer("fafurion_poison", npc, null);
cancelQuestTimer("fafurion_despawn", npc, null);
cancelQuestTimer("first_spawn", npc, null);
cancelQuestTimer("second_spawn", npc, null);
cancelQuestTimer("third_spawn", npc, null);
cancelQuestTimer("fourth_spawn", npc, null);
cancelQuestTimer("1", npc, null);
cancelQuestTimer("2", npc, null);
cancelQuestTimer("3", npc, null);
cancelQuestTimer("4", npc, null);
MY_TRACKING_SET.remove(npcObjId);
ID_MAP.remove(npcObjId);
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
int npcId = npc.getId();
int npcObjId = npc.getObjectId();
if (npcId == FAFURION)
{
if (!MY_TRACKING_SET.contains(npcObjId))
{
MY_TRACKING_SET.add(npcObjId);
// Spawn 4 Detractors on spawn of Fafurion
int x = npc.getX();
int y = npc.getY();
addSpawn(DETRACTOR2, x + 100, y + 100, npc.getZ(), 0, false, 40000);
addSpawn(DETRACTOR1, x + 100, y - 100, npc.getZ(), 0, false, 40000);
addSpawn(DETRACTOR2, x - 100, y + 100, npc.getZ(), 0, false, 40000);
addSpawn(DETRACTOR1, x - 100, y - 100, npc.getZ(), 0, false, 40000);
startQuestTimer("first_spawn", 2000, npc, null); // timer to delay timer "1"
startQuestTimer("second_spawn", 4000, npc, null); // timer to delay timer "2"
startQuestTimer("third_spawn", 8000, npc, null); // timer to delay timer "3"
startQuestTimer("fourth_spawn", 10000, npc, null); // timer to delay timer "4"
startQuestTimer("fafurion_poison", 3000, npc, null, true); // Every three seconds reduces Fafurions hp like it is poisoned
startQuestTimer("fafurion_despawn", 120000, npc, null); // Fafurion Kindred disappears after two minutes
}
}
return super.onSpawn(npc);
}
public void spawnShade(L2Character attacker, int npcId, int x, int y, int z)
{
final L2Npc shade = addSpawn(npcId, x, y, z, 0, false, 0);
shade.setRunning();
((L2Attackable) shade).addDamageHate(attacker, 0, 999);
shade.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
}
public static void main(String[] args)
{
new DarkWaterDragon();
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Summon;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
/**
* Simple AI that manages special conditions for Divine Beast summon.
* @author UnAfraid
*/
public final class DivineBeast extends AbstractNpcAI
{
private static final int DIVINE_BEAST = 14870;
private static final int TRANSFORMATION_ID = 258;
private static final int CHECK_TIME = 2 * 1000;
private DivineBeast()
{
super(DivineBeast.class.getSimpleName(), "ai");
addSummonSpawnId(DIVINE_BEAST);
}
@Override
public void onSummonSpawn(L2Summon summon)
{
startQuestTimer("VALIDATE_TRANSFORMATION", CHECK_TIME, null, summon.getActingPlayer(), true);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if ((player == null) || !player.hasServitor())
{
cancelQuestTimer(event, npc, player);
}
else if (player.getTransformationId() != TRANSFORMATION_ID)
{
cancelQuestTimer(event, npc, player);
player.getSummon().unSummon(player);
}
return super.onAdvEvent(event, npc, player);
}
public static void main(String[] args)
{
new DivineBeast();
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
import com.l2jserver.gameserver.network.serverpackets.SpecialCamera;
/**
* DrChaos' AI.
* @author Kerberos
*/
public final class DrChaos extends Quest
{
private static final int DR_CHAOS = 32033;
private static final int STRANGE_MACHINE = 32032;
private static final int CHAOS_GOLEM = 25703;
private static boolean _IsGolemSpawned;
private static final Location PLAYER_TELEPORT = new Location(94832, -112624, -3304);
private static final Location NPC_LOCATION = new Location(-113091, -243942, -15536);
private DrChaos()
{
// TODO extends AbstractNpcAI
super(-1, "Doctor Chaos", "ai/individual");
addFirstTalkId(DR_CHAOS);
_IsGolemSpawned = false;
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "1":
{
L2Npc machine = null;
for (L2Spawn spawn : SpawnTable.getInstance().getSpawns(STRANGE_MACHINE))
{
if (spawn != null)
{
machine = spawn.getLastSpawn();
}
}
if (machine != null)
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, machine);
machine.broadcastPacket(new SpecialCamera(machine, 1, -200, 15, 10000, 1000, 20000, 0, 0, 0, 0, 0));
}
else
{
startQuestTimer("2", 2000, npc, player);
}
startQuestTimer("3", 10000, npc, player);
break;
}
case "2":
{
npc.broadcastSocialAction(3);
break;
}
case "3":
{
npc.broadcastPacket(new SpecialCamera(npc, 1, -150, 10, 3000, 1000, 20000, 0, 0, 0, 0, 0));
startQuestTimer("4", 2500, npc, player);
break;
}
case "4":
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(96055, -110759, -3312, 0));
startQuestTimer("5", 2000, npc, player);
break;
}
case "5":
{
player.teleToLocation(PLAYER_TELEPORT);
npc.teleToLocation(NPC_LOCATION);
if (!_IsGolemSpawned)
{
L2Npc golem = addSpawn(CHAOS_GOLEM, 94640, -112496, -3336, 0, false, 0);
_IsGolemSpawned = true;
startQuestTimer("6", 1000, golem, player);
player.sendPacket(new PlaySound(1, "Rm03_A", 0, 0, 0, 0, 0));
}
break;
}
case "6":
{
npc.broadcastPacket(new SpecialCamera(npc, 30, -200, 20, 6000, 700, 8000, 0, 0, 0, 0, 0));
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
if (npc.getId() == DR_CHAOS)
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(96323, -110914, -3328, 0));
this.startQuestTimer("1", 3000, npc, player);
}
return "";
}
public static void main(String[] args)
{
new DrChaos();
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
/**
* Drill Sergeant AI.
* @author St3eT
*/
public final class DrillSergeant extends AbstractNpcAI
{
// NPCs
private static final int SERGANT = 33007; // Drill Sergant
private static final int GUARD = 33018;
// Misc
//@formatter:off
private final int[] SOCIAL_ACTIONS = {9, 10, 11, 1 };
//@formatter:on
private DrillSergeant()
{
super(DrillSergeant.class.getSimpleName(), "ai/individual");
addSpawnId(SERGANT);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("SOCIAL_SHOW"))
{
final int socialActionId = SOCIAL_ACTIONS[getRandom(SOCIAL_ACTIONS.length)];
npc.broadcastSocialAction(socialActionId);
for (L2Character chars : npc.getKnownList().getKnownCharactersInRadius(500))
{
if (chars.isNpc() && (chars.getId() == GUARD))
{
final L2Npc guard = (L2Npc) chars;
guard.getVariables().set("SOCIAL_ACTION_ID", socialActionId);
startQuestTimer("SOCIAL_ACTION", getRandom(500, 1500), guard, null);
}
}
}
else if (event.equals("SOCIAL_ACTION"))
{
final int socialActionId = npc.getVariables().getInt("SOCIAL_ACTION_ID", 0);
if (socialActionId > 0)
{
npc.broadcastSocialAction(socialActionId);
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(L2Npc npc)
{
if (npc.getId() == SERGANT)
{
startQuestTimer("SOCIAL_SHOW", 10000, npc, null, true);
}
npc.setRandomAnimationEnabled(false);
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new DrillSergeant();
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.util.MinionList;
/**
* Manages minion's spawn, idle despawn and Teleportation Cube spawn.
* @author GKR
*/
public final class Epidos extends AbstractNpcAI
{
private static final int[] EPIDOSES =
{
25609,
25610,
25611,
25612
};
private static final int[] MINIONS =
{
25605,
25606,
25607,
25608
};
private static final int[] MINIONS_COUNT =
{
3,
6,
11
};
private final Map<Integer, Double> _lastHp = new ConcurrentHashMap<>();
private Epidos()
{
super(Epidos.class.getSimpleName(), "ai/individual");
addKillId(EPIDOSES);
addSpawnId(EPIDOSES);
}
@Override
public final String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equalsIgnoreCase("check_minions"))
{
if ((getRandom(1000) > 250) && _lastHp.containsKey(npc.getObjectId()))
{
int hpDecreasePercent = (int) (((_lastHp.get(npc.getObjectId()) - npc.getCurrentHp()) * 100) / npc.getMaxHp());
int minionsCount = 0;
int spawnedMinions = ((L2MonsterInstance) npc).getMinionList().countSpawnedMinions();
if ((hpDecreasePercent > 5) && (hpDecreasePercent <= 15) && (spawnedMinions <= 9))
{
minionsCount = MINIONS_COUNT[0];
}
else if ((((hpDecreasePercent > 1) && (hpDecreasePercent <= 5)) || ((hpDecreasePercent > 15) && (hpDecreasePercent <= 30))) && (spawnedMinions <= 6))
{
minionsCount = MINIONS_COUNT[1];
}
else if (spawnedMinions == 0)
{
minionsCount = MINIONS_COUNT[2];
}
for (int i = 0; i < minionsCount; i++)
{
MinionList.spawnMinion((L2MonsterInstance) npc, MINIONS[Arrays.binarySearch(EPIDOSES, npc.getId())]);
}
_lastHp.put(npc.getObjectId(), npc.getCurrentHp());
}
startQuestTimer("check_minions", 10000, npc, null);
}
else if (event.equalsIgnoreCase("check_idle"))
{
if (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE)
{
npc.deleteMe();
}
else
{
startQuestTimer("check_idle", 600000, npc, null);
}
}
return null;
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (npc.isInsideRadius(-45474, 247450, -13994, 2000, true, false))
{
addSpawn(32376, -45482, 246277, -14184, 0, false, 0, false);
}
_lastHp.remove(npc.getObjectId());
return super.onKill(npc, killer, isSummon);
}
@Override
public final String onSpawn(L2Npc npc)
{
startQuestTimer("check_minions", 10000, npc, null);
startQuestTimer("check_idle", 600000, npc, null);
_lastHp.put(npc.getObjectId(), (double) npc.getMaxHp());
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new Epidos();
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.ItemHolder;
/**
* Eva's Gift Box AI.
* @author St3eT
*/
public final class EvasGiftBox extends AbstractNpcAI
{
// NPC
private static final int BOX = 32342; // Eva's Gift Box
// Skill
private static final int BUFF = 1073; // Kiss of Eva
// Items
private static final ItemHolder CORAL = new ItemHolder(9692, 1); // Red Coral
private static final ItemHolder CRYSTAL = new ItemHolder(9693, 1); // Crystal Fragment
private EvasGiftBox()
{
super(EvasGiftBox.class.getSimpleName(), "ai/individual");
addKillId(BOX);
addSpawnId(BOX);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (killer.isAffectedBySkill(BUFF))
{
if (getRandomBoolean())
{
npc.dropItem(killer, CRYSTAL);
}
if (getRandom(100) < 33)
{
npc.dropItem(killer, CORAL);
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
npc.setIsNoRndWalk(true);
((L2Attackable) npc).setOnKillDelay(0);
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new EvasGiftBox();
}
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* Frightened Ragna Orc AI.
* @author Gladicek, malyelfik
*/
public final class FrightenedRagnaOrc extends AbstractNpcAI
{
// NPC ID
private static final int MOB_ID = 18807;
// Chances
private static final int ADENA = 10000;
private static final int CHANCE = 1000;
private static final int ADENA2 = 1000000;
private static final int CHANCE2 = 10;
// Skill
private static final SkillHolder SKILL = new SkillHolder(6234, 1);
private FrightenedRagnaOrc()
{
super(FrightenedRagnaOrc.class.getSimpleName(), "ai/individual");
addAttackId(MOB_ID);
addKillId(MOB_ID);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (npc.isScriptValue(0))
{
npc.setScriptValue(1);
startQuestTimer("say", (getRandom(5) + 3) * 1000, npc, null, true);
}
else if ((npc.getCurrentHp() < (npc.getMaxHp() * 0.2)) && npc.isScriptValue(1))
{
startQuestTimer("reward", 10000, npc, attacker);
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.WAIT_WAIT_STOP_SAVE_ME_AND_I_LL_GIVE_YOU_10_000_000_ADENA);
npc.setScriptValue(2);
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
{
final NpcStringId msg = getRandomBoolean() ? NpcStringId.UGH_A_CURSE_UPON_YOU : NpcStringId.I_REALLY_DIDN_T_WANT_TO_FIGHT;
broadcastNpcSay(npc, Say2.NPC_ALL, msg);
cancelQuestTimer("say", npc, null);
cancelQuestTimer("reward", npc, player);
return super.onKill(npc, player, isSummon);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "say":
{
if (npc.isDead() || !npc.isScriptValue(1))
{
cancelQuestTimer("say", npc, null);
return null;
}
final NpcStringId msg = getRandomBoolean() ? NpcStringId.I_DON_T_WANT_TO_FIGHT : NpcStringId.IS_THIS_REALLY_NECESSARY;
broadcastNpcSay(npc, Say2.NPC_ALL, msg);
break;
}
case "reward":
{
if (!npc.isDead() && npc.isScriptValue(2))
{
if (getRandom(100000) < CHANCE2)
{
final NpcStringId msg = getRandomBoolean() ? NpcStringId.TH_THANKS_I_COULD_HAVE_BECOME_GOOD_FRIENDS_WITH_YOU : NpcStringId.I_LL_GIVE_YOU_10_000_000_ADENA_LIKE_I_PROMISED_I_MIGHT_BE_AN_ORC_WHO_KEEPS_MY_PROMISES;
broadcastNpcSay(npc, Say2.NPC_ALL, msg);
npc.setScriptValue(3);
npc.doCast(SKILL.getSkill());
for (int i = 0; i < 10; i++)
{
npc.dropItem(player, Inventory.ADENA_ID, ADENA2);
}
}
else if (getRandom(100000) < CHANCE)
{
final NpcStringId msg = getRandomBoolean() ? NpcStringId.TH_THANKS_I_COULD_HAVE_BECOME_GOOD_FRIENDS_WITH_YOU : NpcStringId.SORRY_BUT_THIS_IS_ALL_I_HAVE_GIVE_ME_A_BREAK;
broadcastNpcSay(npc, Say2.NPC_ALL, msg);
npc.setScriptValue(3);
npc.doCast(SKILL.getSkill());
for (int i = 0; i < 10; i++)
{
((L2Attackable) npc).dropItem(player, Inventory.ADENA_ID, ADENA);
}
}
else
{
final NpcStringId msg = getRandomBoolean() ? NpcStringId.THANKS_BUT_THAT_THING_ABOUT_10_000_000_ADENA_WAS_A_LIE_SEE_YA : NpcStringId.YOU_RE_PRETTY_DUMB_TO_BELIEVE_ME;
broadcastNpcSay(npc, Say2.NPC_ALL, msg);
}
startQuestTimer("despawn", 1000, npc, null);
}
break;
}
case "despawn":
{
npc.setRunning();
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location((npc.getX() + getRandom(-800, 800)), (npc.getY() + getRandom(-800, 800)), npc.getZ(), npc.getHeading()));
npc.deleteMe();
break;
}
}
return null;
}
public static void main(String[] args)
{
new FrightenedRagnaOrc();
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
/**
* Gordon AI
* @author TOFIZ, malyelfik
*/
public final class Gordon extends AbstractNpcAI
{
private static final int GORDON = 29095;
private Gordon()
{
super(Gordon.class.getSimpleName(), "ai/individual");
addSpawnId(GORDON);
addSeeCreatureId(GORDON);
}
@Override
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
{
if (creature.isPlayer() && ((L2PcInstance) creature).isCursedWeaponEquipped())
{
addAttackPlayerDesire(npc, (L2PcInstance) creature);
}
return super.onSeeCreature(npc, creature, isSummon);
}
@Override
public String onSpawn(L2Npc npc)
{
((L2Attackable) npc).setCanReturnToSpawnPoint(false);
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new Gordon();
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
/**
* Grove Robber's AI.<br>
* <ul>
* <li>Grove Robber Summoner</li>
* <li>Grove Robber Megician</li>
* </ul>
* @author Zealar
*/
public final class GraveRobbers extends AbstractNpcAI
{
private static final int GRAVE_ROBBER_SUMMONER = 22678;
private static final int GRAVE_ROBBER_MEGICIAN = 22679;
private GraveRobbers()
{
super(GraveRobbers.class.getSimpleName(), "ai/individual");
addSpawnId(GRAVE_ROBBER_SUMMONER, GRAVE_ROBBER_MEGICIAN);
}
@Override
public String onSpawn(L2Npc npc)
{
spawnMinions(npc, "Privates" + getRandom(1, 2));
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new GraveRobbers();
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* Mahram AI.
* @author St3eT
*/
public final class Mahram extends AbstractNpcAI
{
// NPCs
private static final int MAHRAM = 33271;
private Mahram()
{
super(Mahram.class.getSimpleName(), "ai/individual");
addSpawnId(MAHRAM);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("SPAM_TEXT") && (npc != null))
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.ALCHEMY_IS_A_SCIENCE_AND_AN_ART);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(L2Npc npc)
{
startQuestTimer("SPAM_TEXT", 10000, npc, null, true);
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new Mahram();
}
}

View File

@@ -0,0 +1,357 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.List;
import javolution.util.FastList;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.type.L2BossZone;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
/**
* 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 List<L2Attackable> _Minions = new FastList<>();
private static L2BossZone ZONE;
private static final byte ALIVE = 0;
private static final byte DEAD = 1;
private Orfen()
{
super(Orfen.class.getSimpleName(), "ai/individual");
int[] mobs =
{
ORFEN,
RAIKEL_LEOS,
RIBA_IREN
};
registerMobs(mobs);
_IsTeleported = false;
ZONE = GrandBossManager.getInstance().getZone(POS[0]);
StatsSet info = GrandBossManager.getInstance().getStatsSet(ORFEN);
int status = GrandBossManager.getInstance().getBossStatus(ORFEN);
if (status == DEAD)
{
// load the unlock date and time for Orfen from DB
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.
int i = getRandom(10);
Location loc;
if (i < 4)
{
loc = POS[1];
}
else if (i < 7)
{
loc = POS[2];
}
else
{
loc = POS[3];
}
L2GrandBossInstance orfen = (L2GrandBossInstance) addSpawn(ORFEN, loc, false, 0);
GrandBossManager.getInstance().setBossStatus(ORFEN, ALIVE);
spawnBoss(orfen);
}
}
else
{
int loc_x = info.getInt("loc_x");
int loc_y = info.getInt("loc_y");
int loc_z = info.getInt("loc_z");
int heading = info.getInt("heading");
int hp = info.getInt("currentHP");
int mp = info.getInt("currentMP");
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);
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
int x = npc.getX();
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"))
{
int i = getRandom(10);
Location loc;
if (i < 4)
{
loc = POS[1];
}
else if (i < 7)
{
loc = POS[2];
}
else
{
loc = POS[3];
}
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 (int i = 0; i < _Minions.size(); i++)
{
L2Attackable mob = _Minions.get(i);
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 (int i = 0; i < _Minions.size(); i++)
{
L2Attackable mob = _Minions.get(i);
if (mob != null)
{
mob.decayMe();
}
}
_Minions.clear();
}
else if (event.equalsIgnoreCase("spawn_minion"))
{
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)
{
L2Character originalCaster = isSummon ? caster.getSummon() : caster;
if ((skill.getEffectPoint() > 0) && (getRandom(5) == 0) && npc.isInsideRadius(originalCaster, 1000, false, false))
{
NpcSay packet = new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), TEXT[getRandom(4)]);
packet.addStringParameter(caster.getName().toString());
npc.broadcastPacket(packet);
originalCaster.teleToLocation(npc.getLocation());
npc.setTarget(originalCaster);
npc.doCast(SkillData.getInstance().getSkill(4064, 1));
}
}
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())
{
return super.onFactionCall(npc, caller, attacker, isSummon);
}
int npcId = npc.getId();
int callerId = caller.getId();
if ((npcId == RAIKEL_LEOS) && (getRandom(20) == 0))
{
npc.setTarget(attacker);
npc.doCast(SkillData.getInstance().getSkill(4067, 4));
}
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(SkillData.getInstance().getSkill(4516, 1));
}
}
return super.onFactionCall(npc, caller, attacker, isSummon);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
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))
{
NpcSay packet = new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npcId, TEXT[getRandom(3)]);
packet.addStringParameter(attacker.getName().toString());
npc.broadcastPacket(packet);
attacker.teleToLocation(npc.getLocation());
npc.setTarget(attacker);
npc.doCast(SkillData.getInstance().getSkill(4064, 1));
}
}
else if (npcId == RIBA_IREN)
{
if (!npc.isCastingNow() && ((npc.getCurrentHp() - damage) < (npc.getMaxHp() / 2.0)))
{
npc.setTarget(attacker);
npc.doCast(SkillData.getInstance().getSkill(4516, 1));
}
}
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
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();
}
}

View File

@@ -0,0 +1,378 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.List;
import javolution.util.FastList;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.CommonSkill;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.type.L2BossZone;
import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
/**
* 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 L2BossZone _zone;
private static SkillHolder HEAL1 = new SkillHolder(4020, 1);
private static SkillHolder HEAL2 = new SkillHolder(4024, 1);
private L2MonsterInstance _queen = null;
private L2MonsterInstance _larva = null;
private final List<L2MonsterInstance> _nurses = new FastList<>(5);
private QueenAnt()
{
super(QueenAnt.class.getSimpleName(), "ai/individual");
addSpawnId(MOBS);
addKillId(MOBS);
addAggroRangeEnterId(MOBS);
addFactionCallId(NURSE);
_zone = GrandBossManager.getInstance().getZone(QUEEN_X, QUEEN_Y, QUEEN_Z);
StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
int status = GrandBossManager.getInstance().getBossStatus(QUEEN);
if (status == DEAD)
{
// load the unlock date and time for queen ant from DB
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.
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");
int heading = info.getInt("heading");
int hp = info.getInt("currentHP");
int mp = info.getInt("currentMP");
if (!_zone.isInsideZone(loc_x, loc_y, loc_z))
{
loc_x = QUEEN_X;
loc_y = QUEEN_Y;
loc_z = QUEEN_Z;
}
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())
{
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"))
{
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.setIsMortal(false);
mob.setIsRaidMinion(true);
break;
case NURSE:
mob.disableCoreAI(true);
mob.setIsRaidMinion(true);
_nurses.add(mob);
break;
case ROYAL:
case GUARD:
mob.setIsRaidMinion(true);
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() && (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.getSummon();
}
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.isMuted() && (getRandom(4) == 0))
{
curse = CommonSkill.RAID_CURSE.getSkill();
}
}
else
{
if (!character.isParalyzed() && (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)
{
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.
long respawnTime = Config.QUEEN_ANT_SPAWN_INTERVAL + getRandom(-Config.QUEEN_ANT_SPAWN_RANDOM, Config.QUEEN_ANT_SPAWN_RANDOM);
respawnTime *= 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
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;
}
else if ((_queen != null) && !_queen.isAlikeDead())
{
if (npcId == ROYAL)
{
L2MonsterInstance mob = (L2MonsterInstance) npc;
if (mob.getLeader() != null)
{
mob.getLeader().getMinionList().onMinionDie(mob, (280 + getRandom(40)) * 1000);
}
}
else if (npcId == NURSE)
{
L2MonsterInstance mob = (L2MonsterInstance) npc;
_nurses.remove(mob);
if (mob.getLeader() != null)
{
mob.getLeader().getMinionList().onMinionDie(mob, 10000);
}
}
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new QueenAnt();
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.zone.type.L2EffectZone;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* Queen Shyeed AI
* @author malyelfik
*/
public final class QueenShyeed extends AbstractNpcAI
{
// NPC
private static final int SHYEED = 25671;
private static final Location SHYEED_LOC = new Location(79634, -55428, -6104, 0);
// Respawn
private static final int RESPAWN = 86400000; // 24 h
private static final int RANDOM_RESPAWN = 43200000; // 12 h
// Zones
private static final L2EffectZone MOB_BUFF_ZONE = ZoneManager.getInstance().getZoneById(200103, L2EffectZone.class);
private static final L2EffectZone MOB_BUFF_DISPLAY_ZONE = ZoneManager.getInstance().getZoneById(200104, L2EffectZone.class);
private static final L2EffectZone PC_BUFF_ZONE = ZoneManager.getInstance().getZoneById(200105, L2EffectZone.class);
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "respawn":
spawnShyeed();
break;
case "despawn":
if (!npc.isDead())
{
npc.deleteMe();
startRespawn();
}
break;
}
return null;
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.SHYEED_S_CRY_IS_STEADILY_DYING_DOWN);
startRespawn();
PC_BUFF_ZONE.setEnabled(true);
return super.onKill(npc, killer, isSummon);
}
private QueenShyeed()
{
super(QueenShyeed.class.getSimpleName(), "ai/individual");
addKillId(SHYEED);
spawnShyeed();
}
private void spawnShyeed()
{
final String respawn = loadGlobalQuestVar("Respawn");
final long remain = (!respawn.isEmpty()) ? Long.parseLong(respawn) - System.currentTimeMillis() : 0;
if (remain > 0)
{
startQuestTimer("respawn", remain, null, null);
return;
}
final L2Npc npc = addSpawn(SHYEED, SHYEED_LOC, false, 0);
startQuestTimer("despawn", 10800000, npc, null);
PC_BUFF_ZONE.setEnabled(false);
MOB_BUFF_ZONE.setEnabled(true);
MOB_BUFF_DISPLAY_ZONE.setEnabled(true);
}
private void startRespawn()
{
final int respawnTime = RESPAWN - getRandom(RANDOM_RESPAWN);
saveGlobalQuestVar("Respawn", Long.toString(System.currentTimeMillis() + respawnTime));
startQuestTimer("respawn", respawnTime, null, null);
MOB_BUFF_ZONE.setEnabled(false);
MOB_BUFF_DISPLAY_ZONE.setEnabled(false);
}
public static void main(String[] args)
{
new QueenShyeed();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
/**
* Ragna Orc Commander AI.
* @author Zealar
*/
public final class RagnaOrcCommander extends AbstractNpcAI
{
private static final int RAGNA_ORC_COMMANDER = 22694;
private RagnaOrcCommander()
{
super(RagnaOrcCommander.class.getSimpleName(), "ai/individual");
addSpawnId(RAGNA_ORC_COMMANDER);
}
@Override
public String onSpawn(L2Npc npc)
{
spawnMinions(npc, "Privates1");
spawnMinions(npc, getRandomBoolean() ? "Privates2" : "Privates3");
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new RagnaOrcCommander();
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
/**
* Ragna Orc Hero AI.
* @author Zealar
*/
public final class RagnaOrcHero extends AbstractNpcAI
{
private static final int RAGNA_ORC_HERO = 22693;
private RagnaOrcHero()
{
super(RagnaOrcHero.class.getSimpleName(), "ai/individual");
addSpawnId(RAGNA_ORC_HERO);
}
@Override
public String onSpawn(L2Npc npc)
{
spawnMinions(npc, getRandom(100) < 70 ? "Privates1" : "Privates2");
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new RagnaOrcHero();
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
/**
* Ragna Orc Seer AI.
* @author Zealar
*/
public final class RagnaOrcSeer extends AbstractNpcAI
{
private static final int RAGNA_ORC_SEER = 22697;
private RagnaOrcSeer()
{
super(RagnaOrcSeer.class.getSimpleName(), "ai/individual");
addSpawnId(RAGNA_ORC_SEER);
}
@Override
public String onSpawn(L2Npc npc)
{
spawnMinions(npc, "Privates" + getRandom(1, 2));
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new RagnaOrcSeer();
}
}

View File

@@ -0,0 +1,4 @@
<html><body>Shilen's Stone Statue:<br>
Wait.. It doesn't seem as though you are the one destined for the front lines in this battle. I was supposed to open a passage to Sailren's lair only to the leader of one party. If you wish to teleport, bring your party leader to me or return here as a party leader.<br>
<a action="bypass -h npc_%objectId%_Quest Sailren 32109-01a.html">Prep for battle.</a>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Shilen's Stone Statue:<br>
You know that in the past, Mother Shilen paid a great sacrifice to lock Sailren here.<br>
Afterward, she created a stone likeness of herself and bestowed upon it the power to seal, making it a guardian of this place to ensure that Sailren remained imprisoned.<br>
I am that stone statue of Shilen.<br>
Mother Shilen also entrusted the power to seal to those who wield the sacred ax Gazkh.<br>
I will only open the gate for those who have Gazkh and their friends. When the seal is at its weakest, however, I allow a warrior to enter in order to minimize the sacrifice.<br>
<a action="bypass -h npc_%objectId%_Quest Sailren 32109-02a.html">Listen to the conditions to enter in detail.</a>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Shilen's Stone Statue:<br>
You have the heart to fight Sailren, of that there can be no doubt. But if you do not have Gazkh given to you by Shilen, Sailren will certainly kill you. If you want to teleport within, complete my quest and obtain Gazkh.<br>
<a action="bypass -h npc_%objectId%_Quest Sailren 32109-01a.html">Prep for battle.</a>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Shilen's Stone Statue:<br>
Only a party whose leader weilds Gazkh can enter Sailren's Stronghold and battle the creature.<br>
Be aware that any party member who is far away at the time of entry cannot enter the Stronghold. Nor can another party enter until the first party has exited.<br>
<a action="bypass -h npc_%objectId%_Quest Sailren 32109-03a.html">Learn more about Sailren's power and how to fight it.</a>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Shilen's Stone Statue:<br>
Shilen's protection is not with you -- go away! You are not qualified to fight against Sailren...<br>
If you want to enter Sailren's nest, then you should find a party leader who can fight against Sailren and join his party. Or you can complete my quest to become a party leader, form your own party, and then return here.<br>
<a action="bypass -h npc_%objectId%_Quest Sailren 32109-01a.html">Listen to the entry requirements and battle method.</a>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Shilen's Stone Statue:<br>
There are not many of them, but Sailren is protected by its dinosaur followers. Combined with my enchantment and the power of the other statues, we are restraining Sailren and its followers from escaping. But as they begin to break free of our control, their power and magic also begins to extend beyond the Lost Nest, affecting even the Primeval Plains!<br>
If the powers of the Stone Statues are completely broken, Sailren and its followers will escape and this island and everything on it will perish.<br>
Alas, Shilen is not here to protect us! In order to re-seal that horrifying dinosaur, you must defeat its followers first, and then work as a team to defeat Sailren.
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Shilen's Stone Statue:<br>
Currently the magic power of Sailren and its followers is very strong. I do not think you can win solely with your own power, especially given how weak the seal stones have become.<br>
My counsel is that you first recover the power to seal and wait 'til Sailren's strength lessens a bit. Then you will have your best chance of entering the nest and defeating this ancient evil.<br>
<a action="bypass -h npc_%objectId%_Quest Sailren 32109-01a.html">Prep for battle.</a>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Shilen's Stone Statue:<br>
There is another brave party fighting against Sailren right now, so I cannot teleport you into the nest. When they return, I will teleport you.<br>
<a action="bypass -h npc_%objectId%_Quest Sailren 32109-01a.html">Prep for battle.</a>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Stone Statue of Shilen:<br>
(The statue is worn in places by wind and rain -- proof that it has stood guard here a long, long time. Despite its weatherbeaten appearance, it feels somehow dignified and majestic. Standing before it, you sense a presence.)<br>
You, outsider... Why have you come here to this statue? For I am Mother Shilen's avatar and the last guard of Sailren!<br>
<a action="bypass -h npc_%objectId%_Quest Sailren 32109-01.html">Prep for battle.</a><br>
<a action="bypass -h npc_%objectId%_Quest Sailren enter">"I wish to participate in clearing out Sailren and its followers."</a><br>
<a action="bypass -h npc_%objectId%_Quest">Quest.</a>
</body></html>

View File

@@ -0,0 +1,330 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual.Sailren;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.instancemanager.GlobalVariablesManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.TeleportWhereType;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2RaidBossInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.zone.type.L2NoRestartZone;
import com.l2jserver.gameserver.network.serverpackets.SpecialCamera;
/**
* Sailren AI.
* @author St3eT
*/
public final class Sailren extends AbstractNpcAI
{
// NPCs
private static final int STATUE = 32109; // Shilen's Stone Statue
private static final int MOVIE_NPC = 32110; // Invisible NPC for movie
private static final int SAILREN = 29065; // Sailren
private static final int VELOCIRAPTOR = 22218; // Velociraptor
private static final int PTEROSAUR = 22199; // Pterosaur
private static final int TREX = 22217; // Tyrannosaurus
private static final int CUBIC = 32107; // Teleportation Cubic
// Item
private static final int GAZKH = 8784; // Gazkh
// Skill
private static final SkillHolder ANIMATION = new SkillHolder(5090, 1);
// Zone
private static final L2NoRestartZone zone = ZoneManager.getInstance().getZoneById(70049, L2NoRestartZone.class);
// Misc
private static final int RESPAWN = 1; // Respawn time (in hours)
private static final int MAX_TIME = 3200; // Max time for Sailren fight (in minutes)
private static Status STATUS = Status.ALIVE;
private static int _killCount = 0;
private static long _lastAttack = 0;
private static enum Status
{
ALIVE,
IN_FIGHT,
DEAD
}
private Sailren()
{
super(Sailren.class.getSimpleName(), "ai/individual");
addStartNpc(STATUE, CUBIC);
addTalkId(STATUE, CUBIC);
addFirstTalkId(STATUE);
addKillId(VELOCIRAPTOR, PTEROSAUR, TREX, SAILREN);
addAttackId(VELOCIRAPTOR, PTEROSAUR, TREX, SAILREN);
final long remain = GlobalVariablesManager.getInstance().getLong("SailrenRespawn", 0) - System.currentTimeMillis();
if (remain > 0)
{
STATUS = Status.DEAD;
startQuestTimer("CLEAR_STATUS", remain, null, null);
}
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "32109-01.html":
case "32109-01a.html":
case "32109-02a.html":
case "32109-03a.html":
{
return event;
}
case "enter":
{
String htmltext = null;
if (!player.isInParty())
{
htmltext = "32109-01.html";
}
else if (STATUS == Status.DEAD)
{
htmltext = "32109-04.html";
}
else if (STATUS == Status.IN_FIGHT)
{
htmltext = "32109-05.html";
}
else if (!player.getParty().isLeader(player))
{
htmltext = "32109-03.html";
}
else if (!hasQuestItems(player, GAZKH))
{
htmltext = "32109-02.html";
}
else
{
takeItems(player, GAZKH, 1);
STATUS = Status.IN_FIGHT;
_lastAttack = System.currentTimeMillis();
for (L2PcInstance member : player.getParty().getMembers())
{
if (member.isInsideRadius(npc, 1000, true, false))
{
member.teleToLocation(27549, -6638, -2008);
}
}
startQuestTimer("SPAWN_VELOCIRAPTOR", 60000, null, null);
startQuestTimer("TIME_OUT", MAX_TIME * 1000, null, null);
startQuestTimer("CHECK_ATTACK", 120000, null, null);
}
return htmltext;
}
case "teleportOut":
{
player.teleToLocation(TeleportWhereType.TOWN);
break;
}
case "SPAWN_VELOCIRAPTOR":
{
for (int i = 0; i < 3; i++)
{
addSpawn(VELOCIRAPTOR, 27313 + getRandom(150), -6766 + getRandom(150), -1975, 0, false, 0);
}
break;
}
case "SPAWN_SAILREN":
{
final L2RaidBossInstance sailren = (L2RaidBossInstance) addSpawn(SAILREN, 27549, -6638, -2008, 0, false, 0);
final L2Npc movieNpc = addSpawn(MOVIE_NPC, sailren.getX(), sailren.getY(), sailren.getZ() + 30, 0, false, 26000);
sailren.setIsInvul(true);
sailren.setIsImmobilized(true);
zone.broadcastPacket(new SpecialCamera(movieNpc, 60, 110, 30, 4000, 1500, 20000, 0, 65, 1, 0, 0));
startQuestTimer("ATTACK", 24600, sailren, null);
startQuestTimer("ANIMATION", 2000, movieNpc, null);
startQuestTimer("CAMERA_1", 4100, movieNpc, null);
break;
}
case "ANIMATION":
{
if (npc != null)
{
npc.setTarget(npc);
npc.doCast(ANIMATION.getSkill());
startQuestTimer("ANIMATION", 2000, npc, null);
}
break;
}
case "CAMERA_1":
{
zone.broadcastPacket(new SpecialCamera(npc, 100, 180, 30, 3000, 1500, 20000, 0, 50, 1, 0, 0));
startQuestTimer("CAMERA_2", 3000, npc, null);
break;
}
case "CAMERA_2":
{
zone.broadcastPacket(new SpecialCamera(npc, 150, 270, 25, 3000, 1500, 20000, 0, 30, 1, 0, 0));
startQuestTimer("CAMERA_3", 3000, npc, null);
break;
}
case "CAMERA_3":
{
zone.broadcastPacket(new SpecialCamera(npc, 160, 360, 20, 3000, 1500, 20000, 10, 15, 1, 0, 0));
startQuestTimer("CAMERA_4", 3000, npc, null);
break;
}
case "CAMERA_4":
{
zone.broadcastPacket(new SpecialCamera(npc, 160, 450, 10, 3000, 1500, 20000, 0, 10, 1, 0, 0));
startQuestTimer("CAMERA_5", 3000, npc, null);
break;
}
case "CAMERA_5":
{
zone.broadcastPacket(new SpecialCamera(npc, 160, 560, 0, 3000, 1500, 20000, 0, 10, 1, 0, 0));
startQuestTimer("CAMERA_6", 7000, npc, null);
break;
}
case "CAMERA_6":
{
zone.broadcastPacket(new SpecialCamera(npc, 70, 560, 0, 500, 1500, 7000, -15, 20, 1, 0, 0));
break;
}
case "ATTACK":
{
npc.setIsInvul(false);
npc.setIsImmobilized(false);
break;
}
case "CLEAR_STATUS":
{
STATUS = Status.ALIVE;
break;
}
case "TIME_OUT":
{
if (STATUS == Status.IN_FIGHT)
{
STATUS = Status.ALIVE;
}
for (L2Character charInside : zone.getCharactersInside())
{
if (charInside != null)
{
if (charInside.isPlayer())
{
charInside.teleToLocation(TeleportWhereType.TOWN);
}
else if (charInside.isNpc())
{
charInside.deleteMe();
}
}
}
break;
}
case "CHECK_ATTACK":
{
if (!zone.getPlayersInside().isEmpty() && ((_lastAttack + 600000) < System.currentTimeMillis()))
{
cancelQuestTimer("TIME_OUT", null, null);
notifyEvent("TIME_OUT", null, null);
}
else
{
startQuestTimer("CHECK_ATTACK", 120000, null, null);
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (zone.isCharacterInZone(attacker))
{
_lastAttack = System.currentTimeMillis();
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (zone.isCharacterInZone(killer))
{
switch (npc.getId())
{
case SAILREN:
{
STATUS = Status.DEAD;
addSpawn(CUBIC, 27644, -6638, -2008, 0, false, 300000);
final long respawnTime = RESPAWN * 3600000;
GlobalVariablesManager.getInstance().set("SailrenRespawn", System.currentTimeMillis() + respawnTime);
cancelQuestTimer("CHECK_ATTACK", null, null);
cancelQuestTimer("TIME_OUT", null, null);
startQuestTimer("CLEAR_STATUS", respawnTime, null, null);
startQuestTimer("TIME_OUT", 300000, null, null);
break;
}
case VELOCIRAPTOR:
{
_killCount++;
if (_killCount == 3)
{
final L2Npc pterosaur = addSpawn(PTEROSAUR, 27313, -6766, -1975, 0, false, 0);
addAttackPlayerDesire(pterosaur, killer);
_killCount = 0;
}
break;
}
case PTEROSAUR:
{
final L2Npc trex = addSpawn(TREX, 27313, -6766, -1975, 0, false, 0);
addAttackPlayerDesire(trex, killer);
break;
}
case TREX:
{
startQuestTimer("SPAWN_SAILREN", 180000, null, null);
break;
}
}
}
return super.onKill(npc, killer, isSummon);
}
@Override
public boolean unload(boolean removeFromList)
{
if (STATUS == Status.IN_FIGHT)
{
_log.info(getClass().getSimpleName() + ": Script is being unloaded while Sailren is active, clearing zone.");
notifyEvent("TIME_OUT", null, null);
}
return super.unload(removeFromList);
}
public static void main(String[] args)
{
new Sailren();
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* Shannon AI.
* @author St3eT
*/
public final class Shannon extends AbstractNpcAI
{
// NPCs
private static final int SHANNON = 32974;
private Shannon()
{
super(Shannon.class.getSimpleName(), "ai/individual");
addSpawnId(SHANNON);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("SPAM_TEXT") && (npc != null))
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.LOOK_AT_ALL_THE_NEWBIES_HA_HA_HA);
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(L2Npc npc)
{
startQuestTimer("SPAM_TEXT", 12000, npc, null, true);
return super.onSpawn(npc);
}
public static void main(String[] args)
{
new Shannon();
}
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Summon;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.events.EventType;
import com.l2jserver.gameserver.model.events.ListenerRegisterType;
import com.l2jserver.gameserver.model.events.annotations.Id;
import com.l2jserver.gameserver.model.events.annotations.RegisterEvent;
import com.l2jserver.gameserver.model.events.annotations.RegisterType;
import com.l2jserver.gameserver.model.events.impl.character.OnCreatureAttacked;
import com.l2jserver.gameserver.model.events.impl.character.OnCreatureKill;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
/**
* Sin Eater AI.
* @author St3eT.
*/
public final class SinEater extends AbstractNpcAI
{
// NPCs
private static final int SIN_EATER = 12564;
private SinEater()
{
super(SinEater.class.getSimpleName(), "ai/individual");
addSummonSpawnId(SIN_EATER);
addSummonTalkId(SIN_EATER);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("TALK") && (player != null) && (player.getSummon() != null))
{
if (getRandom(100) < 30)
{
final int random = getRandom(100);
final L2Summon summon = player.getSummon();
if (random < 20)
{
broadcastSummonSay(summon, NpcStringId.YAWWWWN_IT_S_SO_BORING_HERE_WE_SHOULD_GO_AND_FIND_SOME_ACTION);
}
else if (random < 40)
{
broadcastSummonSay(summon, NpcStringId.HEY_IF_YOU_CONTINUE_TO_WASTE_TIME_YOU_WILL_NEVER_FINISH_YOUR_PENANCE);
}
else if (random < 60)
{
broadcastSummonSay(summon, NpcStringId.I_KNOW_YOU_DON_T_LIKE_ME_THE_FEELING_IS_MUTUAL);
}
else if (random < 80)
{
broadcastSummonSay(summon, NpcStringId.I_NEED_A_DRINK);
}
else
{
broadcastSummonSay(summon, NpcStringId.OH_THIS_IS_DRAGGING_ON_TOO_LONG_AT_THIS_RATE_I_WON_T_MAKE_IT_HOME_BEFORE_THE_SEVEN_SEALS_ARE_BROKEN);
}
}
startQuestTimer("TALK", 60000, null, player);
}
return super.onAdvEvent(event, npc, player);
}
@RegisterEvent(EventType.ON_CREATURE_KILL)
@RegisterType(ListenerRegisterType.NPC)
@Id(SIN_EATER)
public void onCreatureKill(OnCreatureKill event)
{
final int random = getRandom(100);
final L2Summon summon = (L2Summon) event.getTarget();
if (random < 30)
{
broadcastSummonSay(summon, NpcStringId.OH_THIS_IS_JUST_GREAT_WHAT_ARE_YOU_GOING_TO_DO_NOW);
}
else if (random < 70)
{
broadcastSummonSay(summon, NpcStringId.YOU_INCONSIDERATE_MORON_CAN_T_YOU_EVEN_TAKE_CARE_OF_LITTLE_OLD_ME);
}
else
{
broadcastSummonSay(summon, NpcStringId.OH_NO_THE_MAN_WHO_EATS_ONE_S_SINS_HAS_DIED_PENITENCE_IS_FURTHER_AWAY);
}
}
@RegisterEvent(EventType.ON_CREATURE_ATTACKED)
@RegisterType(ListenerRegisterType.NPC)
@Id(SIN_EATER)
public void onCreatureAttacked(OnCreatureAttacked event)
{
if (getRandom(100) < 30)
{
final int random = getRandom(100);
final L2Summon summon = (L2Summon) event.getTarget();
if (random < 35)
{
broadcastSummonSay(summon, NpcStringId.OH_THAT_SMARTS);
}
else if (random < 70)
{
broadcastSummonSay(summon, NpcStringId.HEY_MASTER_PAY_ATTENTION_I_M_DYING_OVER_HERE);
}
else
{
broadcastSummonSay(summon, NpcStringId.WHAT_HAVE_I_DONE_TO_DESERVE_THIS);
}
}
}
@Override
public void onSummonSpawn(L2Summon summon)
{
broadcastSummonSay(summon, getRandomBoolean() ? NpcStringId.HEY_IT_SEEMS_LIKE_YOU_NEED_MY_HELP_DOESN_T_IT : NpcStringId.ALMOST_GOT_IT_OUCH_STOP_DAMN_THESE_BLOODY_MANACLES);
startQuestTimer("TALK", 60000, null, summon.getOwner());
}
@Override
public void onSummonTalk(L2Summon summon)
{
if (getRandom(100) < 10)
{
final int random = getRandom(100);
if (random < 25)
{
broadcastSummonSay(summon, NpcStringId.USING_A_SPECIAL_SKILL_HERE_COULD_TRIGGER_A_BLOODBATH);
}
else if (random < 50)
{
broadcastSummonSay(summon, NpcStringId.HEY_WHAT_DO_YOU_EXPECT_OF_ME);
}
else if (random < 75)
{
broadcastSummonSay(summon, NpcStringId.UGGGGGH_PUSH_IT_S_NOT_COMING_OUT);
}
else
{
broadcastSummonSay(summon, NpcStringId.AH_I_MISSED_THE_MARK);
}
}
}
private void broadcastSummonSay(L2Summon summon, NpcStringId npcstringId)
{
summon.broadcastPacket(new NpcSay(summon.getObjectId(), Say2.NPC_ALL, summon.getId(), npcstringId));
}
public static void main(String[] args)
{
new SinEater();
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.Map;
import javolution.util.FastMap;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
/**
* Manages Sin Wardens disappearing and chat.
* @author GKR
*/
public final class SinWardens extends AbstractNpcAI
{
private static final int[] SIN_WARDEN_MINIONS =
{
22424,
22425,
22426,
22427,
22428,
22429,
22430,
22432,
22433,
22434,
22435,
22436,
22437,
22438
};
private final Map<Integer, Integer> killedMinionsCount = new FastMap<>();
private SinWardens()
{
super(SinWardens.class.getSimpleName(), "ai/individual");
addKillId(SIN_WARDEN_MINIONS);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
if (npc.isMinion())
{
final L2MonsterInstance master = ((L2MonsterInstance) npc).getLeader();
if ((master != null) && !master.isDead())
{
int killedCount = killedMinionsCount.containsKey(master.getObjectId()) ? killedMinionsCount.get(master.getObjectId()) : 0;
killedCount++;
if ((killedCount) == 5)
{
master.broadcastPacket(new NpcSay(master.getObjectId(), Say2.NPC_ALL, master.getId(), NpcStringId.WE_MIGHT_NEED_NEW_SLAVES_I_LL_BE_BACK_SOON_SO_WAIT));
master.doDie(killer);
killedMinionsCount.remove(master.getObjectId());
}
else
{
killedMinionsCount.put(master.getObjectId(), killedCount);
}
}
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new SinWardens();
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2QuestGuardInstance;
/**
* Trainning Soldier AI.
* @author St3eT
*/
public final class TrainningSoldier extends AbstractNpcAI
{
// NPCs
private static final int SOLDIER = 33201; // Trainning Soldier
private static final int DUMMY = 33023; // Trainning Dummy
private TrainningSoldier()
{
super(TrainningSoldier.class.getSimpleName(), "ai/individual");
addSeeCreatureId(SOLDIER);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("START_ATTACK") && (npc instanceof L2QuestGuardInstance))
{
final L2QuestGuardInstance soldier = (L2QuestGuardInstance) npc;
//@formatter:off
final L2Npc dummy = (L2Npc) soldier.getKnownList().getKnownCharactersInRadius(150)
.stream()
.filter(L2Object::isNpc)
.filter(obj -> (obj.getId() == DUMMY))
.findFirst()
.orElse(null);
//@formatter:on
if (dummy != null)
{
soldier.reduceCurrentHp(1, dummy, null); // TODO: Find better way for attack
dummy.reduceCurrentHp(1, soldier, null);
soldier.setCanStopAttackByTime(false);
soldier.setCanReturnToSpawnPoint(false);
soldier.setIsInvul(true);
}
else
{
startQuestTimer("START_ATTACK", 250, npc, null);
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
{
if (creature.isPlayer() && (npc.getAI().getIntention() != CtrlIntention.AI_INTENTION_ATTACK))
{
startQuestTimer("START_ATTACK", 250, npc, null);
}
return super.onSeeCreature(npc, creature, isSummon);
}
public static void main(String[] args)
{
new TrainningSoldier();
}
}

View File

@@ -0,0 +1,571 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual;
import java.util.ArrayList;
import java.util.List;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.enums.MountType;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.BuffInfo;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.type.L2BossZone;
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.network.serverpackets.SpecialCamera;
import com.l2jserver.gameserver.util.Util;
/**
* Valakas' AI.
* @author Tryskell
*/
public final class Valakas extends AbstractNpcAI
{
// NPC
private static final int VALAKAS = 29028;
// Skills
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
private static final int VALAKAS_REGENERATION = 4691;
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
{
new SkillHolder(4681, 1), // Valakas Trample
new SkillHolder(4682, 1), // Valakas Trample
new SkillHolder(4683, 1), // Valakas Dragon Breath
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
};
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
{
new SkillHolder(4681, 1), // Valakas Trample
new SkillHolder(4682, 1), // Valakas Trample
new SkillHolder(4683, 1), // Valakas Dragon Breath
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
new SkillHolder(4690, 1), // Valakas Meteor Storm
};
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
{
new SkillHolder(4683, 1), // Valakas Dragon Breath
new SkillHolder(4684, 1), // Valakas Dragon Breath
new SkillHolder(4685, 1), // Valakas Tail Stomp
new SkillHolder(4686, 1), // Valakas Tail Stomp
new SkillHolder(4688, 1), // Valakas Stun
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
new SkillHolder(4690, 1), // Valakas Meteor Storm
};
// Locations
private static final Location TELEPORT_CUBE_LOCATIONS[] =
{
new Location(214880, -116144, -1644),
new Location(213696, -116592, -1644),
new Location(212112, -116688, -1644),
new Location(211184, -115472, -1664),
new Location(210336, -114592, -1644),
new Location(211360, -113904, -1644),
new Location(213152, -112352, -1644),
new Location(214032, -113232, -1644),
new Location(214752, -114592, -1644),
new Location(209824, -115568, -1421),
new Location(210528, -112192, -1403),
new Location(213120, -111136, -1408),
new Location(215184, -111504, -1392),
new Location(215456, -117328, -1392),
new Location(213200, -118160, -1424)
};
private static final Location ATTACKER_REMOVE = new Location(150037, -57255, -2976);
private static final Location VALAKAS_LAIR = new Location(212852, -114842, -1632);
private static final Location VALAKAS_REGENERATION_LOC = new Location(-105200, -253104, -15264);
// Valakas status.
private static final byte DORMANT = 0; // Valakas is spawned and no one has entered yet. Entry is unlocked.
private static final byte WAITING = 1; // Valakas is spawned and someone has entered, triggering a 30 minute window for additional people to enter. Entry is unlocked.
private static final byte FIGHTING = 2; // Valakas is engaged in battle, annihilating his foes. Entry is locked.
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
// Misc
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
private L2Playable _actualVictim; // Actual target of Valakas.
private static L2BossZone ZONE;
private Valakas()
{
super(Valakas.class.getSimpleName(), "ai/individual");
registerMobs(VALAKAS);
ZONE = GrandBossManager.getInstance().getZone(212852, -114842, -1632);
final StatsSet info = GrandBossManager.getInstance().getStatsSet(VALAKAS);
final int status = GrandBossManager.getInstance().getBossStatus(VALAKAS);
if (status == DEAD)
{
// load the unlock date and time for valakas from DB
long temp = (info.getLong("respawn_time") - System.currentTimeMillis());
if (temp > 0)
{
// The time has not yet expired. Mark Valakas as currently locked (dead).
startQuestTimer("valakas_unlock", temp, null, null);
}
else
{
// The time has expired while the server was offline. Spawn valakas in his cave as DORMANT.
final L2Npc valakas = addSpawn(VALAKAS, -105200, -253104, -15264, 0, false, 0);
GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
GrandBossManager.getInstance().addBoss((L2GrandBossInstance) valakas);
valakas.setIsInvul(true);
valakas.setRunning();
valakas.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
}
}
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 int hp = info.getInt("currentHP");
final int mp = info.getInt("currentMP");
final L2Npc valakas = addSpawn(VALAKAS, loc_x, loc_y, loc_z, heading, false, 0);
GrandBossManager.getInstance().addBoss((L2GrandBossInstance) valakas);
valakas.setCurrentHpMp(hp, mp);
valakas.setRunning();
// Start timers.
if (status == FIGHTING)
{
// stores current time for inactivity task.
_timeTracker = System.currentTimeMillis();
startQuestTimer("regen_task", 60000, valakas, null, true);
startQuestTimer("skill_task", 2000, valakas, null, true);
}
else
{
valakas.setIsInvul(true);
valakas.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
// Start timer to lock entry after 30 minutes
if (status == WAITING)
{
startQuestTimer("beginning", (Config.VALAKAS_WAIT_TIME * 60000), valakas, null);
}
}
}
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (npc != null)
{
if (event.equalsIgnoreCase("beginning"))
{
// Stores current time
_timeTracker = System.currentTimeMillis();
// Teleport Valakas to his lair.
npc.teleToLocation(VALAKAS_LAIR);
// Sound + socialAction.
for (L2PcInstance plyr : ZONE.getPlayersInside())
{
plyr.sendPacket(new PlaySound(1, "B03_A", 0, 0, 0, 0, 0));
plyr.sendPacket(new SocialAction(npc.getObjectId(), 3));
}
// Launch the cinematic, and tasks (regen + skill).
startQuestTimer("spawn_1", 1700, npc, null); // 1700
startQuestTimer("spawn_2", 3200, npc, null); // 1500
startQuestTimer("spawn_3", 6500, npc, null); // 3300
startQuestTimer("spawn_4", 9400, npc, null); // 2900
startQuestTimer("spawn_5", 12100, npc, null); // 2700
startQuestTimer("spawn_6", 12430, npc, null); // 330
startQuestTimer("spawn_7", 15430, npc, null); // 3000
startQuestTimer("spawn_8", 16830, npc, null); // 1400
startQuestTimer("spawn_9", 23530, npc, null); // 6700 - end of cinematic
startQuestTimer("spawn_10", 26000, npc, null); // 2500 - AI + unlock
}
// Regeneration && inactivity task
else if (event.equalsIgnoreCase("regen_task"))
{
// Inactivity task - 15min
if (GrandBossManager.getInstance().getBossStatus(VALAKAS) == FIGHTING)
{
if ((_timeTracker + 900000) < System.currentTimeMillis())
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
npc.teleToLocation(VALAKAS_REGENERATION_LOC);
GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
// Drop all players from the zone.
ZONE.oustAllPlayers();
// Cancel skill_task and regen_task.
cancelQuestTimer("regen_task", npc, null);
cancelQuestTimer("skill_task", npc, null);
return null;
}
}
// Verify if "Valakas Regeneration" skill is active.
final BuffInfo info = npc.getEffectList().getBuffInfoBySkillId(VALAKAS_REGENERATION);
final int lvl = info != null ? info.getSkill().getLevel() : 0;
// Current HPs are inferior to 25% ; apply lvl 4 of regen skill.
if ((npc.getCurrentHp() < (npc.getMaxHp() / 4)) && (lvl != 4))
{
npc.setTarget(npc);
npc.doCast(SkillData.getInstance().getSkill(VALAKAS_REGENERATION, 4));
}
// Current HPs are inferior to 50% ; apply lvl 3 of regen skill.
else if ((npc.getCurrentHp() < ((npc.getMaxHp() * 2) / 4.0)) && (lvl != 3))
{
npc.setTarget(npc);
npc.doCast(SkillData.getInstance().getSkill(VALAKAS_REGENERATION, 3));
}
// Current HPs are inferior to 75% ; apply lvl 2 of regen skill.
else if ((npc.getCurrentHp() < ((npc.getMaxHp() * 3) / 4.0)) && (lvl != 2))
{
npc.setTarget(npc);
npc.doCast(SkillData.getInstance().getSkill(VALAKAS_REGENERATION, 2));
}
// Apply lvl 1.
else if (lvl != 1)
{
npc.setTarget(npc);
npc.doCast(SkillData.getInstance().getSkill(VALAKAS_REGENERATION, 1));
}
}
// Spawn cinematic, regen_task and choose of skill.
else if (event.equalsIgnoreCase("spawn_1"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1800, 180, -1, 1500, 15000, 10000, 0, 0, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_2"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1300, 180, -5, 3000, 15000, 10000, 0, -5, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_3"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 500, 180, -8, 600, 15000, 10000, 0, 60, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_4"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 800, 180, -8, 2700, 15000, 10000, 0, 30, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_5"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 200, 250, 70, 0, 15000, 10000, 30, 80, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_6"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1100, 250, 70, 2500, 15000, 10000, 30, 80, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_7"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 700, 150, 30, 0, 15000, 10000, -10, 60, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_8"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1200, 150, 20, 2900, 15000, 10000, -10, 30, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_9"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 750, 170, -10, 3400, 15000, 4000, 10, -15, 1, 0, 0));
}
else if (event.equalsIgnoreCase("spawn_10"))
{
GrandBossManager.getInstance().setBossStatus(VALAKAS, FIGHTING);
npc.setIsInvul(false);
startQuestTimer("regen_task", 60000, npc, null, true);
startQuestTimer("skill_task", 2000, npc, null, true);
}
// Death cinematic, spawn of Teleport Cubes.
else if (event.equalsIgnoreCase("die_1"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 2000, 130, -1, 0, 15000, 10000, 0, 0, 1, 1, 0));
}
else if (event.equalsIgnoreCase("die_2"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1100, 210, -5, 3000, 15000, 10000, -13, 0, 1, 1, 0));
}
else if (event.equalsIgnoreCase("die_3"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1300, 200, -8, 3000, 15000, 10000, 0, 15, 1, 1, 0));
}
else if (event.equalsIgnoreCase("die_4"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1000, 190, 0, 500, 15000, 10000, 0, 10, 1, 1, 0));
}
else if (event.equalsIgnoreCase("die_5"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1700, 120, 0, 2500, 15000, 10000, 12, 40, 1, 1, 0));
}
else if (event.equalsIgnoreCase("die_6"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1700, 20, 0, 700, 15000, 10000, 10, 10, 1, 1, 0));
}
else if (event.equalsIgnoreCase("die_7"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1700, 10, 0, 1000, 15000, 10000, 20, 70, 1, 1, 0));
}
else if (event.equalsIgnoreCase("die_8"))
{
ZONE.broadcastPacket(new SpecialCamera(npc, 1700, 10, 0, 300, 15000, 250, 20, -20, 1, 1, 0));
for (Location loc : TELEPORT_CUBE_LOCATIONS)
{
addSpawn(31759, loc, false, 900000);
}
startQuestTimer("remove_players", 900000, null, null);
}
else if (event.equalsIgnoreCase("skill_task"))
{
callSkillAI(npc);
}
}
else
{
if (event.equalsIgnoreCase("valakas_unlock"))
{
final L2Npc valakas = addSpawn(VALAKAS, -105200, -253104, -15264, 32768, false, 0);
GrandBossManager.getInstance().addBoss((L2GrandBossInstance) valakas);
GrandBossManager.getInstance().setBossStatus(VALAKAS, DORMANT);
}
else if (event.equalsIgnoreCase("remove_players"))
{
ZONE.oustAllPlayers();
}
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onSpawn(L2Npc npc)
{
npc.disableCoreAI(true);
return super.onSpawn(npc);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
if (!ZONE.isInsideZone(attacker))
{
attacker.doDie(attacker);
return null;
}
if (npc.isInvul())
{
return null;
}
if (GrandBossManager.getInstance().getBossStatus(VALAKAS) != FIGHTING)
{
attacker.teleToLocation(ATTACKER_REMOVE);
return null;
}
// Debuff strider-mounted players.
if (attacker.getMountType() == MountType.STRIDER)
{
final Skill skill = SkillData.getInstance().getSkill(4258, 1);
if (!attacker.isAffectedBySkill(4258))
{
npc.setTarget(attacker);
npc.doCast(skill);
}
}
_timeTracker = System.currentTimeMillis();
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
// Cancel skill_task and regen_task.
cancelQuestTimer("regen_task", npc, null);
cancelQuestTimer("skill_task", npc, null);
// Launch death animation.
ZONE.broadcastPacket(new PlaySound(1, "B03_D", 0, 0, 0, 0, 0));
ZONE.broadcastPacket(new SpecialCamera(npc, 1200, 20, -10, 0, 10000, 13000, 0, 0, 0, 0, 0));
startQuestTimer("die_1", 300, npc, null); // 300
startQuestTimer("die_2", 600, npc, null); // 300
startQuestTimer("die_3", 3800, npc, null); // 3200
startQuestTimer("die_4", 8200, npc, null); // 4400
startQuestTimer("die_5", 8700, npc, null); // 500
startQuestTimer("die_6", 13300, npc, null); // 4600
startQuestTimer("die_7", 14000, npc, null); // 700
startQuestTimer("die_8", 16500, npc, null); // 2500
GrandBossManager.getInstance().setBossStatus(VALAKAS, DEAD);
// Calculate Min and Max respawn times randomly.
long respawnTime = Config.VALAKAS_SPAWN_INTERVAL + getRandom(-Config.VALAKAS_SPAWN_RANDOM, Config.VALAKAS_SPAWN_RANDOM);
respawnTime *= 3600000;
startQuestTimer("valakas_unlock", respawnTime, null, null);
// also save the respawn time so that the info is maintained past reboots
StatsSet info = GrandBossManager.getInstance().getStatsSet(VALAKAS);
info.set("respawn_time", (System.currentTimeMillis() + respawnTime));
GrandBossManager.getInstance().setStatsSet(VALAKAS, info);
return super.onKill(npc, killer, isSummon);
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
return null;
}
private void callSkillAI(L2Npc npc)
{
if (npc.isInvul() || npc.isCastingNow())
{
return;
}
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.getKnownList().knowsObject(_actualVictim)) || (getRandom(10) == 0))
{
_actualVictim = getRandomTarget(npc);
}
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
if (_actualVictim == null)
{
if (getRandom(10) == 0)
{
int x = npc.getX();
int y = npc.getY();
int z = npc.getZ();
int posX = x + getRandom(-1400, 1400);
int posY = y + getRandom(-1400, 1400);
if (GeoData.getInstance().canMove(x, y, z, posX, posY, z, npc.getInstanceId()))
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
}
}
return;
}
final Skill skill = getRandomSkill(npc).getSkill();
// Cast the skill or follow the target.
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
npc.setIsCastingNow(true);
npc.setTarget(_actualVictim);
npc.doCast(skill);
}
else
{
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
npc.setIsCastingNow(false);
}
}
/**
* Pick a random skill.<br>
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
* Lower than 50% HPs, he will begin to use Meteor skill.
* @param npc valakas
* @return a skill holder
*/
private SkillHolder getRandomSkill(L2Npc npc)
{
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
// Valakas Lava Skin has priority.
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
{
return VALAKAS_LAVA_SKIN;
}
// Valakas will use mass spells if he feels surrounded.
if (Util.getPlayersCountInRadius(1200, npc, false, false) >= 20)
{
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
}
if (hpRatio > 50)
{
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
}
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
}
/**
* Pickup a random L2Playable from the zone, deads targets aren't included.
* @param npc
* @return a random L2Playable.
*/
private L2Playable getRandomTarget(L2Npc npc)
{
List<L2Playable> result = new ArrayList<>();
for (L2Character obj : npc.getKnownList().getKnownCharacters())
{
if ((obj == null) || obj.isPet())
{
continue;
}
else if (!obj.isDead() && obj.isPlayable())
{
result.add((L2Playable) obj);
}
}
return (result.isEmpty()) ? null : result.get(getRandom(result.size()));
}
public static void main(String[] args)
{
new Valakas();
}
}

View File

@@ -0,0 +1,3 @@
<html><body>Teleportation Cubic:<br>
<a action="bypass -h npc_%objectId%_Quest Venom">Leave the prison.</a><br>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>
When attacking a castle, its defenses can easily be paralyzed.... What if that demon escapes?
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>
The roar of that scary demon in the dungeon always makes me want to run away! I know the dungeon is well-built, but if its defenses are broken, it could collapse!<br><p>
<a action="bypass -h npc_%objectId%_Quest Venom">Teleport to the dungeon</a>
</body></html>

View File

@@ -0,0 +1,414 @@
/*
* Copyright (C) 2004-2014 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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.
*
* L2J DataPack 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.individual.Venom;
import java.util.ArrayList;
import java.util.List;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.instancemanager.CastleManager;
import com.l2jserver.gameserver.instancemanager.GlobalVariablesManager;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.TeleportWhereType;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.events.impl.sieges.castle.OnCastleSiegeFinish;
import com.l2jserver.gameserver.model.events.impl.sieges.castle.OnCastleSiegeStart;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.zone.ZoneId;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
/**
* Venom AI on Rune Castle.
* @author nonom, MELERIX
*/
public final class Venom extends AbstractNpcAI
{
private static final int CASTLE = 8; // Rune
private static final int VENOM = 29054;
private static final int TELEPORT_CUBE = 29055;
private static final int DUNGEON_KEEPER = 35506;
private static final byte ALIVE = 0;
private static final byte DEAD = 1;
private static final int HOURS_BEFORE = 24;
private static final Location[] TARGET_TELEPORTS =
{
new Location(12860, -49158, 976),
new Location(14878, -51339, 1024),
new Location(15674, -49970, 864),
new Location(15696, -48326, 864),
new Location(14873, -46956, 1024),
new Location(12157, -49135, -1088),
new Location(12875, -46392, -288),
new Location(14087, -46706, -288),
new Location(14086, -51593, -288),
new Location(12864, -51898, -288),
new Location(15538, -49153, -1056),
new Location(17001, -49149, -1064)
};
private static final Location TRHONE = new Location(11025, -49152, -537);
private static final Location DUNGEON = new Location(11882, -49216, -3008);
private static final Location TELEPORT = new Location(12589, -49044, -3008);
private static final Location CUBE = new Location(12047, -49211, -3009);
private static final SkillHolder VENOM_STRIKE = new SkillHolder(4993, 1);
private static final SkillHolder SONIC_STORM = new SkillHolder(4994, 1);
private static final SkillHolder VENOM_TELEPORT = new SkillHolder(4995, 1);
private static final SkillHolder RANGE_TELEPORT = new SkillHolder(4996, 1);
private L2Npc _venom;
private L2Npc _massymore;
private Location _loc;
private boolean _aggroMode = false;
private boolean _prisonIsOpen = false;
// @formatter:off
private static final int[] TARGET_TELEPORTS_OFFSET =
{
650, 100, 100, 100, 100, 650, 200, 200, 200, 200, 200, 650
};
// @formatter:on
private static List<L2PcInstance> _targets = new ArrayList<>();
private Venom()
{
super(Venom.class.getSimpleName(), "ai/individual");
addStartNpc(DUNGEON_KEEPER, TELEPORT_CUBE);
addFirstTalkId(DUNGEON_KEEPER, TELEPORT_CUBE);
addTalkId(DUNGEON_KEEPER, TELEPORT_CUBE);
addSpawnId(VENOM, DUNGEON_KEEPER);
addSpellFinishedId(VENOM);
addAttackId(VENOM);
addKillId(VENOM);
addAggroRangeEnterId(VENOM);
setCastleSiegeStartId(this::onSiegeStart, CASTLE);
setCastleSiegeFinishId(this::onSiegeFinish, CASTLE);
final long currentTime = System.currentTimeMillis();
final long startSiegeDate = CastleManager.getInstance().getCastleById(CASTLE).getSiegeDate().getTimeInMillis();
final long openingDungeonDate = startSiegeDate - (HOURS_BEFORE * 360000);
if ((currentTime > openingDungeonDate) && (currentTime < startSiegeDate))
{
_prisonIsOpen = true;
}
}
@Override
public String onTalk(L2Npc npc, L2PcInstance talker)
{
switch (npc.getId())
{
case TELEPORT_CUBE:
{
talker.teleToLocation(TeleportWhereType.TOWN);
break;
}
case DUNGEON_KEEPER:
{
if (_prisonIsOpen)
{
talker.teleToLocation(TELEPORT);
}
else
{
return "35506-02.html";
}
break;
}
}
return super.onTalk(npc, talker);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "tower_check":
if (CastleManager.getInstance().getCastleById(CASTLE).getSiege().getControlTowerCount() <= 1)
{
changeLocation(MoveTo.THRONE);
broadcastNpcSay(_massymore, Say2.NPC_SHOUT, NpcStringId.OH_NO_THE_DEFENSES_HAVE_FAILED_IT_IS_TOO_DANGEROUS_TO_REMAIN_INSIDE_THE_CASTLE_FLEE_EVERY_MAN_FOR_HIMSELF);
cancelQuestTimer("tower_check", npc, null);
startQuestTimer("raid_check", 10000, npc, null, true);
}
break;
case "raid_check":
if (!npc.isInsideZone(ZoneId.SIEGE) && !npc.isTeleporting())
{
npc.teleToLocation(_loc);
}
break;
case "cube_despawn":
if (npc != null)
{
npc.deleteMe();
}
break;
}
return event;
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
if (isSummon)
{
return super.onAggroRangeEnter(npc, player, isSummon);
}
if (_aggroMode && (_targets.size() < 10) && (getRandom(3) < 1) && !player.isDead())
{
_targets.add(player);
}
return super.onAggroRangeEnter(npc, player, isSummon);
}
public void onSiegeStart(OnCastleSiegeStart event)
{
_aggroMode = true;
_prisonIsOpen = false;
if ((_venom != null) && !_venom.isDead())
{
_venom.setCurrentHp(_venom.getMaxHp());
_venom.setCurrentMp(_venom.getMaxMp());
_venom.enableSkill(VENOM_TELEPORT.getSkill());
_venom.enableSkill(RANGE_TELEPORT.getSkill());
startQuestTimer("tower_check", 30000, _venom, null, true);
}
}
public void onSiegeFinish(OnCastleSiegeFinish event)
{
_aggroMode = false;
if ((_venom != null) && !_venom.isDead())
{
changeLocation(MoveTo.PRISON);
_venom.disableSkill(VENOM_TELEPORT.getSkill(), -1);
_venom.disableSkill(RANGE_TELEPORT.getSkill(), -1);
}
updateStatus(ALIVE);
cancelQuestTimer("tower_check", _venom, null);
cancelQuestTimer("raid_check", _venom, null);
}
@Override
public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
{
switch (skill.getId())
{
case 4222:
npc.teleToLocation(_loc);
break;
case 4995:
teleportTarget(player);
((L2Attackable) npc).stopHating(player);
break;
case 4996:
teleportTarget(player);
((L2Attackable) npc).stopHating(player);
if ((_targets != null) && (_targets.size() > 0))
{
for (L2PcInstance target : _targets)
{
final long x = player.getX() - target.getX();
final long y = player.getY() - target.getY();
final long z = player.getZ() - target.getZ();
final long range = 250;
if (((x * x) + (y * y) + (z * z)) <= (range * range))
{
teleportTarget(target);
((L2Attackable) npc).stopHating(target);
}
}
_targets.clear();
}
break;
}
return super.onSpellFinished(npc, player, skill);
}
@Override
public final String onSpawn(L2Npc npc)
{
switch (npc.getId())
{
case DUNGEON_KEEPER:
{
_massymore = npc;
break;
}
case VENOM:
{
_venom = npc;
_loc = _venom.getLocation();
_venom.disableSkill(VENOM_TELEPORT.getSkill(), -1);
_venom.disableSkill(RANGE_TELEPORT.getSkill(), -1);
_venom.doRevive();
broadcastNpcSay(npc, Say2.NPC_SHOUT, NpcStringId.WHO_DARES_TO_COVET_THE_THRONE_OF_OUR_CASTLE_LEAVE_IMMEDIATELY_OR_YOU_WILL_PAY_THE_PRICE_OF_YOUR_AUDACITY_WITH_YOUR_VERY_OWN_BLOOD);
((L2Attackable) _venom).setCanReturnToSpawnPoint(false);
if (checkStatus() == DEAD)
{
_venom.deleteMe();
}
break;
}
}
if (checkStatus() == DEAD)
{
npc.deleteMe();
}
else
{
npc.doRevive();
}
return super.onSpawn(npc);
}
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
{
final double distance = npc.calculateDistance(attacker, false, false);
if (_aggroMode && (getRandom(100) < 25))
{
npc.setTarget(attacker);
npc.doCast(VENOM_TELEPORT.getSkill());
}
else if (_aggroMode && (npc.getCurrentHp() < (npc.getMaxHp() / 3)) && (getRandom(100) < 25) && !npc.isCastingNow())
{
npc.setTarget(attacker);
npc.doCast(RANGE_TELEPORT.getSkill());
}
else if ((distance > 300) && (getRandom(100) < 10) && !npc.isCastingNow())
{
npc.setTarget(attacker);
npc.doCast(VENOM_STRIKE.getSkill());
}
else if ((getRandom(100) < 10) && !npc.isCastingNow())
{
npc.setTarget(attacker);
npc.doCast(SONIC_STORM.getSkill());
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
updateStatus(DEAD);
broadcastNpcSay(npc, Say2.NPC_SHOUT, NpcStringId.IT_S_NOT_OVER_YET_IT_WON_T_BE_OVER_LIKE_THIS_NEVER);
if (!CastleManager.getInstance().getCastleById(CASTLE).getSiege().isInProgress())
{
L2Npc cube = addSpawn(TELEPORT_CUBE, CUBE, false, 0);
startQuestTimer("cube_despawn", 120000, cube, null);
}
cancelQuestTimer("raid_check", npc, null);
return super.onKill(npc, killer, isSummon);
}
/**
* Alters the Venom location
* @param loc enum
*/
private void changeLocation(MoveTo loc)
{
switch (loc)
{
case THRONE:
_venom.teleToLocation(TRHONE, false);
break;
case PRISON:
if ((_venom == null) || _venom.isDead() || _venom.isDecayed())
{
_venom = addSpawn(VENOM, DUNGEON, false, 0);
}
else
{
_venom.teleToLocation(DUNGEON, false);
}
cancelQuestTimer("raid_check", _venom, null);
cancelQuestTimer("tower_check", _venom, null);
break;
}
_loc.setLocation(_venom.getLocation());
}
private void teleportTarget(L2PcInstance player)
{
if ((player != null) && !player.isDead())
{
final int rnd = getRandom(11);
player.teleToLocation(TARGET_TELEPORTS[rnd], TARGET_TELEPORTS_OFFSET[rnd]);
player.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
}
}
/**
* Checks if Venom is Alive or Dead
* @return status
*/
private int checkStatus()
{
int checkStatus = ALIVE;
if (GlobalVariablesManager.getInstance().hasVariable("VenomStatus"))
{
checkStatus = GlobalVariablesManager.getInstance().getInt("VenomStatus");
}
else
{
GlobalVariablesManager.getInstance().set("VenomStatus", 0);
}
return checkStatus;
}
/**
* Update the Venom status
* @param status the new status. 0 = ALIVE, 1 = DEAD.
*/
private void updateStatus(int status)
{
GlobalVariablesManager.getInstance().set("VenomStatus", Integer.toString(status));
}
private enum MoveTo
{
THRONE,
PRISON
}
public static void main(String[] args)
{
new Venom();
}
}

View File

@@ -0,0 +1,13 @@
Individual AI:
This folder contains AI scripts for single npc templates (one npc ID, but possibly many instances).
That is, if a particular NPC/mob has a unique AI or something slightly different from all other generic NPCs,
an individual AI script can be created for all occurences of that npc/mob. Such individual scripts ought to be here.
Individual AI scripts can be subclassed. In other words, an individual may inherit from a group or other individual.
For example, one group template might define mobs that cast spells. A particular mob may cast spells but may also
talk whenever it gets attacked. In that case, instead of writing all the AI for attacking and casting spells, it may
inherit from a group template that defines AI for ALL mobs that cast spells, then add behaviours for talking onAttack.
"NPC registrations" refers to the addition of NPCs in the various events of the scripts, such as onAttack, onKill, etc
Those are done by using keywords such as "addKillId" etc. For more details on registrations, see
"scripts/quests/documentation.txt"