FANDOM


Please note: This is taken straight out of the RealmCrafter: Standard documentation and there are much better introductions and tutorials on the RealmCrafter scripting language. This page is here purely for archiving reasons and should be avoided by most users.

Realm Crafter Scripting Language Tutorial and Introduction

In this section of the Realm Crafter guide we will begin to learn how to really bring your game to life. With the Realm Crafter scripting language, we can design quests to immerse your players into the lore of your world. We can create crafting systems to allow your players to be productive members of the games society. We can design combat skills to enhance the experience of battle. We can create useful and powerful spells to aid allies, or to hinder enemies. In short, those elements which define your game will be created by you through the RC scripting language.

We will begin with the basic structure of RC scripts, and progress to creating some interesting effects and abilities and placing them into your game. Those with a basic understanding of programming and scripting may still wish to review the early parts of this guide, as there will be some useful information related to the structure of the language, and some of the limitations and their work around.

The Realm Crafter Scripts Editor


The Script Editor itself has a very clean and simple interface. The documentation of the script editor should provide all of the explanation of it's workings needed..

Scripting Example

Every scripting language needs some structure to tell the software how to process the instructions. Without proper structure, the instructions become unrecognizable to the script processor, resulting in errors. Here we will look at the structure of one of the scripts included with realm crafter.

The first thing we see is two forward slash characters (//) followed by some text. This character combination is used to place text inside of the script which is not processed by the script processor. These are called comments, and are used to place information inside of the script to give clearly understandable information to anyone who may be working within the script. Well commented scripts will be much easier to understand and debug than uncommented scripts. This is especially true when a script begins to get very large and complex. 

Next we see the line Function Main(). At the end of the script you will see the line End Function. Everything between these two lines will be within the function named Main. Main is the default function for all scripts and should be included in every script you create. We will discuss function in greater depth later, but for now, all you need to remember is that these lines are required for every script.

The next line Player = Actor() assigns the output from the Actor() command to the variable Player. From this point forward we can use the name Player to refer to the Actor of this script. In simple terms, the output of the Actor() command is the handle (a unique numeric identifier) of the actor (Player or NPC) who is running the script.

Next we see another comment informing us that the next section of code is doing a “Mana Check”. This section of code checks the current value of the players Attribute “Mana” and assigns it to the variable ManaLevel. If the Players “Mana” is “less than” 1, the result of the check is True and the instructions between the If and EndIf commands are executed. This results in a message to the Player stating that there is insufficient mana to cast the spell. If, however, the players Mana level is not “less than” 1, every instruction within the “If statement” is ignored and the next section of code is executed.

The next line is Return(). This command is used to end a function and optionally return some value to the function from which the current function was called. In this instance, there is no calling function, since this piece of code resides within the Main() function. This results in this script ending at this point, preventing any further script execution, which happens to be the desired result if the player does not have enough mana to cast the spell.

The next line SetAttribute(Player, “Mana”, ManaLevel – 1) will only run if the result of the previous If statement is False. This code will “Set” the players Mana attribute to 1 less than the value of ManaLevel, which was the variable assigned earlier to hold the value of the players current “Mana” attribute value.

The next section of code plays the characters casting animation (named “Magic Cast”), places a short particle effect using the CreateEmitter() command and pauses the script for 1 second (1000 milliseconds).

Next we see the part of the script which actually does the “Healing” for which the script is named. By this time you should be able to follow the flow and understand what is happening here. A random integer between 5 and 10 is added to the players current “Health” attribute and assigned to the variable Health. The Maximum “Health” for the player is also checked and assigned to the variable Max.

The If statement checks to see if Health is greater than Max. If the result is True, then Health is set to the Max value for the players “Health” attribute. This prevents the player from being healed for more than he should have been healed.

And finally, the players “Health” is increased and the script ends with the Return() command.

In the tutorial section, we will create a script called “A_Heal Other” and create an ability in the Game Editor which will allow a character to learn the ability to “Heal Others”.

 

We have just reviewed one of the scripts included with Realm Crafter. What we have seen is how a few of the scripting commands are utilized, how variables can be used, how the flow of a script can be controlled using If .. EndIf, and how to increase and decrease player attributes using simple arithmetic operators.

At this point lets look at the assignment operator. An assignment operator is used to assign a value to a variable. We saw an example of this in the A_Heal Self script every time a variable was initiated. The format for assigning a value to a variable is extremely simple and won't require much space to discuss.

The most basic assignment is as simple as A = 1. This will cause future occurrences of the variable A to be used as the integer 1 in any operation within the function in which it is defined. Another example, A = Actor(), assigns the output of a RC Script command to a variable. The above examples assign a numerical value to a variable. If we wish to compare values in variables, we use a double = sign (==) to check for equality. Using a single = will result in assigning the values.

We can also assign text to a variable using the assignment operator and enclosing the text within double quotation marks, for example: A = “Text” will assign the word Text to all coinsurances of the variable A within the function.

Commonly, any text is referred to as a String when dealing with programming or scripting. We will be using the term String in this document from this point forward when referring to non-numerical values.

When dealing with strings, there are some specific operators which we must use when comparing or modifying strings. When adding strings, or concatenating, we use the $+ sign. This will result in the value to the Right of the $+ sign being appended to the value on the Left side (“Hello “ $+ “World!” results in “Hello World!”). When comparing strings we use the $= operator, this compares the string value on the Left side of the operator to the Right side, and returns 1 if true, or 0 if false (“Hello” $= “World” results in a false result). Strings are assigned to variables in the same manner as numerical values with the string value enclosed within double quotes. (A = “World”).

Basic Scripting Control Structures in Realm Crafter

At this time, we will go a little more in depth into some of the methods for controlling the flow of a script, including a few more commands, and expanding more on the If ... EndIf structure. We will also be introducing the GoTo() command and the use of labels for control purposes. Last but not least, we will discuss the use of Functions for organizing code and controlling the flow of a script.

We saw examples of If ... EndIf controls in the “A_Heal Self” script. What if we want to have multiple levels of checks within a script, or we want to have multiple alternative checks. Luckily for us, there is much more to the If statement than a simple one time check.

At this time we will look at the Else and ElseIf commands which allow us to check for multiple values sequentially within an If statement. Lets look at an example in pseudo code.

If(Value1 < 2) // Our first condition statement

Code to be run

ElseIf(Value1 > 2) // If the first condition is false check this condition

Code to be run

Else // If the above 2 values are both false Run the next code

Code to be run

EndIf

This is a great way to check one value against multiple possible values. If, however we want to check for multiple conditions before running a segment of code, we would place If statements within If statements. This is generally referred to as “Nesting” the If statements, or as “Nested If's”. An example in pseudo code follows.

If(Value1 > 2) // If condition1 is met

If(Value2 < 10) // Check to see if condition2 is also met

Code to be executed // If so, run this code

Else

Execute alternate code // If only condition1 is true, execute this code

EndIf

Else

Code to be executed // If neither value is true, execute this code

EndIf

As you can see using the If ()... ElseIf() ... Else ... EndIf commands we can create some pretty complex checks of our data before executing a section of code. An example of this can be seen in the “Blacksmith” script found within the default project. This script also uses another useful form of control, which we will discuss later when we begin working with Player Dialogs.

Functions are useful for organizing our code into smaller useful segments and can also be useful for controlling the flow of our scripts. We have already seen the use of a function within the above script. The Main() function is the primary entry function within a script. It is possible, however, to have as many functions within a script as you feel are necessary.

An example of the basic structure of a function is found below:

Function Two()

A = 1 + 1

Output(Actor(), A)

Return()

End Function

Admittedly, this function doesn't seem to be overly useful, since it doesn't do anything but add 1 + 1, assign the value to the variable A and display the result to the player via the chat window. However, we will expand on this below and begin to demonstrate the usefulness of functions.

// Basic Function Example

// This script will perform a simple calculation within a function

// and return the result to the calling function

Function Main()

A = 2

B = 3

// Sends the values of A and B to the function Add()

// and place the results of that function into the variable Result

Result = Add(A, B)

// Outputs the result to the players chat window

Output(Actor(), “The Sum of “ $+ A $+ “ and “ $+ B $+ “ is “ $+ Result $+ “.”)

Return()

End Function

// Here is where we create our Add function and do the dirty work

// The values passed to Add() from the main function are placed in the

// variables C and D

Function Add(C, D)

// Sum is the result of C + D

Sum = C + D

// The value stored in Sum is sent back to the calling function Main()

Return(Sum)

End Function

The above is a very simple illustration of how to use functions and pass values to and from functions. This concept can be used to create some very complex scripts, while keeping the script organized, compartmentalized and easy to read and understand.

Those of you who are familiar with other scripting and/or programming languages will likely be wondering when the For...Next and While type loops will be covered. At the time of this writing, these structures don't exist within the Realm Crafter scripting language. There is, however, the ability to create loops and control them in a similar fashion using the GoTo() statement.

The GoTo() statement will send the currently executing section of code to the label specified within the parenthesis of the GoTo() statement. The following code example will illustrate the basic concept.

// GoTo example

Function Main()

A = 10

.Loop // Note there is a period before the label name

Output(Actor(), A)

A = A – 1

If(A > 0)

GoTo(Loop)

EndIf

Return()

End Function

The above code will continue to subtract 1 from the value of A until A is no longer greater than 0. With some adjustments to the If statement and placement of the GoTo() command within or outside of the If statement, virtually any form of loop can be created with just a few lines of code.

This covers the basic structure of Realm Crafter scripts. Next we will create a new which will heal a targeted actor.

Begin by creating a new project within the Realm Crafter Project Manager, we will be using this project to illustrate some of the scripting hooks available to us in the Game Editor. Use any name you like for the project.

Now, with your project selected, switch to the Toolbox tab and open the Script Editor. Select File > New Script. Now we will name our script A_Heal Other, we will not be using the existing script A_Heal Others, since this may be changed in a future update, and we don't want to loose our work. Your screen should look similar to the following.


 Now click “File -> Save As” and typing the name “A_Heal Other” and we can begin.We will begin by adding some comments to let others know exactly what our script will be doing. We will also create our Main function and associated commands.

Lets begin with our comments and our Main function structure. Type the following text into the editor.

// script for the heal other ability

// Restores 5-10 health to a targeted actor

Function Main()

Return()

End Function

This is the basic structure from which we will create every script. We also know that within this script we will need to access the Players health and mana attributes and a Targets Health attribute. Lets begin by assigning some variables to make reading the code easier.

// script for the heal other ability

// Restores 5-10 health to a targeted actor

Function Main()

Player = Actor()

Target = ContextActor()

ManaLevel = Attribute(Player, “Mana”)

Health = Attribute(Target, “Health”)

MaxHealth = MaxAttribute(Target, “Health”)

Return()

End Function

What we have done here is to designate the Player variable to the actor who is running the script (Actor()), the Target variable to the actor who the Player has targeted (ContextActor()), the ManaLevel variable to the current amount of Mana available to the Player, the Health variable to the amount of Health the Target currently has, and MaxHealth to the maximum value which the Target can have in their health attribute.

We now have all of the data necessary to begin writing our script. First we will want to verify that our Player has enough Mana available to cast our heal spell. We do this within an If structure as we discussed earlier

// script for the heal other ability

// Restores 5-10 health to a targeted actor

Function Main()

Player = Actor()

Target = ContextActor()

ManaLevel = Attribute(Player, “Mana”)

Health = Attribute(Target, “Health”)

MaxHealth = MaxAttribute(Target, “Health”)

If(ManaLevel < 1)

Output(Player, “Insufficient Mana to cast this spell”)

Return()

EndIf

 

Return()

End Function

Now, if the player does not have enough mana to cast our spell, the spell will end and let the player know it failed.

By eliminating the possibility of an improper cast early in the script, we have reduced the chances of an error when an attribute becomes negative.We have also shortened the amount of time the server will be processing this script in the event the player does not meet the requirements to cast.

We could also have checked to verify that the player has a sufficient level of the Magic Skill, if it were present in our game, or verified that the target met requirements, such as a high enough rating with a given faction, or was a member of a given faction. However, we are keeping this script simple.

Now we need to include the code which will run if the player has sufficient Mana to cast the spell.

// script for the heal other ability

// Restores 5-10 health to a targeted actor

Function Main()

Player = Actor()

Target = ContextActor()

ManaLevel = Attribute(Player, “Mana”)

Health = Attribute(Target, “Health”)

MaxHealth = MaxAttribute(Target, “Health”)

If(ManaLevel < 1)

Output(Player, “Insufficient Mana to cast this spell”)

Return()

EndIf

SetAttribute(Player, “Mana”, ManaLevel – 1)

DoEvents(1000)

Health = Health + Rand(5,10)

If(Health > MaxHealth)

Health = MaxHealth

EndIf

SetAttribute(Target, “Health”, Health)

Return()

End Function

Our script is now complete, if a little boring visually. We have first reduced the Players mana by 1 and paused the script function for 1 second. We next updated the Health variable by increasing its value by a random integer between 5 and 10.

Next we used an If structure to be certain that the new Health value was not greater than the players maximum health value, and set it to the Max value if it was indeed higher.

And finally, we actually increased the players health value to reflect the action of the spell.

We can also include some visual elements to liven up the game and as visual feedback that the spell is actually working. We should have some animations for the casting, as well as some visual effects to see our target getting healed.

At the time of this writing, we do not yet have a casting animation defined for the included models, so will use the Yawn animation for the purposes of this script. This document will be updated at a later date once we have the correct animations in place.

We will now add the visual elements and our script will be complete.

// script for the heal other ability

// Restores 5-10 health to a targeted actor

Function Main()

Player = Actor()

Target = ContextActor()

ManaLevel = Attribute(Player, “Mana”)

Health = Attribute(Target, “Health”)

MaxHealth = MaxAttribute(Target, “Health”)

If(ManaLevel < 1)

Output(Player, “Insufficient Mana to cast this spell”)

Return()

EndIf

SetAttribute(Player, “Mana”, ManaLevel – 1)

// Particles and casting animation

// Note at the time of this writing AnimateActor is not functioning

// CreateEmitter is also not displaying correctly

AnimateActor(Player, "Yawn", 0.5, 1)

CreateEmitter(Target, "HealthSpell", 15, 1000)

DoEvents(1000)

Health = Health + Rand(5,10)

If(Health > MaxHealth)

Health = MaxHealth

EndIf

SetAttribute(Target, “Health”, Health)

Return()

End Function

The AnimateActor() command and the CreateEmitter() commands are explained in detail in the script command reference, so I'll just briefly cover their use here. What we have done is to play a predefined animation sequence which is defined in the Animations tab in the Game Editor, and to place a particle effect on our Target. The particle effect HealthSpell is one of the included particle effects in the engine. Any defined particle effect may be used.

Congratulations, you have now completed your first RC Script, which later we will be using to create abilities in the Game Editor.

This concludes the introduction section of this document. Next we will discuss the actual process of creating abilities and other features for our games.

 

Implementing Scripts in Realm Crafter

Thus far, we have been discussing the creation of scripts for use in Realm Crafter. From this point forward, we will be learning how to use these scripts to bring some life to our world.

In this section we will cover the creation of Abilities and adding them to our game. We will also begin to work with the different Dialog functions to create NPC's who will teach us these new abilities.

Earlier, we created a script named A_Heal Other, This will be the first of our abilities which we will add to the editor. Notice the A_ at the beginning of our script name. The purpose is to identify to us that this is designed as an Ability script. This naming convention isn't required, but does make identifying our scripts much easier and helps to keep everything organized together in the various drop down lists we will be accessing over the course of this tutorial.

Lets begin by opening our project, which we created created earlier. Your screen should look similar to this:

We will begin by clicking on the Abilities Tab. Next we will click on the “New Ability” button to create a newly defined ability.


 In the Ability Name box, change New Ability to Heal Other. Give a short description of what your ability does, in the Ability Description box. Next, we need to define and Icon to represent this ability in our game. We are using for this tutorial, the Fire.bmp file located in the particles directory, but you may use any supported image file for the icon.

Next, we set an ability recharge time. This is the amount of time which must pass before the ability may be used again. The default is 2 seconds, and we will use this for now. A note on recharge times, as related to abilities, very often the difference between an ability being under powered or over powered can be the result of a too short or too long recharge time.

We next have the option of restricting our ability to use by only one race, or one class, or both. There are situations in every game, where the designer may want to restrict access to an ability based on these criteria. Placing this choice here helps to reduce the amount of scripting we will be doing. We will leave these set to None at this time.

And now, finally, we are ready to assign our script to the ability we have created. Select our script A_Heal Other (Not A_Heal Others) from the drop down list. We are also given the option of selecting the function which our script will begin running from. We have designed our script with all of the code inside of the Main function, so there is no need to select an alternate function.

The ability to choose the starting function for our ability allows us a greater level of organization for our ability scripts. As an example, if we wished to have 10 heal abilities, we could create each ability within one script, with each ability being defined inside of one function. Then we simply select the function which corresponds to the version of the heal spell we wish to assign.

At this time, your screen should look similar to the following:


 Click the Save abilities button, and our new ability will be defined and available for use within our game.

Likewise, Items can have scripts attached to them which are activated with a right click. Lets look at the Items tab in the Game Editor. Scroll through the items which are predefined in the default game until you find the Magician's Ring item. Looking at the various tabs in the editor shows that this ring is rather boring.

We will now procede to create a ring which is truly worthy of a great magician. Every magician could use a little more Mana, so we will create a script which will add an effect on the player which will increase his Mana pool for a short period of time when it is right clicked in the inventory screen. An Icon will be displayed at the top of the players screen to indicate when the effect is active, and disappear when the effect is removed.

The script we will be using is posted below. You may wish to create this script inside your project, for use in this tutorial. I have used the name I_Magicians Ring. The I_ prepended to the script name is to identify this as an Item script.

// Magicians Ring right click script

// One time use Mana Buff which lasts for 5 minutes

Function Main()

Player = Actor()

If(HasItem(Player, "Magician's Ring", 1))

GiveItem(Player, "Magician's Ring", -1)

AddActorEffect(Player, "Mana Buff", "Mana", +30, 300, 10)

Else

Output(Player, “This script should not be running!”)

EndIf

Return()

End Function

This script first checks to see if the player does in fact have the Magician's Ring item. This seems as if it is an unnecessary check, since it will be assigned to the Magicians Ring item, but errors can always be made, and this will help to prevent them from progressing.

Next we Give the player a negative amount of the Magician's Ring item. When given a negative value, the item will actually be removed from the players inventory. Remember we're making this a one time use item. This is the same sort of process which would be used to create a potion, or any other consumable item.

Now that we have removed the item, we can add the effect onto the player. Effects are very useful tools for designing any sort of attribute increase or decrease which will take place for a limited amount of time. In this instance we have added 30 points of Mana to the players Mana Pool. We have assigned a texture to be presented as the Icon for the effect on the players screen. In this instance, since we are working within what is available in the default project, we have assigned an image from the particles directory, just as we used an image from the particles directory for the Heal Other ability icon.

We have also set this effect to last for a period of 300 seconds, or 5 minutes, after which, it will be removed and the players mana pool returned to normal.

Now lets assign this script to the actual item in the Game Editor. With our project opened, click on the Items tab, make certain you have the Magician's Ring item selected, and choose the Other tab. Your screen should look like this:

From the “Item runs this script on right-click” drop down, select the I_Magicians Ring script, and start the script in the Main function. Save your Items and we now have a magical ring for players to find and use in our game.

Next, we will be creating scenery objects which may be owned by players. The benefit to owning an object includes using that objects inventory space for item storage, as well as playing item animations which only function for that player. The reason we will be placing ownable objects, is the fact that ownership can only be applied via scripting.

Lets place our object now. Open the project we have been working in, click the Zones tab select scenery mode and change the active mesh. I am using the Chest 6.b3d mesh located in the Props 2 directory. Place the chest and set Inventory size to 40, collisions to Polygon, check on Scenery can be owned, and make note of the Ownership ID. Your screen should be similar to the following.

Now, we will move on to placing some scripts using the Waypoint scripting hooks. In this section we will spawn a salesman who will offer to sell us a chest for storage. Once we have purchased the chest, we will be have some additional storage to hold all of the great items we will be placing in our game.

 


 Begin by selecting the Waypoints icon at the top of the screen. We will be spawning an actor who will become our salesman. This salesman won't be very good at his job, and will do nothing more than give us a storage chest. But we will do a few other things with him. We will give him a name and give him some equipment which he will equip. This will be accomplished through the use of the Spawn script dropdown in the Waypoint configuration.

We will be using the following script for this purpose.

// Simple Spawn script

// Gives actor equip able items and sets a name

Function Main()

GiveItem(Actor(), "Steel Helmet", 1)

GiveItem(Actor(), "Razor Mace", 1)

SetName(Actor(), "Bubba de Chest")

Return()

End Function

I have named this script S_Chest Salesman. I am using the S_ to represent a Setup script.

We will also be using the I_Storage Chest script in our Right-click script location. This script will open a dialog prompting the player to take ownership of a storage chest. The text of this script is found below, The red 0 in the SetOwner command should be replaced with the ownership ID of the chest you placed in the zone.

// Storage Chest script

// To be placed in the Right Click slot of an actor

Function Main()

Player = Actor()

Chest = ContextActor()

D = OpenDialog(Player, Chest, "Storage Chest")

DialogOutput(Player, D, "Would you like a chest for extra storage?", 255, 255, 255)

Result = DialogInput(Player, D, "Yes", "No")

If (Result == 1)

SetOwner(Player, Darklands, 0)

DialogOutput(Player, D, "Congratulations on your new chest.", 255, 255, 255)

DoEvents(2000)

CloseDialog(Player, D)

ElseIf (Result == 2)

DialogOutput(Player, D, "Then I have no use for you!", 255, 255, 255)

DoEvents(2000)

CloseDialog(Player, D)

EndIf

CloseDialog(Player, D)

Return()

End Function

Place a waypoint and select the Elf(Defender) actor in the “Spawn this actor:” drop down. In the Spawn script drop down, select the S_Chest Salesman script. For the right click script, select the I_Storage Chest script for the Right click script.

Your screen should look similar to the following:


 Another example of placing an NPC can be found in the Blacksmith and Blacksmith Setup scripts. Feel free to place a Blacksmith NPC following the steps we have just used. BlacksmithSetup will be your Spawn script and Blacksmith will be the Right-click script.

Waypoint Death Scripts will be covered in an update to this document.

The last items to cover in the Game Editor are Triggers and their associated scripts and Zone Entry and Exit scripts. I will cover these in generalities, since we have covered placing scripts in the game well enough that you should have a good understanding of the process.

Triggers are defined in the Game Editor much like a Portal is. The trigger is placed, and scaled to the size desired. A script is then assigned to the portal which will execute once a player has entered its sphere of influence. A trigger script can be used for any script you would like to be executed once a player has entered a specific area. For example, a trigger can be useful to update a Quest which requires the user go to a certain area. It can also be used to send a message to the players chat window to announce that the player has entered an area, about which some information should be known.

Zone entry and exit scripts are defined in the Other Options section of the Zone Editor. These optional scripts can be used to perform zone specific functions, such as granting a zone specific ability or Item to a player, or updating a Quest. Exit scripts are much the same.

This covers the major areas of the Game Editor and the available scripting hooks in each. The information included in this section, should be enough to help you to develop much of your games scripting needs. There are other areas of scripting which we will be covering in the next section of this Guide, including the functions and purposes of the default scripts, which will be required in every Realm Crafter game, even if they are not used. We will also begin to create a simple tradeskill system. And cover the basics of building a Custom Combat script, including a very simple example.

Required Scripts

If you have browsed through the scripts which are included with the default Realm Crafter install, you will likely have seen this line in 3 of the scripts.

// You may alter this script however you like, but DO NOT RENAME OR DELETE IT

 

This line appears in the Death ,EquipChange and the LevelUp scripts. This indicates that these scripts must be present for a Realm Crafter game to function properly, even if they are empty.

These scripts are triggered at certain events in the course of a game, and are used to cause specific actions at the time of these events. We will briefly cover these scripts, and their functions. We will then view some examples of how these scripts might be used to customize your game.

Lets begin with the Death script. This script is run anytime a Played Character dies in the course of their adventures. At this time we will look at the text of the default death script, and make a few small modifications.

// Default death script for player characters

// You may alter this script however you like, but DO NOT RENAME OR DELETE IT

// The entry function for this script is always "Main"

// The context actor for the script is set to whoever killed the player

Function Main()

// Death animation

Output(Actor(), "You have died...")

Death = Rand(1, 3)

If (Death == 1)

AnimateActor(Actor(), "Death 1", 0.2, 0)

ElseIf (Death == 2)

AnimateActor(Actor(), "Death 2", 0.2, 0)

Else

AnimateActor(Actor(), "Death 3", 0.2, 0)

EndIf

// Wait

DoEvents(1000)

// Restore some health and take away some gold

SetAttribute(Actor(), "Health", 50)

ChangeGold(Actor(), -10)

// Warp back to area start

Warp(Actor(), ActorZone(Actor()), "Start")

// Done

Return()

End Function

This script, upon a players death, will randomly select and play one of 3 predefined death animations. After 1 second, the player is partially healed, and a death penalty applied, in the form of gold removed from his inventory. Next the player is ported to the start portal of the current zone.

This is a perfectly fine death script, but since this is a scripting tutorial, lets look at customizing this a little. To begin with, lets remove the death tax, and instead incur a penalty to player experience (XP).

We simply need to change this line:

// Restore some health and take away some gold

SetAttribute(Actor(), "Health", 50)

ChangeGold(Actor(), -10)

To this:

GiveXP(Actor(), -100)

Now, our players can recover from death, and avoid taxes. If we wished, we could also transport them to another zone entirely, place negative effects on them or any of a number of other scriptable actions.

The next required script is the Equip Change script. This script is executed everytime a player equips an equipable item. There are many possible uses for this script, from performing checks to ascertain if the specified class has the ability to wield the item, to checking if a specific item remains equipped.

Our task in this tutorial is to apply a specific effect when a specific enchanted item is equipped. For this we will use the Magician's Ring we enhanced earlier. Rather than invoking the script we placed in our ring in the earlier exercise, we will be applying an effect directly. When the ring is no longer equipped, we will immediately remove the effect.

The code of our new Equip Change is located below:

// Default equipped items change script for player characters

// You may alter this script however you like, but DO NOT RENAME OR DELETE IT

// The entry function for this script is always "Main"

// The context actor for the script is null

Function Main()

Player = Actor()

Weapon = ItemName(ActorWeapon(Player))

If(Weapon $= "Razor Mace")

AddActorEffect(Player, "HP Boost", "Health", +30, 6000, 15)

Else

DeleteActorEffect(Player, "HP Boost")

EndIf

// Done

Return()

End Function

This was a very simple script intended to only show the functionality of the Equip Change script. There are several checks which could have been made, every equipable slot should have been checked, and either a function called on a slot basis, or a ThreadExecute() command used to run a specific script per slot.

This should give you an idea of the potential for this required script.

Next we will look at the LevelUp script. This script will execute everytime our player gains a level in the game. Possible uses for this script is to check the ActorLevel() and award certain bonuses or items when leveling milestones are reached. The CreateEmitter can also be used to generate a visual signal for every increase in level. The possibilities are virtually endless, and limited only by your imagination.

Below is a simple example of a slightly modified LevelUp script.

// Default level up for all characters

// You may alter this script however you like, but DO NOT RENAME OR DELETE IT

// The entry function for this script is always "Main"

// There is no context actor for this script

Function Main()

Player = Actor()

Output(Player, "You advanced to level " $+ ActorLevel(Player) $+ "!")

Output(Player, "You have been awarded a Razor Mace!")

GiveItem(Player, "Razor Mace", 1)

Return()

End Function

This script will let the player know every time the player gains a level, and will award a Razor Mace to the player.

This covers the required scripts, however there a few other default scripts which do not fall into the required category, but can be very useful and will function in much the same way.

These are the Login, Startup and Attack scripts. The Login script will run whenever a player logs into your game. The Startup script will run when your server boots up, and the Attack script is used if the option for custom combat script is selected in the Game Editor. The Login and Startup scripts should not require more explanation.

Attack Scripts will be covered in an update to this guide.

Every game needs a story, a history, a reason to exist. These elements are often introduced to players slowly, over time using a questing system. Realm Crafter has incorporated several commands into the scripting language to assist us in setting these quests.

In this section of the guide, we will create a multi-part quest which will use every quest specific command currently available to us, as well as a few other commands which haven't been covered thus far.

This section will require the placement of certain NPC's and MOB's, which our players will interact with during the course of our quest. While creating this quest various actions will be required which assume a basic familiarity with the Zone tab of the Game Editor. We will not be covering the placement of NPC's or objects in detail, so if you are not comfortable with the basic operation of the Game Editor, you may need to go through some of the Game Editor tutorials before proceding.

Lets begin with a simple “Kill task” quest. I'm sure you've all noticed a large number of rats wandering about the Darklands zone. I think we should do something about that.

// Kill task quest

// kill 3 rats for a reward

// Set as right click script on an NPC

Function Main()

Player = Actor()

Target = ContextActor()

// Talk to Bart to begin the quest

D = OpenDialog(Player, Target, "Bart")

DialogOutput(Player, D, "Hello adventurer, would you like to earn a little gold?", 255, 255, 255)

Result = DialogInput(Player, D, "Yes", "No")

If(Result==1)

DialogOutput(Player, D, "Great! Kill 3 of these filthy rats, and I'll pay you 5 gold pieces.", 255, 255, 255)

DialogInput(Player, D, "Close")

CloseDialog(Player, D)

// Passing the Player variable to the Kill Task function

// Just to keep from having to redefine it there

KillTask(Player, Target)

EndIf

CloseDialog(Player, D)

Return()

End Function

Function KillTask(Player)

// Here we define our kill task target

ID = ActorID("Rat", "Critter")

// and here we actually define our Quest, and set its Status

NewQuest(Player, "Kill Task", "Kill 3 Rats", 255, 0, 0)

// Here, we wait until we have killed our 3 rats before executing the next line

WaitKill(Player, ID, 3)

// Here we flag our quest as completed

CompleteQuest(Player, "Kill Task")

// Here we give some feedback to the player, letting him/her know they have completed the task

D = OpenDialog(Player, 0, "Completed Task")

DialogOutput(Player, D, "You have successfully killed 3 Rats")

DialogInput(Player, D, "Close")

CloseDialog(Player, D)

Output(Player, "You recieve 5 Gold pieces")

// And here is our players reward

ChangeGold(Player, 5)

Return()

End Function

The above is the most basic of quests. We have seen how to start a quest, how to wait until we've killed a certain number of creatures to give the reward, and how to flag the quest as completed. We can do a little more with this quest. Lets begin by updating the quest status to reflect how many rats we have to kill. We'll do this by breaking our WaitKill() command into several WaitKill() commands. This isn't really necessary, but it does demonstrate how to update a quest. The modified KillTask() function is below.

Function KillTask(Player)

// Here we define our kill task target

ID = ActorID("Rat", "Critter")

// and here we actually define our Quest, and set its Status

NewQuest(Player, "Kill Task", "Kill 3 Rats", 255, 0, 0)

// Here, we wait until we have killed 1 rat before executing the next line

WaitKill(Player, ID, 1)

// Here, we update our quest log to show how many rats remain to be killed

UpdateQuest(Player, “Kill Task”, “Kill 2 Rats”, 0, 255, 255)

WaitKill(Player, ID, 1)

UpdateQuest(Player, “Kill Task”, “Kill 1 Rat”, 0, 255, 255)

WaitKill(Player, ID, 1)

// Here we flag our quest as completed

CompleteQuest(Player, "Kill Task")

// Here we give some feedback to the player, letting him/her know they have completed the task

D = OpenDialog(Player, 0, "Completed Task")

DialogOutput(Player, D, "You have successfully killed 3 Rats")

DialogInput(Player, D, "Close")

CloseDialog(Player, D)

Output(Player, "You recieve 5 Gold pieces")

// And here is our players reward

ChangeGold(Player, 5)

Return()

End Function

The changes above demonstrate how the UpdateQuest() command works. When you run this script, every kill will update the quest log to show the current state of the quest. Next, we will alter the quest a little more. Giving the reward automatically may take away from the role playing aspect of the game. Lets send our player back to our NPC to retrieve his reward.

// Here we also pass Target to the KillTask function, since we will need to identify the NPC in the new function

// Don't forget to also place Target in our call to the function.

Function KillTask(Player, Target)

// Here we define our kill task target

ID = ActorID("Rat", "Critter")

// and here we actually define our Quest, and set its Status

NewQuest(Player, "Kill Task", "Kill 3 Rats", 255, 0, 0)

// Here, we wait until we have killed 1 rat before executing the next line

WaitKill(Player, ID, 1)

// Here, we update our quest log to show how many rats remain to be killed

UpdateQuest(Player, “Kill Task”, “Kill 2 Rats”, 0, 255, 255)

WaitKill(Player, ID, 1)

UpdateQuest(Player, “Kill Task”, “Kill 1 Rat”, 0, 255, 255)

WaitKill(Player, ID, 1)

Update Quest(Player, “Kill Task”, “Return to Bart for your reward”, 0,0,255)

WaitSpeak(Player, Target)

D = OpenDialog(Player, Target, "Bart")

DialogOutput(Player, D, "You have successfully killed 3 Rats", 255, 255, 255)

DialogOutput(Player, D, “And here is your reward, 5 gold as promised.”, 255, 255, 255)

Output(Player, "You recieve 5 Gold pieces")

// And here is our players reward

ChangeGold(Player, 5)

// Here we flag our quest as completed

DialogInput(Player, D, "Close")

CloseDialog(Player, D)

CompleteQuest(Player, "Kill Task")

Return()

End Function

Well there you have a fully functional quest script using most of the quest commands available to us. What do you suppose happens if we return to talk to Bart after our quest is complete? Why he begins our quest script all over again. Selecting “Yes” will restart the quest.

One note, Since this is a quest, we should add the command Persistent(1) to the beginning of our Main() function. This will ensure that if a player logs out before completing the quest, his/her script will be paused until he/she logs back in. Without this flag, our quest script will stop running when the player logs out, but the quest status will remain in the quest log. This quest would not be able to be completed without restarting the quest at the beginning.

We have just seen a method of running a small quest using a single script. It is also possible to create our quests in such a way that they spread across several scripts, with each section being completable only after certain milestones have been met. For example, an Epic Quest, which begins early in the life of our character, and continues as the character grows in levels. This sort of quest is very common, and is a useful method of telling our games' “Story” to our players. We will begin to explore this sort of quest now.

{To Be Continued}