Addition of Battle with Keber event.

Contributed by Index.
This commit is contained in:
MobiusDevelopment 2022-08-15 22:19:19 +00:00
parent ecce207f6b
commit 41417f5367
18 changed files with 1248 additions and 10 deletions

View File

@ -0,0 +1,10 @@
<html><body>Event Manager Bonnie:<br>
Hey, you! You're right, I'm talking you!<br>
Do you know we have a new problem? It's <font color="LEVEL">Keber</font>!
&nbsp;He threatens to Aden.
&nbsp;They say Keber and his lackeys appear
&nbsp;<font color="LEVEL">every hour</font> on the <font color="LEVEL">Plains of Glory, War-Torn Plains and in the Silent Valley</font>.<br>
If you defeat Keber and his servants, you can get <font color="LEVEL">Talisman of Aden</font>.
&nbsp;I can teleport you to the villain. Do to want to go?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BattleWithKeber 34216-02.html">"I'll go right now"</Button>
</body></html>

View File

@ -0,0 +1,6 @@
<html><body>Event Manager Bonnie:<br>
If you don't have time to get to the destination by yourself, I can teleport you. Of course, it's not for free. Where do to want to go?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BattleWithKeber TELEPORT_01">Plains of Glory (%n1% adena)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BattleWithKeber TELEPORT_02">War-Torn Plains (%n2% adena)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BattleWithKeber TELEPORT_03">Silent Valley (%n3% adena)</Button>
</body></html>

View File

@ -0,0 +1,3 @@
<html><body>Event Manager Bonnie:<br>
Good luck! I hope you will defeat Keber.
</body></html>

View File

@ -0,0 +1,3 @@
<html><body>Event Manager Bonnie:<br>
You don't have enough adena. Check your pockets once again!
</body></html>

View File

@ -0,0 +1,494 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package events.BattleWithKeber;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicReference;
import org.l2jmobius.gameserver.data.xml.SpawnData;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.holders.ItemChanceHolder;
import org.l2jmobius.gameserver.model.quest.LongTimeEvent;
import org.l2jmobius.gameserver.model.spawns.SpawnGroup;
import org.l2jmobius.gameserver.model.spawns.SpawnTemplate;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import org.l2jmobius.gameserver.util.Broadcast;
/**
* @author Index
*/
public class BattleWithKeber extends LongTimeEvent
{
// NPCs
private static final int BONNIE = 34216;
private static final int KEBER_SEAL_STONE = 18551;
// Locations from Bonnie teleport
private static final Location PLAINS_OF_GLORY_TELEPORT = new Location(133994, 7136, -4352);
private static final Location WAR_TORN_PLAINS_TELEPORT = new Location(161658, 21299, -3672);
private static final Location SILENT_VALLEY_TELEPORT = new Location(181645, 52823, -6112);
// Spawn locations for monsters
private static final Location PLAINS_OF_GLORY_BOSS = new Location(132573, 7865, -4300);
private static final Location WAR_TORN_PLAINS_BOSS = new Location(161205, 21680, -3680);
private static final Location SILENT_VALLEY_BOSS = new Location(180640, 52824, -6096);
// Monsters
private static final int KEBER_LOW = 18537; // 63
private static final int KEBER_MIDDLE = 18552; // 69
private static final int KEBER_HIGH = 18553; // 75
private static final int KISHAN = 18538; // 63
private static final int NOMA = 18542; // 69
private static final int SPALL = 18546; // 75
private static final Set<Integer> BOSSES = new HashSet<>();
static
{
BOSSES.add(KEBER_LOW);
BOSSES.add(KEBER_MIDDLE);
BOSSES.add(KEBER_HIGH);
BOSSES.add(KISHAN);
BOSSES.add(NOMA);
BOSSES.add(SPALL);
}
private static final List<Integer> NORMAL_MINIONS = new ArrayList<>();
static
{
NORMAL_MINIONS.add(18539);
NORMAL_MINIONS.add(18543);
NORMAL_MINIONS.add(18547);
}
private static final List<Integer> ELITE_MINIONS = new ArrayList<>();
static
{
ELITE_MINIONS.add(18540);
ELITE_MINIONS.add(18544);
ELITE_MINIONS.add(18548);
}
private static final List<Integer> BRAINWASHED_MINIONS = new ArrayList<>();
static
{
BRAINWASHED_MINIONS.add(18541);
BRAINWASHED_MINIONS.add(18545);
BRAINWASHED_MINIONS.add(18549);
}
// Drop
private static final Set<ItemChanceHolder> KEBER_LOW_DROP = new HashSet<>();
static
{
KEBER_LOW_DROP.add(new ItemChanceHolder(57, 100, 525000)); // Adena x525000
KEBER_LOW_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x2
KEBER_LOW_DROP.add(new ItemChanceHolder(94481, 100, 150)); // Clan XP x150
}
private static final Set<ItemChanceHolder> KEBER_MIDDLE_DROP = new HashSet<>();
static
{
KEBER_MIDDLE_DROP.add(new ItemChanceHolder(57, 100, 725000)); // Adena 725000
KEBER_MIDDLE_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x2
KEBER_MIDDLE_DROP.add(new ItemChanceHolder(94481, 100, 150)); // Clan XP x150
}
private static final Set<ItemChanceHolder> KEBER_HIGH_DROP = new HashSet<>();
static
{
KEBER_HIGH_DROP.add(new ItemChanceHolder(57, 100, 925000)); // Adena x925000
KEBER_HIGH_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x2
KEBER_HIGH_DROP.add(new ItemChanceHolder(94481, 100, 150)); // Clan XP x150
}
private static final Set<ItemChanceHolder> KISHAN_DROP = new HashSet<>();
static
{
KISHAN_DROP.add(new ItemChanceHolder(57, 100, 45000)); // Adena x45000
KISHAN_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x1
KISHAN_DROP.add(new ItemChanceHolder(94481, 100, 50)); // Clan XP x50
}
private static final Set<ItemChanceHolder> NOMA_DROP = new HashSet<>();
static
{
NOMA_DROP.add(new ItemChanceHolder(57, 100, 55000)); // Adena x55000
NOMA_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x1
NOMA_DROP.add(new ItemChanceHolder(94481, 100, 50)); // Clan XP x50
}
private static final Set<ItemChanceHolder> SPALL_DROP = new HashSet<>();
static
{
SPALL_DROP.add(new ItemChanceHolder(57, 100, 65000)); // Adena x55000
SPALL_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x1
SPALL_DROP.add(new ItemChanceHolder(94481, 100, 50)); // Clan XP x50
}
private static final Set<ItemChanceHolder> MINION_DROP = new HashSet<>();
static
{
MINION_DROP.add(new ItemChanceHolder(91767, 10, 1)); // Enchant Kit: Talisman of Aden x1
}
private static final Map<Integer, Set<ItemChanceHolder>> NPC_DROP = new HashMap<>();
static
{
NPC_DROP.put(KEBER_LOW, KEBER_LOW_DROP);
NPC_DROP.put(KEBER_MIDDLE, KEBER_MIDDLE_DROP);
NPC_DROP.put(KEBER_HIGH, KEBER_HIGH_DROP);
NPC_DROP.put(KISHAN, KISHAN_DROP);
NPC_DROP.put(NOMA, NOMA_DROP);
NPC_DROP.put(SPALL, SPALL_DROP);
}
// Misc
private static final int EVENT_MESSAGE_START = -1;
private static final int EVENT_MESSAGE_KILL = -2;
private static final int EVENT_MESSAGE_TO_KILLER = -3;
private static final int EVENT_MESSAGE_WEAK = -4;
private static final int ELITE_MONSTER_COUNT = 200;
private static final int BRAINWASHED_MONSTER_COUNT = 100;
private static final int PLAINS_OF_GLORY_TELEPORT_COST = 2000;
private static final int WAR_TORN_PLAINS_TELEPORT_COST = 2500;
private static final int SILENT_VALLEY_TELEPORT_COST = 3000;
private static final Map<Integer, NpcStringId> BROADCAST_MESSAGES = new HashMap<>();
static
{
BROADCAST_MESSAGES.put(KEBER_LOW, NpcStringId.AHEM_YOU_DARE_TO_BOTHER_KEBER_YOU_WILL_SEE_NO_MERCY);
BROADCAST_MESSAGES.put(KEBER_MIDDLE, NpcStringId.AHEM_YOU_DARE_TO_BOTHER_KEBER_YOU_WILL_SEE_NO_MERCY);
BROADCAST_MESSAGES.put(KEBER_HIGH, NpcStringId.AHEM_YOU_DARE_TO_BOTHER_KEBER_YOU_WILL_SEE_NO_MERCY);
BROADCAST_MESSAGES.put(KISHAN, NpcStringId.KISHAN_MY_SERVANT_ATTACK);
BROADCAST_MESSAGES.put(NOMA, NpcStringId.NOMA_MY_SERVANT_ATTACK);
BROADCAST_MESSAGES.put(SPALL, NpcStringId.SPALL_MY_SERVANT_ATTACK);
BROADCAST_MESSAGES.put(EVENT_MESSAGE_START, NpcStringId.MAKE_THE_SACRED_BLOOD_SACRIFICE_TO_KEBER_ATTACK);
BROADCAST_MESSAGES.put(EVENT_MESSAGE_KILL, NpcStringId.AH_YOU_ARE_INDEED_STRONG_S1_I_HAVE_TO_RETREAT_THIS_TIME);
BROADCAST_MESSAGES.put(EVENT_MESSAGE_TO_KILLER, NpcStringId.YOU_WILL_NOT_BE_FORGIVEN_I_WILL_BE_BACK_AND_YOU_LL_REGRET_IT);
BROADCAST_MESSAGES.put(EVENT_MESSAGE_WEAK, NpcStringId.LOOKS_LIKE_YOU_RE_WAY_TOO_WEAK_TO_BEAT_ME);
}
private static final AtomicIntegerArray MINION_KILL_COUNTER = new AtomicIntegerArray(3);
private static final AtomicReference<SpawnTemplate> SPAWN_TEMPLATE = new AtomicReference<>();
private static final AtomicIntegerArray MINION_MAX_COUNT = new AtomicIntegerArray(3);
private BattleWithKeber()
{
if (isEventPeriod())
{
addFirstTalkId(BONNIE);
addTalkId(BONNIE);
addKillId(KEBER_LOW, KEBER_MIDDLE, KEBER_HIGH, KISHAN, NOMA, SPALL);
addKillId(NORMAL_MINIONS);
addKillId(ELITE_MINIONS);
addKillId(BRAINWASHED_MINIONS);
addSpawnId(KEBER_LOW, KEBER_MIDDLE, KEBER_HIGH, KISHAN, NOMA, SPALL);
addSpawnId(NORMAL_MINIONS);
addSpawnId(ELITE_MINIONS);
startQuestTimer("KEBER_EVENT_START", getMsTimeForEventStage(1), null, null);
SPAWN_TEMPLATE.set(SpawnData.getInstance().getSpawns().stream().filter(t -> t.getName() != null).filter(t -> t.getName().contains("KEBER_MINIONS")).findAny().orElse(null));
if (SPAWN_TEMPLATE.get() != null)
{
MINION_MAX_COUNT.set(0, SPAWN_TEMPLATE.get().getGroups().stream().filter(g -> ((g.getName() != null) && g.getName().equalsIgnoreCase("KISHAN"))).findFirst().get().getSpawns().stream().findFirst().get().getCount());
MINION_MAX_COUNT.set(1, SPAWN_TEMPLATE.get().getGroups().stream().filter(g -> ((g.getName() != null) && g.getName().equalsIgnoreCase("NOMA"))).findFirst().get().getSpawns().stream().findFirst().get().getCount());
MINION_MAX_COUNT.set(2, SPAWN_TEMPLATE.get().getGroups().stream().filter(g -> ((g.getName() != null) && g.getName().equalsIgnoreCase("SPALL"))).findFirst().get().getSpawns().stream().findFirst().get().getCount());
}
}
}
@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
switch (event)
{
case "34216-02.html":
{
String html = getHtm(player, "34216-02.html");
html = html.replace("%n1%", String.valueOf(PLAINS_OF_GLORY_TELEPORT_COST));
html = html.replace("%n2%", String.valueOf(WAR_TORN_PLAINS_TELEPORT_COST));
html = html.replace("%n3%", String.valueOf(SILENT_VALLEY_TELEPORT_COST));
return html;
}
case "TELEPORT_01":
case "TELEPORT_02":
case "TELEPORT_03":
{
final byte requestLocation = Byte.parseByte(event.replace("TELEPORT_0", ""));
if (player.getAdena() < (requestLocation == 1 ? PLAINS_OF_GLORY_TELEPORT_COST : requestLocation == 2 ? WAR_TORN_PLAINS_TELEPORT_COST : SILENT_VALLEY_TELEPORT_COST))
{
return "34216-04.html";
}
player.teleToLocation((requestLocation == 1 ? PLAINS_OF_GLORY_TELEPORT : requestLocation == 2 ? WAR_TORN_PLAINS_TELEPORT : SILENT_VALLEY_TELEPORT));
return "34216-03.html";
}
case "KEBER_EVENT_START":
{
for (Npc wo : World.getInstance().getVisibleObjects(player, Npc.class))
{
if (wo.getId() == KEBER_SEAL_STONE)
{
wo.setDisplayEffect(1);
Broadcast.toKnownPlayers((wo), new ExShowScreenMessage(BROADCAST_MESSAGES.get(EVENT_MESSAGE_START), ExShowScreenMessage.TOP_CENTER, 5000));
}
}
MINION_KILL_COUNTER.set(0, 0);
MINION_KILL_COUNTER.set(1, 0);
MINION_KILL_COUNTER.set(2, 0);
SPAWN_TEMPLATE.get().getGroups().forEach(SpawnGroup::spawnAll);
cancelQuestTimer("KEBER_EVENT_START", null, null);
startQuestTimer("KEBER_EVENT_BOSS_STAGE", getMsTimeForEventStage(2), null, null);
break;
}
case "KEBER_EVENT_BOSS_STAGE":
{
changeNpcSpawn(3, false, false);
for (int fieldType = 0; fieldType < 3; fieldType++)
{
final int summonedBossId = (getRandomBoolean() ? (fieldType == 0 ? KEBER_LOW : fieldType == 1 ? KEBER_MIDDLE : KEBER_HIGH) : (fieldType == 0 ? KISHAN : fieldType == 1 ? NOMA : SPALL));
final Location spawnLoc = (fieldType == 0 ? PLAINS_OF_GLORY_BOSS : fieldType == 1 ? WAR_TORN_PLAINS_BOSS : SILENT_VALLEY_BOSS);
addSpawn(summonedBossId, spawnLoc, false, 5 * 60 * 1000); // 5 minutes
}
cancelQuestTimer("KEBER_EVENT_BOSS_STAGE", null, null);
startQuestTimer("KEBER_EVENT_END", getMsTimeForEventStage(3), null, null);
break;
}
case "KEBER_EVENT_END":
{
for (Npc wo : World.getInstance().getVisibleObjects(player, Npc.class))
{
if (wo.getId() == KEBER_SEAL_STONE)
{
wo.setDisplayEffect(2); // remove effect
for (Npc boss : World.getInstance().getVisibleObjects((wo), Npc.class))
{
if (BOSSES.contains(boss.getId()) && !boss.isAlikeDead())
{
Broadcast.toKnownPlayers((wo), new ExShowScreenMessage(BROADCAST_MESSAGES.get(EVENT_MESSAGE_WEAK), ExShowScreenMessage.TOP_CENTER, 5000));
break;
}
}
}
}
cancelQuestTimer("KEBER_EVENT_END", null, null);
startQuestTimer("KEBER_EVENT_START", getMsTimeForEventStage(1), null, null);
changeNpcSpawn(3, true, true);
break;
}
}
return null;
}
@Override
public String onFirstTalk(Npc npc, Player player)
{
return "34216-01.html";
}
@Override
public String onSpawn(Npc npc)
{
final int type = getFieldType(npc.getId());
final boolean eventIsPending = (getQuestTimer("KEBER_EVENT_START", null, null) != null) && getQuestTimer("KEBER_EVENT_START", null, null).isActive();
final boolean eventOnBossStage = (getQuestTimer("KEBER_EVENT_END", null, null) != null) && getQuestTimer("KEBER_EVENT_END", null, null).isActive();
if ((type != -1) && (npc.getId() == NORMAL_MINIONS.get(type)))
{
if (eventIsPending || eventOnBossStage)
{
npc.getSpawn().stopRespawn();
npc.deleteMe();
return super.onSpawn(npc);
}
final int eliteMonsterId = ELITE_MINIONS.get(type);
final int brainWashedMonsterId = BRAINWASHED_MINIONS.get(type);
final int nearbyMonstersCount = World.getInstance().getVisibleObjects(npc, Npc.class).stream().filter(nearby -> ((nearby.getId() == NORMAL_MINIONS.get(type)) || (nearby.getId() == eliteMonsterId) || (nearby.getId() == brainWashedMonsterId))).toList().size();
final int maxSpawnMonsters = MINION_MAX_COUNT.length() == 0 ? 0 : MINION_MAX_COUNT.get(type);
if (nearbyMonstersCount >= maxSpawnMonsters)
{
npc.deleteMe();
return super.onSpawn(npc);
}
final int killedCount = MINION_KILL_COUNTER.get(type);
if (killedCount >= (ELITE_MONSTER_COUNT + BRAINWASHED_MONSTER_COUNT))
{
addSpawn(brainWashedMonsterId, npc.getLocation());
npc.deleteMe();
}
else if (killedCount >= ELITE_MONSTER_COUNT)
{
addSpawn(eliteMonsterId, npc.getLocation());
npc.deleteMe();
}
}
else if (BOSSES.contains(npc.getId()))
{
// Broadcast to nearby players string which says "monster respawn"
Broadcast.toKnownPlayers(npc, new ExShowScreenMessage(BROADCAST_MESSAGES.get(npc.getId()), ExShowScreenMessage.TOP_CENTER, 5000));
World.getInstance().getVisibleObjects(npc, Player.class).stream().findAny().ifPresent(player -> addAttackPlayerDesire(npc, player));
}
return super.onSpawn(npc);
}
@Override
public String onKill(Npc npc, Player killer, boolean isSummon)
{
if (NORMAL_MINIONS.contains(npc.getId()) || ELITE_MINIONS.contains(npc.getId()))
{
final int type = getFieldType(npc.getId());
int count = MINION_KILL_COUNTER.get(type);
if ((count >= ELITE_MONSTER_COUNT) && ELITE_MINIONS.contains(npc.getId()))
{
MINION_KILL_COUNTER.addAndGet(type, 1);
}
else if (count < ELITE_MONSTER_COUNT)
{
MINION_KILL_COUNTER.addAndGet(type, 1);
}
}
else
{
final Set<ItemChanceHolder> monsterDrop = ((npc.getTemplate().getLevel() > (killer.getLevel() - 15)) && (npc.getTemplate().getLevel() < (killer.getLevel() + 15))) ? NPC_DROP.getOrDefault(npc.getId(), MINION_DROP) : new HashSet<>();
for (ItemChanceHolder drop : monsterDrop)
{
if (getRandom(100) < drop.getChance())
{
if ((drop.getId() == 94481) && (killer.getClan() != null)) // Avoid to get clan points as item.
{
killer.getClan().addExp(killer.getObjectId(), (int) drop.getCount());
}
else
{
killer.addItem(_eventName, drop.getId(), drop.getCount(), null, true);
}
}
}
if (BOSSES.contains(npc.getId()))
{
changeNpcSpawn(getFieldType(npc.getId()), true, false);
Broadcast.toKnownPlayers(killer, new ExShowScreenMessage(BROADCAST_MESSAGES.get(EVENT_MESSAGE_KILL), ExShowScreenMessage.TOP_CENTER, 10000, killer.getName()));
killer.sendPacket(new ExShowScreenMessage(BROADCAST_MESSAGES.get(EVENT_MESSAGE_TO_KILLER), ExShowScreenMessage.TOP_CENTER, 5000));
for (Npc crystal : World.getInstance().getVisibleObjects(npc, Npc.class))
{
if (crystal.getId() == KEBER_SEAL_STONE)
{
crystal.setDisplayEffect(2);
break;
}
}
}
}
return super.onKill(npc, killer, isSummon);
}
private long getMsTimeForEventStage(int type)
{
final Calendar returnTime = Calendar.getInstance();
final long currentTime = System.currentTimeMillis();
returnTime.set(Calendar.MILLISECOND, 0);
returnTime.set(Calendar.SECOND, 0);
if (type == 1)
{
returnTime.set(Calendar.MINUTE, 0);
returnTime.add(Calendar.HOUR_OF_DAY, 1);
}
else if (type == 2)
{
returnTime.add(Calendar.MINUTE, 10);
}
else if (type == 3)
{
returnTime.add(Calendar.MINUTE, 5);
}
if (returnTime.getTimeInMillis() < currentTime)
{
returnTime.add(Calendar.DAY_OF_YEAR, 1);
}
return returnTime.getTimeInMillis() - currentTime;
}
/**
* Because value is set and we know all ids, it can be used to get fast access to any field monster.
* @param npcId
* @return 0 - Plains, 1 - War-Torn, 2 - Silent Valley
*/
private int getFieldType(int npcId)
{
if ((npcId == KEBER_LOW) || (npcId == KISHAN) || (npcId == NORMAL_MINIONS.get(0)) || (npcId == ELITE_MINIONS.get(0)) || (npcId == BRAINWASHED_MINIONS.get(0)))
{
return 0;
}
else if ((npcId == KEBER_MIDDLE) || (npcId == NOMA) || (npcId == NORMAL_MINIONS.get(1)) || (npcId == ELITE_MINIONS.get(1)) || (npcId == BRAINWASHED_MINIONS.get(1)))
{
return 1;
}
else if ((npcId == KEBER_HIGH) || (npcId == SPALL) || (npcId == NORMAL_MINIONS.get(2)) || (npcId == ELITE_MINIONS.get(2)) || (npcId == BRAINWASHED_MINIONS.get(2)))
{
return 2;
}
return -1;
}
private void changeNpcSpawn(int type, boolean delete, boolean removeAll)
{
if (removeAll)
{
SPAWN_TEMPLATE.get().getGroups().forEach(SpawnGroup::despawnAll);
}
for (WorldObject wo : World.getInstance().getVisibleObjects())
{
if (!wo.isMonster())
{
continue;
}
if (((type == 0) || (type == 3)) //
&& ((!removeAll && (NORMAL_MINIONS.get(0) == wo.getId())) //
|| (ELITE_MINIONS.get(0) == wo.getId()) //
|| (BRAINWASHED_MINIONS.get(0) == wo.getId()) //
|| (removeAll && ((KISHAN == wo.getId()) || (KEBER_LOW == wo.getId())))))
{
removeSpawn(wo, delete);
}
if (((type == 1) || (type == 3)) //
&& ((!removeAll && (NORMAL_MINIONS.get(1) == wo.getId())) //
|| (ELITE_MINIONS.get(1) == wo.getId()) //
|| (BRAINWASHED_MINIONS.get(1) == wo.getId()) //
|| (removeAll && ((NOMA == wo.getId()) || (KEBER_MIDDLE == wo.getId())))))
{
removeSpawn(wo, delete);
}
if (((type == 2) || (type == 3)) //
&& ((!removeAll && (NORMAL_MINIONS.get(2) == wo.getId())) //
|| (ELITE_MINIONS.get(2) == wo.getId()) //
|| (BRAINWASHED_MINIONS.get(2) == wo.getId()) //
|| (removeAll && ((SPALL == wo.getId()) || (KEBER_HIGH == wo.getId())))))
{
removeSpawn(wo, delete);
}
}
}
private void removeSpawn(WorldObject wo, boolean delete)
{
final Npc npc = ((Npc) wo);
npc.getSpawn().stopRespawn();
if (delete && (!BOSSES.contains(npc.getTemplate().getId()) || !npc.isAlikeDead()))
{
npc.deleteMe();
}
}
public static void main(String[] args)
{
new BattleWithKeber();
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<event name="Battle With Keber" active="19 08 2020-16 10 2020" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/eventConfig.xsd">
<spawnlist>
<add npc="34216" x="146966" y="25726" z="-2020" heading="6133" /> <!-- Bonnie -->
<add npc="34216" x="83673" y="148857" z="-3413" heading="29500" /> <!-- Bonnie -->
<add npc="18551" x="133474" y="7730" z="-4320" heading="0" /> <!-- Keber's Seal Stone / Plains of Glory -->
<add npc="18551" x="161481" y="22041" z="-3696" heading="0" /> <!-- Keber's Seal Stone / War-Torn Plains -->
<add npc="18551" x="180942" y="52673" z="-6100" heading="0" /> <!-- Keber's Seal Stone / Silent Valley -->
</spawnlist>
</event>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../xsd/spawns.xsd">
<spawn name="KEBER_MINIONS" spawnByDefault="false" >
<group name="KISHAN" spawnByDefault="false" >
<territories>
<territory shape="NPoly" rad="1" minZ="-4200" maxZ="-3900">
<node x="132014" y="8285"/>
<node x="131835" y="7488"/>
<node x="133928" y="6075"/>
<node x="134502" y="6557"/>
<node x="134451" y="7720"/>
<node x="133914" y="8721"/>
</territory>
</territories>
<npc id="18539" count="100" respawnTime="10sec" respawnRandom="0sec" /> <!-- Kishan's Minion -->
</group>
<group name="NOMA" spawnByDefault="false" >
<territories>
<territory shape="NPoly" rad="1" minZ="-3740" maxZ="-3700">
<node x="160635" y="21541"/>
<node x="161147" y="20888"/>
<node x="162234" y="20084"/>
<node x="161978" y="23005"/>
<node x="162910" y="23084"/>
<node x="163398" y="22379"/>
<node x="163727" y="23411"/>
<node x="162218" y="23713"/>
<node x="161268" y="23180"/>
</territory>
</territories>
<npc id="18543" count="120" respawnTime="10sec" respawnRandom="0sec" /> <!-- Noma's Minion -->
</group>
<group name="SPALL" spawnByDefault="false" >
<territories>
<territory shape="Cylinder" rad="700" minZ="-6100" maxZ="-6000">
<node x="180942" y="52673"/>
</territory>
</territories>
<npc id="18547" count="80" respawnTime="10sec" respawnRandom="0sec" /> <!-- Spall's Minion -->
</group>
</spawn>
</list>

View File

@ -1141,6 +1141,10 @@
<item id="57" min="439" max="485" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18540" level="63" type="Monster" name="Kishan's Minion" title="Elite">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1168,6 +1172,10 @@
<item id="57" min="1171" max="1295" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18541" level="63" type="Monster" name="Kishan's Minion" title="Brainwashed">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1190,6 +1198,9 @@
<radius normal="9" />
<height normal="41.5" />
</collision>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
</skillList>
</npc>
<npc id="18542" level="69" type="RaidBoss" name="Noma" title="Keber's Henchman">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1211,6 +1222,10 @@
<radius normal="35" />
<height normal="48.1" />
</collision>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="12" /> <!-- HP Increase 4x -->
</skillList>
</npc>
<npc id="18543" level="69" type="Monster" name="Noma's Minion">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1238,6 +1253,10 @@
<item id="57" min="836" max="924" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="11" /> <!-- Giants -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18544" level="69" type="Monster" name="Noma's Minion" title="Elite">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1264,6 +1283,10 @@
<item id="57" min="2233" max="2468" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="11" /> <!-- Giants -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18545" level="69" type="Monster" name="Noma's Minion" title="Brainwashed">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1286,6 +1309,9 @@
<radius normal="15" />
<height normal="40" />
</collision>
<skillList>
<skill id="4416" level="11" /> <!-- Giants -->
</skillList>
</npc>
<npc id="18546" level="75" type="RaidBoss" name="Spall" title="Keber's Henchman">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1307,6 +1333,10 @@
<radius normal="36.3" />
<height normal="65.2" />
</collision>
<skillList>
<skill id="4416" level="11" /> <!-- Giants -->
<skill id="4408" level="12" /> <!-- HP Increase 4x -->
</skillList>
</npc>
<npc id="18547" level="75" type="Monster" name="Spall's Minion">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1333,6 +1363,10 @@
<item id="57" min="1188" max="1313" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18548" level="75" type="Monster" name="Spall's Minion" title="Elite">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1359,6 +1393,10 @@
<item id="57" min="3135" max="3465" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18549" level="75" type="Monster" name="Spall's Minion" title="Brainwashed">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1380,6 +1418,9 @@
<radius normal="30.8" />
<height normal="51.065" />
</collision>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
</skillList>
</npc>
<npc id="18550" level="85" type="Folk" name="">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1400,8 +1441,7 @@
<height normal="0.1" />
</collision>
</npc>
<npc id="18551" level="80" type="Monster" name="Keber's Seal Stone">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
<npc id="18551" level="80" type="Folk" name="Keber's Seal Stone">
<race>ETC</race>
<sex>MALE</sex>
<acquire exp="5786" />
@ -1415,11 +1455,14 @@
</speed>
<hitTime>600</hitTime>
</stats>
<status attackable="true" />
<status attackable="false" randomWalk="false" targetable="false" talkable="false" undying="true" showName="false" />
<collision>
<radius normal="25" />
<height normal="62.5" />
</collision>
<skillList>
<skill id="4416" level="2" /> <!-- Magical Creatures -->
</skillList>
</npc>
<npc id="18552" level="69" type="RaidBoss" name="Keber" title="Maddened">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1441,6 +1484,10 @@
<radius normal="60" />
<height normal="99.5" />
</collision>
<skillList>
<skill id="4416" level="7" /> <!-- Spirits -->
<skill id="4408" level="12" /> <!-- HP Increase 4x -->
</skillList>
</npc>
<npc id="18553" level="75" type="RaidBoss" name="Keber" title="Maddened">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1462,6 +1509,10 @@
<radius normal="60" />
<height normal="99.5" />
</collision>
<skillList>
<skill id="4416" level="7" /> <!-- Spirits -->
<skill id="4408" level="12" /> <!-- HP Increase 4x -->
</skillList>
</npc>
<npc id="18554" level="85" type="Monster" name="Otherworldly Shard" title="Full of Energy">
<!-- AUTO GENERATED NPC TODO: FIX IT -->

View File

@ -431,13 +431,13 @@
</attribute>
<abnormalResist physical="0" magical="0" />
</stats>
<status attackable="false" undying="true" canMove="false" targetable="false" showName="false" />
<status attackable="false" undying="true" canMove="false" targetable="true" showName="true" />
<collision>
<radius normal="11" />
<height normal="17" />
</collision>
<skillList>
<skill id="4416" level="2" /> <!-- Magical Creatures -->
<skill id="4416" level="18" /> <!-- Dwarves -->
<skill id="4408" level="1" /> <!-- HP Increase (1x) -->
<skill id="4409" level="1" /> <!-- MP Increase (1x) -->
<skill id="4410" level="11" /> <!-- Average Damage Dealer -->

View File

@ -0,0 +1,10 @@
<html><body>Event Manager Bonnie:<br>
Hey, you! You're right, I'm talking you!<br>
Do you know we have a new problem? It's <font color="LEVEL">Keber</font>!
&nbsp;He threatens to Aden.
&nbsp;They say Keber and his lackeys appear
&nbsp;<font color="LEVEL">every hour</font> on the <font color="LEVEL">Plains of Glory, War-Torn Plains and in the Silent Valley</font>.<br>
If you defeat Keber and his servants, you can get <font color="LEVEL">Talisman of Aden</font>.
&nbsp;I can teleport you to the villain. Do to want to go?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BattleWithKeber 34216-02.html">"I'll go right now"</Button>
</body></html>

View File

@ -0,0 +1,6 @@
<html><body>Event Manager Bonnie:<br>
If you don't have time to get to the destination by yourself, I can teleport you. Of course, it's not for free. Where do to want to go?<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BattleWithKeber TELEPORT_01">Plains of Glory (%n1% adena)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BattleWithKeber TELEPORT_02">War-Torn Plains (%n2% adena)</Button>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass -h Quest BattleWithKeber TELEPORT_03">Silent Valley (%n3% adena)</Button>
</body></html>

View File

@ -0,0 +1,3 @@
<html><body>Event Manager Bonnie:<br>
Good luck! I hope you will defeat Keber.
</body></html>

View File

@ -0,0 +1,3 @@
<html><body>Event Manager Bonnie:<br>
You don't have enough adena. Check your pockets once again!
</body></html>

View File

@ -0,0 +1,494 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package events.BattleWithKeber;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicReference;
import org.l2jmobius.gameserver.data.xml.SpawnData;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.holders.ItemChanceHolder;
import org.l2jmobius.gameserver.model.quest.LongTimeEvent;
import org.l2jmobius.gameserver.model.spawns.SpawnGroup;
import org.l2jmobius.gameserver.model.spawns.SpawnTemplate;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import org.l2jmobius.gameserver.util.Broadcast;
/**
* @author Index
*/
public class BattleWithKeber extends LongTimeEvent
{
// NPCs
private static final int BONNIE = 34216;
private static final int KEBER_SEAL_STONE = 18551;
// Locations from Bonnie teleport
private static final Location PLAINS_OF_GLORY_TELEPORT = new Location(133994, 7136, -4352);
private static final Location WAR_TORN_PLAINS_TELEPORT = new Location(161658, 21299, -3672);
private static final Location SILENT_VALLEY_TELEPORT = new Location(181645, 52823, -6112);
// Spawn locations for monsters
private static final Location PLAINS_OF_GLORY_BOSS = new Location(132573, 7865, -4300);
private static final Location WAR_TORN_PLAINS_BOSS = new Location(161205, 21680, -3680);
private static final Location SILENT_VALLEY_BOSS = new Location(180640, 52824, -6096);
// Monsters
private static final int KEBER_LOW = 18537; // 63
private static final int KEBER_MIDDLE = 18552; // 69
private static final int KEBER_HIGH = 18553; // 75
private static final int KISHAN = 18538; // 63
private static final int NOMA = 18542; // 69
private static final int SPALL = 18546; // 75
private static final Set<Integer> BOSSES = new HashSet<>();
static
{
BOSSES.add(KEBER_LOW);
BOSSES.add(KEBER_MIDDLE);
BOSSES.add(KEBER_HIGH);
BOSSES.add(KISHAN);
BOSSES.add(NOMA);
BOSSES.add(SPALL);
}
private static final List<Integer> NORMAL_MINIONS = new ArrayList<>();
static
{
NORMAL_MINIONS.add(18539);
NORMAL_MINIONS.add(18543);
NORMAL_MINIONS.add(18547);
}
private static final List<Integer> ELITE_MINIONS = new ArrayList<>();
static
{
ELITE_MINIONS.add(18540);
ELITE_MINIONS.add(18544);
ELITE_MINIONS.add(18548);
}
private static final List<Integer> BRAINWASHED_MINIONS = new ArrayList<>();
static
{
BRAINWASHED_MINIONS.add(18541);
BRAINWASHED_MINIONS.add(18545);
BRAINWASHED_MINIONS.add(18549);
}
// Drop
private static final Set<ItemChanceHolder> KEBER_LOW_DROP = new HashSet<>();
static
{
KEBER_LOW_DROP.add(new ItemChanceHolder(57, 100, 525000)); // Adena x525000
KEBER_LOW_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x2
KEBER_LOW_DROP.add(new ItemChanceHolder(94481, 100, 150)); // Clan XP x150
}
private static final Set<ItemChanceHolder> KEBER_MIDDLE_DROP = new HashSet<>();
static
{
KEBER_MIDDLE_DROP.add(new ItemChanceHolder(57, 100, 725000)); // Adena 725000
KEBER_MIDDLE_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x2
KEBER_MIDDLE_DROP.add(new ItemChanceHolder(94481, 100, 150)); // Clan XP x150
}
private static final Set<ItemChanceHolder> KEBER_HIGH_DROP = new HashSet<>();
static
{
KEBER_HIGH_DROP.add(new ItemChanceHolder(57, 100, 925000)); // Adena x925000
KEBER_HIGH_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x2
KEBER_HIGH_DROP.add(new ItemChanceHolder(94481, 100, 150)); // Clan XP x150
}
private static final Set<ItemChanceHolder> KISHAN_DROP = new HashSet<>();
static
{
KISHAN_DROP.add(new ItemChanceHolder(57, 100, 45000)); // Adena x45000
KISHAN_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x1
KISHAN_DROP.add(new ItemChanceHolder(94481, 100, 50)); // Clan XP x50
}
private static final Set<ItemChanceHolder> NOMA_DROP = new HashSet<>();
static
{
NOMA_DROP.add(new ItemChanceHolder(57, 100, 55000)); // Adena x55000
NOMA_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x1
NOMA_DROP.add(new ItemChanceHolder(94481, 100, 50)); // Clan XP x50
}
private static final Set<ItemChanceHolder> SPALL_DROP = new HashSet<>();
static
{
SPALL_DROP.add(new ItemChanceHolder(57, 100, 65000)); // Adena x55000
SPALL_DROP.add(new ItemChanceHolder(91767, 100, 1)); // Enchant Kit: Talisman of Aden x1
SPALL_DROP.add(new ItemChanceHolder(94481, 100, 50)); // Clan XP x50
}
private static final Set<ItemChanceHolder> MINION_DROP = new HashSet<>();
static
{
MINION_DROP.add(new ItemChanceHolder(91767, 10, 1)); // Enchant Kit: Talisman of Aden x1
}
private static final Map<Integer, Set<ItemChanceHolder>> NPC_DROP = new HashMap<>();
static
{
NPC_DROP.put(KEBER_LOW, KEBER_LOW_DROP);
NPC_DROP.put(KEBER_MIDDLE, KEBER_MIDDLE_DROP);
NPC_DROP.put(KEBER_HIGH, KEBER_HIGH_DROP);
NPC_DROP.put(KISHAN, KISHAN_DROP);
NPC_DROP.put(NOMA, NOMA_DROP);
NPC_DROP.put(SPALL, SPALL_DROP);
}
// Misc
private static final int EVENT_MESSAGE_START = -1;
private static final int EVENT_MESSAGE_KILL = -2;
private static final int EVENT_MESSAGE_TO_KILLER = -3;
private static final int EVENT_MESSAGE_WEAK = -4;
private static final int ELITE_MONSTER_COUNT = 200;
private static final int BRAINWASHED_MONSTER_COUNT = 100;
private static final int PLAINS_OF_GLORY_TELEPORT_COST = 2000;
private static final int WAR_TORN_PLAINS_TELEPORT_COST = 2500;
private static final int SILENT_VALLEY_TELEPORT_COST = 3000;
private static final Map<Integer, NpcStringId> BROADCAST_MESSAGES = new HashMap<>();
static
{
BROADCAST_MESSAGES.put(KEBER_LOW, NpcStringId.AHEM_YOU_DARE_TO_BOTHER_KEBER_YOU_WILL_SEE_NO_MERCY);
BROADCAST_MESSAGES.put(KEBER_MIDDLE, NpcStringId.AHEM_YOU_DARE_TO_BOTHER_KEBER_YOU_WILL_SEE_NO_MERCY);
BROADCAST_MESSAGES.put(KEBER_HIGH, NpcStringId.AHEM_YOU_DARE_TO_BOTHER_KEBER_YOU_WILL_SEE_NO_MERCY);
BROADCAST_MESSAGES.put(KISHAN, NpcStringId.KISHAN_MY_SERVANT_ATTACK);
BROADCAST_MESSAGES.put(NOMA, NpcStringId.NOMA_MY_SERVANT_ATTACK);
BROADCAST_MESSAGES.put(SPALL, NpcStringId.SPALL_MY_SERVANT_ATTACK);
BROADCAST_MESSAGES.put(EVENT_MESSAGE_START, NpcStringId.MAKE_THE_SACRED_BLOOD_SACRIFICE_TO_KEBER_ATTACK);
BROADCAST_MESSAGES.put(EVENT_MESSAGE_KILL, NpcStringId.AH_YOU_ARE_INDEED_STRONG_S1_I_HAVE_TO_RETREAT_THIS_TIME);
BROADCAST_MESSAGES.put(EVENT_MESSAGE_TO_KILLER, NpcStringId.YOU_WILL_NOT_BE_FORGIVEN_I_WILL_BE_BACK_AND_YOU_LL_REGRET_IT);
BROADCAST_MESSAGES.put(EVENT_MESSAGE_WEAK, NpcStringId.LOOKS_LIKE_YOU_RE_WAY_TOO_WEAK_TO_BEAT_ME);
}
private static final AtomicIntegerArray MINION_KILL_COUNTER = new AtomicIntegerArray(3);
private static final AtomicReference<SpawnTemplate> SPAWN_TEMPLATE = new AtomicReference<>();
private static final AtomicIntegerArray MINION_MAX_COUNT = new AtomicIntegerArray(3);
private BattleWithKeber()
{
if (isEventPeriod())
{
addFirstTalkId(BONNIE);
addTalkId(BONNIE);
addKillId(KEBER_LOW, KEBER_MIDDLE, KEBER_HIGH, KISHAN, NOMA, SPALL);
addKillId(NORMAL_MINIONS);
addKillId(ELITE_MINIONS);
addKillId(BRAINWASHED_MINIONS);
addSpawnId(KEBER_LOW, KEBER_MIDDLE, KEBER_HIGH, KISHAN, NOMA, SPALL);
addSpawnId(NORMAL_MINIONS);
addSpawnId(ELITE_MINIONS);
startQuestTimer("KEBER_EVENT_START", getMsTimeForEventStage(1), null, null);
SPAWN_TEMPLATE.set(SpawnData.getInstance().getSpawns().stream().filter(t -> t.getName() != null).filter(t -> t.getName().contains("KEBER_MINIONS")).findAny().orElse(null));
if (SPAWN_TEMPLATE.get() != null)
{
MINION_MAX_COUNT.set(0, SPAWN_TEMPLATE.get().getGroups().stream().filter(g -> ((g.getName() != null) && g.getName().equalsIgnoreCase("KISHAN"))).findFirst().get().getSpawns().stream().findFirst().get().getCount());
MINION_MAX_COUNT.set(1, SPAWN_TEMPLATE.get().getGroups().stream().filter(g -> ((g.getName() != null) && g.getName().equalsIgnoreCase("NOMA"))).findFirst().get().getSpawns().stream().findFirst().get().getCount());
MINION_MAX_COUNT.set(2, SPAWN_TEMPLATE.get().getGroups().stream().filter(g -> ((g.getName() != null) && g.getName().equalsIgnoreCase("SPALL"))).findFirst().get().getSpawns().stream().findFirst().get().getCount());
}
}
}
@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
switch (event)
{
case "34216-02.html":
{
String html = getHtm(player, "34216-02.html");
html = html.replace("%n1%", String.valueOf(PLAINS_OF_GLORY_TELEPORT_COST));
html = html.replace("%n2%", String.valueOf(WAR_TORN_PLAINS_TELEPORT_COST));
html = html.replace("%n3%", String.valueOf(SILENT_VALLEY_TELEPORT_COST));
return html;
}
case "TELEPORT_01":
case "TELEPORT_02":
case "TELEPORT_03":
{
final byte requestLocation = Byte.parseByte(event.replace("TELEPORT_0", ""));
if (player.getAdena() < (requestLocation == 1 ? PLAINS_OF_GLORY_TELEPORT_COST : requestLocation == 2 ? WAR_TORN_PLAINS_TELEPORT_COST : SILENT_VALLEY_TELEPORT_COST))
{
return "34216-04.html";
}
player.teleToLocation((requestLocation == 1 ? PLAINS_OF_GLORY_TELEPORT : requestLocation == 2 ? WAR_TORN_PLAINS_TELEPORT : SILENT_VALLEY_TELEPORT));
return "34216-03.html";
}
case "KEBER_EVENT_START":
{
for (Npc wo : World.getInstance().getVisibleObjects(player, Npc.class))
{
if (wo.getId() == KEBER_SEAL_STONE)
{
wo.setDisplayEffect(1);
Broadcast.toKnownPlayers((wo), new ExShowScreenMessage(BROADCAST_MESSAGES.get(EVENT_MESSAGE_START), ExShowScreenMessage.TOP_CENTER, 5000));
}
}
MINION_KILL_COUNTER.set(0, 0);
MINION_KILL_COUNTER.set(1, 0);
MINION_KILL_COUNTER.set(2, 0);
SPAWN_TEMPLATE.get().getGroups().forEach(SpawnGroup::spawnAll);
cancelQuestTimer("KEBER_EVENT_START", null, null);
startQuestTimer("KEBER_EVENT_BOSS_STAGE", getMsTimeForEventStage(2), null, null);
break;
}
case "KEBER_EVENT_BOSS_STAGE":
{
changeNpcSpawn(3, false, false);
for (int fieldType = 0; fieldType < 3; fieldType++)
{
final int summonedBossId = (getRandomBoolean() ? (fieldType == 0 ? KEBER_LOW : fieldType == 1 ? KEBER_MIDDLE : KEBER_HIGH) : (fieldType == 0 ? KISHAN : fieldType == 1 ? NOMA : SPALL));
final Location spawnLoc = (fieldType == 0 ? PLAINS_OF_GLORY_BOSS : fieldType == 1 ? WAR_TORN_PLAINS_BOSS : SILENT_VALLEY_BOSS);
addSpawn(summonedBossId, spawnLoc, false, 5 * 60 * 1000); // 5 minutes
}
cancelQuestTimer("KEBER_EVENT_BOSS_STAGE", null, null);
startQuestTimer("KEBER_EVENT_END", getMsTimeForEventStage(3), null, null);
break;
}
case "KEBER_EVENT_END":
{
for (Npc wo : World.getInstance().getVisibleObjects(player, Npc.class))
{
if (wo.getId() == KEBER_SEAL_STONE)
{
wo.setDisplayEffect(2); // remove effect
for (Npc boss : World.getInstance().getVisibleObjects((wo), Npc.class))
{
if (BOSSES.contains(boss.getId()) && !boss.isAlikeDead())
{
Broadcast.toKnownPlayers((wo), new ExShowScreenMessage(BROADCAST_MESSAGES.get(EVENT_MESSAGE_WEAK), ExShowScreenMessage.TOP_CENTER, 5000));
break;
}
}
}
}
cancelQuestTimer("KEBER_EVENT_END", null, null);
startQuestTimer("KEBER_EVENT_START", getMsTimeForEventStage(1), null, null);
changeNpcSpawn(3, true, true);
break;
}
}
return null;
}
@Override
public String onFirstTalk(Npc npc, Player player)
{
return "34216-01.html";
}
@Override
public String onSpawn(Npc npc)
{
final int type = getFieldType(npc.getId());
final boolean eventIsPending = (getQuestTimer("KEBER_EVENT_START", null, null) != null) && getQuestTimer("KEBER_EVENT_START", null, null).isActive();
final boolean eventOnBossStage = (getQuestTimer("KEBER_EVENT_END", null, null) != null) && getQuestTimer("KEBER_EVENT_END", null, null).isActive();
if ((type != -1) && (npc.getId() == NORMAL_MINIONS.get(type)))
{
if (eventIsPending || eventOnBossStage)
{
npc.getSpawn().stopRespawn();
npc.deleteMe();
return super.onSpawn(npc);
}
final int eliteMonsterId = ELITE_MINIONS.get(type);
final int brainWashedMonsterId = BRAINWASHED_MINIONS.get(type);
final int nearbyMonstersCount = World.getInstance().getVisibleObjects(npc, Npc.class).stream().filter(nearby -> ((nearby.getId() == NORMAL_MINIONS.get(type)) || (nearby.getId() == eliteMonsterId) || (nearby.getId() == brainWashedMonsterId))).toList().size();
final int maxSpawnMonsters = MINION_MAX_COUNT.length() == 0 ? 0 : MINION_MAX_COUNT.get(type);
if (nearbyMonstersCount >= maxSpawnMonsters)
{
npc.deleteMe();
return super.onSpawn(npc);
}
final int killedCount = MINION_KILL_COUNTER.get(type);
if (killedCount >= (ELITE_MONSTER_COUNT + BRAINWASHED_MONSTER_COUNT))
{
addSpawn(brainWashedMonsterId, npc.getLocation());
npc.deleteMe();
}
else if (killedCount >= ELITE_MONSTER_COUNT)
{
addSpawn(eliteMonsterId, npc.getLocation());
npc.deleteMe();
}
}
else if (BOSSES.contains(npc.getId()))
{
// Broadcast to nearby players string which says "monster respawn"
Broadcast.toKnownPlayers(npc, new ExShowScreenMessage(BROADCAST_MESSAGES.get(npc.getId()), ExShowScreenMessage.TOP_CENTER, 5000));
World.getInstance().getVisibleObjects(npc, Player.class).stream().findAny().ifPresent(player -> addAttackPlayerDesire(npc, player));
}
return super.onSpawn(npc);
}
@Override
public String onKill(Npc npc, Player killer, boolean isSummon)
{
if (NORMAL_MINIONS.contains(npc.getId()) || ELITE_MINIONS.contains(npc.getId()))
{
final int type = getFieldType(npc.getId());
int count = MINION_KILL_COUNTER.get(type);
if ((count >= ELITE_MONSTER_COUNT) && ELITE_MINIONS.contains(npc.getId()))
{
MINION_KILL_COUNTER.addAndGet(type, 1);
}
else if (count < ELITE_MONSTER_COUNT)
{
MINION_KILL_COUNTER.addAndGet(type, 1);
}
}
else
{
final Set<ItemChanceHolder> monsterDrop = ((npc.getTemplate().getLevel() > (killer.getLevel() - 15)) && (npc.getTemplate().getLevel() < (killer.getLevel() + 15))) ? NPC_DROP.getOrDefault(npc.getId(), MINION_DROP) : new HashSet<>();
for (ItemChanceHolder drop : monsterDrop)
{
if (getRandom(100) < drop.getChance())
{
if ((drop.getId() == 94481) && (killer.getClan() != null)) // Avoid to get clan points as item.
{
killer.getClan().addExp(killer.getObjectId(), (int) drop.getCount());
}
else
{
killer.addItem(_eventName, drop.getId(), drop.getCount(), null, true);
}
}
}
if (BOSSES.contains(npc.getId()))
{
changeNpcSpawn(getFieldType(npc.getId()), true, false);
Broadcast.toKnownPlayers(killer, new ExShowScreenMessage(BROADCAST_MESSAGES.get(EVENT_MESSAGE_KILL), ExShowScreenMessage.TOP_CENTER, 10000, killer.getName()));
killer.sendPacket(new ExShowScreenMessage(BROADCAST_MESSAGES.get(EVENT_MESSAGE_TO_KILLER), ExShowScreenMessage.TOP_CENTER, 5000));
for (Npc crystal : World.getInstance().getVisibleObjects(npc, Npc.class))
{
if (crystal.getId() == KEBER_SEAL_STONE)
{
crystal.setDisplayEffect(2);
break;
}
}
}
}
return super.onKill(npc, killer, isSummon);
}
private long getMsTimeForEventStage(int type)
{
final Calendar returnTime = Calendar.getInstance();
final long currentTime = System.currentTimeMillis();
returnTime.set(Calendar.MILLISECOND, 0);
returnTime.set(Calendar.SECOND, 0);
if (type == 1)
{
returnTime.set(Calendar.MINUTE, 0);
returnTime.add(Calendar.HOUR_OF_DAY, 1);
}
else if (type == 2)
{
returnTime.add(Calendar.MINUTE, 10);
}
else if (type == 3)
{
returnTime.add(Calendar.MINUTE, 5);
}
if (returnTime.getTimeInMillis() < currentTime)
{
returnTime.add(Calendar.DAY_OF_YEAR, 1);
}
return returnTime.getTimeInMillis() - currentTime;
}
/**
* Because value is set and we know all ids, it can be used to get fast access to any field monster.
* @param npcId
* @return 0 - Plains, 1 - War-Torn, 2 - Silent Valley
*/
private int getFieldType(int npcId)
{
if ((npcId == KEBER_LOW) || (npcId == KISHAN) || (npcId == NORMAL_MINIONS.get(0)) || (npcId == ELITE_MINIONS.get(0)) || (npcId == BRAINWASHED_MINIONS.get(0)))
{
return 0;
}
else if ((npcId == KEBER_MIDDLE) || (npcId == NOMA) || (npcId == NORMAL_MINIONS.get(1)) || (npcId == ELITE_MINIONS.get(1)) || (npcId == BRAINWASHED_MINIONS.get(1)))
{
return 1;
}
else if ((npcId == KEBER_HIGH) || (npcId == SPALL) || (npcId == NORMAL_MINIONS.get(2)) || (npcId == ELITE_MINIONS.get(2)) || (npcId == BRAINWASHED_MINIONS.get(2)))
{
return 2;
}
return -1;
}
private void changeNpcSpawn(int type, boolean delete, boolean removeAll)
{
if (removeAll)
{
SPAWN_TEMPLATE.get().getGroups().forEach(SpawnGroup::despawnAll);
}
for (WorldObject wo : World.getInstance().getVisibleObjects())
{
if (!wo.isMonster())
{
continue;
}
if (((type == 0) || (type == 3)) //
&& ((!removeAll && (NORMAL_MINIONS.get(0) == wo.getId())) //
|| (ELITE_MINIONS.get(0) == wo.getId()) //
|| (BRAINWASHED_MINIONS.get(0) == wo.getId()) //
|| (removeAll && ((KISHAN == wo.getId()) || (KEBER_LOW == wo.getId())))))
{
removeSpawn(wo, delete);
}
if (((type == 1) || (type == 3)) //
&& ((!removeAll && (NORMAL_MINIONS.get(1) == wo.getId())) //
|| (ELITE_MINIONS.get(1) == wo.getId()) //
|| (BRAINWASHED_MINIONS.get(1) == wo.getId()) //
|| (removeAll && ((NOMA == wo.getId()) || (KEBER_MIDDLE == wo.getId())))))
{
removeSpawn(wo, delete);
}
if (((type == 2) || (type == 3)) //
&& ((!removeAll && (NORMAL_MINIONS.get(2) == wo.getId())) //
|| (ELITE_MINIONS.get(2) == wo.getId()) //
|| (BRAINWASHED_MINIONS.get(2) == wo.getId()) //
|| (removeAll && ((SPALL == wo.getId()) || (KEBER_HIGH == wo.getId())))))
{
removeSpawn(wo, delete);
}
}
}
private void removeSpawn(WorldObject wo, boolean delete)
{
final Npc npc = ((Npc) wo);
npc.getSpawn().stopRespawn();
if (delete && (!BOSSES.contains(npc.getTemplate().getId()) || !npc.isAlikeDead()))
{
npc.deleteMe();
}
}
public static void main(String[] args)
{
new BattleWithKeber();
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<event name="Battle With Keber" active="19 08 2020-16 10 2020" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/eventConfig.xsd">
<spawnlist>
<add npc="34216" x="146966" y="25726" z="-2020" heading="6133" /> <!-- Bonnie -->
<add npc="34216" x="83673" y="148857" z="-3413" heading="29500" /> <!-- Bonnie -->
<add npc="18551" x="133474" y="7730" z="-4320" heading="0" /> <!-- Keber's Seal Stone / Plains of Glory -->
<add npc="18551" x="161481" y="22041" z="-3696" heading="0" /> <!-- Keber's Seal Stone / War-Torn Plains -->
<add npc="18551" x="180942" y="52673" z="-6100" heading="0" /> <!-- Keber's Seal Stone / Silent Valley -->
</spawnlist>
</event>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../xsd/spawns.xsd">
<spawn name="KEBER_MINIONS" spawnByDefault="false" >
<group name="KISHAN" spawnByDefault="false" >
<territories>
<territory shape="NPoly" rad="1" minZ="-4200" maxZ="-3900">
<node x="132014" y="8285"/>
<node x="131835" y="7488"/>
<node x="133928" y="6075"/>
<node x="134502" y="6557"/>
<node x="134451" y="7720"/>
<node x="133914" y="8721"/>
</territory>
</territories>
<npc id="18539" count="100" respawnTime="10sec" respawnRandom="0sec" /> <!-- Kishan's Minion -->
</group>
<group name="NOMA" spawnByDefault="false" >
<territories>
<territory shape="NPoly" rad="1" minZ="-3740" maxZ="-3700">
<node x="160635" y="21541"/>
<node x="161147" y="20888"/>
<node x="162234" y="20084"/>
<node x="161978" y="23005"/>
<node x="162910" y="23084"/>
<node x="163398" y="22379"/>
<node x="163727" y="23411"/>
<node x="162218" y="23713"/>
<node x="161268" y="23180"/>
</territory>
</territories>
<npc id="18543" count="120" respawnTime="10sec" respawnRandom="0sec" /> <!-- Noma's Minion -->
</group>
<group name="SPALL" spawnByDefault="false" >
<territories>
<territory shape="Cylinder" rad="700" minZ="-6100" maxZ="-6000">
<node x="180942" y="52673"/>
</territory>
</territories>
<npc id="18547" count="80" respawnTime="10sec" respawnRandom="0sec" /> <!-- Spall's Minion -->
</group>
</spawn>
</list>

View File

@ -1137,6 +1137,10 @@
<item id="57" min="439" max="485" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18540" level="63" type="Monster" name="Kishan's Minion" title="Elite">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1164,6 +1168,10 @@
<item id="57" min="1171" max="1295" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18541" level="63" type="Monster" name="Kishan's Minion" title="Brainwashed">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1186,6 +1194,9 @@
<radius normal="9" />
<height normal="41.5" />
</collision>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
</skillList>
</npc>
<npc id="18542" level="69" type="RaidBoss" name="Noma" title="Keber's Henchman">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1207,6 +1218,10 @@
<radius normal="35" />
<height normal="48.1" />
</collision>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="12" /> <!-- HP Increase 4x -->
</skillList>
</npc>
<npc id="18543" level="69" type="Monster" name="Noma's Minion">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1234,6 +1249,10 @@
<item id="57" min="836" max="924" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="11" /> <!-- Giants -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18544" level="69" type="Monster" name="Noma's Minion" title="Elite">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1260,6 +1279,10 @@
<item id="57" min="2233" max="2468" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="11" /> <!-- Giants -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18545" level="69" type="Monster" name="Noma's Minion" title="Brainwashed">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1282,6 +1305,9 @@
<radius normal="15" />
<height normal="40" />
</collision>
<skillList>
<skill id="4416" level="11" /> <!-- Giants -->
</skillList>
</npc>
<npc id="18546" level="75" type="RaidBoss" name="Spall" title="Keber's Henchman">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1303,6 +1329,10 @@
<radius normal="36.3" />
<height normal="65.2" />
</collision>
<skillList>
<skill id="4416" level="11" /> <!-- Giants -->
<skill id="4408" level="12" /> <!-- HP Increase 4x -->
</skillList>
</npc>
<npc id="18547" level="75" type="Monster" name="Spall's Minion">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1329,6 +1359,10 @@
<item id="57" min="1188" max="1313" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18548" level="75" type="Monster" name="Spall's Minion" title="Elite">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1355,6 +1389,10 @@
<item id="57" min="3135" max="3465" chance="100" /> <!-- Adena -->
</drop>
</dropLists>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
<skill id="4408" level="10" /> <!-- HP Increase 2x -->
</skillList>
</npc>
<npc id="18549" level="75" type="Monster" name="Spall's Minion" title="Brainwashed">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1376,6 +1414,9 @@
<radius normal="30.8" />
<height normal="51.065" />
</collision>
<skillList>
<skill id="4416" level="6" /> <!-- Humanoids -->
</skillList>
</npc>
<npc id="18550" level="85" type="Folk" name="">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1396,8 +1437,7 @@
<height normal="0.1" />
</collision>
</npc>
<npc id="18551" level="80" type="Monster" name="Keber's Seal Stone">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
<npc id="18551" level="80" type="Folk" name="Keber's Seal Stone">
<race>ETC</race>
<sex>MALE</sex>
<acquire exp="5786" />
@ -1411,11 +1451,14 @@
</speed>
<hitTime>600</hitTime>
</stats>
<status attackable="true" />
<status attackable="false" randomWalk="false" targetable="false" talkable="false" undying="true" showName="false" />
<collision>
<radius normal="25" />
<height normal="62.5" />
</collision>
<skillList>
<skill id="4416" level="2" /> <!-- Magical Creatures -->
</skillList>
</npc>
<npc id="18552" level="69" type="RaidBoss" name="Keber" title="Maddened">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1437,6 +1480,10 @@
<radius normal="60" />
<height normal="99.5" />
</collision>
<skillList>
<skill id="4416" level="7" /> <!-- Spirits -->
<skill id="4408" level="12" /> <!-- HP Increase 4x -->
</skillList>
</npc>
<npc id="18553" level="75" type="RaidBoss" name="Keber" title="Maddened">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
@ -1458,6 +1505,10 @@
<radius normal="60" />
<height normal="99.5" />
</collision>
<skillList>
<skill id="4416" level="7" /> <!-- Spirits -->
<skill id="4408" level="12" /> <!-- HP Increase 4x -->
</skillList>
</npc>
<npc id="18554" level="85" type="Monster" name="Otherworldly Shard" title="Full of Energy">
<!-- AUTO GENERATED NPC TODO: FIX IT -->

View File

@ -431,13 +431,13 @@
</attribute>
<abnormalResist physical="0" magical="0" />
</stats>
<status attackable="false" undying="true" canMove="false" targetable="false" showName="false" />
<status attackable="false" undying="true" canMove="false" targetable="true" showName="true" />
<collision>
<radius normal="11" />
<height normal="17" />
</collision>
<skillList>
<skill id="4416" level="2" /> <!-- Magical Creatures -->
<skill id="4416" level="18" /> <!-- Dwarves -->
<skill id="4408" level="1" /> <!-- HP Increase (1x) -->
<skill id="4409" level="1" /> <!-- MP Increase (1x) -->
<skill id="4410" level="11" /> <!-- Average Damage Dealer -->