Sync with L2JServer Jan 24th 2015.

This commit is contained in:
mobius
2015-01-24 20:02:32 +00:00
parent d349bd3924
commit 1c6301c46d
1012 changed files with 23069 additions and 6307 deletions

View File

@@ -27,15 +27,12 @@ import quests.Q00020_BringUpWithLove.Q00020_BringUpWithLove;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.L2Object;
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.actor.instance.L2TamedBeastInstance;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.serverpackets.NpcInfo;
@@ -254,8 +251,7 @@ public final class BeastFarm extends AbstractNpcAI
// player might have and initialize the Tamed Beast.
if (Util.contains(TAMED_BEASTS, nextNpcId))
{
L2NpcTemplate template = NpcData.getInstance().getTemplate(nextNpcId);
L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(IdFactory.getInstance().getNextId(), template, player, food, npc.getX(), npc.getY(), npc.getZ(), true);
final L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(nextNpcId, player, food, npc.getX(), npc.getY(), npc.getZ(), true);
TamedBeast beast = TAMED_BEAST_DATA.get(getRandom(TAMED_BEAST_DATA.size()));
String name = beast.getName();

View File

@@ -174,7 +174,7 @@ public final class DragonValley extends AbstractNpcAI
final int rnd = getRandom(3, 5);
for (int i = 0; i < rnd; i++)
{
final L2Playable playable = isSummon ? attacker.getSummon() : attacker;
final L2Playable playable = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
final L2Npc minion = addSpawn(DRAKOS_ASSASSIN, npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), true, 0, true);
addAttackPlayerDesire(minion, playable);
}
@@ -276,7 +276,7 @@ public final class DragonValley extends AbstractNpcAI
if ((npc.getScriptValue() < 2) && (getRandom(100) < chance))
{
int val = npc.getScriptValue();
final L2Playable attacker = isSummon ? player.getSummon() : player;
final L2Playable attacker = isSummon ? player.getServitors().values().stream().findFirst().orElse(player.getPet()) : player;
final L2Npc ghost1 = addSpawn(EXPLODING_ORC_GHOST, npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), false, 0, true);
ghost1.getVariables().set("playable", attacker);
addAttackPlayerDesire(ghost1, attacker);

View File

@@ -63,7 +63,7 @@ public class FairyTrees extends AbstractNpcAI
for (int i = 0; i < 20; i++)
{
final L2Npc guardian = addSpawn(SOUL_GUARDIAN, npc, false, 30000);
final L2Playable attacker = isSummon ? killer.getSummon() : killer;
final L2Playable attacker = isSummon ? killer.getServitors().values().stream().findFirst().orElse(killer.getPet()) : killer;
addAttackPlayerDesire(guardian, attacker);
if (getRandomBoolean())
{

View File

@@ -22,17 +22,15 @@ import java.util.Map;
import javolution.util.FastMap;
import quests.Q00020_BringUpWithLove.Q00020_BringUpWithLove;
import quests.Q00655_AGrandPlanForTamingWildBeasts.Q00655_AGrandPlanForTamingWildBeasts;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.L2Object;
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.actor.instance.L2TamedBeastInstance;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
@@ -49,10 +47,20 @@ public final class FeedableBeasts extends AbstractNpcAI
private static final int SKILL_GOLDEN_SPICE = 2188;
private static final int SKILL_CRYSTAL_SPICE = 2189;
private static final int FOODSKILLDIFF = GOLDEN_SPICE - SKILL_GOLDEN_SPICE;
// Tamed Wild Beasts
private static final int TRAINED_BUFFALO1 = 16013;
private static final int TRAINED_BUFFALO2 = 16014;
private static final int TRAINED_COUGAR1 = 16015;
private static final int TRAINED_COUGAR2 = 16016;
private static final int TRAINED_KOOKABURRA1 = 16017;
private static final int TRAINED_KOOKABURRA2 = 16018;
// private static final int TRAINED_TINY_BABY_BUFFALO = 16020; // TODO: Implement.
// private static final int TRAINED_TINY_BABY_COUGAR = 16022; // TODO: Implement.
// private static final int TRAINED_TINY_BABY_KOOKABURRA = 16024; // TODO: Implement.
// @formatter:off
private static final int[] TAMED_BEASTS =
{
16013, 16014, 16015, 16016, 16017, 16018
TRAINED_BUFFALO1, TRAINED_BUFFALO2, TRAINED_COUGAR1, TRAINED_COUGAR2, TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2
};
// all mobs that can eat...
private static final int[] FEEDABLE_BEASTS =
@@ -63,7 +71,7 @@ public final class FeedableBeasts extends AbstractNpcAI
21481, 21482, 21483, 21484, 21485, 21486, 21487, 21488, 21489, 21490,
21491, 21492, 21493, 21494, 21495, 21496, 21497, 21498, 21499, 21500,
21501, 21502, 21503, 21504, 21505, 21506, 21507, 21824, 21825, 21826,
21827, 21828, 21829, 16013, 16014, 16015, 16016, 16017, 16018
21827, 21828, 21829, TRAINED_BUFFALO1, TRAINED_BUFFALO2, TRAINED_COUGAR1, TRAINED_COUGAR2, TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2
};
// @formatter:on
@@ -186,8 +194,8 @@ public final class FeedableBeasts extends AbstractNpcAI
final int[][] Kookabura_1_Gold_2 = {{ 21461, 21463 }};
final int[][] Kookabura_1_Crystal_1 = {{ 21464, 21466 }};
final int[][] Kookabura_1_Crystal_2 = {{ 21465, 21467 }};
final int[][] Kookabura_2_1 = {{ 21468, 21824}, { 16017, 16018 }};
final int[][] Kookabura_2_2 = {{ 21469, 21825}, { 16017, 16018 }};
final int[][] Kookabura_2_1 = {{ 21468, 21824}, { TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2 }};
final int[][] Kookabura_2_2 = {{ 21469, 21825}, { TRAINED_KOOKABURRA1, TRAINED_KOOKABURRA2 }};
final int[][] Buffalo_0_Gold = {{ 21471, 21472, 21473, 21474 }};
final int[][] Buffalo_0_Crystal = {{ 21475, 21476, 21477, 21478 }};
@@ -195,17 +203,17 @@ public final class FeedableBeasts extends AbstractNpcAI
final int[][] Buffalo_1_Gold_2 = {{ 21481, 21482 }};
final int[][] Buffalo_1_Crystal_1 = {{ 21483, 21485 }};
final int[][] Buffalo_1_Crystal_2 = {{ 21484, 21486 }};
final int[][] Buffalo_2_1 = {{ 21487,21826}, {16013, 16014 }};
final int[][] Buffalo_2_2 = {{ 21488,21827}, {16013, 16014 }};
final int[][] Buffalo_2_1 = {{ 21487, 21826}, {TRAINED_BUFFALO1, TRAINED_BUFFALO2 }};
final int[][] Buffalo_2_2 = {{ 21488, 21827}, {TRAINED_BUFFALO1, TRAINED_BUFFALO2 }};
final int[][] Cougar_0_Gold = {{ 21490, 21491, 21492, 21493 }};
final int[][] Cougar_0_Crystal = {{ 21494,21495, 21496, 21497 }};
final int[][] Cougar_0_Crystal = {{ 21494, 21495, 21496, 21497 }};
final int[][] Cougar_1_Gold_1 = {{ 21498, 21500 }};
final int[][] Cougar_1_Gold_2 = {{ 21499, 21501 }};
final int[][] Cougar_1_Crystal_1 = {{ 21502,21504 }};
final int[][] Cougar_1_Crystal_2 = {{ 21503,21505 }};
final int[][] Cougar_2_1 = {{ 21506, 21828 }, { 16015,16016 }};
final int[][] Cougar_2_2 = {{ 21507, 21829 }, { 16015,16016 }};
final int[][] Cougar_1_Crystal_1 = {{ 21502, 21504 }};
final int[][] Cougar_1_Crystal_2 = {{ 21503, 21505 }};
final int[][] Cougar_2_1 = {{ 21506, 21828 }, { TRAINED_COUGAR1, TRAINED_COUGAR2 }};
final int[][] Cougar_2_2 = {{ 21507, 21829 }, { TRAINED_COUGAR1, TRAINED_COUGAR2 }};
//@formatter:on
// Alpen Kookabura
@@ -422,11 +430,13 @@ public final class FeedableBeasts extends AbstractNpcAI
}
}
L2NpcTemplate template = NpcData.getInstance().getTemplate(nextNpcId);
L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(IdFactory.getInstance().getNextId(), template, player, food - FOODSKILLDIFF, npc.getX(), npc.getY(), npc.getZ());
final L2TamedBeastInstance nextNpc = new L2TamedBeastInstance(nextNpcId, player, food - FOODSKILLDIFF, npc.getX(), npc.getY(), npc.getZ());
nextNpc.setRunning();
Q00020_BringUpWithLove.checkJewelOfInnocence(player);
// Support for A Grand Plan for Taming Wild Beasts (655) quest.
Q00655_AGrandPlanForTamingWildBeasts.reward(player, nextNpc);
// also, perform a rare random chat
if (getRandom(20) == 0)
{

View File

@@ -20,7 +20,6 @@ package ai.group_template;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.Location;
@@ -67,22 +66,14 @@ public final class FleeMonsters extends AbstractNpcAI
npc.disableCoreAI(true);
npc.setRunning();
final L2Summon summon = isSummon ? attacker.getSummon() : null;
final L2Summon summon = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : null;
final ILocational attackerLoc = summon == null ? attacker : summon;
final double radians = Math.toRadians(Util.calculateAngleFrom(attackerLoc, npc));
final int posX = (int) (npc.getX() + (FLEE_DISTANCE * Math.cos(radians)));
final int posY = (int) (npc.getY() + (FLEE_DISTANCE * Math.sin(radians)));
final int posZ = npc.getZ();
final Location destination;
if (Config.GEODATA > 0)
{
destination = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), posX, posY, posZ, attacker.getInstanceId());
}
else
{
destination = new Location(posX, posY, posZ);
}
final Location destination = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), posX, posY, posZ, attacker.getInstanceId());
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, destination);
return super.onAttack(npc, attacker, damage, isSummon);
}

View File

@@ -103,7 +103,7 @@ public final class PolymorphingOnAttack extends AbstractNpcAI
}
npc.deleteMe();
final L2Attackable newNpc = (L2Attackable) addSpawn(tmp.get(0), npc.getX(), npc.getY(), npc.getZ() + 10, npc.getHeading(), false, 0, true);
final L2Character originalAttacker = isSummon ? attacker.getSummon() : attacker;
final L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
newNpc.setRunning();
newNpc.addDamageHate(originalAttacker, 0, 500);
newNpc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, originalAttacker);

View File

@@ -326,7 +326,7 @@ public final class PrimevalIsle extends AbstractNpcAI
if ((getRandom(100) <= 80) && npc.isScriptValue(0))
{
npc.setScriptValue(1);
final L2Playable playable = isSummon ? attacker.getSummon() : attacker;
final L2Playable playable = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
for (L2Character characters : npc.getKnownList().getKnownCharactersInRadius(500))
{
if ((characters != null) && (characters.isAttackable()) && (getRandomBoolean()))

View File

@@ -20,7 +20,7 @@ package ai.group_template;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
@@ -95,7 +95,7 @@ public final class RangeGuard extends AbstractNpcAI
@Override
public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
{
final L2Playable playable = (isSummon) ? attacker.getSummon() : attacker;
final L2Playable playable = (isSummon) ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : attacker;
final int longRangeGuardRate = npc.getTemplate().getParameters().getInt("LongRangeGuardRate");
final double distance = Util.calculateDistance(npc, playable, true, false);

View File

@@ -27,8 +27,8 @@ 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.data.xml.impl.DoorData;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.L2Object;
@@ -109,7 +109,7 @@ public final class Beleth extends AbstractNpcAI
{
GrandBossManager.getInstance().setBossStatus(29118, 0);
}
DoorTable.getInstance().getDoor(20240001).openMe();
DoorData.getInstance().getDoor(20240001).openMe();
}
protected static L2Npc spawn(int npcId, Location loc)
@@ -143,7 +143,7 @@ public final class Beleth extends AbstractNpcAI
public void run()
{
GrandBossManager.getInstance().setBossStatus(29118, 0);
DoorTable.getInstance().getDoor(20240001).openMe();
DoorData.getInstance().getDoor(20240001).openMe();
}
}
@@ -221,7 +221,7 @@ public final class Beleth extends AbstractNpcAI
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(6), 2500);
break;
case 6:
L2DoorInstance door = DoorTable.getInstance().getDoor(20240001);
L2DoorInstance door = DoorData.getInstance().getDoor(20240001);
door.closeMe();
ZONE.broadcastPacket(new StaticObject(door, false));
ZONE.broadcastPacket(new DoorStatusUpdate(door));
@@ -368,11 +368,11 @@ public final class Beleth extends AbstractNpcAI
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);
L2DoorInstance door2 = DoorData.getInstance().getDoor(20240002);
door2.openMe();
ZONE.broadcastPacket(new StaticObject(door2, false));
ZONE.broadcastPacket(new DoorStatusUpdate(door2));
DoorTable.getInstance().getDoor(20240003).openMe();
DoorData.getInstance().getDoor(20240003).openMe();
ThreadPoolManager.getInstance().scheduleGeneral(new Spawn(33), 4000);
break;
case 33:

View File

@@ -26,7 +26,7 @@ import javolution.util.FastSet;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
@@ -153,7 +153,7 @@ public final class DarkWaterDragon extends AbstractNpcAI
{
MY_TRACKING_SET.add(npcObjId);
// Spawn first 5 shades on first attack on Dark Water Dragon
L2Character originalAttacker = isSummon ? attacker.getSummon() : attacker;
L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : 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());
@@ -164,7 +164,7 @@ public final class DarkWaterDragon extends AbstractNpcAI
{
SECOND_SPAWN.add(npcObjId);
// Spawn second 5 shades on half hp of on Dark Water Dragon
L2Character originalAttacker = isSummon ? attacker.getSummon() : attacker;
L2Character originalAttacker = isSummon ? attacker.getServitors().values().stream().findFirst().orElse(attacker.getPet()) : 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());

View File

@@ -49,14 +49,14 @@ public final class DivineBeast extends AbstractNpcAI
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if ((player == null) || !player.hasServitor())
if ((player == null) || !player.hasServitors())
{
cancelQuestTimer(event, npc, player);
}
else if (player.getTransformationId() != TRANSFORMATION_ID)
{
cancelQuestTimer(event, npc, player);
player.getSummon().unSummon(player);
player.getServitors().values().forEach(summon -> summon.unSummon(player));
}
return super.onAdvEvent(event, npc, player);

View File

@@ -245,7 +245,7 @@ public final class Orfen extends AbstractNpcAI
{
if (npc.getId() == ORFEN)
{
L2Character originalCaster = isSummon ? caster.getSummon() : caster;
L2Character originalCaster = isSummon ? caster.getServitors().values().stream().findFirst().orElse(caster.getPet()) : caster;
if ((skill.getEffectPoint() > 0) && (getRandom(5) == 0) && npc.isInsideRadius(originalCaster, 1000, false, false))
{
NpcSay packet = new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), TEXT[getRandom(4)]);

View File

@@ -282,7 +282,7 @@ public final class QueenAnt extends AbstractNpcAI
if (isSummon)
{
isMage = false;
character = player.getSummon();
character = player.getServitors().values().stream().findFirst().orElse(player.getPet());
}
else
{

View File

@@ -53,12 +53,12 @@ public final class SinEater extends AbstractNpcAI
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
if (event.equals("TALK") && (player != null) && (player.getSummon() != null))
if (event.equals("TALK") && (player != null) && (player.getPet() != null))
{
if (getRandom(100) < 30)
{
final int random = getRandom(100);
final L2Summon summon = player.getSummon();
final L2Summon summon = player.getPet();
if (random < 20)
{

View File

@@ -45,32 +45,22 @@ public final class Acateo extends AbstractNpcAI
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
switch (event)
if (event.equals("give_circlet"))
{
case "give_circlet":
if (hasQuestItems(player, ACADEMY_CIRCLET))
{
if (hasQuestItems(player, ACADEMY_CIRCLET))
{
htmltext = "33905-3.html";
break;
}
giveItems(player, ACADEMY_CIRCLET, 1);
htmltext = "33905-2.html";
break;
return "33905-3.html";
}
giveItems(player, ACADEMY_CIRCLET, 1);
return "33905-2.html";
}
return htmltext;
return super.onAdvEvent(event, npc, player);
}
@Override
public String onFirstTalk(L2Npc npc, L2PcInstance player)
{
if (player.isAcademyMember())
{
return "33905-1.html";
}
return "33905.html";
return player.isAcademyMember() ? "33905-1.html" : "33905.html";
}
public static void main(String[] args)

View File

@@ -22,7 +22,7 @@ import java.util.List;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.datatables.SkillTreesData;
import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
import com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.L2SkillLearn;
import com.l2jserver.gameserver.model.actor.L2Npc;

View File

@@ -31,7 +31,7 @@ import com.l2jserver.gameserver.network.SystemMessageId;
* Arena Manager AI.
* @author St3eT
*/
public class ArenaManager extends AbstractNpcAI
public final class ArenaManager extends AbstractNpcAI
{
// NPCs
private static final int[] ARENA_MANAGER =
@@ -131,11 +131,11 @@ public class ArenaManager extends AbstractNpcAI
break;
}
}
return null;
return super.onAdvEvent(event, npc, player);
}
public static void main(String[] args)
{
new ArenaManager();
}
}
}

View File

@@ -23,9 +23,9 @@ import java.util.List;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.MultisellData;
import com.l2jserver.gameserver.data.xml.impl.MultisellData;
import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.datatables.SkillTreesData;
import com.l2jserver.gameserver.instancemanager.QuestManager;
import com.l2jserver.gameserver.model.L2SkillLearn;
import com.l2jserver.gameserver.model.actor.L2Npc;
@@ -48,7 +48,7 @@ import custom.Validators.SubClassSkills;
* Transformation skill learning and transformation scroll sell.
* @author Zoey76
*/
public class AvantGarde extends AbstractNpcAI
public final class AvantGarde extends AbstractNpcAI
{
// NPC
private static final int AVANT_GARDE = 32323;

View File

@@ -22,6 +22,7 @@ import quests.Q10338_SeizeYourDestiny.Q10338_SeizeYourDestiny;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
import com.l2jserver.gameserver.enums.CategoryType;
import com.l2jserver.gameserver.enums.UserInfoType;
import com.l2jserver.gameserver.model.actor.L2Npc;
@@ -36,6 +37,7 @@ import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerChang
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.AcquireSkillList;
import com.l2jserver.gameserver.network.serverpackets.ExChangeToAwakenedClass;
import com.l2jserver.gameserver.network.serverpackets.ExShowUsm;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
@@ -238,45 +240,47 @@ public final class AwakeningMaster extends AbstractNpcAI
int socialId = 21; // Sigel
int itemId = ABELIUS_POWER; // Sigel
if (player.isInCategory(CategoryType.TYRR_CANDIDATE))
if (player.isInCategory(CategoryType.TYRR_GROUP))
{
socialId = 22;
itemId = SAPYROS_POWER;
}
else if (player.isInCategory(CategoryType.OTHELL_CANDIDATE))
else if (player.isInCategory(CategoryType.OTHELL_GROUP))
{
socialId = 23;
itemId = ASHAGEN_POWER;
}
else if (player.isInCategory(CategoryType.YUL_CANDIDATE))
else if (player.isInCategory(CategoryType.YUL_GROUP))
{
socialId = 24;
itemId = CRANIGG_POWER;
}
else if (player.isInCategory(CategoryType.FEOH_CANDIDATE))
else if (player.isInCategory(CategoryType.FEOH_GROUP))
{
socialId = 25;
itemId = SOLTKREIG_POWER;
}
else if (player.isInCategory(CategoryType.ISS_CANDIDATE))
else if (player.isInCategory(CategoryType.ISS_GROUP))
{
socialId = 26;
itemId = NAVIAROPE_POWER;
}
else if (player.isInCategory(CategoryType.WYNN_CANDIDATE))
else if (player.isInCategory(CategoryType.WYNN_GROUP))
{
socialId = 27;
itemId = LEISTER_POWER;
}
else if (player.isInCategory(CategoryType.AEORE_CANDIDATE))
else if (player.isInCategory(CategoryType.AEORE_GROUP))
{
socialId = 28;
itemId = LAKCIS_POWER;
}
player.broadcastPacket(new SocialAction(player.getObjectId(), socialId));
player.addItem("Awakening", itemId, 1, player, true);
giveItems(player, itemId, 1);
// TODO: Remove skill which does not level up later are removed
SkillTreesData.getInstance().cleanSkillUponAwakening(player);
player.sendPacket(new AcquireSkillList(player));
player.sendSkillList();
}
ThreadPoolManager.getInstance().scheduleGeneral(() ->

View File

@@ -28,8 +28,8 @@ import java.util.StringTokenizer;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.datatables.TeleportLocationTable;
import com.l2jserver.gameserver.data.sql.impl.ClanTable;
import com.l2jserver.gameserver.data.sql.impl.TeleportLocationTable;
import com.l2jserver.gameserver.enums.CastleSide;
import com.l2jserver.gameserver.instancemanager.CastleManorManager;
import com.l2jserver.gameserver.instancemanager.FortManager;

View File

@@ -312,4 +312,4 @@ public final class CastleCourtMagician extends AbstractNpcAI
{
new CastleCourtMagician();
}
}
}

View File

@@ -30,8 +30,8 @@ import org.w3c.dom.Node;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.engines.DocumentParser;
import com.l2jserver.gameserver.data.xml.IXmlReader;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.L2Territory;
import com.l2jserver.gameserver.model.Location;
@@ -42,7 +42,7 @@ import com.l2jserver.util.Rnd;
* Tar Beetle zone spawn
* @author malyelfik
*/
public class TarBeetleSpawn implements DocumentParser
public class TarBeetleSpawn implements IXmlReader
{
private final List<SpawnZone> zones = new ArrayList<>();
private ScheduledFuture<?> spawnTask;

View File

@@ -1,6 +1,6 @@
<html><body>Blacksmith of Mammon:<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 778">Craft R-Grade Dual Weapon</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Mammons 31126-01.html">Bestow Special Ability on R-Grade Weapon</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_exc_multisell 779">Bestow Special Ability on R-Grade Weapon</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Mammons 31126-01.html">Change Special Ability of R-Grade Weapon</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest Mammons 31126-01.html">Change Special Ability of R95-Grade Weapon</Button>
</body></html>

View File

@@ -29,6 +29,8 @@ import com.l2jserver.Config;
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.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.util.Broadcast;
/**
@@ -116,6 +118,11 @@ public final class Mammons extends AbstractNpcAI
final L2Npc priest = addSpawn(MAMMONS[2], PRIEST_LOC[town]);
_mammons.addAll(Arrays.asList(blacksmith, merchant, priest));
if (blacksmith != null)
{
broadcastNpcSay(blacksmith, Say2.NPC_ALL, NpcStringId.I_HAVE_SOME_EXCELLENT_WEAPONS_TO_SHOW_YOU);
}
if (Config.ANNOUNCE_MAMMON_SPAWN)
{
Broadcast.toAllOnlinePlayers("Mammon's has been spawned in " + TOWN_NAME[town] + ".", false);

View File

@@ -29,7 +29,7 @@ import org.w3c.dom.Node;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.engines.DocumentParser;
import com.l2jserver.gameserver.data.xml.IXmlReader;
import com.l2jserver.gameserver.enums.CategoryType;
import com.l2jserver.gameserver.enums.MailType;
import com.l2jserver.gameserver.instancemanager.MailManager;
@@ -62,21 +62,18 @@ import com.l2jserver.gameserver.util.Util;
* Mentor Guide.
* @author Gnacik, UnAfraid
*/
public class MentorGuide extends AbstractNpcAI implements DocumentParser
public class MentorGuide extends AbstractNpcAI implements IXmlReader
{
// NPCs
private static final int MENTOR_GUIDE = 33587;
// ITEMs
// Items
private static final int MENTEE_CERT = 33800;
private static final int MENTEE_MARK = 33804;
private static final int MENTEE_HEADPHONE = 34759;
private static final int DIPLOMA = 33805;
// Misc
private static final int MAX_LEVEL = 85;
// SKILLs
// Skills
private final static SkillHolder[] MENTEE_BUFFS =
{
new SkillHolder(9227, 1), // Mentor's Poem of Horn
@@ -95,19 +92,21 @@ public class MentorGuide extends AbstractNpcAI implements DocumentParser
private static final SkillHolder MENTEE_MENTOR_SUMMON = new SkillHolder(9379, 1); // Mentee's Mentor Summon
// Misc
private static final int MAX_LEVEL = 85;
private static final String LEVEL_UP_TITLE = "Mentee coin from Mentee leveling";
private static final String LEVEL_UP_BODY = "Your mentee %s has reached level %d, so you are receiving some Mentee Coin. After Mentee Coin has successfully been removed and placed into your inventory please be sure to delete this letter. If your mailbox is full when any future letters are sent to you cannot be delivered and you will not receive these items.";
private static final String MENTEE_ADDED_TITLE = "Congratulations on becoming a mentee.";
private static final String MENTEE_ADDED_BODY = "Greetings. This is the Mentor Guide.\n\nYou will experience a world of unlimited adventures with your mentor, Exciting, isn't it?\n\nWhen you graduate from mentee status (upon awakening at level 85), you will receive a Mentee Certificate. If you bring it to me, I will give you a Diploma that you can exchange for R-grade equipment.";
private static final String MENTEE_GRADUATE_TITLE = "Congratulations on your graduation";
private static final String MENTEE_GRADUATE_BODY = "Greetings! This is the Mentor Guide.\nCongratulations! Did you enjoy the time with a mentor? Here is a Mentee Certificate for graduating.\n\nFind me in town, and I'll give you a Diploma if you show me your Mentee Certificatee. You'll also get a small graduation gift!\n\nNow, on to your next Adventure!";
static final Map<Integer, Integer> MENTEE_COINS = new HashMap<>();
@Override
public void load()
{
parseDatapackFile("config/MentorCoins.xml");
LOGGER.log(Level.INFO, MentorGuide.class.getSimpleName() + ": Loaded: " + MENTEE_COINS.size() + " mentee coins");
LOGGER.log(Level.INFO, getClass().getSimpleName() + ": Loaded: " + MENTEE_COINS.size() + " mentee coins");
}
@Override
@@ -137,6 +136,8 @@ public class MentorGuide extends AbstractNpcAI implements DocumentParser
addFirstTalkId(MENTOR_GUIDE);
addStartNpc(MENTOR_GUIDE);
addTalkId(MENTOR_GUIDE);
load();
}
@Override
@@ -420,8 +421,7 @@ public class MentorGuide extends AbstractNpcAI implements DocumentParser
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOUR_MENTOR_MENTEE_RELATIONSHIP_WITH_YOUR_MENTOR_S1_HAS_ENDED_AS_YOU_ARE_AN_AWAKENED_CHARACTER_OF_LV_85_OR_ABOVE_YOU_CAN_NO_LONGER_BE_PAIRED_WITH_A_MENTOR).addPcName(player));
// TODO: Find correct message!
sendMail(player, MENTEE_ADDED_TITLE, MENTEE_ADDED_BODY, MENTEE_CERT, 1);
sendMail(player, MENTEE_GRADUATE_TITLE, MENTEE_GRADUATE_BODY, MENTEE_CERT, 1);
}
}

View File

@@ -1,12 +1,8 @@
<html>
<head></head>
<body>
Monk of Chaos:<br>
The skills that were once given to each race to balance their power have been taken back. Through the will of Chaos, you can learn the skills of other races as long as you have a Chaos Pomander.<br>
Chaos Pomander is a crystal of power that can combine anything. If you have one, you have been selected by my master to work for a balanced world.<br>
Are you ready for that world? If so, select the Revelation of Chaos, and through it a power appropriate for you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest MonkOfChaos LearnRevelationSkills">Receive the Revelation of Chaos.</Button><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest MonkOfChaos CancelRevelationSkills">Reset the Revelation skill.(100,000,000 Adena)</Button><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest MonkOfChaos 33880-2.html">"Who are Monks of Chaos?"</Button><br>
</body>
</html>
<html><body>Monk of Chaos:<br>
The skills that were once given to each race to balance their power have been taken back. Through the will of Chaos, you can learn the skills of other races as long as you have a Chaos Pomander.<br>
Chaos Pomander is a crystal of power that can combine anything. If you have one, you have been selected by my master to work for a balanced world.<br>
Are you ready for that world? If so, select the Revelation of Chaos, and through it a power appropriate for you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest MonkOfChaos LearnRevelationSkills">Receive the Revelation of Chaos.</Button><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest MonkOfChaos CancelRevelationSkills">Reset the Revelation skill.(100,000,000 Adena)</Button><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest MonkOfChaos 33880-2.html">"Who are Monks of Chaos?"</Button><br>
</body></html>

View File

@@ -1,10 +1,6 @@
<html>
<head></head>
<body>
Monk of Chaos:<br>
We, the Monks of Chaos, serve the balance.<br>
You may think chaos is a destructive force, but nothing could be further from the truth.
<font color="LEVEL">Chaos</font> seeks to balance light and darkness by reverting them to the original energies.<br>
We who respect his will are the only ones truly free to act on it.
</body>
</html>
<html><body>Monk of Chaos:<br>
We, the Monks of Chaos, serve the balance.<br>
You may think chaos is a destructive force, but nothing could be further from the truth.
<font color="LEVEL">Chaos</font> seeks to balance light and darkness by reverting them to the original energies.<br>
We who respect his will are the only ones truly free to act on it.
</body></html>

View File

@@ -1,8 +1,6 @@
<html>
<head></head>
<body>Monk of Chaos:<br>
Nothing could be created or destroyed without chaos. It is the beginning and the end of all things.<br>
We, the Monks of Chaos, understand this. It is the law of the universe.<br>
If you wish, we will reveal our master's will to you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest MonkOfChaos 33880-1.html">"So tell me about this Revelation of Chaos."</Button></body>
</html>
<html><body>Monk of Chaos:<br>
Nothing could be created or destroyed without chaos. It is the beginning and the end of all things.<br>
We, the Monks of Chaos, understand this. It is the law of the universe.<br>
If you wish, we will reveal our master's will to you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest MonkOfChaos 33880-1.html">"So tell me about this Revelation of Chaos."</Button>
</body></html>

View File

@@ -22,8 +22,8 @@ import java.util.List;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.datatables.SkillTreesData;
import com.l2jserver.gameserver.enums.CategoryType;
import com.l2jserver.gameserver.enums.SubclassType;
import com.l2jserver.gameserver.model.L2SkillLearn;
@@ -35,9 +35,10 @@ import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExAcquirableSkillListByClass;
/**
* Monk of Chaos AI.
* @author Sdw
*/
public class MonkOfChaos extends AbstractNpcAI
public final class MonkOfChaos extends AbstractNpcAI
{
private static final int MONK_OF_CHAOS = 33880;
private static final int MIN_LEVEL = 85;
@@ -177,4 +178,4 @@ public class MonkOfChaos extends AbstractNpcAI
{
new MonkOfChaos();
}
}
}

View File

@@ -1,7 +1,3 @@
<html>
<head></head>
<body>
Monk of Chaos:<br>
Heh! The Revelation of Chaos has been canceled. But you can pass it again when you come back to your senses.
</body>
</html>
<html><body>Monk of Chaos:<br>
Heh! The Revelation of Chaos has been canceled. But you can pass it again when you come back to your senses.
</body></html>

View File

@@ -1,8 +1,4 @@
<html>
<head></head>
<body>
Monk of Chaos:<br>
You do not have enough <font color="level">Adena</font> to cancel the Revelation of Chaos.<br>
Come back another time.
</body>
</html>
<html><body>Monk of Chaos:<br>
You do not have enough <font color="level">Adena</font> to cancel the Revelation of Chaos.<br>
Come back another time.
</body></html>

View File

@@ -1,8 +1,4 @@
<html>
<head></head>
<body>
Monk of Chaos:<br>
You cannot cancel the Revelation of Chaos, because you have not passed it.<br>
Come back another time.
</body>
</html>
<html><body>Monk of Chaos:<br>
You cannot cancel the Revelation of Chaos, because you have not passed it.<br>
Come back another time.
</body></html>

View File

@@ -1,9 +1,5 @@
<html>
<head></head>
<body>
Monk of Chaos:<br>
You are not strong enough to fulfill the Revelation of Chaos.<br>
Come back another time.<br>
(Available only to Awaken characters level 85 or above.)
</body>
</html>
<html><body>Monk of Chaos:<br>
You are not strong enough to fulfill the Revelation of Chaos.<br>
Come back another time.<br>
(Available only to Awaken characters level 85 or above.)
</body></html>

View File

@@ -1,9 +1,5 @@
<html>
<head></head>
<body>
Monk of Chaos:<br>
The skills that weYou are not strong enough to fulfill the Revelation of Chaos.<br>
Come back another time. <br>
(Not available on subclasses.)
</body>
</html>
<html><body>Monk of Chaos:<br>
The skills that weYou are not strong enough to fulfill the Revelation of Chaos.<br>
Come back another time.<br>
(Not available on subclasses.)
</body></html>

View File

@@ -28,13 +28,13 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jserver.gameserver.engines.DocumentParser;
import com.l2jserver.gameserver.data.xml.IXmlReader;
import com.l2jserver.gameserver.model.StatsSet;
/**
* @author UnAfraid
*/
public class NpcBuffersData implements DocumentParser
public class NpcBuffersData implements IXmlReader
{
private final Map<Integer, NpcBufferData> _npcBuffers = new HashMap<>();

View File

@@ -65,7 +65,7 @@ public final class Proclaimer extends AbstractNpcAI
String htmltext = null;
if (!player.isOnDarkSide())
{
player.sendPacket(new NpcSay(npc.getObjectId(), Say2.TELL, npc.getId(), NpcStringId.WHEN_THE_WORLD_PLUNGES_INTO_CHAOS_WE_WILL_NEED_YOUR_HELP_WE_HOPE_YOU_JOIN_US_WHEN_THE_TIME_COMES));
player.sendPacket(new NpcSay(npc.getObjectId(), Say2.NPC_TELL, npc.getId(), NpcStringId.WHEN_THE_WORLD_PLUNGES_INTO_CHAOS_WE_WILL_NEED_YOUR_HELP_WE_HOPE_YOU_JOIN_US_WHEN_THE_TIME_COMES));
final L2Clan ownerClan = npc.getCastle().getOwner();
if (ownerClan != null)

View File

@@ -0,0 +1,9 @@
<html><head><body>Subclass/Dual Class Master Raina:<br>
So you need to <font color="LEVEL">create/reset a subclass</font>?<br>
<font color="af9878">A new class subclass starts at </font><font color="LEVEL">level 40</font><font color="af9878">.<br>
</font><Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addSubclass">"I'll add a new subclass (create new)."</Button><br>
(<font color="af9878">Change dual classes and your level will be </font><font color="LEVEL">reset to level 40</font><font color="af9878">.)<br>
</font><Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina removeSubclass">"I'll eliminate a subclass and add another one (reset)."</Button><br>
<font color="LEVEL">Maintain your level while changing classes</font><font color="af9878">.<br>
</font><Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina changeSubclass">"I'll change my subclass (requires Subclass Change Certificate)."</Button>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Subclass/Dual Class Master Raina:<br>
I heard that Ertheia are curious people. But a gem that absorbs power... I still can't help thinking that it's really dangerous. You could have died. <br>
But thanks to your efforts, even Ertheia can use the power of the giants now.<br>
But because you're different than the race from the Material Realm, your power will not merge with the giants'. Because they do not mingle, you will not be able to use your power while using the giants' power. Of course, you can use your original power instead of the giants' power anytime you wish.<br>
Now! Would you like to use the power of the giants?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina ertheiaDualClass">"Yes, on with a dual class!"</Button>
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Subclass/Dual Class Master Raina:<br>
Hello!<br1>
I will be assisting you with <font color="LEVEL">reawakening an Awakened dual class</font>.<br1>
To reawaken a dual class, you need to have an Awakened dual class. After reawakening, your level will be reduced to level 85, and all the skills you've learned will be forgotten.<br>
(<font color="af9878">Change dual classes and your level will be </font><font color="LEVEL">reset to level 85</font><font color="af9878"></font>).<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawekenDualclass">"I'll reawaken."</Button>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Subclass/Dual Class Master Raina:<br>
So you want to know about <font color="LEVEL">items designated for a dual class</font>?<br1>
They're for those who grow their dual class powers beyond imaginable limits.<br1>
You can purchase as many as you want, but <font color="LEVEL">you have to be at certain level with your main and dual classes in order to use them</font>.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 2027">"Let me take a look at the items for dual classes."</Button>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body> Subclass/Dual Class Master Raina:<br><br>
Hello!<br>
I'm collecting XP Bottles.<br>
I'll give you items if you bring me XP Bottles, how's that?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 857">"I have XP bottles right here."</Button>
</body> </html>

View File

@@ -0,0 +1,10 @@
<html><body>Subclass/Dual Class Master Raina:<br>
Hello!<br1>
You have a question about subclass or dual class?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina 33491-01.html">"Yeah. How do I create or reset a subclass?"</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina 33491-02.html">"I want to add a dual class." (for Ertheia only)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina 33491-03.html">"Can I reawaken my Awakened dual class?"</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina 33491-04.html">"So...what are the items for dual classes?" </Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina 33491-05.html">"What's with these XP Bottles?"</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -0,0 +1,866 @@
/*
* Copyright (C) 2004-2015 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.npc.Raina;
import static com.l2jserver.gameserver.model.base.ClassLevel.THIRD;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.data.xml.impl.CategoryData;
import com.l2jserver.gameserver.data.xml.impl.ClassListData;
import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
import com.l2jserver.gameserver.enums.CategoryType;
import com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.base.ClassId;
import com.l2jserver.gameserver.model.base.ClassLevel;
import com.l2jserver.gameserver.model.base.PlayerClass;
import com.l2jserver.gameserver.model.base.SubClass;
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.npc.OnNpcMenuSelect;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.AcquireSkillList;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
/**
* Raina AI.
* @author St3eT
*/
public final class Raina extends AbstractNpcAI
{
// NPC
private static final int RAINA = 33491;
// Items
private static final int SUBCLASS_CERTIFICATE = 30433;
private final static int ABELIUS_POWER = 32264;
private final static int SAPYROS_POWER = 32265;
private final static int ASHAGEN_POWER = 32266;
private final static int CRANIGG_POWER = 32267;
private final static int SOLTKREIG_POWER = 32268;
private final static int NAVIAROPE_POWER = 32269;
private final static int LEISTER_POWER = 32270;
private final static int LAKCIS_POWER = 32271;
// Misc
private static final Set<PlayerClass> mainSubclassSet;
private static final Set<PlayerClass> neverSubclassed = EnumSet.of(PlayerClass.Overlord, PlayerClass.Warsmith);
private static final Set<PlayerClass> subclasseSet1 = EnumSet.of(PlayerClass.DarkAvenger, PlayerClass.Paladin, PlayerClass.TempleKnight, PlayerClass.ShillienKnight);
private static final Set<PlayerClass> subclasseSet2 = EnumSet.of(PlayerClass.TreasureHunter, PlayerClass.AbyssWalker, PlayerClass.Plainswalker);
private static final Set<PlayerClass> subclasseSet3 = EnumSet.of(PlayerClass.Hawkeye, PlayerClass.SilverRanger, PlayerClass.PhantomRanger);
private static final Set<PlayerClass> subclasseSet4 = EnumSet.of(PlayerClass.Warlock, PlayerClass.ElementalSummoner, PlayerClass.PhantomSummoner);
private static final Set<PlayerClass> subclasseSet5 = EnumSet.of(PlayerClass.Sorceror, PlayerClass.Spellsinger, PlayerClass.Spellhowler);
private static final EnumMap<PlayerClass, Set<PlayerClass>> subclassSetMap = new EnumMap<>(PlayerClass.class);
static
{
final Set<PlayerClass> subclasses = PlayerClass.getSet(null, THIRD);
subclasses.removeAll(neverSubclassed);
mainSubclassSet = subclasses;
subclassSetMap.put(PlayerClass.DarkAvenger, subclasseSet1);
subclassSetMap.put(PlayerClass.Paladin, subclasseSet1);
subclassSetMap.put(PlayerClass.TempleKnight, subclasseSet1);
subclassSetMap.put(PlayerClass.ShillienKnight, subclasseSet1);
subclassSetMap.put(PlayerClass.TreasureHunter, subclasseSet2);
subclassSetMap.put(PlayerClass.AbyssWalker, subclasseSet2);
subclassSetMap.put(PlayerClass.Plainswalker, subclasseSet2);
subclassSetMap.put(PlayerClass.Hawkeye, subclasseSet3);
subclassSetMap.put(PlayerClass.SilverRanger, subclasseSet3);
subclassSetMap.put(PlayerClass.PhantomRanger, subclasseSet3);
subclassSetMap.put(PlayerClass.Warlock, subclasseSet4);
subclassSetMap.put(PlayerClass.ElementalSummoner, subclasseSet4);
subclassSetMap.put(PlayerClass.PhantomSummoner, subclasseSet4);
subclassSetMap.put(PlayerClass.Sorceror, subclasseSet5);
subclassSetMap.put(PlayerClass.Spellsinger, subclasseSet5);
subclassSetMap.put(PlayerClass.Spellhowler, subclasseSet5);
}
private static final Map<CategoryType, Integer> classCloak = new HashMap<>();
{
classCloak.put(CategoryType.SIGEL_GROUP, 30310); // Abelius Cloak
classCloak.put(CategoryType.TYRR_GROUP, 30311); // Sapyros Cloak Grade
classCloak.put(CategoryType.OTHELL_GROUP, 30312); // Ashagen Cloak Grade
classCloak.put(CategoryType.YUL_GROUP, 30313); // Cranigg Cloak Grade
classCloak.put(CategoryType.FEOH_GROUP, 30314); // Soltkreig Cloak Grade
classCloak.put(CategoryType.ISS_GROUP, 30315); // Naviarope Cloak Grade
classCloak.put(CategoryType.WYNN_GROUP, 30316); // Leister Cloak Grade
classCloak.put(CategoryType.AEORE_GROUP, 30317); // Laksis Cloak Grade
}
private static final List<PlayerClass> dualClassList = new ArrayList<>();
{
dualClassList.addAll(Arrays.asList(PlayerClass.sigelPhoenixKnight, PlayerClass.sigelHellKnight, PlayerClass.sigelEvasTemplar, PlayerClass.sigelShilenTemplar));
dualClassList.addAll(Arrays.asList(PlayerClass.tyrrDuelist, PlayerClass.tyrrDreadnought, PlayerClass.tyrrTitan, PlayerClass.tyrrGrandKhavatari, PlayerClass.tyrrDoombringer));
dualClassList.addAll(Arrays.asList(PlayerClass.othellAdventurer, PlayerClass.othellWindRider, PlayerClass.othellGhostHunter, PlayerClass.othellFortuneSeeker));
dualClassList.addAll(Arrays.asList(PlayerClass.yulSagittarius, PlayerClass.yulMoonlightSentinel, PlayerClass.yulGhostSentinel, PlayerClass.yulTrickster));
dualClassList.addAll(Arrays.asList(PlayerClass.feohArchmage, PlayerClass.feohSoultaker, PlayerClass.feohMysticMuse, PlayerClass.feoStormScreamer, PlayerClass.feohSoulHound));
dualClassList.addAll(Arrays.asList(PlayerClass.issHierophant, PlayerClass.issSwordMuse, PlayerClass.issSpectralDancer, PlayerClass.issDoomcryer));
dualClassList.addAll(Arrays.asList(PlayerClass.wynnArcanaLord, PlayerClass.wynnElementalMaster, PlayerClass.wynnSpectralMaster));
dualClassList.addAll(Arrays.asList(PlayerClass.aeoreCardinal, PlayerClass.aeoreEvaSaint, PlayerClass.aeoreShillienSaint));
}
// @formatter:off
private static final int[] REAWAKEN_PRICE =
{
100_000_000, 90_000_000, 80_000_000, 70_000_000, 60_000_000, 50_000_000, 40_000_000, 30_000_000, 20_000_000, 10_000_000
};
// @formatter:on
private Raina()
{
super(Raina.class.getSimpleName(), "ai/npc");
addStartNpc(RAINA);
addFirstTalkId(RAINA);
addTalkId(RAINA);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
String htmltext = null;
switch (event)
{
case "33491-01.html":
case "33491-02.html":
case "33491-03.html":
case "33491-04.html":
case "reawakenCancel.html":
{
htmltext = event;
break;
}
case "addSubclass":
{
if (player.isTransformed())
{
htmltext = "noTransform.html";
break;
}
else if (player.hasSummon())
{
htmltext = "noSummon.html";
break;
}
else if (player.getRace() == Race.ERTHEIA)
{
htmltext = "noErtheia.html";
break;
}
else if (!haveDoneQuest(player) && Config.ALT_GAME_SUBCLASS_WITHOUT_QUESTS && !player.isGM())
{
htmltext = "noQuest.html";
break;
}
else if (!hasAllSubclassLeveled(player) || (player.getTotalSubClasses() >= Config.MAX_SUBCLASS))
{
htmltext = "addFailed.html";
break;
}
else if (!player.isInventoryUnder90(true) || (player.getWeightPenalty() >= 2))
{
htmltext = "inventoryLimit.html";
break;
}
final Set<PlayerClass> availSubs = getAvailableSubClasses(player);
final StringBuilder sb = new StringBuilder();
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "subclassList.html");
if ((availSubs == null) || availSubs.isEmpty())
{
break;
}
for (PlayerClass subClass : availSubs)
{
if (subClass != null)
{
final int classId = subClass.ordinal();
final int npcStringId = 11170000 + classId;
sb.append("<fstring p1=\"0\" p2=\"" + classId + "\">" + npcStringId + "</fstring>");
}
}
html.replace("%subclassList%", sb.toString());
player.sendPacket(html);
break;
}
case "removeSubclass":
{
if (player.isTransformed())
{
htmltext = "noTransform.html";
break;
}
else if (player.hasSummon())
{
htmltext = "noSummon.html";
break;
}
else if (player.getRace() == Race.ERTHEIA)
{
htmltext = "noErtheia.html";
break;
}
else if (!player.isInventoryUnder90(true) || (player.getWeightPenalty() >= 2))
{
htmltext = "inventoryLimit.html";
break;
}
else if (player.getSubClasses().isEmpty())
{
htmltext = "noSubChange.html";
break;
}
final StringBuilder sb = new StringBuilder();
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "subclassRemoveList.html");
for (SubClass subClass : player.getSubClasses().values())
{
if (subClass != null)
{
final int classId = subClass.getClassId();
final int npcStringId = 11170000 + classId;
sb.append("<fstring p1=\"2\" p2=\"" + subClass.getClassIndex() + "\">" + npcStringId + "</fstring>");
}
}
html.replace("%removeList%", sb.toString());
player.sendPacket(html);
break;
}
case "changeSubclass":
{
if (player.isTransformed())
{
htmltext = "noTransform.html";
break;
}
else if (player.hasSummon())
{
htmltext = "noSummon.html";
break;
}
else if (player.getRace() == Race.ERTHEIA)
{
htmltext = "noErtheia.html";
break;
}
else if (player.getSubClasses().isEmpty())
{
htmltext = "noSubChange.html";
break;
}
else if (!hasQuestItems(player, SUBCLASS_CERTIFICATE))
{
htmltext = "noCertificate.html";
break;
}
player.sendMessage("Not done yet.");
break;
}
case "ertheiaDualClass":
{
if ((player.getRace() != Race.ERTHEIA) || (player.getLevel() < 85) || player.hasDualClass())
{
htmltext = "addDualClassErtheiaFailed.html";
break;
}
htmltext = "addDualClassErtheia.html";
break;
}
case "addDualClass_SIGEL_GROUP":
case "addDualClass_TYRR_GROUP":
case "addDualClass_OTHELL_GROUP":
case "addDualClass_YUL_GROUP":
case "addDualClass_FEOH_GROUP":
case "addDualClass_ISS_GROUP":
case "addDualClass_WYNN_GROUP":
case "addDualClass_AEORE_GROUP":
{
final CategoryType cType = CategoryType.valueOf(event.replace("addDualClass_", ""));
if (cType == null)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Cannot parse CategoryType, event: " + event);
}
final StringBuilder sb = new StringBuilder();
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "addDualClassErtheiaList.html");
for (PlayerClass dualClasses : getDualClasses(player, cType))
{
if (dualClasses != null)
{
sb.append("<button value=\"" + ClassListData.getInstance().getClass(dualClasses.ordinal()).getClassName() + "\" action=\"bypass -h menu_select?ask=6&reply=" + dualClasses.ordinal() + "\" width=\"200\" height=\"31\" back=\"L2UI_CT1.HtmlWnd_DF_Awake_Down\" fore=\"L2UI_CT1.HtmlWnd_DF_Awake\"><br>");
}
}
html.replace("%dualclassList%", sb.toString());
player.sendPacket(html);
break;
}
case "reawekenDualclass":
{
if (player.isTransformed())
{
htmltext = "noTransform.html";
break;
}
else if (player.hasSummon())
{
htmltext = "noSummon.html";
break;
}
else if (!player.hasDualClass() || !player.isDualClassActive() || (player.getClassId().level() != ClassLevel.AWAKEN.ordinal()))
{
htmltext = "reawakenNoDual.html";
break;
}
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "reawaken.html");
final int index = player.getLevel() > 94 ? REAWAKEN_PRICE.length - 1 : player.getLevel() - 85;
html.replace("%price%", REAWAKEN_PRICE[index]);
player.sendPacket(html);
break;
}
case "reawakenDualclassConfirm":
{
final int index = player.getLevel() > 94 ? REAWAKEN_PRICE.length - 1 : player.getLevel() - 85;
if (player.isTransformed())
{
htmltext = "noTransform.html";
break;
}
else if (player.hasSummon())
{
htmltext = "noSummon.html";
break;
}
else if (!player.hasDualClass() || !player.isDualClassActive() || (player.getClassId().level() != ClassLevel.AWAKEN.ordinal()))
{
htmltext = "reawakenNoDual.html";
break;
}
else if ((player.getAdena() < REAWAKEN_PRICE[index]) || !hasQuestItems(player, getCloakId(player)))
{
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "reawakenNoFee.html");
html.replace("%price%", REAWAKEN_PRICE[index]);
player.sendPacket(html);
break;
}
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "reawakenList.html");
player.sendPacket(html);
break;
}
case "reawaken_SIGEL_GROUP":
case "reawaken_TYRR_GROUP":
case "reawaken_OTHELL_GROUP":
case "reawaken_YUL_GROUP":
case "reawaken_FEOH_GROUP":
case "reawaken_ISS_GROUP":
case "reawaken_WYNN_GROUP":
case "reawaken_AEORE_GROUP":
{
final CategoryType cType = CategoryType.valueOf(event.replace("reawaken_", ""));
if (cType == null)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Cannot parse CategoryType, event: " + event);
}
final StringBuilder sb = new StringBuilder();
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "reawakenClassList.html");
for (PlayerClass dualClasses : getDualClasses(player, cType))
{
if (dualClasses != null)
{
sb.append("<button value=\"" + ClassListData.getInstance().getClass(dualClasses.ordinal()).getClassName() + "\" action=\"bypass -h menu_select?ask=5&reply=" + dualClasses.ordinal() + "\" width=\"200\" height=\"31\" back=\"L2UI_CT1.HtmlWnd_DF_Awake_Down\" fore=\"L2UI_CT1.HtmlWnd_DF_Awake\"><br>");
}
}
html.replace("%dualclassList%", sb.toString());
player.sendPacket(html);
break;
}
}
return htmltext;
}
@RegisterEvent(EventType.ON_NPC_MENU_SELECT)
@RegisterType(ListenerRegisterType.NPC)
@Id(RAINA)
public final void OnNpcMenuSelect(OnNpcMenuSelect event)
{
final L2PcInstance player = event.getTalker();
final L2Npc npc = event.getNpc();
final int ask = event.getAsk();
switch (ask)
{
case 0: // Add subclass confirm menu
{
final int classId = event.getReply();
final StringBuilder sb = new StringBuilder();
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "addConfirm.html");
if (!isValidNewSubClass(player, classId))
{
return;
}
final int npcStringId = 11170000 + classId;
sb.append("<fstring p1=\"1\" p2=\"" + classId + "\">" + npcStringId + "</fstring>");
html.replace("%confirmButton%", sb.toString());
player.sendPacket(html);
break;
}
case 1: // Add subclass
{
final int classId = event.getReply();
if (!isValidNewSubClass(player, classId))
{
return;
}
if (!player.addSubClass(classId, player.getTotalSubClasses() + 1, false))
{
return;
}
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "addSuccess.html");
player.setActiveClass(player.getTotalSubClasses());
player.sendPacket(SystemMessageId.THE_NEW_SUBCLASS_HAS_BEEN_ADDED);
player.sendPacket(html);
break;
}
case 2: // Remove (change) subclass list
{
final int subclassIndex = event.getReply();
final Set<PlayerClass> availSubs = getAvailableSubClasses(player);
final StringBuilder sb = new StringBuilder();
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "removeSubclassList.html");
if ((availSubs == null) || availSubs.isEmpty())
{
return;
}
for (PlayerClass subClass : availSubs)
{
if (subClass != null)
{
final int classId = subClass.ordinal();
final int npcStringId = 11170000 + classId;
sb.append("<fstring p1=\"3\" p2=\"" + classId + "\">" + npcStringId + "</fstring>");
}
}
npc.getVariables().set("SUBCLASS_INDEX_" + player.getObjectId(), subclassIndex);
html.replace("%subclassList%", sb.toString());
player.sendPacket(html);
break;
}
case 3: // Remove (change) subclass confirm menu
{
final int classId = event.getReply();
final int classIndex = npc.getVariables().getInt("SUBCLASS_INDEX_" + player.getObjectId(), -1);
if (classIndex < 0)
{
return;
}
final StringBuilder sb = new StringBuilder();
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "addConfirm2.html");
final int npcStringId = 11170000 + classId;
sb.append("<fstring p1=\"4\" p2=\"" + classId + "\">" + npcStringId + "</fstring>");
html.replace("%confirmButton%", sb.toString());
player.sendPacket(html);
break;
}
case 4: // Remove (change) subclass
{
final int classId = event.getReply();
final int classIndex = npc.getVariables().getInt("SUBCLASS_INDEX_" + player.getObjectId(), -1);
if (classIndex < 0)
{
return;
}
if (player.modifySubClass(classIndex, classId, false))
{
player.abortCast();
player.stopAllEffectsExceptThoseThatLastThroughDeath();
player.stopAllEffectsNotStayOnSubclassChange();
player.stopCubics();
player.setActiveClass(classIndex);
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "addSuccess.html");
player.sendPacket(html);
player.sendPacket(SystemMessageId.THE_NEW_SUBCLASS_HAS_BEEN_ADDED);
}
break;
}
case 5: // Reawaken (change dual class)
{
final int classId = event.getReply();
if (player.isTransformed() || player.hasSummon() || (!player.hasDualClass() || !player.isDualClassActive() || (player.getClassId().level() != ClassLevel.AWAKEN.ordinal())))
{
break;
}
// Validating classId
if (!getDualClasses(player, null).contains(PlayerClass.values()[classId]))
{
break;
}
final int index = player.getLevel() > 94 ? REAWAKEN_PRICE.length - 1 : player.getLevel() - 85;
if ((player.getAdena() < REAWAKEN_PRICE[index]) || !hasQuestItems(player, getCloakId(player)))
{
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "reawakenNoFee.html");
html.replace("%price%", REAWAKEN_PRICE[index]);
player.sendPacket(html);
break;
}
player.reduceAdena((getClass().getSimpleName() + "_Reawaken"), REAWAKEN_PRICE[index], npc, true);
takeItems(player, getCloakId(player), 1);
final int classIndex = player.getClassIndex();
if (player.modifySubClass(classIndex, classId, true))
{
player.abortCast();
player.stopAllEffectsExceptThoseThatLastThroughDeath();
player.stopAllEffectsNotStayOnSubclassChange();
player.stopCubics();
player.setActiveClass(classIndex);
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "reawakenSuccess.html");
player.sendPacket(html);
SkillTreesData.getInstance().cleanSkillUponAwakening(player);
player.sendPacket(new AcquireSkillList(player));
player.sendSkillList();
addPowerItem(player);
}
break;
}
case 6: // Add dual class for ertheia
{
final int classId = event.getReply();
if (player.isTransformed() || player.hasSummon())
{
break;
}
// Validating classId
if (!getDualClasses(player, null).contains(PlayerClass.values()[classId]))
{
break;
}
if (player.addSubClass(classId, player.getTotalSubClasses() + 1, true))
{
final NpcHtmlMessage html = getNpcHtmlMessage(player, npc, "addSuccess.html");
player.setActiveClass(player.getTotalSubClasses());
player.sendPacket(SystemMessageId.THE_NEW_SUBCLASS_HAS_BEEN_ADDED);
player.sendPacket(html);
SkillTreesData.getInstance().cleanSkillUponAwakening(player);
player.sendPacket(new AcquireSkillList(player));
player.sendSkillList();
addPowerItem(player);
}
break;
}
}
}
private void addPowerItem(L2PcInstance player)
{
int itemId = ABELIUS_POWER; // Sigel
if (player.isInCategory(CategoryType.TYRR_GROUP))
{
itemId = SAPYROS_POWER;
}
else if (player.isInCategory(CategoryType.OTHELL_GROUP))
{
itemId = ASHAGEN_POWER;
}
else if (player.isInCategory(CategoryType.YUL_GROUP))
{
itemId = CRANIGG_POWER;
}
else if (player.isInCategory(CategoryType.FEOH_GROUP))
{
itemId = SOLTKREIG_POWER;
}
else if (player.isInCategory(CategoryType.ISS_GROUP))
{
itemId = NAVIAROPE_POWER;
}
else if (player.isInCategory(CategoryType.WYNN_GROUP))
{
itemId = LEISTER_POWER;
}
else if (player.isInCategory(CategoryType.AEORE_GROUP))
{
itemId = LAKCIS_POWER;
}
giveItems(player, itemId, 1);
}
/**
* Returns list of available subclasses Base class and already used subclasses removed
* @param player
* @return
*/
private Set<PlayerClass> getAvailableSubClasses(L2PcInstance player)
{
final int currentBaseId = player.getBaseClass();
final ClassId baseCID = ClassId.getClassId(currentBaseId);
int baseClassId = (baseCID.level() > 2) ? baseCID.getParent().ordinal() : currentBaseId;
final Set<PlayerClass> availSubs = getSubclasses(player, baseClassId);
if ((availSubs != null) && !availSubs.isEmpty())
{
for (PlayerClass pclass : availSubs)
{
// scan for already used subclasses
final int availClassId = pclass.ordinal();
final ClassId cid = ClassId.getClassId(availClassId);
for (SubClass subList : player.getSubClasses().values())
{
final ClassId subId = ClassId.getClassId(subList.getClassId());
if (subId.equalsOrChildOf(cid))
{
availSubs.remove(cid);
break;
}
}
}
}
return availSubs;
}
private boolean haveDoneQuest(L2PcInstance player)
{
final QuestState qs = player.getQuestState("Q10385_RedThreadOfFate"); // TODO: Replace with class name
return qs == null ? false : qs.isCompleted();
}
/**
* Check new subclass classId for validity. Base class not added into allowed subclasses.
* @param player
* @param classId
* @return
*/
private boolean isValidNewSubClass(L2PcInstance player, int classId)
{
final ClassId cid = ClassId.values()[classId];
ClassId subClassId;
for (SubClass subList : player.getSubClasses().values())
{
subClassId = ClassId.values()[subList.getClassId()];
if (subClassId.equalsOrChildOf(cid))
{
return false;
}
}
// get player base class
final int currentBaseId = player.getBaseClass();
final ClassId baseCID = ClassId.getClassId(currentBaseId);
// we need 2nd occupation ID
final int baseClassId = baseCID.level() > 2 ? baseCID.getParent().ordinal() : currentBaseId;
final Set<PlayerClass> availSubs = getSubclasses(player, baseClassId);
if ((availSubs == null) || availSubs.isEmpty())
{
return false;
}
boolean found = false;
for (PlayerClass pclass : availSubs)
{
if (pclass.ordinal() == classId)
{
found = true;
break;
}
}
return found;
}
private boolean hasAllSubclassLeveled(L2PcInstance player)
{
boolean leveled = true;
for (SubClass sub : player.getSubClasses().values())
{
if ((sub != null) && (sub.getLevel() < 75))
{
leveled = false;
}
}
return leveled;
}
public final List<PlayerClass> getAvailableDualclasses(L2PcInstance player)
{
final List<PlayerClass> dualClasses = new ArrayList<>();
for (PlayerClass playerClass : PlayerClass.values())
{
if (!playerClass.isOfRace(Race.ERTHEIA) && playerClass.isOfLevel(ClassLevel.AWAKEN) && (playerClass.ordinal() != player.getClassId().getId()))
{
dualClasses.add(playerClass);
}
}
return dualClasses;
}
private List<PlayerClass> getDualClasses(L2PcInstance player, CategoryType cType)
{
final List<PlayerClass> tempList = new ArrayList<>();
final int baseClassId = player.getBaseClass();
final int dualClassId = player.getClassId().getId();
for (PlayerClass temp : dualClassList)
{
if ((temp.ordinal() != baseClassId) && (temp.ordinal() != dualClassId) && ((cType == null) || CategoryData.getInstance().isInCategory(cType, temp.ordinal())))
{
tempList.add(temp);
}
}
return tempList;
}
public final Set<PlayerClass> getSubclasses(L2PcInstance player, int classId)
{
Set<PlayerClass> subclasses = null;
final PlayerClass pClass = PlayerClass.values()[classId];
if ((pClass.getLevel() == ClassLevel.THIRD) || (pClass.getLevel() == ClassLevel.FOURTH))
{
subclasses = EnumSet.copyOf(mainSubclassSet);
subclasses.remove(this);
subclasses.removeAll(PlayerClass.getSet(Race.ERTHEIA, THIRD));
if (player.getRace() == Race.KAMAEL)
{
if (player.getAppearance().getSex())
{
subclasses.remove(PlayerClass.femaleSoulbreaker);
}
else
{
subclasses.remove(PlayerClass.maleSoulbreaker);
}
if (!player.getSubClasses().containsKey(2) || (player.getSubClasses().get(2).getLevel() < 75))
{
subclasses.remove(PlayerClass.inspector);
}
}
else
{
// Only Kamael can take Kamael classes as subclasses.
subclasses.removeAll(PlayerClass.getSet(Race.KAMAEL, THIRD));
}
Set<PlayerClass> unavailableClasses = subclassSetMap.get(this);
if (unavailableClasses != null)
{
subclasses.removeAll(unavailableClasses);
}
}
return subclasses;
}
private NpcHtmlMessage getNpcHtmlMessage(L2PcInstance player, L2Npc npc, String fileName)
{
final NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
html.setHtml(HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/scripts/ai/npc/Raina/" + fileName));
return html;
}
private int getCloakId(L2PcInstance player)
{
CategoryType catType = null;
if (player.isInCategory(CategoryType.SIGEL_GROUP))
{
catType = CategoryType.SIGEL_GROUP;
}
else if (player.isInCategory(CategoryType.TYRR_GROUP))
{
catType = CategoryType.TYRR_GROUP;
}
else if (player.isInCategory(CategoryType.OTHELL_GROUP))
{
catType = CategoryType.OTHELL_GROUP;
}
else if (player.isInCategory(CategoryType.YUL_GROUP))
{
catType = CategoryType.YUL_GROUP;
}
else if (player.isInCategory(CategoryType.FEOH_GROUP))
{
catType = CategoryType.FEOH_GROUP;
}
else if (player.isInCategory(CategoryType.ISS_GROUP))
{
catType = CategoryType.ISS_GROUP;
}
else if (player.isInCategory(CategoryType.WYNN_GROUP))
{
catType = CategoryType.WYNN_GROUP;
}
else if (player.isInCategory(CategoryType.AEORE_GROUP))
{
catType = CategoryType.AEORE_GROUP;
}
return classCloak.get(catType);
}
public static void main(String[] args)
{
new Raina();
}
}

View File

@@ -0,0 +1,6 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
The choice is no easy one.<br>
The new subclass will be a level 40, 2nd-transfer class. <br>
Are you sure you want to go ahead with this decision? <br>
%confirmButton%
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
The choice is no easy one.<br>
<font="LEVEL">The new subclass will have none of the skill enchants or the skills you learned through codices. Think carefully.</font><br>
Are you sure you want to go ahead with this decision? <br>
%confirmButton%
</body></html>

View File

@@ -0,0 +1,12 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
So, into which class would you like to Reawaken?<br>
Remember that if you proceed, you will go back to <font color="LEVEL">Lv. 85, and all your skills will be reset.</font><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addDualClass_SIGEL_GROUP">"I will change to the Knight class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addDualClass_TYRR_GROUP">"I will change to the Warrior class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addDualClass_OTHELL_GROUP">"I will change to the Rogue class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addDualClass_YUL_GROUP">"I will change to the Archer class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addDualClass_FEOH_GROUP">"I will change to the Wizard class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addDualClass_ISS_GROUP">"I will change to the Enchanter class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addDualClass_WYNN_GROUP">"I will change to the Summoner class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina addDualClass_AEORE_GROUP">"I will change to the Healer class."</Button>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
You do not meet the conditions to add a dual class.<br>
Come back when you're ready, or ask for something else.<br>
(Only Ertheia characters Lv. 85 or above may add a dual class once.)
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body scroll="no">
<table border=0 cellpadding=0 cellspacing=0 width=292 height=358 background="L2UI_CH3.refinewnd_back_Pattern">
<tr><td valign="top" align="center"><br><br><br><br>
These are the classes available to you.<br1>
You must choose which you want to be.<br><br>
%dualclassList%
</td></tr>
</table>
</body></html>

View File

@@ -0,0 +1,8 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
Sorry, but you're not qualified to add a subclass.<br1>
To add a new subclass, you need the following qualifications:<br>
First, <font color="LEVEL">you've completed the 'Red Thread of Fate' quest</font>. If you want to get on that, let me know.<br>
Second, <font color="LEVEL">your current class has done the 2nd class transfer, and all your subclass levels are 75 or higher</font>. For example, if your subclasses are Temple Knight and Silver Ranger, they must both be level 75 for you to add a third subclass.<br>
Third, you may only have <font color="LEVEL">up to 3 subclasses</font>, I'm afraid.<br>
Got it?
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
Congratulations!<br>
Your new subclass has been added.<br>
I look forward to your future endeavors with your new subclass!<br>
</body></html>

View File

@@ -0,0 +1,3 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
You need inventory space and free weight to create or renew a subclass. Go free up your weight and inventory to less than 80%, and I'll see what I can do.
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
You need a Subclass Change Certificate in order to receive the power of the gods. This was given to heroes long before Shilen's destructive rampages came about, so you can't find new ones anymore.<br>
But if you have the certificate, talk to me again as a subclass ready to receive the power of the gods.<br>
<font color="af9878">But a dual class isn't ready to receive the power of the gods, so I can't change classes for that.</font>
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
Ertheia cannot add or modify subclasses.<br>
Please talk to me when you're ready to add a dual class.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
You haven't completed the 'Red Thread of Fate' quest yet.<br>
To create a subclass, you have to <font color="LEVEL">complete the 'Red Thread of Fate' quest</font>. If you want to work on the quest, let me know.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
You don't have a subclass to change.<br>
Make a subclass.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
You cannot create a new subclass<br>
when there is a pet or servitor.
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
I cannot create a new subclass while you're transformed.<br>
Change back to your original form, then talk to me again.
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
You do not meet the conditions to add a dual class.<br>
Come back when you're ready, or ask for something else.<br>
(Only Ertheia characters Lv. 85 or above may add a dual class once.)
</body></html>

View File

@@ -0,0 +1,10 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
In order to reawaken your dual class,<br>
<font color="LEVEL">you need the cloak you received when you first awakened it,<br>
and some %price% Adena</font> to pay the fee.<br>
Upon reawakening, zou will lose zour current<br>
abilities, but gain new powers is exchange. You will be reducted to <font color="LEVEL">level 85, and all your skills will be reset.</font> You can choose the class you want, but <font color="LEVEL">you cannot receive powers from the same class as your main class</font>.<br>
<font color="af9878">(After reawakening, the 3rd skills provided will be based on human classes.)</font><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawakenDualclassConfirm">"I'll reawaken."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawakenCancel.html">"I will think about it."</Button>
</body></html>

View File

@@ -0,0 +1,5 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
I see.<br>
Make a carful decision because you will lose the power you have, to get new power.<br>
When you make up your mind, come back to me.
</body></html>

View File

@@ -0,0 +1,9 @@
<html><body scroll="no">
<table border=0 cellpadding=0 cellspacing=0 width=292 height=358 background="L2UI_CH3.refinewnd_back_Pattern">
<tr><td valign="top" align="center"><br><br><br><br>
These are the classes available to you.<br1>
You must choose which you want to be.<br><br>
%dualclassList%
</td></tr>
</table>
</body></html>

View File

@@ -0,0 +1,12 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
So, into which class would you like to Reawaken?<br>
Remember that if you proceed, you will go back to <font color="LEVEL">Lv. 85, and all your skills will be reset.</font><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawaken_SIGEL_GROUP">"I will change to the Knight class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawaken_TYRR_GROUP">"I will change to the Warrior class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawaken_OTHELL_GROUP">"I will change to the Rogue class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawaken_YUL_GROUP">"I will change to the Archer class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawaken_FEOH_GROUP">"I will change to the Wizard class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawaken_ISS_GROUP">"I will change to the Enchanter class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawaken_WYNN_GROUP">"I will change to the Summoner class."</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest Raina reawaken_AEORE_GROUP">"I will change to the Healer class."</Button>
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
You don't look like a Awakened dual class.<br>
If you want to Reawaken, you must be an <font color="LEVEL">Awakened dual class</font>.<br>
Please come find me when you have Awakened as a dual class.<br><br>
(You can become a specialized Awakened class through Hardin or the Giant's stone statue at the Reliquary of the Giants.)
</body></html>

View File

@@ -0,0 +1,6 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
To change your dual class,<br>
<font color="LEVEL">you need the cloak you received when you awakened your dual class,<br>
and %price% Adena</font> for a fee.<br>
Please come back with everything you need.
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
Which subclass would you like to change to?<br>
Please select a subclass from the list below.<br>
<font color="LEVEL">The new subclas will be a level 40, 2nd-transfer class with none of the skill enchants or the skills you learned through codices. Think carefully.</font><br>
Also, dual classes can't be reset.<br>
%subclassList%
</body></html>

View File

@@ -0,0 +1,4 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
Select a Subclass.<br><br>
%subclassList%
</body></html>

View File

@@ -0,0 +1,7 @@
<html><body>Subclass/Dual Class Master Raina:<br><br>
Which subclass would you like to change to?<br>
Please select a subclass from the list below.<br>
<font color="LEVEL">The new subclas will be a level 40, 2nd-transfer class with none of the skill enchants or the skills you learned through codices. Think carefully.</font><br>
Also, dual classes can't be reset.<br>
%removeList%
</body></html>

View File

@@ -21,6 +21,7 @@ package ai.npc.Rignos;
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.holders.SkillHolder;
@@ -64,10 +65,15 @@ public class Rignos extends AbstractNpcAI
npc.setScriptValue(1);
startQuestTimer("TIME_OUT", 1800000, npc, null);
TIMER.getSkill().applyEffects(player, player);
if (player.hasSummon())
final L2Summon pet = player.getPet();
if (pet != null)
{
TIMER.getSkill().applyEffects(player.getSummon(), player.getSummon());
TIMER.getSkill().applyEffects(pet, pet);
}
player.getServitors().values().forEach(s ->
{
TIMER.getSkill().applyEffects(s, s);
});
if (hasQuestItems(player, STAMP))
{

View File

@@ -26,8 +26,9 @@ import com.l2jserver.gameserver.model.actor.L2Npc;
* Scarecrow AI.
* @author ivantotov
*/
class Scarecrow extends AbstractNpcAI
public final class Scarecrow extends AbstractNpcAI
{
// NPCs
private static final int SCARECROW = 27457;
private static final int TRAINING_DUMMY = 19546;

View File

@@ -23,7 +23,7 @@ import java.util.Map;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.datatables.ClassListData;
import com.l2jserver.gameserver.data.xml.impl.ClassListData;
import com.l2jserver.gameserver.enums.CategoryType;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;

View File

@@ -22,7 +22,7 @@ import ai.individual.Valakas;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.DoorTable;
import com.l2jserver.gameserver.data.xml.impl.DoorData;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
import com.l2jserver.gameserver.instancemanager.QuestManager;
import com.l2jserver.gameserver.model.Location;
@@ -151,17 +151,17 @@ public final class GrandBossTeleporters extends AbstractNpcAI
}
case 31384:
{
DoorTable.getInstance().getDoor(24210004).openMe();
DoorData.getInstance().getDoor(24210004).openMe();
break;
}
case 31686:
{
DoorTable.getInstance().getDoor(24210006).openMe();
DoorData.getInstance().getDoor(24210006).openMe();
break;
}
case 31687:
{
DoorTable.getInstance().getDoor(24210005).openMe();
DoorData.getInstance().getDoor(24210005).openMe();
break;
}
case 31540:

View File

@@ -1,10 +0,0 @@
<html><body>Gatekeeper Ragara:<br>
Ages ago, the Kamael were barred from using teleportation magic. Needless to say, this has put us at a distinct disadvantage. Finally, we learned how to borrow other races' power.<br>
The Wizards of the Ivory Tower sympathized with us, so they created the Staff of Transferring and built strongholds everywhere. Beginning adventurers may move freely to strongholds as a result.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Chat 1">Teleport</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Chat 4">Move to a stronghold (free).</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 002">Exchange Dimension Diamonds.</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest NoblesseTeleport">Noblesse Exclusive Teleport</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest CharacterBirthday">Receive your Birthday Gift!</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -1,10 +0,0 @@
<html><body>Gatekeeper Ragara:<br>
Ages ago, the Kamael were barred from using teleportation magic. Needless to say, this has put us at a distinct disadvantage. Finally, we learned how to borrow other races' power.<br>
The Wizards of the Ivory Tower sympathized with us, so they created the Staff of Transferring and built strongholds everywhere. Beginning adventurers may move freely to strongholds as a result.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Chat 1">Teleport</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Chat 5">Move to a stronghold (free).</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_multisell 002">Exchange Dimension Diamonds.</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest NoblesseTeleport">Noblesse Exclusive Teleport</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest CharacterBirthday">Receive your Birthday Gift!</Button>
<Button ALIGN=LEFT ICON="QUEST" action="bypass -h npc_%objectId%_Quest">Quest</Button>
</body></html>

View File

@@ -33,7 +33,6 @@ public final class StrongholdsTeleports extends AbstractNpcAI
// NPCs
private final static int[] NPCs =
{
32163,
32181,
32184,
32186

View File

@@ -24,7 +24,7 @@ import java.util.List;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.SkillTreesData;
import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
import com.l2jserver.gameserver.model.L2SkillLearn;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;

View File

@@ -23,8 +23,8 @@ import java.util.Map;
import java.util.Map.Entry;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.data.sql.impl.ClanTable;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.actor.L2Npc;

View File

@@ -23,8 +23,8 @@ import java.util.Map;
import java.util.Map.Entry;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.data.sql.impl.ClanTable;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.Location;

View File

@@ -24,7 +24,7 @@ import java.util.Map.Entry;
import com.l2jserver.gameserver.GameTimeController;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.data.sql.impl.ClanTable;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;

View File

@@ -34,8 +34,8 @@ import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.data.sql.impl.ClanTable;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.instancemanager.CHSiegeManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
@@ -47,6 +47,7 @@ import com.l2jserver.gameserver.model.Location;
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.L2Summon;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.clanhall.ClanHallSiegeEngine;
import com.l2jserver.gameserver.model.entity.clanhall.SiegableHall;
@@ -692,10 +693,15 @@ public final class RainbowSpringsChateau extends ClanHallSiegeEngine
if (pc != null)
{
pc.stopAllEffects();
if (pc.hasSummon())
final L2Summon pet = pc.getPet();
if (pet != null)
{
pc.getSummon().unSummon(pc);
pet.unSummon(pc);
}
pc.getServitors().values().forEach(s ->
{
s.unSummon(pc);
});
pc.teleToLocation(ARENAS[arena]);
}
}

View File

@@ -31,8 +31,8 @@ import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.ai.L2SpecialSiegeGuardAI;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.data.sql.impl.ClanTable;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.enums.SiegeClanType;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2ClanMember;

View File

@@ -1,8 +1,8 @@
<html><body>
Are you ready? Remember, these are wild animals! Don't let them bite you! It won't be easy!<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest WildBeastReserve register_clan">Clan Register (Leader)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest WildBeastReserve messenger_allychoose.htm">Choose Clan NPC (Leader)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest WildBeastReserve view_clan_npc">See Clan NPC (Member)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest WildBeastReserver register_member">Clan Member Register (Member)</Button><br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest 655_AGrandPlanforTamingWildBeasts">Quest</Button>
<a action="bypass -h Quest WildBeastReserve register_clan">Clan Register (Leader)</a><br>
<a action="bypass -h Quest WildBeastReserve messenger_allychoose.htm">Choose Clan NPC (Leader)</a><br>
<a action="bypass -h Quest WildBeastReserve view_clan_npc">See Clan NPC (Member)</a><br>
<a action="bypass -h Quest WildBeastReserver register_member">Clan Member Register (Member)</a><br><br>
<a action="bypass -h npc_%objectId%_Quest">Quest</a>
</body></html>

View File

@@ -1,7 +1,7 @@
<html><body>Messenger:<br>
What brings you to this place? I can't be responsible for your safety here!<br>
Unless, that is, you're a member of the <font color=00ffff><?my_pledge_name?></font> Clan in charge of the farm.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest 655_AGrandPlanforTamingWildBeasts">Qualification Test for Clan Hall Battle Registration</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest WildBeastReserve register_clan">Register for Clan Hall Battle</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest WildBeastReserve view_attacker_list">Clans Participating in the Preliminaries</Button>
<a action="bypass -h npc_%objectId%_Quest">Qualification Test for Clan Hall Battle Registration</a><br>
<a action="bypass -h Quest WildBeastReserve register_clan">Register for Clan Hall Battle</a><br>
<a action="bypass -h Quest WildBeastReserve view_attacker_list">Clans Participating in the Preliminaries</a>
</body></html>

View File

@@ -18,7 +18,7 @@
*/
package custom.NewbieCoupons;
import com.l2jserver.gameserver.datatables.MultisellData;
import com.l2jserver.gameserver.data.xml.impl.MultisellData;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.quest.Quest;

View File

@@ -21,7 +21,7 @@ package custom.RaidbossInfo;
import java.util.ArrayList;
import java.util.List;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.Location;

View File

@@ -23,7 +23,7 @@ import java.util.Arrays;
import javolution.util.FastList;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.ClassListData;
import com.l2jserver.gameserver.data.xml.impl.ClassListData;
import com.l2jserver.gameserver.enums.IllegalActionPunishmentType;
import com.l2jserver.gameserver.model.PcCondOverride;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;

View File

@@ -150,17 +150,20 @@ public final class GiftOfVitality extends LongTimeEvent
{
htmltext = "4306-nolevel.htm";
}
else if (!player.hasServitor())
else if (!player.hasServitors())
{
htmltext = "4306-nosummon.htm";
}
else
{
npc.setTarget(player.getSummon());
for (SkillHolder sk : SERVITOR_SKILLS)
player.getServitors().values().forEach(s ->
{
npc.doCast(sk.getSkill());
}
npc.setTarget(s);
for (SkillHolder sk : SERVITOR_SKILLS)
{
npc.doCast(sk.getSkill());
}
});
htmltext = "4306-okbuff.htm";
}
break;

View File

@@ -21,8 +21,8 @@ package features.SkillTransfer;
import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.ClassListData;
import com.l2jserver.gameserver.datatables.SkillTreesData;
import com.l2jserver.gameserver.data.xml.impl.ClassListData;
import com.l2jserver.gameserver.data.xml.impl.SkillTreesData;
import com.l2jserver.gameserver.enums.IllegalActionPunishmentType;
import com.l2jserver.gameserver.model.L2SkillLearn;
import com.l2jserver.gameserver.model.PcCondOverride;
@@ -42,11 +42,11 @@ public final class SkillTransfer extends AbstractNpcAI
private static final ItemHolder[] PORMANDERS =
{
// Cardinal (97)
new ItemHolder(15307, 1),
new ItemHolder(15307, 7),
// Eva's Saint (105)
new ItemHolder(15308, 1),
new ItemHolder(15308, 7),
// Shillen Saint (112)
new ItemHolder(15309, 4)
new ItemHolder(15309, 7)
};
private SkillTransfer()

View File

@@ -27,8 +27,8 @@ import ai.npc.AbstractNpcAI;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.DoorTable;
import com.l2jserver.gameserver.datatables.NpcData;
import com.l2jserver.gameserver.data.xml.impl.DoorData;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.enums.QuestSound;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.instancemanager.GraciaSeedsManager;
@@ -189,7 +189,7 @@ public class EnergySeeds extends AbstractNpcAI
{
for (int doorId : SEED_OF_DESTRUCTION_DOORS)
{
L2DoorInstance doorInstance = DoorTable.getInstance().getDoor(doorId);
L2DoorInstance doorInstance = DoorData.getInstance().getDoor(doorId);
if (doorInstance != null)
{
doorInstance.openMe();
@@ -201,7 +201,7 @@ public class EnergySeeds extends AbstractNpcAI
{
for (int doorId : SEED_OF_DESTRUCTION_DOORS)
{
L2DoorInstance doorInstance = DoorTable.getInstance().getDoor(doorId);
L2DoorInstance doorInstance = DoorData.getInstance().getDoor(doorId);
if (doorInstance != null)
{
doorInstance.closeMe();

View File

@@ -18,6 +18,7 @@
*/
package gracia.AI.NPC.Nemo;
import gracia.AI.Maguen;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.ai.CtrlIntention;
@@ -27,8 +28,6 @@ import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.network.NpcStringId;
import gracia.AI.Maguen;
/**
* Nemo AI.
* @author St3eT

View File

@@ -18,9 +18,6 @@
*/
package gracia;
import java.util.logging.Level;
import java.util.logging.Logger;
import gracia.AI.EnergySeeds;
import gracia.AI.Lindvior;
import gracia.AI.Maguen;
@@ -35,13 +32,16 @@ import gracia.AI.NPC.ZealotOfShilen.ZealotOfShilen;
import gracia.AI.SeedOfAnnihilation.SeedOfAnnihilation;
import gracia.instances.SecretArea.SecretArea;
import gracia.instances.SeedOfDestruction.Stage1;
import gracia.instances.SeedOfInfinity.HallOfSuffering;
import gracia.instances.SeedOfInfinity.HallOfSuffering.HallOfSuffering;
import gracia.vehicles.AirShipGludioGracia.AirShipGludioGracia;
import gracia.vehicles.KeucereusNorthController.KeucereusNorthController;
import gracia.vehicles.KeucereusSouthController.KeucereusSouthController;
import gracia.vehicles.SoDController.SoDController;
import gracia.vehicles.SoIController.SoIController;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Gracia class-loader.
* @author Pandragon

View File

@@ -3,5 +3,5 @@ I'm very impressed.<br>
No one has ever broken through this fast to the Hall of Suffering. Extraordinary! In recognition of your achievement, I will give you a <font color="LEVEL">Jeweled Battle Supply</font>.<br>
It is granted only to those who achieve an especially impressive feat in battle.<br>
Your leader may receive it on your behalf.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
Unknown Text!<br>
The reward is <font color="LEVEL">Mother-of-Pearl Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
Unknown Text!<br>
The reward is <font color="LEVEL">Gold-Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
Unknown Text!<br>
The reward is <font color="LEVEL">Silver-Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
Unknown Text!<br>
The reward is <font color="LEVEL">Bronze-Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
Unknown Text!<br>
The reward is <font color="LEVEL">Non-Ornamented Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
Unknown Text!<br>
The reward is <font color="LEVEL">Weak-Looking Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
Unknown Text!<br>
The reward is <font color="LEVEL">Sad-Looking Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
Unknown Text!<br>
The reward is <font color="LEVEL">Poor-Looking Duel Supplies</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

View File

@@ -2,5 +2,5 @@
I'm very disappointed.<br>
If I had known your skills were this embarrasingly poor, I would not have assigned you this mission. You're lucky to still be alive! Still, a promise is a promise, so I will give you this <font color="LEVEL">Worthless Battle Supply</font>.<br>
I'll grant this reward to the leader who represents all of you.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</Button>
<a action="bypass -h npc_%objectId%_Quest SeedOfInfinity">Receive the supply.</a>
</body></html>

Some files were not shown because too many files have changed in this diff Show More