This is a forum for all discussions regarding Nexon and their games!
Would you like to login?
This is a forum for all discussions regarding Nexon and their games!
Would you like to login?
This is a forum for all discussions regarding Nexon and their games!
Would you like to react to this message? Create an account in a few clicks or log in to continue.

This is a forum for all discussions regarding Nexon and their games!

Details on the newest private server releases, recruit for your server here, or just find new friends!
 
HomeHome  Latest imagesLatest images  RegisterRegister  Log inLog in  

 

 [Coding]Xanes-Coding Npcs start to finish.

Go down 
2 posters
AuthorMessage
Sorrow
Admin
Sorrow


Posts : 9
Join date : 2011-03-28
Age : 34
Location : Burning Emblem

[Coding]Xanes-Coding Npcs start to finish. Empty
PostSubject: [Coding]Xanes-Coding Npcs start to finish.   [Coding]Xanes-Coding Npcs start to finish. EmptyFri Apr 22, 2011 6:25 am

Heres his tutorial for Npcs
Learning NPCs, From Start To Finish

Hello, and welcome to my attempt to teach everyone NPC scripts better. Regardless of the countless tutorials, and countless Help threads that have been posted and solved, people still seem to have issues with NPCs. Hopefully, with this tutorial, people will learn something. I hope my tutorial teaches you something, even if it's just one thing.

Class 1: Beginning Level

Lesson 1: Useful programs for scripting

There are many programs that can assist with creating codes/scripts. Some allow key features like language changing, so you can have the proper vocabulary, and highlighting of brackets, so you can see where they open and close. It also helps when trying to organize a script. Here are some programs I recommend.
NotePad++
PSPad

Lesson 2: Types of NPCs

There are two main types of NPCs. One that deals with status, and one that doesn't. The easiest way to tell them apart is obviously... the status. When creating an NPC, always think to yourself. "Will my NPC be opening more than 2 windows when I talk to it before it's over?" If your answer is yes, you will most likely need to use status. If you answered no, then status probably won't be needed. Here are some examples in the spoiler.
Spoiler:

Lesson 3: Communicating with yourself and other scripters

One of the key things when scripting is being able to understand what exactly you are doing or being able to understand what the author was doing. What better way to understand than to make notes while scripting? Have you ever looked at a script, and seen two // at the end of a line? Those are called comments. There are a few types of comments, and I will brush up on them.
Code:

// This is one form of a comment
// When using this type of comment, it is typically used for single lines, hence why it is called a Single-Lined Comment.

/**
 This is a Multi-Lined Comment
 Anything in between the *s will not be read by whatever program is reading the script.
 **/ 
Comments are ignored by programs when being read. This means whatever you put as a comment, is strictly for the person reading the script. They are very useful if you are writing a long script and need to keep track of what you are doing. They also help by allowing you to tell other people what it is you were intending to do, in case they can't understand just by reading the code.

Lesson 4: Learning the Terminology

Let's face it. You can't code an NPC if you have no idea what the proper terminology is. Here are some quick notes.

NPC Color codes/Item pictures/etc
Spoiler:

cm.[Commands]
Code:

dispose
Ends the conversation with an NPC, allows you to talk to NPCs again.
How to use: cm.dispose();

sendNext
Shows a conversation window with a 'Next' button.
How to use: cm.sendNext("[text]");

sendPrev
Shows a conversation window with a 'Prev' (previous) button.
How to use: cm.sendPrev("[text]");

sendNextPrev
Shows a conversation window with a 'Next' and 'Prev' button (see above).
How to use: cm.sendNextPrev("[text]");

sendOk
Shows a conversation window with an 'Ok' button.
How to use: cm.sendOk("[text]");

sendYesNo
Shows a conversation window with a 'Yes' and 'No' button, 'No' ends the conversation unless otherwise stated.
How to use: cm.sendYesNo("[text]");

sendAcceptDecline
Shows a conversation window with an 'Accept' and 'Decline' button. 'Decline' ends the conversation unless otherwise stated.
How to use: cm.sendAcceptDecline("[text]");

sendSimple
Shows a conversation window with no buttons.
How to use: cm.sendSimple("[text]");

sendStyle
Shows a style-select window.
How to use: cm.sendStyle("[Text]", [variable]); // You'll need to declare the variable in a Var statement.

warp
Warps the player to a map.
How to use: cm.warp([mapid], [portal]); // Set [portal] as 0 if you want default.

openShop
Opens a shop window.
How to use: cm.openShop([shopid]);

haveItem
Checks if the player has an item (in their inventories or equipped).
How to use: cm.haveItem([itemid]);

gainItem
Gives the player an item/takes an item from a player.
How to use: cm.gainItem([itemid],[ammount]); // Change [ammount] to -[ammount] to take an item.

changeJob
Changes the job of the player.
How to use: cm.changeJob([jobid]);

getJob
Finds out what job the player has.
How to use: cm.getJob();

startQuest
Starts a quest.
How to use: cm.startQuest([questid]);

completeQuest
Finishes a quest.
How to use: cm.completeQuest([questid]);

forfeitQuest
Forfeits a quest.
How to use: cm.forfeitQuest([questid]);

getMeso
Finds out how many mesos a player has.
How to use: cm.getMeso();

gainMeso
Gives a player mesos/takes mesos from a player.
How to use: cm.gainMeso([ammount]); // use -[ammount] to take mesos.

gainExp
Gives a player exp/takes exp from a player.
How to use: cm.gainExp([ammount]); // use -[ammount] to take exp.

getLevel
Finds out the level of the player.
How to use: cm.getLevel();

teachSkill
Teaches a player a skill.
How to use: cm.teachSkill([skillid],[skilllevel],[maxskilllevel]);

get[Stat]
Finds out the [Stat] of the player. [Stat] being: HP, MP, STR, DEX, INT, LUK.
How to use: cm.get[Stat]();

modifyNX
Gives/Takes the player nx
How to use: cm.gainNX([amount]);
Make it negative to make it take away.

Checking for mesos, items, donator, gm, and gender
Code:

if (cm.getPlayer().isGM()) { // checks for GM

if (cm.getChar().isDonator() == true) { // checks for donator

if (cm.getJob().equals(net.sf.odinms.client.MapleJob.BOWMAN)) { // checks for Bowman job (list of jobs in below spoiler)

if (cm.getLevel() >= 30) { // checks if level is more than or equal to 30.

if (cm.getChar().getGender() == 0) { // 0 = male, 1 = female
if (cm.getPlayer().getGender() == 0) { // 0 = male, 1 = female

if (cm.getMeso() >= amount) { // >= greater than or equal to, <= less than or equal to,  == is equal to

if (cm.haveItem(itemid, amount)) { // checks if the player has a certain amount of an item

if (cm.getPlayer().getitemQuantity(itemid)); // gets a count of how much a player has of an item 

Job Terms and Ids
Spoiler:
Keep in mind that some repacks use a different Terminology than this, so it's best to browse your repack/source folder to get familiar with yours.

Partial Credits: Here for easy copy/pasting and editing.

Class 2: Intermediate Level

Lesson 1: Learning to code an NPC

When creating an NPC, it's always best to have a general idea of what you are doing. A quick way to do this is to open a Notepad file, with little notes of what you want it to do. Example:
Code:

Item Exchanger
Window 1 - Shows different options
Window 2 - Shows different options after picking from Window 1

Window 1 choices - ores for a maple coin, ores for a maple leaf
Window 2 choices - if picked maple coin = 10 ores for 1 coin, 20 ores for 3 coins
            if picked maple leaf = 5 ores for 1 leaf, 10 ores for 3 leafs


That was just an example, but by making little notes like that, you can think of the best layout beforehand. It also helps having something to look back on to remind you, in case you don't have the time to do your script in one sitting.

Now, before you begin, you need to think of what type of NPC you are going to do. If you need reference, revert to Class 1, Lesson 2. In this example, I will be using an NPC that uses status. Please read the comments (Class 1, Lesson 3) in the script, to understand what I am doing.
Code:

var status;

function start() { // starts the NPC
    status = -1; // sets the status of the NPC to -1
    action(1, 0, 0); // sets the mode to 1, type to 0, and selection to 0 for the NPC
} // closes off the start function

function action(mode, type, selection) { // calls what you set above in function start, almost all actions are done here
    if (mode == 1) { // the mode is set to 1 because of the function start, as shown above
        status++; // advances the NPC to the next status, in this case, status 0
    }else{ // if mode does not equal 1
        status--; // does not advance the NPC to the next status.
    }
   
    if (status == 0) { // if mode was 1, status would move from -1 to 0. If status is 0, these actions will happen
        cm.sendSimple("Hello. I am going to show you how to use #belse#k and #bif#k. Are you ready? \r\n #L0# Yes, I am. #l \r\n #L1# No, I'm not. #l"); // Opens a window with 2 choices (selections)
    } else if (status == 1) { // NPC advances to next status if a selection is chosen.
        if (selection == 0) { // selection 0 is #L0#, "Yes, I am."
            if (cm.haveItem(4001129, 10)) { // checks for an item
                cm.sendOk("IF you chose selection 0, or in easier terms, the first choice, I will say this."); // IF you have the item, this will show
                cm.dispose();
            }else{
                cm.sendOk("I'm sorry, you don't have the item."); // ELSE, you don't have the item.
                cm.dispose();
            }
        } else if (selection == 1) { // "No, I'm not."
            cm.sendOk("ELSE IF you chose selection 1, I will say this.");
            cm.dispose();
        }
    }

Here's a little something to help you with NPCs as well.

Code:

-----------
sendNext(); & sendOk();
-----------
Type = 0
If end chat    -    mode = -1
If next/ok    -    mode = 1

-----------
sendNextPrev();
-----------
Type = 0
If end chat    -    mode = -1
If next        -    mode = 1
if back        -    mode = 0

-----------
sendYesNo();
-----------
Type = 1
If end chat    -    mode = -1
If yes        -    mode = 1
If no        -    mode = 0

-----------
sendAcceptDecline();
-----------
Type = 12
If end chat    -    mode = -1
If accept    -    mode = 1
If decline    -    mode = 0

-----------
sendGetText();
-----------
Nothing o____o its something special <3

-----------
sendGetNumber();
-----------
Type = 3
If end chat    -    mode = 0
if ok        -    mode = 1

-----------
sendSimple();
-----------
Type = 4
If end chat    -    mode = 0
if select    -    mode = 1
Brackets can be a key factor between a working NPC and a non working NPC. Let's take a look at a part of the above NPC.
Code:

if (cm.haveItem(4001129, 10)) { // checks for an item
            cm.sendOk("IF you chose selection 0, or in easier terms, the first choice, I will say this."); // IF you have the item, this will show
            cm.dispose();
         }
If you look at the first line...
Code:

if (cm.haveItem(4001129, 10)) {
There is an opening bracket at the end of the line. This means, in an easier understanding, if the condition is true, anything after will happen. So, for that line, if you have 10 of 4001129, the following line will happen. Look at the end of the snippet of code. Notice the other bracket?
Code:
}

That is a closing bracket. It closes the condition. So, anything between the opening and closing bracket is for that specific condition. The closing bracket will usually be followed by an else, which means if you don't have the item, the actions under else will happen.

Lesson 2: Using Operators

In this lesson, you will learn the different types of Operators and how to use them. There are a few types of Operators. They can help you determine if something is bigger or smaller, and even if it's equal to. Below is a list of Operators you will most likely be using.
Code:

Operator   Name         Type      Description
!      Not         Unary       Returns true if the operand to the right evaluates
to false. Returns false If the
operand to the right is true.

&&       Conditional And    Binary       If the operand on the left
returns false, returns false without evaluating
the operand on the right.

||       Conditional Or       Binary       If the operand on the left
returns true, returns true without evaluating
the operand on the right.
The above Operators are commonly used in between conditions. What is a condition? Things you see quite often in NPC scripts.
Code:

if (cm.haveItem(itemid, amount)) {
if (cm.getMeso() >= amount) {
if (cm.getPlayer().getLevel() >= amount) { 
These are all conditions. So, when used in between, you can further specify certain requirements for players. Examples:
Code:
if (cm.haveItem(4001129, 50) && cm.getMeso() >= 1000) { // This requires the player to have both 50 Maple Coins and 1000 Mesos
if (cm.haveItem(4001129, 50) || cm.getMeso() >= 1000) { // This checks if the player has either 50 Maple coins [b]or[/b] 1000 Mesos
if (!cm.haveItem(4001129, 50)) { // This will check to see if they don't have at 50 Maple Coins 
Using this is a good way to limit players from saving up loads of an item to cash in at once. Next, we have Relational Operators. These are commonly used inside conditions. Here is a list of a few.
Code:
Operator   Description
==       Returns true if the expression on the left evaluates to the
same value as the expression on the right.

<        Returns true if the expression on the left evaluates to a value
that is less than the value of the expression on the right.

<=       Returns true if the expression on the left evaluates to a value
that is less than or equal to the expression on the right.

>        Returns true if the expression on the left evaluates to a value
that is greater than the value of the expression on the right.

>=       Returns true if the expression on the left evaluates to a value
that is greater than or equal to the expression on the right.

I've already given you a few examples of these, if you haven't noticed, but let me run a few more by you.
Code:

if (cm.getMeso() >= 1000) { // if player has GREATER THAN OR EQUAL TO 1000 Mesos
if (cm.getPlayer().getLevel() == 120) { // if player IS level 120
if (cm.getJobById() <= 112) { // if players' job id is LESS THAN OR EQUAL TO 112 (Hero, Crusader, Fighter, Warrior, Beginner) 

Lesson 3: Learning how to use Variables

As you progress in your learning experiences, you'll begin to notice and wonder why there are things at the top of a script that start with "var". This is called a variable. Variables, in short, are used to "replace" something. They basically take a number, or a sentence, and "replace it" with whatever you name the variable. Typically, you would want the variable to shorten the script, even if by a few characters. Here is an example.
Code:
var gl = 4000313;

function start() {
    cm.sendOk("Hello, do you have any #v"+gl+"#?"); // Calls the variable gl, and the information it is replacing
    cm.dispose();
As you can see from the example, the item id 4000313 is being replaced with the variable "gl". Even though it's only a minor difference, I shortend the script by 1 character. Now imagine having hundreds of places on a script where 4000313 was replaced by "gl". It adds up on how much space you save by using variables. That was an example on how to use a variable for a number. Here is one on how to use a variable for a string, or text sentence.
Code:

var yes = "Good Job! You have enough Golden Maple Leafs!";
var no = "I'm sorry, you don't have enough Golden Maple Leafs.";
var status;

function start() {
    status = -1;
    action(1, 0, 0);
}

function action(mode, type, selection) {
    if (mode == 1) {
        status++;
    }else{
        status--;
    }
    if (status == 0) {
        cm.sendSimple("#L0# I have 10 Golden Maple Leafs #l \r\n #L1# I have 20 Golden Maple Leafs #l");
    }else if (status == 1) {
        if (selection == 0) {
            if (cm.haveItem(4000313, 10)) {
                cm.sendOk(yes); // Calls the variable "yes", and displays what you have set for it
                cm.dispose();
            }else{
                cm.sendOk(no); // Calls the variable "no", and displays what you have set for it
                cm.dispose();
            }
        } else if (selection == 1) {
            if (cm.haveItem(4000313, 20)) {
                cm.sendOk(yes); // Calls the variable "yes", and displays what you have set for it
                cm.dispose();
            }else{
                cm.sendOk(no); // Calls the variable "no", and displays what you have set for it
                cm.dispose();
            }
        }
    }
As you can clearly see, using these variables saved me a great deal of space. Instead of using 202 characters by typing in those long lines, I used 111 characters, and that's including the top variables! Using variables also makes it easier to edit scripts in the future.

Class 3: Advanced Level

Lesson 1: Learning Arrays

Now we get to the fun part. Arrays are what all the "pros" stress about. If Arrays can be used, they want to see it. It not only makes the script cleaner, but helps with the overall performance of the script. Arrays can be easily edited, and once you learn how to use them, can help you understand what the creator of the script is doing. Here are some examples of Arra
Code:
item = [4000313, 4001129, 4001126];

function start() {
    cm.sendSimple("Which would you like? \r\n #L0# Golden Maple Leaf #l \r\n #L1# Maple Coin #l \r\n #L2# Maple Leaf #l");
}

function action(mode, type, selection) {
    if (mode == 1) {
        cm.gainItem(item[selection], 1);
    }
    cm.dispose();
As you can see, the item ids are placed in the order they are shown in the sendSimple. The [selection] in the cm.gainItem method, calls the Array to determine which item to give the player. If they chose the second selection, it would call the second number in the Array. By placing the items in an Array, it shortens the script by a lot. Here is what the script would look like without an Array.
Code:
function start() {
    cm.sendSimple("Which would you like? \r\n #L0# Golden Maple Leaf #l \r\n #L1# Maple Coin #l \r\n #L2# Maple Leaf #l");
}

function action(mode, type, selection) {
    if (mode == 1) {
        if (selection == 0)
            cm.gainItem(4000313, 1);
        else if (selection == 1)
            cm.gainItem(4001129, 1);
        else if (selection == 2)
            cm.gainItem(4001126, 1);
    }
    cm.dispose();

There is a clear difference between the two in which is longer. One of the most common ways to use Arrays, is with the infamous for loop, which I will explain in a later lesson.

Lesson 2: Learning Multi-Dimentional Arrays and Randoms

In this section, I will teach you about Multi-Dimentional Arrays and Randoms. Now, I'm not an expert at this, so I'll only be able to show you what I know. So what is a Multi-Dimentional Array? A Multi-Dimentional array is an array made up of separate arrays. Basically, you can have more than one array, and simplify them further by making them into a multi-dimentional array. Unfortunately, I only know how to use them with randoms, so that is what I'll be teaching you. First, lets' set up a simple multi-dimentional array NPC.
Code:
var status;
var item = [[4001129, 4001129], [1082025, 1102023], [4000313, 1002085]];
var rand = Math.floor(Math.random()*100);

function start() {
    status -1;
    action(1, 0, 0);
}

function action(mode, type, selection) {
    if (mode == -1) {
        cm.dispose();
    }else{
    if (status >= 2 && mode == 0) {
        cm.sendOk("See you next time!.");
        cm.dispose();
        return;                   
    }
   
    if (mode == 1) {
        status++;
    }else{
        status--;
    }
   
    if (status == 0) {
        cm.sendYesNo("Are you sure you want to take a chance?");
    } else if (status == 1) {
        var rand2;
        if ((rand >= 1) && (rand <= 50)) {
            rand2 = Math.floor(Math.random() * item[0].length);
        } else if ((rand >= 51) && (rand <= 90)) {
            rand2 = Math.floor(Math.random() * item[1].length);
        }else{
            rand2 = Math.floor(Math.random() * item[2].length);
            }
            cm.gainItem([rand >= 1 && rand <= 50 ? item[0][rand2] : rand >= 51 && rand <= 90 ? item[1][rand2] : item[2][rand2]]);
            cm.sendOk("Congrats on your item.");
            cm.dispose();
        }
    }

Alright, time to explain. This is the multi-dimentional array.
Code:

var item = [[4001129, 4001129], [1082025, 1102023], [4000313, 1002085]];

Each separete array is colored, so you can see the 3 different arrays within the multi-dimentional array. Next is the random part, or this little snippet.
Code:

var rand2;
        if ((rand >= 1) && (rand <= 50)) {
            rand2 = Math.floor(Math.random() * item[0].length);
        } else if ((rand >= 51) && (rand <= 90)) {
            rand2 = Math.floor(Math.random() * item[1].length);
        }else{
            rand2 = Math.floor(Math.random() * item[2].length);
        } 

Ok, at the top of the script, you see this line.
Code:

var rand = Math.floor(Math.random()*100);
Think of this as if it were a dice. The number symbolizes the sides of a dice. So on this dice, there are 100 sides. Continue reading the random part as you read this. If the dice lands on side 1 - 50, give an item in the first array. If the dice lands on side 51 - 90, give an item in the second array. If it lands on any other side, give an item in the third array. This line here...
Code:

cm.gainItem([rand >= 1 && rand <= 50 ? item[0][rand2] : rand >= 51 && rand <= 90 ? item[1][rand2] : item[2][rand2]]);
Basically follows through with the action. That is all I know about these types of arrays.

Lesson 3: Learning the Infamous For Loop

Have you ever looked at a script, and seen something like this?
Code:
for (var i = 0; i < options.length; i++)
            text += "\r\n#L"+i+"#"+options[i]+"#l"; 
This is the infamous for loop. It simplifies almost anything it is used with. It was created to specifically deal with Arrays. Here is the entire part of the code, so I can explain what it means.
Code:
var text = "#e#k What region have you trained in?#b";
        var options = new Array("Aqua Road Region = 1 #v4001010#", "Ariant Region = 1 #v4001011#", "El Nath Region = 1 #v4001013#", "Ludas Lake Region = 1 #v4001012#", "Minar Forest Region = 1 #v4001009#", "Victoria Island Region = 5 #v4001126#", "World Tour = 5 #v4001129#", "Ores/Crystals = 1 #v4001014#");
        for (var i = 0; i < options.length; i++)
            text += "\r\n#L"+i+"#"+options[i]+"#l";
        cm.sendSimple(text); 
Ok so, i = 0. While 0 is less than the options array, do the code. After executing the code, do i++. i++ basically tells the program running the script to increase i until it reaches the length of the array. So since the options array has a length of 8, it will keep increasing until it displays all 8 options.
Back to top Go down
https://mapleburst.forumotion.com
Alex
Admin



Posts : 1
Join date : 2011-07-01

[Coding]Xanes-Coding Npcs start to finish. Empty
PostSubject: Awsome   [Coding]Xanes-Coding Npcs start to finish. EmptySun Aug 14, 2011 4:27 pm

Fucken A.
Back to top Go down
 
[Coding]Xanes-Coding Npcs start to finish.
Back to top 
Page 1 of 1

Permissions in this forum:You cannot reply to topics in this forum
This is a forum for all discussions regarding Nexon and their games! :: Server Development :: Coding Tutorials-
Jump to: