Jump to content

  •  





Basic Healer & Buffer Script

Posted by GmOcean, in 1. Beginner Scripts 25 November 2014 · 1681 views

Basic Healer & Buffer Script (5 Parts)
A Basic Healer Script. Here we will cover most, if not all of the basics of scripting.

Part 1
Okay, for this healer were going to create one that heals you 100% HP&SP when you click on it and choose heal me.
So let's start off by wring the NPC header.
<map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>}
 // Facing Directions, each number is the equivalent to a point on a compass.
 [1][0][7]
 [2]   [6]
 [3][4][5]

Alright time to begin, starting with the NPC header:
prontera,150,180,4    script    Healer    4_F_ARUNA_POP,{

Now that we have the header out of the way it's time to write a little bit of dialogue.
To do that, we're going to use the command: mes "<text>"; Additionally, we are going to be using the color codes, to make the name of the healer appear blue within the text box.
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";

Okay, we got the little bit of dialogue out of the way. Now let's give them the choice of whether or not they want to be healed.
To do so, we're going to be using a combination of 2 commands. The first being: if( <condition> ) { <statement> }; and Second: select("<option>"{,"<option>",...})
But we are also going to end the script early, if they decided to choose: ' No thank you. ' by using the command: close;
The reason we are using the close command, is because when we used mes, it caused a text window to open up. And we need to close that window. Simple right?
*Note - Options can be grouped together, separated by the character ' : '.*
If you are unsure what I mean by " condition " take a look at this: Operators
if (select("Yes, heal me.", "No thank you.") == 2) {
    close;
}

Now that we have that finished, it is time to heal them for 100% HP&SP using the command: percentheal <hp>,<sp>;
And also end the script. Again, using the close command.
percentheal 100,100;
close;

Now all we need to do is add the last } to the end of our script, so that it knows there is nothing more to add.
Once you're done, your script should look something like this:
prontera,150,180,4    script    Healer    4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
if (select("Yes, heal me.", "No thank you.") == 2) {
    close;
}
percentheal 100,100;
close;
}
And that's it for your first script. You just created a healer npc.

Part 2
Okay, firstly you should have already completed Part 1 of this tutorial. If not you need to do so to follow along.

In part 2, we are going to be making a small edit to our script to let player's know it cost zeny to use the healer. Then we are going to check if they have enough zeny. If they do, we'll take some away and heal them.
Let's start by opening up the script we made in Part 1.
prontera,150,180,4    script    Healer    4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
if (select("Yes, heal me.", "No thank you.") == 2) {
    close;
}
percentheal 100,100;
close;
}

Okay, let's add the following line above the menu options:
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";

Next, directly above percentheal 100,100; we're going to be adding our check to see if they have enough zeny. If they do not, we'll be telling them that they don't have enough zeny. Then we'll end the script.
To do so, we're going to be using the command: if( <condition> ) { <statement> };
If you are unsure what I mean by " condition " take a look at this: Operators
if (Zeny < 1000) {
    mes "I'm sorry, but you don't have enough zeny.";
    close;
}

Okay we got the check out of the way. Now we just need to take the zeny away from them if they do have enough zeny.
To do that we'll be setting the Constant Variable Zeny to a value of Zeny - 1000. To see how this is done look here: Assigning variables
Now then, lets add it in:
Zeny -= 1000;

And that's all there is to edit. When you're done it should look something like this:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
if (select("Yes, heal me.", "No thank you.") == 2) {
    close;
}
if (Zeny < 1000) {
    mes "I'm sorry, but you don't have enough zeny.";
    close;
}
Zeny -= 1000;
percentheal 100,100;
close;
}
And that's it, you just finished editing your script, and now it costs players 1,000 zeny to get healed.

Part 3
Alright, to start this off. I'm assuming you already finished Part 1 & 2. If not, I recommend you do so,
since we will be using those scripts to make this one. I will attempt to continue this pattern until we deviate away from the healer and move on to a different type of script.

So first, let's open up the script we made in Part 2.
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
if (select("Yes, heal me.", "No thank you.") == 2) {
    close;
}
if (Zeny < 1000) {
    mes "I'm sorry, but you don't have enough zeny.";
    close;
}
Zeny -= 1000;
percentheal 100,100;
close;
}

Let's start by adding a MES to show how much they cost. For this script were going to make it nice and cheap. 5,000z to get both INCREASED AGI & BLESSING Lvl 10.
And were going to add this right above our menu options.
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs 5,000 zeny.* ^000000";

Now that people know we offer buffs, we need to give them the option to choose to get buffed.
So lets modify our menu to have a 3rd option.
if (select("Yes, heal me.", "I want buffs", "No thank you.") == 3) {
    close;
}

Now that we got that out of the way. It's time to modify our zeny check. It's going to be customized a little bit.
Were now going to use | | and && operators in our checks.
So go ahead and find our zeny check and change it to the below:
if ((Zeny < 1000 && @menu == 1) || (Zeny < 5000 && @menu == 2)) {
    mes "I'm sorry, but you don't have enough zeny.";
    close;
}

Your probably wondering why were using @menu == 1 or @menu == 2. This is because when ever a menu option is selected, the variable @menu is set to that option. So, the first option is equal to 1, and the second is equal to 2, so on and so forth.

At anyrate, since we are still in the beginner section of scripting, were going to be adding 1 more check to our script.
So go ahead and add the following to your script beneath the checks we did above:
if (@menu == 1) {
    Zeny -= 1000;
    percentheal 100,100;
}

However, this isn't complete. We still need to add the last part, which deals with our buffs.
To do that we're going to be using the command: sc_start <effect type>,<ticks>,<value 1>{,<rate>,<flag>{,<GID>}};
Where, effect type is the buff we want to give them, ticks is how long it will last in 1/1000ths of a second, and value is the level of the buff.

In our case, we are using Blessing Level 10 and AGI-UP Level 10. And to keep things simple, we're going to make it last for 5mins each.
If you wish to add other status-effects then look in this file: const.txt. It will be the things starting with: SC_ .
So, let's start by finding our previous check and find: } . And add the following next to it:
else {
    Zeny -= 5000;
    sc_start SC_BLESSING,300000,10;
    sc_start SC_INC_AGI,300000,10;
}

So your probably looking at the 300000 and wondering why it's like that. Well the answer is simple.
Ticks are 1/1,000ths of a second. So to find 5 minutes we do the following math.
1 * 1,000 = 1 second * 60 = 60,000 OR 1 Minute * 5 = 300,000 OR 5 Minutes. So now that we have our number we just put it in.
Okay, now that it's done. Your script should look like the following:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs 5,000 zeny.* ^000000";
if (select("Yes, heal me.", "I want buffs", "No thank you.") == 3) {
	close;
}
if ((Zeny < 1000 && @menu == 1) || (Zeny < 5000 && @menu == 2)) {
	mes "I'm sorry, but you don't have enough zeny.";
	close;
}
if (@menu == 1) {
	Zeny -= 1000;
	percentheal 100,100;
} else {
	Zeny -= 5000;
	sc_start SC_BLESSING,300000,10;
	sc_start SC_INC_AGI,300000,10;
}
Zeny -= 1000;
percentheal 100,100;
close;
}

Now we're just going to delete those last 2 lines above close;
When you're finished deleting them, your script will be done. And it should look something like this:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs 5,000 zeny.* ^000000";
if (select("Yes, heal me.", "I want buffs", "No thank you.") == 3) {
	close;
}
if ((Zeny < 1000 && @menu == 1) || (Zeny < 5000 && @menu == 2)) {
	mes "I'm sorry, but you don't have enough zeny.";
	close;
}
if (@menu == 1) {
	Zeny -= 1000;
	percentheal 100,100;
} else {
	Zeny -= 5000;
	sc_start SC_BLESSING,300000,10;
	sc_start SC_INC_AGI,300000,10;
}
close;
}
And that's it. You just finished editing your script and now players have the option to receive Increased AGI and Blessing Level 10 at the cost of 5,000 zeny.

Part 4
Okay, so by now, you've learned how to make a pretty standard healing npc. But, it looks kind of messy. So in this lesson, we're going to clean it up, by getting rid of some of those if( stantements ).

So as always, let's start by opening up the previous script:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs 5,000 zeny.* ^000000";
if (select("Yes, heal me.", "I want buffs", "No thank you.") == 3) {
	close;
}
if ((Zeny < 1000 && @menu == 1) || (Zeny < 5000 && @menu == 2)) {
	mes "I'm sorry, but you don't have enough zeny.";
	close;
}
if (@menu == 1) {
	Zeny -= 1000;
	percentheal 100,100;
} else {
	Zeny -= 5000;
	sc_start SC_BLESSING,300000,10;
	sc_start SC_INC_AGI,300000,10;
}
close;
}

What were going to do here is just delete everything after the last mes command. So highlight everything beneath that and just press DELETE or BACKSPACE ( your choice =P ).

When your done your script should look like this:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs 5,000 zeny.* ^000000";

Looks like we went back to the drawing board. But don't worry, you'll be doing this a lot down the line when writing your own scripts. Finding better ways to write it and such. So, let's start by adding the following line beneath it.

This will serve as our new menu:
switch(select("Yes, heal me.", "I want buffs", "No thank you")) {
I'm sure you've noticed the ' switch ' which took the place of ' if '. We also got rid of the ' == 3 ' part. This is because switch is much cleaner and easier to read. But, first let's explain what it does. Simply, all it does is cycle through labels called: case 1: case 2: etc... depending on the value of a variable or number. In our case, it's the variable @menu which will have either a value of 1, 2 or 3 because of our menu.

If you want a further explanation, you can click the spoiler below for a bit more detail. Otherwise, let's continue to the next step.
Spoiler
Okay, let's add the sub-label: case 1: to our script. This will deal with players click on " Yes, heal me. ". Let's also add the zeny check & percentheal in there as well.

So add the following:
case 1:
	if (Zeny < 1000) {
		mes "I'm sorry, you don't have enough zeny.";
		close;
	}
	Zeny -= 1000;
	percentheal 100,100;
	break;

That's done. I'm sure you see the command: break; there. What this does is allow us to ' exit ', a pair of { }. Doing so, will allow us to continue on with the script if there is some other things to do. You can take a look at the spoiler above to see how we utilize this. Other wise, let's go a head and make the second label: case 2: beneath all of that.

This one will deal with when they click on " I want buffs. ", so we are going to be adding the zeny check for that, along with the buffs:
case 2:
	if (Zeny < 5000) {
		mes "I'm sorry, but you don't have enough zeny.";
		close;
	}
	Zeny -= 5000;
	sc_start SC_BLESSING,300000,10;
	sc_start SC_INC_AGI,300000,10;
	break;

Now that we got that out of the way. Let's add } to the end of that, to let the script know were done with the: switch() command. Then directly beneath that, were going to add: close; To let the script knows that were ending it. Followed by the final } so that the script knows that there is nothing more to do.
}
close;
}

Once your done with that, your script should look something like the below:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs 5,000 zeny.* ^000000";
switch( select("Yes, heal me.", "I want buffs", "No thank you") ) {
	case 1:
		if (Zeny < 1000) {
			mes "I'm sorry, but you don't have enough zeny.";
			close;
		}
		Zeny -= 1000;
		percentheal 100,100;
		break;
	
	case 2:
		if (Zeny < 5000) {
			mes "I'm sorry, but you don't have enough zeny.";
			close;
		}
		Zeny -= 5000;
		sc_start SC_BLESSING,300000,10;
		sc_start SC_INC_AGI,300000,10;
		break;
}
close;
}
And there you go, you just finished cleaning up your script. It looks much better, and it still does the exact same thing! Who would of thought.

Part 5
Alright, so far we've completed Parts 1 -> 4. And we have a working script because of it. Now, what we need to do is, make it easily configurable. Sure, we could scroll through the script, and change the zeny prices. But if we do that, we might make a mistake. So what were going to do is, add a label called: OnInit: in our script. This label will active each and every time the server starts up, or scripts are reloaded.
And under this label we'll be adding our variables, which will be our focus for when we want to configure things in our script.

For a list of all variable types look here: Variables
So go ahead and open up the script from the last lesson:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs 5,000 zeny.* ^000000";
switch( select("Yes, heal me.", "I want buffs", "No thank you") ) {
	case 1:
		if (Zeny < 1000) {
			mes "I'm sorry, but you don't have enough zeny.";
			close;
		}
		Zeny -= 1000;
		percentheal 100,100;
		break;
	
	case 2:
		if (Zeny < 5000) {
			mes "I'm sorry, but you don't have enough zeny.";
			close;
		}
		Zeny -= 5000;
		sc_start SC_BLESSING,300000,10;
		sc_start SC_INC_AGI,300000,10;
		break;
}
close;
}

We are going to add the: OnInit: label beneath the final: close; command. But let's also add a couple of npc_variables there as well. And let's name those variables: heal_price and buff_price .

Remeber, those are NPC variables. So let's go ahead and add the following:
OnInit:
.heal_price = 1000;
.buff_price = 5000;

Here you can see we used the set command. This is because we are telling the script to set those variables, to those values. In this case, .heal_price to 1,000 and .buff_price to 5,000 since that is what our script uses as prices for healing and buffing. Now, we really should add this command beneath that: end; .
Go ahead and click that link to find out why we need to add it.
end;

Alright, we have officially created variables. However as they are now, they aren't doing anything and just taking up space. So now were going to put them to use. Let's comb through our script and find all of our zeny checks. Let's replace all those: 1000 and 5000 with the corresponding variables.
When your done, your script should look like this so far:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs 1,000 zeny to get healed.* ^000000";
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs 5,000 zeny.* ^000000";
switch( select("Yes, heal me.", "I want buffs", "No thank you") ) {
	case 1:
		if (Zeny < .heal_price) {
			mes "I'm sorry, but you don't have enough zeny.";
			close;
		}
		Zeny -= .heal_price;
		percentheal 100,100;
		break;
	
	case 2:
		if (Zeny < .buff_price) {
			mes "I'm sorry, but you don't have enough zeny.";
			close;
		}
		Zeny -= .buff_price;
		sc_start SC_BLESSING,300000,10;
		sc_start SC_INC_AGI,300000,10;
		break;
}
close;

OnInit:
.heal_price = 1000;
.buff_price = 5000;
end;
}

Now, there being put to use! But wait, if you look at the mes commands, they still say 1,000 and 5,000 in them. This isn't good, because if we change the values of our variables, those mes commands won't show the proper amount. And we don't want to type it out EACH and EVERY time we make changes. So let's edit that text. So go over to the line that tells players how much healing costs.
And were going to make the following changes:
mes "^FF0000 *Note - It costs "+ .heal_price +" zeny to get healed.* ^000000";

So, as your looking at this, you'll see the following was removed: 1,000 and the following was added in it's place: "+ .heal_price +" pay close attention to this, as it's very important. Take a close look at these: "+ and +" .
I'm going to go a bit into detail on why we need these in this spoiler. If you already know why we used them, continue on with the lesson.
Spoiler

Okay, now let's make the same changes to line where we tell players how much it costs to get buffed, but using the other variable this time:
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs "+ .buff_price +" zeny.* ^000000";

After that we are done! So, your script should look something like this:
prontera,150,180,4	script	Healer	4_F_ARUNA_POP,{
mes "[^0000FF Healer ^000000]";
mes "Would you like me to heal you?";
mes "^FF0000 *Note - It costs "+ .heal_price +" zeny to get healed.* ^000000";
mes "^FF0000 *Note - INCREASED AGI + BLESSING Level 10 costs "+ .buff_price +" zeny.* ^000000";
switch( select("Yes, heal me.", "I want buffs", "No thank you") ) {
	case 1:
		if (Zeny < .heal_price) {
			mes "I'm sorry, but you don't have enough zeny.";
			close;
		}
		Zeny -= .heal_price;
		percentheal 100,100;
		break;
	
	case 2:
		if (Zeny < .buff_price) {
			mes "I'm sorry, but you don't have enough zeny.";
			close;
		}
		Zeny -= .buff_price;
		sc_start SC_BLESSING,300000,10;
		sc_start SC_INC_AGI,300000,10;
		break;
}
close;

OnInit:
.heal_price = 1000;
.buff_price = 5000;
end;
}
Now, every time we want to change how much getting healed or buffed costs, we just change the values of those variables.