Free version update 14-12-2023.

This commit is contained in:
MobiusDevelopment
2023-12-14 02:11:28 +02:00
parent 6a0a4be1ea
commit 1204ad8e00
6352 changed files with 98838 additions and 68045 deletions

View File

@@ -22,6 +22,7 @@ import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.actor.instance.GrandBoss;
@@ -50,6 +51,10 @@ public class DrChaos extends AbstractNpcAI
private static final byte NORMAL = 0; // Dr. Chaos is in NPC form.
private static final byte CRAZY = 1; // Dr. Chaos entered on golem form.
private static final byte DEAD = 2; // Dr. Chaos has been killed and has not yet spawned.
private static final int CHAOS_X = 96320;
private static final int CHAOS_Y = -110912;
private static final int CHAOS_Z = -3328;
private static final int CHAOS_HEAD = 8191;
private long _lastAttackVsGolem = 0;
private int _pissedOffTimer;
@@ -76,7 +81,7 @@ public class DrChaos extends AbstractNpcAI
{
// The time has already expired while the server was offline. Delete the saved time and
// immediately spawn Dr. Chaos. Also the state need to be changed for NORMAL
addSpawn(DOCTOR_CHAOS, 96320, -110912, -3328, 8191, false, 0, false);
addSpawn(DOCTOR_CHAOS, CHAOS_X, CHAOS_Y, CHAOS_Z, CHAOS_HEAD, false, 0, false);
GrandBossManager.getInstance().setStatus(CHAOS_GOLEM, NORMAL);
}
}
@@ -109,84 +114,115 @@ public class DrChaos extends AbstractNpcAI
@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
if (event.equalsIgnoreCase("reset_drchaos"))
switch (event)
{
GrandBossManager.getInstance().setStatus(CHAOS_GOLEM, NORMAL);
addSpawn(DOCTOR_CHAOS, 96320, -110912, -3328, 8191, false, 0, false);
}
// despawn the live Dr. Chaos after 30 minutes of inactivity
else if (event.equalsIgnoreCase("golem_despawn"))
{
if ((npc.getId() == CHAOS_GOLEM) && ((_lastAttackVsGolem + 1800000) < System.currentTimeMillis()))
case "reset_drchaos":
{
final Npc chaos = addSpawn(DOCTOR_CHAOS, 96320, -110912, -3328, 8191, false, 0, false); // spawn Dr. Chaos
GrandBossManager.getInstance().setStatus(CHAOS_GOLEM, NORMAL); // mark Dr. Chaos is not crazy any more
cancelQuestTimer("golem_despawn", chaos, null);
GrandBossManager.getInstance().setStatus(CHAOS_GOLEM, NORMAL);
addSpawn(DOCTOR_CHAOS, CHAOS_X, CHAOS_Y, CHAOS_Z, CHAOS_HEAD, false, 0, false);
break;
}
case "golem_despawn": // despawn the live Dr. Chaos after 30 minutes of inactivity
{
if ((npc.getId() == CHAOS_GOLEM) && ((_lastAttackVsGolem + 1800000) < System.currentTimeMillis()))
{
final Npc chaos = addSpawn(DOCTOR_CHAOS, CHAOS_X, CHAOS_Y, CHAOS_Z, CHAOS_HEAD, false, 0, false); // spawn Dr. Chaos
GrandBossManager.getInstance().setStatus(CHAOS_GOLEM, NORMAL); // mark Dr. Chaos is not crazy any more
cancelQuestTimer("golem_despawn", chaos, null);
cancelQuestTimers("DISTANCE_CHECK");
// Despawn the war golem.
npc.deleteMe();
}
break;
}
case "1":
{
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 2));
npc.broadcastPacket(new SpecialCamera(npc, 1, -200, 15, 5500, 1000, 13500, 0, 0, 0, 0, 0));
break;
}
case "2":
{
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 3));
break;
}
case "3":
{
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
break;
}
case "4":
{
npc.broadcastPacket(new SpecialCamera(npc, 1, -150, 10, 3500, 1000, 5000, 0, 0, 0, 0, 0));
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(95928, -110671, -3340, 0));
break;
}
case "5":
{
final GrandBoss golem = (GrandBoss) addSpawn(CHAOS_GOLEM, 96080, -110822, -3343, 0, false, 0, false);
GrandBossManager.getInstance().addBoss(golem);
startQuestTimer("DISTANCE_CHECK", 10000, golem, null, true);
golem.broadcastPacket(new SpecialCamera(npc, 30, 200, 20, 6000, 700, 8000, 0, 0, 0, 0, 0));
golem.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
golem.broadcastPacket(new PlaySound(1, "Rm03_A", 0, 0, 0, 0, 0));
// Despawn the war golem.
// start monitoring Dr. Chaos's inactivity
_lastAttackVsGolem = System.currentTimeMillis();
startQuestTimer("golem_despawn", 60000, golem, null, true);
// Delete Dr. Chaos after spawned the war golem.
npc.deleteMe();
break;
}
}
else if (event.equalsIgnoreCase("1"))
{
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 2));
npc.broadcastPacket(new SpecialCamera(npc, 1, -200, 15, 5500, 1000, 13500, 0, 0, 0, 0, 0));
}
else if (event.equalsIgnoreCase("2"))
{
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 3));
}
else if (event.equalsIgnoreCase("3"))
{
npc.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
}
else if (event.equalsIgnoreCase("4"))
{
npc.broadcastPacket(new SpecialCamera(npc, 1, -150, 10, 3500, 1000, 5000, 0, 0, 0, 0, 0));
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(95928, -110671, -3340, 0));
}
else if (event.equalsIgnoreCase("5"))
{
final GrandBoss golem = (GrandBoss) addSpawn(CHAOS_GOLEM, 96080, -110822, -3343, 0, false, 0, false);
GrandBossManager.getInstance().addBoss(golem);
golem.broadcastPacket(new SpecialCamera(npc, 30, 200, 20, 6000, 700, 8000, 0, 0, 0, 0, 0));
golem.broadcastPacket(new SocialAction(npc.getObjectId(), 1));
golem.broadcastPacket(new PlaySound(1, "Rm03_A", 0, 0, 0, 0, 0));
// start monitoring Dr. Chaos's inactivity
_lastAttackVsGolem = System.currentTimeMillis();
startQuestTimer("golem_despawn", 60000, golem, null, true);
// Delete Dr. Chaos after spawned the war golem.
npc.deleteMe();
}
// Check every sec if someone is in range, if found, launch one task to decrease the timer.
else if (event.equalsIgnoreCase("paranoia_activity") && (GrandBossManager.getInstance().getStatus(CHAOS_GOLEM) == NORMAL))
{
for (Player obj : World.getInstance().getVisibleObjectsInRange(npc, Player.class, 500))
case "paranoia_activity":
{
if (obj.isDead())
if (GrandBossManager.getInstance().getStatus(CHAOS_GOLEM) == NORMAL)
{
continue;
for (Player obj : World.getInstance().getVisibleObjectsInRange(npc, Player.class, 500))
{
if (obj.isDead())
{
continue;
}
_pissedOffTimer -= 1;
// Make him speak.
if (_pissedOffTimer == 15)
{
npc.broadcastSay(ChatType.NPC_GENERAL, "How dare you trespass into my territory! Have you no fear?");
}
// That was "too much" for that time.
if (_pissedOffTimer <= 0)
{
crazyMidgetBecomesAngry(npc);
}
}
}
_pissedOffTimer -= 1;
// Make him speak.
if (_pissedOffTimer == 15)
if (npc.calculateDistance2D(CHAOS_X, CHAOS_Y, CHAOS_Z) > 2000)
{
npc.broadcastSay(ChatType.NPC_GENERAL, "How dare you trespass into my territory! Have you no fear?");
((Attackable) npc).clearAggroList();
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(CHAOS_X, CHAOS_Y, CHAOS_Z, 0));
}
// That was "too much" for that time.
if (_pissedOffTimer <= 0)
break;
}
case "DISTANCE_CHECK":
{
if ((npc == null) || npc.isDead())
{
crazyMidgetBecomesAngry(npc);
cancelQuestTimers("DISTANCE_CHECK");
}
else if (npc.calculateDistance2D(npc.getSpawn()) > 10000)
{
((Attackable) npc).clearAggroList();
// npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(CHAOS_X, CHAOS_Y, CHAOS_Z, 0));
npc.teleToLocation(npc.getSpawn(), false);
}
break;
}
}
return super.onAdvEvent(event, npc, player);
}
@@ -225,6 +261,10 @@ public class DrChaos extends AbstractNpcAI
// Initialization of the paranoia.
startQuestTimer("paranoia_activity", 1000, npc, null, true);
cancelQuestTimer("DISTANCE_CHECK", npc, null);
startQuestTimer("DISTANCE_CHECK", 10000, npc, null, true);
return null;
}
@@ -243,6 +283,10 @@ public class DrChaos extends AbstractNpcAI
final StatSet info = GrandBossManager.getInstance().getStatSet(CHAOS_GOLEM);
info.set("respawn_time", System.currentTimeMillis() + respawnTime);
GrandBossManager.getInstance().setStatSet(CHAOS_GOLEM, info);
// Stop distance check task.
cancelQuestTimers("DISTANCE_CHECK");
return null;
}

View File

@@ -240,7 +240,7 @@ public class CabaleBuffer extends AbstractNpcAI
*/
private boolean handleCast(Player player, int skillId)
{
if (player.isDead() || !player.isSpawned() || !_npc.isInsideRadius2D(player, DISTANCE_TO_WATCH_OBJECT))
if (player.isDead() || !player.isSpawned() || !_npc.isInsideRadius3D(player, DISTANCE_TO_WATCH_OBJECT))
{
return false;
}

View File

@@ -37,6 +37,7 @@ import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.actor.Summon;
import org.l2jmobius.gameserver.model.actor.instance.Door;
import org.l2jmobius.gameserver.model.events.EventType;
import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent;
import org.l2jmobius.gameserver.model.events.impl.creature.OnCreatureDeath;
@@ -261,6 +262,8 @@ public class TvT extends Event
world.setInstance(InstanceManager.getInstance().createDynamicInstance(INSTANCE_ID));
InstanceManager.getInstance().addWorld(world);
PVP_WORLD = world;
// Make sure doors are closed.
PVP_WORLD.getDoors().forEach(Door::closeMe);
// Randomize player list and separate teams.
final List<Player> playerList = new ArrayList<>(PLAYER_LIST.size());
playerList.addAll(PLAYER_LIST);

View File

@@ -377,8 +377,8 @@ public class DropSearchBoard implements IParseBoardHandler
icon = "icon.etc_question_mark_i00";
}
builder.append("<td>");
builder.append("<button value=\".\" action=\"bypass _bbs_search_drop " + item.getId() + " 1 $order $level\" width=32 height=32 back=\"" + icon + "\" fore=\"" + icon + "\">");
builder.append("<td width=30 background=\"" + icon + "\">");
builder.append("<button value=\" \" action=\"bypass _bbs_search_drop " + item.getId() + " 1 $order $level\" width=30 height=30 back=\"\" fore=\"\">");
builder.append("</td>");
builder.append("<td width=200>");
builder.append("&#").append(item.getId()).append(";");

View File

@@ -17,10 +17,10 @@
package quests.Q00604_DaimonTheWhiteEyedPart2;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.data.SpawnTable;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.enums.QuestSound;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.quest.Quest;
@@ -265,6 +265,6 @@ public class Q00604_DaimonTheWhiteEyedPart2 extends Quest
private static boolean isDaimonSpawned()
{
return SpawnTable.getInstance().getAnySpawn(DAIMON_THE_WHITE_EYED) != null;
return World.getInstance().getVisibleObjects().stream().anyMatch(object -> object.getId() == DAIMON_THE_WHITE_EYED);
}
}

View File

@@ -17,9 +17,9 @@
package quests.Q00625_TheFinestIngredientsPart2;
import org.l2jmobius.Config;
import org.l2jmobius.gameserver.data.SpawnTable;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.holders.ItemHolder;
@@ -121,7 +121,7 @@ public class Q00625_TheFinestIngredientsPart2 extends Quest
{
rewardItems(player, GREATER_DYE_OF_DEX_2);
}
qs.exitQuest(false, true);
qs.exitQuest(true, true);
htmltext = event;
}
else
@@ -137,12 +137,11 @@ public class Q00625_TheFinestIngredientsPart2 extends Quest
{
if (hasItem(player, FOOD_FOR_BUMBALUMP))
{
qs.setCond(2, true);
if (!isBumbalumpSpawned())
{
qs.setCond(2, true);
takeItem(player, FOOD_FOR_BUMBALUMP);
final Npc umpaloopa = addSpawn(ICICLE_EMPEROR_BUMBALUMP, ICICLE_EMPEROR_BUMBALUMP_LOC);
umpaloopa.setSummoner(player);
addSpawn(ICICLE_EMPEROR_BUMBALUMP, ICICLE_EMPEROR_BUMBALUMP_LOC);
htmltext = event;
}
else
@@ -155,6 +154,18 @@ public class Q00625_TheFinestIngredientsPart2 extends Quest
htmltext = "31542-04.html";
}
}
else if (qs.isCond(2))
{
if (!isBumbalumpSpawned())
{
addSpawn(ICICLE_EMPEROR_BUMBALUMP, ICICLE_EMPEROR_BUMBALUMP_LOC);
htmltext = event;
}
else
{
htmltext = "31542-03.html";
}
}
break;
}
case "NPC_TALK":
@@ -182,7 +193,7 @@ public class Q00625_TheFinestIngredientsPart2 extends Quest
{
if (talker.getLevel() >= MIN_LEVEL)
{
htmltext = (hasItem(talker, SOY_SOURCE_JAR)) ? "31521-01.htm" : "31521-02.htm";
htmltext = hasItem(talker, SOY_SOURCE_JAR) ? "31521-01.htm" : "31521-02.htm";
}
else
{
@@ -222,18 +233,14 @@ public class Q00625_TheFinestIngredientsPart2 extends Quest
{
case 1:
{
if (hasItem(talker, FOOD_FOR_BUMBALUMP))
{
htmltext = "31542-01.html";
}
htmltext = "31542-01.html";
break;
}
case 2:
{
if (!isBumbalumpSpawned())
{
final Npc umpaloopa = addSpawn(ICICLE_EMPEROR_BUMBALUMP, ICICLE_EMPEROR_BUMBALUMP_LOC);
umpaloopa.setSummoner(talker);
addSpawn(ICICLE_EMPEROR_BUMBALUMP, ICICLE_EMPEROR_BUMBALUMP_LOC);
htmltext = "31542-02.html";
}
else
@@ -265,17 +272,23 @@ public class Q00625_TheFinestIngredientsPart2 extends Quest
@Override
public String onKill(Npc npc, Player killer, boolean isSummon)
{
final QuestState qs = getRandomPartyMemberState(killer, 1, 2, npc);
if ((qs != null) && Util.checkIfInRange(Config.ALT_PARTY_RANGE, npc, killer, true) && (npc.getSummoner() == killer))
executeForEachPlayer(killer, npc, isSummon, true, false);
return super.onKill(npc, killer, isSummon);
}
@Override
public void actionForEachPlayer(Player player, Npc npc, boolean isSummon)
{
final QuestState qs = getQuestState(player, false);
if ((qs != null) && qs.isCond(2) && Util.checkIfInRange(Config.ALT_PARTY_RANGE, npc, player, true))
{
qs.setCond(3, true);
giveItems(qs.getPlayer(), SPECIAL_YETI_MEAT);
giveItems(player, SPECIAL_YETI_MEAT);
}
return super.onKill(npc, killer, isSummon);
}
private static boolean isBumbalumpSpawned()
{
return SpawnTable.getInstance().getAnySpawn(ICICLE_EMPEROR_BUMBALUMP) != null;
return World.getInstance().getVisibleObjects().stream().anyMatch(object -> object.getId() == ICICLE_EMPEROR_BUMBALUMP);
}
}

View File

@@ -218,7 +218,7 @@ public class Q00638_SeekersOfTheHolyGrail extends Quest
final DropInfo info = MOBS_DROP_CHANCES.get(npc.getId());
if (giveItemRandomly(qs.getPlayer(), npc, info.getId(), 1, 0, info.getChance(), true) && (info.getKeyId() > 0) && (getRandom(100) < info.getKeyChance()))
{
npc.dropItem(qs.getPlayer(), info.getKeyId(), info.getKeyCount());
giveItems(qs.getPlayer(), info.getKeyId(), info.getKeyCount());
}
}
return super.onKill(npc, killer, isSummon);

View File

@@ -17,6 +17,7 @@
package quests.Q00655_AGrandPlanForTamingWildBeasts;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.l2jmobius.gameserver.cache.HtmCache;
import org.l2jmobius.gameserver.enums.QuestSound;
@@ -181,7 +182,15 @@ public class Q00655_AGrandPlanForTamingWildBeasts extends Quest
private static String getSiegeDate()
{
final SiegableHall hall = CHSiegeManager.getInstance().getSiegableHall(ClanHallSiegeEngine.BEAST_FARM);
return hall != null ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(hall.getSiegeDate()) : "Error in date.";
if (hall != null)
{
final Calendar calendar = hall.getSiegeDate();
if (calendar != null)
{
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
}
}
return "Unknown date.";
}
/**

View File

@@ -564,6 +564,7 @@
<set name="material" val="PAPER" />
<set name="weight" val="120" />
<set name="price" val="100" />
<set name="is_stackable" val="true" />
</item>
<item id="1048" type="EtcItem" name="Spellbook: Might">
<!-- Spellbook needed to learn Might. Used by Human Mystics, Elven Mystics and Dark Mystics. Required level: 7 -->
@@ -653,6 +654,7 @@
<set name="material" val="PAPER" />
<set name="weight" val="120" />
<set name="price" val="500" />
<set name="is_stackable" val="true" />
</item>
<item id="1058" type="EtcItem" name="Spellbook: Shield">
<!-- Spellbook needed to learn Shield. Used by Human Mystics, Elven Mystics and Dark Mystics. Required level: 7 -->
@@ -670,6 +672,7 @@
<set name="material" val="PAPER" />
<set name="weight" val="120" />
<set name="price" val="500" />
<set name="is_stackable" val="true" />
</item>
<item id="1060" type="EtcItem" name="Lesser Healing Potion">
<!-- A magical potion that slowly restores HP. Low endurance. -->

View File

@@ -1349,6 +1349,7 @@
<set name="material" val="PAPER" />
<set name="weight" val="120" />
<set name="price" val="1250" />
<set name="is_stackable" val="true" />
</item>
<item id="1396" type="EtcItem" name="Spellbook: Surrender to Wind">
<!-- Spellbook needed to learn Surrender to Water -->
@@ -1357,6 +1358,7 @@
<set name="material" val="PAPER" />
<set name="weight" val="120" />
<set name="price" val="1250" />
<set name="is_stackable" val="true" />
</item>
<item id="1397" type="EtcItem" name="Spellbook: Peace">
<!-- Spellbook needed to learn Peace. Used by Clerics. Required level: 35 -->