I already send ALOT of examples, that is last time. Look on codeHi!, I'd like to know how to register a custom ByPassHandler.
I want to be able to call my bypass from <a action="bypass -h custombypass.CustomClass:customMethod">
Thanks!
package services;
import l2.gameserver.Config;
import l2.gameserver.model.Player;
import l2.gameserver.network.l2.components.SystemMsg;
import l2.gameserver.network.l2.s2c.NpcHtmlMessage;
import l2.gameserver.scripts.Functions;
import l2.gameserver.templates.item.ItemTemplate;
import l2.gameserver.utils.ItemFunctions;
public class MyCustomService extends Functions
{
public void myCustomBypassToHtml()
{
Player player = getSelf();
if(player == null)
return;
if(!Config.MY_CUSTOM_SERVICE) // If that is disabled we send service_disabled.htm
{
player.sendPacket(new NpcHtmlMessage(5).setFile("scripts/services/service_disabled.htm"));
return;
}
NpcHtmlMessage msg = new NpcHtmlMessage(5).setFile("scripts/services/my_custom_service_page.htm");
msg.replace("%item_id%", String.valueOf(Config.MY_CUSTOM_SERVICE_ITEM));
msg.replace("%item_count%", String.valueOf(Config.MY_CUSTOM_SERVICE_PRICE));
player.sendPacket(msg);
}
public void my_custom_functions()
{
Player player = getSelf();
if(player == null || !CheckPlayerConditions(player)) // Check null and basic condition
return;
if(!Config.MY_CUSTOM_SERVICE) // If that is disabled we send service_disabled.htm
{
player.sendPacket(new NpcHtmlMessage(5).setFile("scripts/services/service_disabled.htm"));
return;
}
if(!player.isInPeaceZone() || !player.getReflection().isDefault()) // If need check at zone peace or not
{
player.sendPacket(new NpcHtmlMessage(5).setFile("scripts/services/service_peace_zone.htm"));
return;
}
if(ItemFunctions.getItemCount(player, Config.MY_CUSTOM_SERVICE_ITEM) < Config.MY_CUSTOM_SERVICE_PRICE) // Check and take items
{
if(Config.MY_CUSTOM_SERVICE_ITEM == ItemTemplate.ITEM_ID_ADENA)
player.sendPacket(SystemMsg.YOU_DO_NOT_HAVE_ENOUGH_ADENA);
else
player.sendPacket(SystemMsg.INCORRECT_ITEM_COUNT);
return;
}
ItemFunctions.removeItem(player, Config.MY_CUSTOM_SERVICE_ITEM, Config.MY_CUSTOM_SERVICE_PRICE, true);
// HERE IS make any own code and change status or any else
player.sendMessage(new CustomMessage("my_custom_functions send Bla bla bla", player));
player.setHairColor(0);
player.setHairStyle(0);
player.setFace(0);
player.setBlaBlaBla(100500);
}
}
package services;
import l2.gameserver.Config;
import l2.gameserver.model.Player;
import l2.gameserver.model.instances.NpcInstance;
import l2.gameserver.network.l2.components.SystemMsg;
import l2.gameserver.network.l2.s2c.NpcHtmlMessage;
import l2.gameserver.scripts.Functions;
import l2.gameserver.templates.item.ItemTemplate;
import l2.gameserver.utils.ItemFunctions;
import l2.gameserver.network.l2.s2c.PlaySound;
public class Simplecode extends Functions
{
public void custom_quest_001()
{
//all req items and rewards
int start_item_id = 1879; //what item need to have to start the quest (cokes example)
int in_progress_item_id = 1867; //get this item to change quest state to in progress (animal skin example)
int bring_item_id = 1872; //items needed to complete quest (animal bone example)
int bring_item_count = 10; //item needed to complete ammount
int[] reward_item_ids = {57,57}; //reward item IDs, can be one or multiple, as many as need
int[] reward_item_counts = {100000, 10}; //quantities
Player player = getSelf();
if(player == null)
return;
if (ItemFunctions.getItemCount(player, start_item_id) < 1 && ItemFunctions.getItemCount(player, in_progress_item_id) < 1) //if dont have any quest items
{
player.sendPacket(new NpcHtmlMessage(5).setFile("custom_quests/no_talk.htm"));
return;
}
else {
if (ItemFunctions.getItemCount(player, start_item_id) == 1) { //start state
NpcHtmlMessage msg = new NpcHtmlMessage(5).setFile("custom_quests/quest_001_1.htm");
player.sendPacket(msg);
player.sendPacket(new PlaySound("ItemSound.quest_accept")); //accept middle finish itemGet
ItemFunctions.removeItem(player, start_item_id, 1, true);
ItemFunctions.addItem(player, in_progress_item_id, 1, true);
}
else if (ItemFunctions.getItemCount(player, in_progress_item_id) == 1 && ItemFunctions.getItemCount(player, bring_item_id) < bring_item_count) { //in progress state
NpcHtmlMessage msg = new NpcHtmlMessage(5).setFile("custom_quests/quest_001_2.htm");
player.sendPacket(msg);
player.sendPacket(new PlaySound("ItemSound.quest_middle"));
}
else if (ItemFunctions.getItemCount(player, in_progress_item_id) == 1 && ItemFunctions.getItemCount(player, bring_item_id) >= bring_item_count) { //quest finish state
NpcHtmlMessage msg = new NpcHtmlMessage(5).setFile("custom_quests/quest_001_3.htm");
player.sendPacket(msg);
player.sendPacket(new PlaySound("ItemSound.quest_finish"));
ItemFunctions.removeItem(player, in_progress_item_id, 1, true);
long itemCount = ItemFunctions.getItemCount(player, bring_item_id);
ItemFunctions.removeItem(player, bring_item_id, itemCount, true);
for (int i = 0; i < reward_item_ids.length; i++) {
ItemFunctions.addItem(player, reward_item_ids[i], reward_item_counts[i], true);
}
}
}
}
}
that is trash. Soon I will make a guide about quests and basic AI.Thanks @Deazer , your guides are very usefull.
I have no experience with Java, but with your guide im able to create my own simple custom quests.
Maybe someone can see if there is some issues ? it works, but more experienced people could see issues in the future.
Java:package services; import l2.gameserver.Config; import l2.gameserver.model.Player; import l2.gameserver.model.instances.NpcInstance; import l2.gameserver.network.l2.components.SystemMsg; import l2.gameserver.network.l2.s2c.NpcHtmlMessage; import l2.gameserver.scripts.Functions; import l2.gameserver.templates.item.ItemTemplate; import l2.gameserver.utils.ItemFunctions; import l2.gameserver.network.l2.s2c.PlaySound; public class Simplecode extends Functions { public void custom_quest_001() { //all req items and rewards int start_item_id = 1879; //what item need to have to start the quest (cokes example) int in_progress_item_id = 1867; //get this item to change quest state to in progress (animal skin example) int bring_item_id = 1872; //items needed to complete quest (animal bone example) int bring_item_count = 10; //item needed to complete ammount int[] reward_item_ids = {57,57}; //reward item IDs, can be one or multiple, as many as need int[] reward_item_counts = {100000, 10}; //quantities Player player = getSelf(); if(player == null) return; if (ItemFunctions.getItemCount(player, start_item_id) < 1 && ItemFunctions.getItemCount(player, in_progress_item_id) < 1) //if dont have any quest items { player.sendPacket(new NpcHtmlMessage(5).setFile("custom_quests/no_talk.htm")); return; } else { if (ItemFunctions.getItemCount(player, start_item_id) == 1) { //start state NpcHtmlMessage msg = new NpcHtmlMessage(5).setFile("custom_quests/quest_001_1.htm"); player.sendPacket(msg); player.sendPacket(new PlaySound("ItemSound.quest_accept")); //accept middle finish itemGet ItemFunctions.removeItem(player, start_item_id, 1, true); ItemFunctions.addItem(player, in_progress_item_id, 1, true); } else if (ItemFunctions.getItemCount(player, in_progress_item_id) == 1 && ItemFunctions.getItemCount(player, bring_item_id) < bring_item_count) { //in progress state NpcHtmlMessage msg = new NpcHtmlMessage(5).setFile("custom_quests/quest_001_2.htm"); player.sendPacket(msg); player.sendPacket(new PlaySound("ItemSound.quest_middle")); } else if (ItemFunctions.getItemCount(player, in_progress_item_id) == 1 && ItemFunctions.getItemCount(player, bring_item_id) >= bring_item_count) { //quest finish state NpcHtmlMessage msg = new NpcHtmlMessage(5).setFile("custom_quests/quest_001_3.htm"); player.sendPacket(msg); player.sendPacket(new PlaySound("ItemSound.quest_finish")); ItemFunctions.removeItem(player, in_progress_item_id, 1, true); long itemCount = ItemFunctions.getItemCount(player, bring_item_id); ItemFunctions.removeItem(player, bring_item_id, itemCount, true); for (int i = 0; i < reward_item_ids.length; i++) { ItemFunctions.addItem(player, reward_item_ids[i], reward_item_counts[i], true); } } } } }
<npc id="40034" name="Santa Girl" title="Merry Christmas!">
<set name="aggroRange" value="0" />
<set name="ai_type" value="CharacterAI" />
<set name="baseAtkRange" value="40" />
<set name="baseCON" value="43" />
<set name="baseCritRate" value="40" />
<set name="baseDEX" value="30" />
<set name="baseHpMax" value="2444.468" />
<set name="baseHpRate" value="1" />
<set name="baseHpReg" value="7.5" />
<set name="baseINT" value="21" />
<set name="baseMAtk" value="780" />
<set name="baseMAtkSpd" value="333" />
<set name="baseMDef" value="382" />
<set name="baseMEN" value="20" />
<set name="baseMpMax" value="1345.8" />
<set name="baseMpReg" value="2.7" />
<set name="basePAtk" value="1303" />
<set name="basePAtkSpd" value="253" />
<set name="basePDef" value="471" />
<set name="baseRunSpd" value="180" />
<set name="baseSTR" value="40" />
<set name="baseShldDef" value="0" />
<set name="baseShldRate" value="0" />
<set name="baseWIT" value="20" />
<set name="baseWalkSpd" value="110" />
<set name="collision_height" value="10" />
<set name="collision_radius" value="6.5" />
<set name="level" value="85" />
<set name="rewardExp" value="0" />
<set name="rewardRp" value="0" />
<set name="rewardSp" value="0" />
<set name="shots" value="NONE" />
<set name="texture" value="" />
<set name="displayId" value="40034"/>
<set name="type" value="Npc" />
<set name="htm_root" value="custom_quests/" />
<skills>
<skill id="4416" level="14" /> <!--Humans-->
</skills>
<attributes>
<defence attribute="fire" value="20" />
<defence attribute="water" value="20" />
<defence attribute="wind" value="20" />
<defence attribute="earth" value="20" />
<defence attribute="holy" value="20" />
<defence attribute="unholy" value="20" />
</attributes>
</npc>
<html>
<title> Santa Girl: </title>
<body>
<center>
Hey adventurer,
isn't it a great day?
<button width=100 height=18 action="bypass -h scripts_services.Simplecode:custom_quest_001" back="L2UI_CH3.bigbutton2_down" fore="L2UI_CH3.bigbutton2" value="Quests"></button><br>
<img src=icon.skill0143 width=32 height=32 align=left>
</center>
</body>
</html>
<html>
<title> Santa Girl: </title>
<body>
<center>
Hello adventurer, please kill gremlins and bring me 3 of their bones!
<img src=icon.skill0141 width=32 height=32 align=left>
</center>
</body>
</html>
=====================================
<html>
<title> Santa Girl: </title>
<body>
<center>
Hey there,
you still have to kills some gremlins.
<img src=icon.skill0143 width=32 height=32 align=left>
</center>
</body>
</html>
=======================================
<html>
<title> Santa Girl: </title>
<body>
<center>
Well done !
Take your reward, and go see another npc.
<img src=icon.skill0144 width=32 height=32 align=left>
</center>
</body>
</html>
Use DisableQuestId in server.propertiesHow do I identify the id of each quest, in case I want to delete from an xml using an extender? I can desactive via configs?
and for quest ID, the _number_questname?, for example 451?Use DisableQuestId in server.properties
package mods.kamalokaRetail;
import l2.gameserver.ThreadPoolManager;
import l2.gameserver.instancemanager.ReflectionManager;
import l2.gameserver.listener.actor.OnDeathListener;
import l2.gameserver.model.Creature;
import l2.gameserver.model.Player;
import l2.gameserver.model.entity.Reflection;
import l2.gameserver.model.instances.DoorInstance;
import l2.gameserver.network.l2.s2c.Say2;
import java.util.List;
import java.util.Arrays;
import java.util.logging.Logger;
public class CustomReflectionListener implements OnDeathListener {
private static final Logger LOGGER = Logger.getLogger(CustomReflectionListener.class.getName());
private final KamalokaConfig cfg;
// Accept config via constructor so it can be loaded once at startup
public CustomReflectionListener(KamalokaConfig cfg) {
this.cfg = cfg;
}
@Override
public void onDeath(Creature actor, Creature killer) {
if (cfg == null || !cfg.enabled) return;
if (actor == null || !actor.isNpc()) return;
if (actor.getReflection() == null || actor.getReflection() == ReflectionManager.DEFAULT) return;
if (killer == null || killer.getReflection() != actor.getReflection()) return;
int npcId = actor.getNpcId();
int[] doors = cfg.getDoorsFor(npcId);
if (doors.length > 0) {
for (int doorId : doors) {
openDoor(actor, doorId);
}
LOGGER.info("NPC " + npcId + " opened doors " + Arrays.toString(doors) + " in reflection " + actor.getReflection().getId());
if (cfg.announce) {
announce(actor, killer, cfg.openMsgAll, cfg.openMsgKiller);
}
}
if (cfg.isBoss(npcId) && cfg.announce) {
LOGGER.info("Boss NPC " + npcId + " died in reflection " + actor.getReflection().getId());
announce(actor, killer, cfg.bossMsgAll, cfg.bossMsgKiller);
}
// End-instance handling: if enabled and this NPC is configured to end the instance
if (cfg.endInstanceEnabled && cfg.isEndInstanceNpc(npcId)) {
long delaySeconds = cfg.getEndDelayFor(npcId);
// announce end messages if configured
if (cfg.announce) {
announce(actor, killer, cfg.endMsgAll, cfg.endMsgKiller);
}
try {
final Reflection ref = actor.getReflection();
if (ref != null) {
final long delayMs = Math.max(0L, delaySeconds * 1000L);
if (delayMs <= 0) {
LOGGER.info("Collapsing reflection " + ref.getId() + " immediately due to NPC " + npcId);
ref.collapse();
} else {
LOGGER.info("Scheduling collapse of reflection " + ref.getId() + " in " + delaySeconds + "s due to NPC " + npcId);
try {
// Primary: ask Reflection to start its collapse timer (internal cleanup, announcements, etc.)
ref.startCollapseTimer(delayMs);
if (cfg.extendedLogging) {
LOGGER.fine("Called Reflection.startCollapseTimer(" + delayMs + ") for reflection " + ref.getId());
}
} catch (Throwable t) {
LOGGER.warning("Reflection.startCollapseTimer threw for reflection " + ref.getId() + ": " + (t.getMessage() != null ? t.getMessage() : t.toString()));
}
// Backup: schedule a forced collapse to ensure the reflection actually ends.
// This runs after delayMs + 5s (buffer) and will call collapse() regardless of collapseStarted state.
final long backupDelay = delayMs + 5000L;
ThreadPoolManager.getInstance().schedule(() -> {
try {
LOGGER.warning("Backup collapse executing for reflection " + ref.getId() + " (npc " + npcId + ") after " + (backupDelay / 1000L) + "s");
ref.collapse();
} catch (Throwable t) {
LOGGER.warning("Backup collapse failed for reflection " + ref.getId() + ": " + (t.getMessage() != null ? t.getMessage() : t.toString()));
}
}, backupDelay);
}
}
} catch (Exception ex) {
LOGGER.warning("Failed to schedule/collapse reflection for NPC " + npcId + ": " + (ex.getMessage() != null ? ex.getMessage() : ex.toString()));
}
}
}
private void openDoor(Creature actor, int doorId) {
if (doorId <= 0) return;
DoorInstance door = actor.getReflection().getDoor(doorId);
if (door != null) {
door.openMe();
} else {
if (cfg != null && cfg.extendedLogging) {
LOGGER.fine("Door " + doorId + " not found in reflection " + (actor.getReflection() != null ? actor.getReflection().getId() : -1));
}
}
}
private void announce(Creature actor, Creature killer, String toAll, String toKiller) {
sendMessageToAll(actor, toAll);
sendMessageToKiller(killer, toKiller);
}
private void sendMessageToAll(Creature actor, String message) {
List<Player> players = actor.getReflection().getPlayers();
if (players == null || players.isEmpty()) return;
for (Player player : players) {
player.sendPacket(new Say2(0, cfg.chatType, cfg.chatName, message));
}
}
private void sendMessageToKiller(Creature killer, String message) {
if (killer == null || !killer.isPlayer()) return;
killer.getPlayer().sendPacket(new Say2(0, cfg.chatType, cfg.chatName, message));
}
}
package mods.kamalokaRetail;
import l2.gameserver.instancemanager.ReflectionManager;
import l2.gameserver.model.Creature;
import l2.gameserver.model.Player;
import l2.gameserver.model.instances.DoorInstance;
import l2.gameserver.model.instances.MonsterInstance;
import l2.gameserver.network.l2.components.ChatType;
import l2.gameserver.network.l2.s2c.Say2;
import l2.gameserver.templates.npc.NpcTemplate;
import java.util.List;
public class CustomReflectionInstance extends MonsterInstance {
public CustomReflectionInstance(int objectId, NpcTemplate template)
{
super(objectId, template);
}
public void onLoad ()
{
System.out.println("CustomReflectionInstance loaded successfully.");
}
@Override
protected void onDeath(Creature killer)
{
super.onDeath(killer);
if(getReflection() == killer.getReflection() && getReflection() != ReflectionManager.DEFAULT)
{
switch(getNpcId())
{
case 41000:
{
DoorInstance door = getReflection().getDoor(25150002);
if(door != null)
{
door.openMe();
sendMessageToAll("The door has been opened!");
sendMessageToKiller(killer, "You have opened the door!");
}
}
break;
case 41001:
{
DoorInstance door = getReflection().getDoor(25150003);
if(door != null)
{
door.openMe();
sendMessageToAll("The door has been opened!");
sendMessageToKiller(killer, "You have opened the door!");
}
}
break;
case 41002:
{
DoorInstance door = getReflection().getDoor(25150004);
if(door != null)
{
door.openMe();
sendMessageToAll("The door has been opened!");
sendMessageToKiller(killer, "You have opened the door!");
}
}
break;
case 41003:
{
DoorInstance door = getReflection().getDoor(25150005);
if(door != null)
{
door.openMe();
sendMessageToAll("The door has been opened!");
sendMessageToKiller(killer, "You have opened the door!");
}
}
break;
case 41004:
{
// Final mob - announce to all
sendMessageToAll("Congratulations! You have defeated the final boss!");
sendMessageToKiller(killer,"You have defeated the final boss!");
}
break;
}
}
}
private void sendMessageToAll(String message)
{
List<Player> players = getReflection().getPlayers();
if(players == null || players.isEmpty())
{
return;
}
for(Player player : players)
{
player.sendPacket(new Say2(0, ChatType.PARTY, "", message));
player.sendPacket(new Say2(1, ChatType.PARTY, "", message));
}
}
private void sendMessageToKiller(Creature killer, String message)
{
if(killer == null || !killer.isPlayer())
{
return;
}
Player player = killer.getPlayer();
player.sendPacket(new Say2(0, ChatType.PARTY, "", message));
}
}
[01:42:43] ERROR Not found type class for type: CustomReflection. NpcId: 41000
[01:42:43] ERROR Not found type class for type: CustomReflection. NpcId: 41001
[01:42:43] ERROR Not found type class for type: CustomReflection. NpcId: 41002
[01:42:43] ERROR Not found type class for type: CustomReflection. NpcId: 41003
CustomReflectionInstance cri = new CustomReflectionInstance(0, null);
NpcListenerList.addGlobal((Listener<Creature>) cri);
LOGGER.info("Loaded mod: CustomReflectionInstance");
[02:14:17] ERROR Scripts: Failed running mods.init.onLoad()
java.lang.NullPointerException: No template for Npc. Please check your datapack is setup correctly.
at l2.gameserver.model.instances.NpcInstance.<init>(Unknown Source)
at l2.gameserver.model.instances.MonsterInstance.<init>(Unknown Source)
at mods.kamalokaRetail.CustomReflectionInstance.<init>(CustomReflectionInstance.java:20)
at mods.init.onLoad(init.java:24)
at l2.gameserver.scripts.Scripts.init(Unknown Source)
at l2.gameserver.GameServer.<init>(Unknown Source)
at l2.gameserver.GameServer.main(Unknown Source)[/CODE[S]]
:confused:[/S]
[/SPOILER]
I always ask to describe the problem as simply as possible without going into technical details, as my profession is to solve technical tasks. People think that by appearing more technically competent they simplify my work - that's not how it works. The simpler you tell me in plain language what is needed, the faster and more accurately I will solve the task.He wants help but won’t explain how he fixed it. Next time, nobody will help him again. At the very least, have the decency, if you ask for help and manage to solve it. to share the solution with everyone. It could be helpful for others. And striking through your whole message: what’s the point of that?
I edited and said ignore it the issue was i was trying to create an npc instance for the reflection to perform some actions after death of specific monsters/bosses .I ended up using another method through Listeners specifically the onDeathListener maybe it's not the right way but it does the job for me for my experimentingView attachment 7077
....read it yourself
I don't remember mentioning you specifically but anyway the question was for Deazer. It was late at night messing around found a sloppy solution at that time used it done my job . Since it was sloppy didn't think that it would help anybody . As for the striking it was to ignore the useless code but anyway updated the post with unstriked content and my solution attached in case somebody needs it which i wouldn't recommend using.He wants help but won’t explain how he fixed it. Next time, nobody will help him again. At the very least, have the decency, if you ask for help and manage to solve it. to share the solution with everyone. It could be helpful for others. And striking through your whole message: what’s the point of that?
I don't remember mentioning you specifically but anyway the question was for Deazer. It was late at night messing around found a sloppy solution at that time used it done my job . Since it was sloppy didn't think that it would help anybody . As for the striking it was to ignore the useless code but anyway updated the post with unstriked content and my solution attached in case somebody needs it which i wouldn't recommend using.
I understood your point very well and I'm with you on that , but as i said it wasn't the right moment for me and also what i mostly see on a lot of posts in here and some other forums is irony and judgement I'm not referring to you no offense, I'm talking in general and for users new to the whole lucera ecosystem or l2j in general is not that encouraging of encouraging so that they keep improving and learning , nobody was born to know everything or is a top coder or anything we learn by making mistakes and asking for help and research but when somebody is asking for help and the other side is nothing but helpful or negative it doesn't help at all ,anyway i made a mistake i should have posted my "solution" directly, better late than never.I don't think you understood my point.
I'll try from my side from now on to share what I know with the rest of the community hoping for a more welcoming aura.Manchmal ist es so