Jump to content

Recommended Posts

Posted

Creating new Npc Instance

 


 

Hello, someone sent me request via pm, thats why I decided to post this Guide.

 

I will show you, and explain few simple steps about how to create own Npc Instance, how does it work etc.

 

It may be useful for someone who would like to create new kinds of L2 Npc Types.

 

Of course, for single/simple tasks handling, it would be better to make quest bassed Npc instead of new Instance.

 

Hope you know how to compile/use eclipse generaly because I won't explain basic steps here.

 

Guide created with latest Freya clean L2JServer source.

 


 

1. Firstly, it would be good to analyze code:

 

  • L2Npc class at least, available functions etc.

 

2. Create new class:

 

(com/l2jserver/gameserver/model/actor/instance package)

 

  • You will have to add "Instance" word at the end of class name
  • Sample: L2TestNpcInstance.java

 

3. Class body, at begining:

 

package com.l2jserver.gameserver.model.actor.instance;

public class L2TestNpcInstance
{

}

 

4. Select extender of your new Npc Instance:

 

  • You will have to select proper extender - superclass.
  • A Java superclass is a class which gives a method or methods to a Java subclass.
  • A Java class may be either a subclass, a superclass, both, or neither.

 

Lets say you want to create some kind of Monster Npc type, so you should choose L2Attackable for example.

 

For educational purposes, we will extend basic Npc Type class - L2Npc (by using extends L2Npc)

 

package com.l2jserver.gameserver.model.actor.instance;

import com.l2jserver.gameserver.model.actor.L2Npc;

public class L2TestNpcInstance extends L2Npc
{

}

 

Now you will have to add constructor:

 

package com.l2jserver.gameserver.model.actor.instance;

import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;

public class L2TestNpcInstance extends L2Npc
{
public L2TestNpcInstance(int objectId, L2NpcTemplate template)
{
	super(objectId, template);
}
}

 

Even now you would be able to use this Npc Instance (it would work as a standard L2Npc type, nothing changed, nothing new)

 

Its up to you, to choice what exactly this NPC should do, for example handle some kind of event etc.

 

Since you extended L2Npc class, you may use functions/booleans etc from this class. Most important:

 

  • onSpawn()  - actions after NPC ingame spawn
  • onBypassFeedback() - handling html bypass functions
  • showChatWindow - handle showing chat window
  • onAction() - determinate what exactly should happen while clicking at Npc, for example show chat/attack etc
  • doDie() - handle NPC death, for example what should happen after npc death

 

Of course, there are plenty of useful codes (...) simply check L2Npc class.

 

Now, I will show few example, about how to use those things from extended class.

 


 

5. Handling NPC spawn:

 

Lets say, we will create npc, which will say something after his spawn, for example "Hello World!"

 

You will have to use and Override onSpawn() function by adding @Override addannotation.

 

And use proper code to broadcast NPC say packet. Take a look at code:

 

package com.l2jserver.gameserver.model.actor.instance;

import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;

public class L2TestNpcInstance extends L2Npc
{
public L2TestNpcInstance(int objectId, L2NpcTemplate template)
{
	super(objectId, template);
}

@Override
public void onSpawn()
{
	super.onSpawn();
	// Broadcast new Npc Say Packet
	this.broadcastPacket(new NpcSay(this.getObjectId(), 0, this.getNpcId(),"Hello World!"));
}
}

 


 

6. Bypass Handling:

 

Its important, when for example you want to handle bypass actions from npc html window.

 

Lets say, you want to add new button in npc chat, and after pressing it, player will receive short message.

 

	@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
	if (player == null || player.getLastFolkNPC() == null || player.getLastFolkNPC().getObjectId() != this.getObjectId()) 
	{
		return;
	}
	if (command.startsWith("showMessage"))
	{	
		player.sendMessage("Hello " + player.getName());
	}
}

 

By adding this code (guess its self explanatory), you may use button bypass with bypass "etiquette" - showMessage

 

You will receive message after pressing button with this bypass (of course, while using this NPC type)

 

bypass -h npc_objectId_mainWindow

 

Of course, you can easily add new bypasses by using else if (command.startsWith("blabla")

 


 

7. Showing Chat Window:

 

First of all, since you extended L2Npc class, you really don't have to create any methods to show npc html window.

 

Why? Because this code already exist in L2Npc class (which is our extender in this sample)

 

But lets say, you would like to modify it a little bit (for example using html generated with java instead of showing htm file from DP)

 

It may be pointless sample, but its just to explain about how does it work.

 

You will have to Override showChatWindow() method.

 

	@Override
public void showChatWindow(L2PcInstance player, int val)
{
	TextBuilder tb = new TextBuilder();
	tb.append("<html><title>Test Npc</title><body><center><br>");

	if (player.getLevel() > 60)
		tb.append("Hello " + player.getName() + "! How are you?");
	else
		tb.append("Sorry " + player.getName() + "! You need level 60 or above!");

	NpcHtmlMessage msg = new NpcHtmlMessage(this.getObjectId());
	msg.setHtml(tb.toString());
	msg.replace("%objectId%", String.valueOf(this.getObjectId()));
	player.sendPacket(msg);
}	

 

While using this sample code, after talking with NPC, there will be window, and If player is level 60 or above, he will see this:

 

Hello 'playerNameHere'! How are you?

 

And if player is level > 60

 

Sorry 'playerNameHere'! ! You need level 60 or above!

 


 

8. How to use new Npc Instance:

 

Lets say to made it, and you already compiled it. Now you will have to create new Npc (new npc in database)

 

With proper NPC type, its simple, since our class name is: L2TestNpcInstance so type is L2TestNpc

 

Its like L2Npc, L2Buffer, L2Merchant, L2Teleporter etc.

 


 

This is just a basic introduction, hope you find it useful. Of course its for beginners.

 

So posts like "Lol, I know it already" or "Nothing new for master of java like me" are pointless..

 

Thanks, if there is something wrong, leave reply, something could go wrong.

 

Posted

A perfect guide for L2NPC Intances with too much details about all,step by step.

These kind of guides need l2jsections and thanks that you are improving them again & again ;) .

You are not doing for karma but +1 from me.

Keep up.

 

Posted

Awesome guide and really helpful. Thanks Matim!

 

Btw...

	if (player.getLevel() < 60)
		tb.append("Hello " + player.getName() + "! How are you?");
	else
		tb.append("Sorry " + player.getName() + "! You need level 60 or above!");

I think here if player is lower level than 60, then "Hello playername! How are you?" message will appear to him, and not that he needs to be lvl 60 or above :S I might be wrong, but that's what i read :P

Posted

Awesome guide and really helpful. Thanks Matim!

 

Btw...

	if (player.getLevel() < 60)
		tb.append("Hello " + player.getName() + "! How are you?");
	else
		tb.append("Sorry " + player.getName() + "! You need level 60 or above!");

I think here if player is lower level than 60, then "Hello playername! How are you?" message will appear to him, and not that he needs to be lvl 60 or above :S I might be wrong, but that's what i read :P

else

You read that?

Posted

If player is less than 60 level, then show him message, if he is not, then show him the other message.

Oh,you have right.

So it might be like that

if (player.getLevel() >= 60)
		tb.append("Hello " + player.getName() + "! How are you?");
	else
		tb.append("Sorry " + player.getName() + "! You need level 60 or above!");

With this if he is 60 level or more,it will show him the message "Hello Player!How are you?

if he is less than 60 Sorry Player! You need level 60 or above!

right?

Posted

Oh,you have right.

So it might be like that

if (player.getLevel() >= 60)
		tb.append("Hello " + player.getName() + "! How are you?");
	else
		tb.append("Sorry " + player.getName() + "! You need level 60 or above!");

With this if he is 60 level or more,it will show him the message "Hello Player!How are you?

if he is less than 60 Sorry Player! You need level 60 or above!

right?

yeah, i think :P

Posted

Right, there was mistake, fixed thanks.

No problem.

 

Btw, i have a problem, i hope you can help me. I created a new instance of npc, L2TownTeleporterInstance, i want it to be like when you talk to it, a html will appear that will be located in data/html/teleporter, and in there there will be a list to choose, and a button Teleport. The list will be like combobox (ex. in l2essiel when you pressed .color a window with combo box list appeared). And with Teleport button, you will be teleported to the selected town. Check what i've done:

/*
* 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 2, 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* http://www.gnu.org/copyleft/gpl.html
*/
package net.sf.l2j.gameserver.model.actor.instance;

import java.util.StringTokenizer;

import net.sf.l2j.Config;
import net.sf.l2j.gameserver.datatables.TeleportLocationTable;
import net.sf.l2j.gameserver.instancemanager.CastleManager;
import net.sf.l2j.gameserver.instancemanager.SiegeManager;
import net.sf.l2j.gameserver.instancemanager.TownManager;
import net.sf.l2j.gameserver.model.L2TeleportLocation;
import net.sf.l2j.gameserver.model.actor.L2Character;
import net.sf.l2j.gameserver.network.SystemMessageId;
import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;

/**
* @author 
*
*/
public final class L2TownTeleporterInstance extends L2NpcInstance
{

   public L2TownTeleporterInstance(int objectId, L2NpcTemplate template)
   {
       super(objectId, template);
   }

@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
	if (player == null || player.getLastFolkNPC() == null || player.getLastFolkNPC().getObjectId() != this.getObjectId()) 
	{
		return;
	}
       if (command.equalsIgnoreCase("Giran"))
	{	
		player.teleToLocation(83400, 147943, -3404);
		player.sendMessage("You have been teleported to Giran!");
	}
       if (command.equalsIgnoreCase("Aden"))
	{	
		player.teleToLocation(146331, 25762, -2018);
		player.sendMessage("You have been teleported to Aden!");
	}
}
   @Override
public String getHtmlPath(int npcId, int val)
   {
       String pom = "";
       if (val == 0)
       {
           pom = "" + npcId;
       }
       else
       {
           pom = npcId + "-" + val;
       }

       return "data/html/teleporter/" + pom + ".htm";
   }
   @Override
public void showChatWindow(L2PcInstance player)
   {
       NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
       html.replace("%objectId%", String.valueOf(getObjectId()));
       html.replace("%npcname%", getName());
       player.sendPacket(html);
   }
}

 

The problem is that, when i select my town(in this case i have only Giran and Aden), i press Teleport but nothing happens. I am working on Interlude, L2JaCis latest rev(54).

 

Check my html too:

<html>
<body>
<table width=270 cellpadding="4">
<tr>
<td>Select Town:</td>
<td><combobox width=120 height=17 var=ebox list=Giran;Aden></td>
</tr>
<tr>
<td></td>
<td><button value="Teleport" action="bypass -h npc_objectId_mainWindow $ebox" width=140 height=21 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df"></td>
</tr>
</table>
</html>
</body>

Posted

~OlyMpuS~ look at your extender ..

 

You are trying something like new type of Gatekeeper.

 

Now think, use L2TeleporterInstance as a extender (teleport bypasse will work then)

Posted

~OlyMpuS~ look at your extender ..

 

You are trying something like new type of Gatekeeper.

 

Now think, use L2TeleporterInstance as a extender (teleport bypasse will work then)

If i use as extender L2TeleporterInstance, i get tons of errors. Also L2TeleporterInstance uses as extender L2NpcInstance.

 

 

EDIT: I removed final modifier from L2TeleporterInstance, and the errors are gone. Let me test it again...

 

EDIT2: Still nothing. I press Teleport but nothing. Any ideas? Maybe if i avoid making a new Instance and just copy my 2 commands in L2TeleporterInstance?

 

I mean these:

        if (command.equalsIgnoreCase("Giran"))
	{	
		player.teleToLocation(83400, 147943, -3404);
		player.sendMessage("You have been teleported to Giran!");
	}
        if (command.equalsIgnoreCase("Aden"))
	{	
		player.teleToLocation(146331, 25762, -2018);
		player.sendMessage("You have been teleported to Aden!");
	}

Posted

Wonder why you can't use goto bypass.

 

L2NpcInstance doesn't support this bypass.

You mean to use goto bypass in another instance? Or in L2TeleporterInstance?

Posted

You mean to use goto bypass in another instance? Or in L2TeleporterInstance?

 

First of all tell me what exactly would you like to code.

 

For now, its looks like you want standard Gatekeeper (so its pointless to create new instance, sine there is L2Teleporter)

 

You can also modify L2TeleportInstance aswell (just to add some small things or something)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...