Jump to content

Recommended Posts

Posted

Hello Mates,

Here we back again with another Lineage Development Tutorial, this time we will  learn how to work and create a Java NPC, Well what is this ?

NPC is stands for Non-Playable Character,  which is a Character in server that provide some help or services like Buffer, GateKeeper, Agumenter ….. etc, y’all know what NPC is i guess  , so let’s get to the point.

javanpc.jpg

Table of Contents :

  • Tools and Requirements
  • Work With NPC XML Files
  • Register your new NPC Type
  • Create your Java NPC Type Class
  • Build and Test

Tools and Requirements :

- Your favorite XML Editor (I Prefer Notepad++ / Download) or you can use Eclipse for that

- Eclipse or Netbeans for Java Edits and Builds ( Eclipse Download – Netbeans Download )

- A Server Pack (for this tutorial i use Private Pack Based on L2JServer – Download)

- Lineage 2 Client (I will use High Five Client, but you can Adapt it to any Chronicle Except for XML Part i guess)

Work with NPC XML Files :

Okay Before we go any further we need to let the server know that we have a new NPC and tell it’s type, id, stats …. etc, to do this you need to go to this path of game/data/stats/npcs inside your server files, there you’ll find some XML files, you can create your own XML file here or go to the folder custom/ and there you’ll find an XML file named custom.xml , i’ll put my new NPC there for the sake of simplicity .

Open this File with your favorite Editor (Notepad++ in my case) and go to the end of the file, you’ll see something like </list> , Add this code just before it :

<npc id="750002" displayId="32140" name="MxC Guide" usingServerSideName="true" title="Java NPC" usingServerSideTitle="true" type="L2MxCNPC">
	<collision>
		<radius normal="11" />
		<height normal="22.25" />
	</collision>
</npc>

We will end up with something like this :
1-3.png

Let’s Break it down and focus on few parts of this code :

- (id=”750002″) : this is the ID of your new NPC that you will use it to spawn, so make sure it’s unique and try to find your unique numeric schema to avoid conflicts

- (displayId=”32140″) : this indicated how your NPC will look like, it can be considered as Template Id, and of course you can change it to the template your want

- (name=”MxC Guide”) : it’s the NPC name that will appear

- (title=”Java NPC”) : is the NPC Title

- (type=”L2MxCNPC”) : it’s the most important parameter since it’s declaring what type this NPC will be and will look for that Type in your java files, so that’s they type we will be Creating L2MxCNPC

So you can manipulate this values according to your needs, but be away of displayId since the collision parameters are very vary based on the NPC Template you use.

Register Your new NPC Type :

Now we need to register our new Type as we said before our type for this tutorial will be L2MxCNPC, so we will register L2MxCNPCInstance as a type, and to do this you need to go to your server java files and find the package called com.l2jserver.gameserver.enums or could be com.PACKNAME.gameserver.enums , it doesn’t really matter since it can be vary from Pack to Pack but i use Official Structure. Inside this package you will find a Java File called InstanceType.java .

2-2.png

Open this Java File and find the Section named Custom, and add this code at the beginning of this section :

L2MxCNPCInstance(L2Npc),

So it will look like this :

3-2.png

Now we have our new NPC Instance Type Registered, so lets move to the next step.

Create Your Java NPC Type Class : 

Here we got to the fun part, to create your NPC Class find a package with name com.l2jserver.gameserver.model.actor.instance or com.PACKNAME.gameserver.model.actor.instance , name can be vary from pack to pack but almost same structure.

Step .1 :

Right Click on this Package then choose >New > Class

4-2.png

You’ll get a “New Java Class” window, we need to set some options there, First of all set name to L2MxCNPCInstance , second Click on Browse in front of Superclass input, you’ll get another window , search for L2Npc, and when you find it just click on it and hit Ok

5-2.png

Step .2 :

Now we need to add what’s called Constructor which is a block of code that Execute at the beginning of initialization of the Type, so just add this code inside your new class (between open and close curly braces of your class { } )

public L2MxCNPCInstance(L2NpcTemplate template)
{
	super(template);
	setInstanceType(InstanceType.L2MxCNPCInstance);
}

So it will look like :

6-1.png

as you can see here we set instance type to L2MxCNPCInstance which we registered in InstanceType.java file.

Step .3 :

Now what we need to do is to override 1 or 2 methods depends on NPC functionality, by overriding we mean that we are replacing the main functionality of L2Npc (since our type extends L2Npc) with a new functionality or implementation, the first method we need to override is showChatWindow which responsible to show the chat window of the NPC to the player when interact with it.

To override this method just go to below L2MxCNPCInstance method (Constructor) and add this code :

@Override
public void showChatWindow(L2PcInstance player, int val) 
{
		
}

Well, we need to add some java code inside this method to show our HTML Document, but guess what , we didn’t created our HTML Document yet, so we don’t we go and create it now ….

Step .4 :

Go to your game html folder (usually at game/data/html ) and create an HTML document there or in any sub folder, for me i’ll create mxcnpc.html in custom subfolder, and initially i’ll put that html code in :

<html><title>L2JSamDev MxC NPC</title>
<body>
<center>
	<br><br>
	<img src="L2UI_CH3.herotower_deco" width=256 height=32><br>
	<font name="hs9" color="00aff0">Hello From MxC Java NPC</font><br>
	<button action="bypass -h npc_%objectId%_MyCommand" value="Click Me (ByPass)" width=130 height=30 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df">
	<br>
	<img src="L2UI_CH3.herotower_deco" width=256 height=32><br>
</center>
</body>
</html>

Of course you can do the HTML code / design you want, but this is just for demonstration, but in real life, you’re free to do any HTML design you want.

Step .5 :

Go back to your Java file and add this code to the showChatWindow method, that we overrided before :

//Try to load the HTML document
String content = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/custom/mxcnpc.html");
//If not found ?
if(content == null)
{
	//Set a Fallback Content
	content = "Sorry we cannot find your document for MxC NPC";
}

//Create a new NPC Message and set Object ID
NpcHtmlMessage message = new NpcHtmlMessage(getObjectId());
//Set Message Content
message.setHtml(content);
//Replace %objecId% in HTMl with Real Object ID
message.replace("%objectId%", String.valueOf(getObjectId()));
//Send HTML to Player
player.sendPacket(message);

Step .6 :

Well I Guess we are ready to go, but our new NPC actually do nothing, just showing an HTML, so what we can do to give this npc some power ? ….

What makes NPC much powerful and full of features is what called ByPass which means it’s the ability to let players able to click on some Buttons or link and with that click they will send a command to the server, and in Java side we implement the feature or the action that will be taken when the player bypass any command.

If you look closely to the HTML Code we’ve created you will notice this line :

<button action="bypass -h npc_%objectId%_MyCommand" value="Click Me (ByPass)" width=130 height=30 back="L2UI_ct1.button_df" fore="L2UI_ct1.button_df">

Focus on action parameter here it’s equal to ( bypass -h npc_%objectId%_MyCommand ) this means by clicking on this button player will pass a command of MyCommand to the Java NPC handler which has the valid Object ID .

but how we can handle commands bypassed by player using our new NPC ?

It’s simple, all we need is to override another method which is onBypassFeedback .. and to do so add this code below showChatWindow method :

@Override
public void onBypassFeedback(L2PcInstance player, String command) {
		
}

Here i’ll add some little simple code to implement the feature of trading 50KK Adena for 1K Clan Reputation if you are the clan leader, so add this code to on onBypassFeedback method :

//Check for Player and Last NPC if Same
if(player == null || player.getLastFolkNPC() == null || player.getLastFolkNPC().getObjectId() != getObjectId())
{ return; }
if(command.startsWith("MyCommand"))
{
	//Check if Player is the clan Leader
	if(player.isClanLeader())
	{
		//Is he has 50kk Adena ?
		if(player.getAdena() >= 50000000)
		{
			L2Clan clan = player.getClan();
			//Give Reputation
			clan.addReputationScore(1000, true);
			//Take Adena
			player.getInventory().reduceAdena("Clan Requtation", 50000000, player, this);
			player.sendMessage("Your Clan has Earned 1000 Rep for 50 Millions Adena");
		}
		else {player.sendMessage("You don't have Enough Adena");}
	}
	else {player.sendMessage("You are not a Clan Leader");}
}

of course you can maintain and make the code much smarter, but we seek simplicity to be easy to any one to start creating amazing Java NPCs .

Step .7 :

Now our NPC Java class will look like :

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

import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.enums.InstanceType;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;

public class L2MxCNPCInstance extends L2Npc {

	public L2MxCNPCInstance(L2NpcTemplate template)
	{
		super(template);
		setInstanceType(InstanceType.L2MxCNPCInstance);
	}
	
	@Override
	public void showChatWindow(L2PcInstance player, int val) 
	{
		
		//Try to load the HTML document
		String content = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/custom/mxcnpc.html");
		//If not found ?
		if(content == null)
		{
			//Set a Fallback Content
			content = "Sorry we cannot find your document for MxC NPC";
		}
		
		//Create a new NPC Message and set Object ID
		NpcHtmlMessage message = new NpcHtmlMessage(getObjectId());
		//Set Message Content
		message.setHtml(content);
		//Replace %objecId% in HTMl with Real Object ID
		message.replace("%objectId%", String.valueOf(getObjectId()));
		//Send HTML to Player
		player.sendPacket(message);
	}
	
	@Override
	public void onBypassFeedback(L2PcInstance player, String command) {
		//Check for Player and Last NPC if Same
		if(player == null || player.getLastFolkNPC() == null || player.getLastFolkNPC().getObjectId() != getObjectId())
		{ return; }
		if(command.startsWith("MyCommand"))
		{
			//Check if Player is the clan Leader
			if(player.isClanLeader())
			{
				//Is he has 50kk Adena ?
				if(player.getAdena() >= 50000000)
				{
					L2Clan clan = player.getClan();
					//Give Reputation
					clan.addReputationScore(1000, true);
					//Take Adena
					player.getInventory().reduceAdena("Clan Requtation", 50000000, player, this);
					player.sendMessage("Your Clan has Earned 1000 Rep for 50 Millions Adena");
				}
				else {player.sendMessage("You don't have Enough Adena");}
			}
			else {player.sendMessage("You are not a Clan Leader");}
		}
	}
}

So let’s Build our Project and Login into our server to check what we got …

– Lets Spawn our NPC

7.jpg

– and Try to interact with ….

8.jpg

– Finally let’s Check if our command work

9.jpg

Yeah, Finally it's working ... :)

Sorry if any mistakes and if you got any question or need a specific Guide just let me know

Thanks Everyone.

 

  • Upvote 2
Posted

nice guide dude.. i really like it and it helped me even though i tried on interlude ... good for newbies a specified interlude guide would even help me :P if u can provide some help i would appreciate it

Posted
1 hour ago, VanGon said:

nice guide dude.. i really like it and it helped me even though i tried on interlude ... good for newbies a specified interlude guide would even help me :P if u can provide some help i would appreciate it

I'm Glad that you like it, and can you tell me what guide you would want for interlude ? and could you suggest a pack to demonstrate guide for interludes on ? i see many people go for aCis and say it's different structure, some go with another so let me know which pack community go for more , and Thanks :)

Posted
12 minutes ago, SamDev-Coder said:

I'm Glad that you like it, and can you tell me what guide you would want for interlude ? and could you suggest a pack to demonstrate guide for interludes on ? i see many people go for aCis and say it's different structure, some go with another so let me know which pack community go for more , and Thanks :)

most ppl nowadays use acis since its the best u will find out there for free.. what i mean is i try to create a fcking npc in acis some time now and it is just getting errors everywhere :P well i would mostly like a guide on how to create a gmshop in acis.. (not the htm/xml parts but the whole process)

Posted
7 minutes ago, VanGon said:

most ppl nowadays use acis since its the best u will find out there for free.. what i mean is i try to create a fcking npc in acis some time now and it is just getting errors everywhere :P well i would mostly like a guide on how to create a gmshop in acis.. (not the htm/xml parts but the whole process)

No worries i'll try to find aCis and create a tutorial for a GM Shop :) ... Thanks for info

Posted
1 minute ago, Reborn12 said:

Nice guide thanks for share..            gm shop is only htm/multisell :D

well y but both the width and height gives me some trouble.. as well as the fcking button lines... christs sake

Posted
39 minutes ago, Reborn12 said:

Nice guide thanks for share..            gm shop is only htm/multisell :D

Thank you, hope that it's useful for the community :)

Posted

For aCis you only need to copy  an existing template, paste it on 50000-50999.xml (common file for all custom NPCs, no forced reason to use it but it's simply common logic), add following tags if you want custom name/title being displayed (otherwise client names are used)

        <set name="usingServerSideName" val="true"/>
        <set name="usingServerSideTitle" val="true"/>

Then you edit following tags : "name"/"title", rename "id" for "idTemplate" and add a new, unused "id"  (you can see existing exemples on 50000-50999.xml) and edit "type" for the name of the server-side instance type (Folk being the common invul one, Monster for basic monster). That's all for the DP.

-----

For the server side part, you only need to create your instance on model.actor.instance. The name of instance is the name of "type" you entered on XML, there is no "L2" and "Instance" anymore on latest aCis.

showChatWindow is also the most common thing to override, but you can basically override everything. For all overriding possibilities, open and read the class than your instance currently extends. Choices would be different depending about it (Monster offer different choices than Npc, etc)

Posted
2 hours ago, Tryskell said:

For aCis you only need to copy  an existing template, paste it on 50000-50999.xml (common file for all custom NPCs, no forced reason to use it but it's simply common logic), add following tags if you want custom name/title being displayed (otherwise client names are used)


        <set name="usingServerSideName" val="true"/>
        <set name="usingServerSideTitle" val="true"/>

Then you edit following tags : "name"/"title", rename "id" for "idTemplate" and add a new, unused "id"  (you can see existing exemples on 50000-50999.xml) and edit "type" for the name of the server-side instance type (Folk being the common invul one, Monster for basic monster). That's all for the DP.

-----

For the server side part, you only need to create your instance on model.actor.instance. The name of instance is the name of "type" you entered on XML, there is no "L2" and "Instance" anymore on latest aCis.

showChatWindow is also the most common thing to override, but you can basically override everything. For all overriding possibilities, open and read the class than your instance currently extends. Choices would be different depending about it (Monster offer different choices than Npc, etc)

oftopic:ty even though i already fixed it .. :P the only thing im missing is the fcking buffer which needs java so im gonna make one ... also i have rev 360 so the l2 and instance are still there for me in the npc management :P

ontopic: any update my dear friend? i saw u updated ur first post and made some significant improvements

Posted
20 minutes ago, SickJacken said:

can be used example to click npc and open community board?

Well i think it's simply doable

instead of calculating adena, give reputation for the class ... etc

just load the HTML of the Community board which located in data/html/CommunityBoard/xxxxx.html (maybe u use custom community board)

String content = HtmCache.getInstance().getHtm("data/html/CommunityBoard/home.html");

and Send it but instead of sending the packet as NPCMessage, Send it via BaseBBSManager , for example :

BaseBBSManager.separateAndSend(content, player);

You may get errors like Cannot Resolve BaseBBSManager .... blablabla

then u need to import it like 

import com.l2jserver.gameserver.communitybbs.Manager.BaseBBSManager;

and Good luck :) lemme know if u need any help

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...