Difference between revisions of "Chapter 8"

From SphereWiki
Jump to: navigation, search
Line 255: Line 255:
  
 
'''Note:''' InsideUO is a popular tool for viewing the contents of the UO files but it is not the only one out there. Check out the [[Third Party Tools]] page for a list of other programs which you may want to use.
 
'''Note:''' InsideUO is a popular tool for viewing the contents of the UO files but it is not the only one out there. Check out the [[Third Party Tools]] page for a list of other programs which you may want to use.
 +
 +
 +
==Gumps==
 +
 +
Congratulations. If you've made it this far, you're way past where many scripters reach. Unfortunately, this is also where many scripters hit a brick wall. Gump scripting, especially gump designing, is one of the hardest things for a scripter to do. Rather than easy-to-remember scripting commands such as REMOVE and NEWITEM, you get cryptic looking strings of letters and numbers, which are made even more complex when they use variables. Due to the difficulty, I've split the Gump Scripting 101 section into two parts. The first part shows the setup and syntax of some of the commands. The second part shows the rest of them.
 +
 +
 +
===Part 1===
 +
First, we need to look at the setup of a gump script, which is different than any script you've seen so far. The tag SPHERE uses to recognize a gump script is '''DIALOG'''. I will use the words dialog and gump interchangeably throughout these sections. Unfortunately, GUMPs come in three parts: The dialog itself, the strings that go into the dialog, and the button responses. Those couldn't all be in one section, so SPHERE has divided things up like this:
 +
 +
 +
<spherescript color="darkgreen">[DIALOG d_test_dialog]
 +
... Code for the dialog layout goes here ...
 +
 +
[DIALOG d_test_dialog TEXT]
 +
... The text that will be displayed in the dialog goes here ...
 +
 +
[DIALOG d_test_dialog BUTTON]
 +
... The events that are triggered when buttons are pressed goes here ...</spherescript>
 +
 +
 +
Now, dialogs are made up of a number of different types of objects. You can have text boxes, buttons, checkboxes, text entry boxes (which you can change), and other various other things. They're each identified with a syntax that looks a lot like a function call. Here is the list of all the commands you can use with dialogs. I'll explain each of them in detail later.
 +
 +
 +
'''Dialog Objects'''<br />
 +
<spherescript color="darkgreen">resizepic <x> <y> <gumpback> <width> <height>                                // can come first if multi page. put up some background gump
 +
dorigin <x> <y>                                                                                              // Sets a dynamic origin point
 +
checkertrans <x> <y> <width> <height>                                                                        // add a trasparent layer (only for clients >= 3)
 +
gumppic <x> <y> <gump> <hue>                                                                                // put gumps in the dlg. (hue only for clients >= 3, otherwise ignored)
 +
gumppictiled <x> <y> <width> <height> <gump>                                                                // tile a gump
 +
tilepic <x> <y> <item>                                                                                      // put item tiles in the dlg.
 +
tilepichue <x> <y> <item> <hue>                                                                              // put colored item tiles in the dlg.
 +
text <x> <y> <color> <stringindex>                                                                          // put some text here.
 +
dtext <x> <y> <color> <text>                                                                                // put some text here.
 +
croppedtext <x> <y> <width> <height> <color> <stringindex>
 +
dcroppedtext <x> <y> <width> <height> <color> <text>
 +
htmlgump <x> <y> <width> <height> <stringindex> <hasbackgroud> <hasscrollbar>                                // add an html gump that show a text
 +
dhtmlgump <x> <y> <width> <height> <hasbackgroud> <hasscrollbar> <text>                                      // add an html gump that show a text
 +
xmfhtmlgump <x> <y> <width> <height> <clilocid> <hasbackgroud> <hasscrollbar>                                // add an html gump that show a cliloc text
 +
button <x> <y> <Down_gump> <Up_gump> <pressable(1/0)> <pagedest> <id>
 +
buttontileart <x> <y> <up_gump> <down_gump> <pressable> <page> <id> <tileid> <tilehue> <x offset> <y offset> // Add a button with tileart.
 +
textentry <x> <y> <width> <height> <color> <id> <startstringindex>                                          // Height should be 20
 +
dtextentry <x> <y> <width> <height> <color> <startstringindex> <text>                                        // Height should be 20
 +
textentrylimited <x> <y> <width> <height> <color> <id> <startstringindex> <limit>                            // Textentry with a limit of characters
 +
dtextentrylimited <x> <y> <width> <height> <color> <id> <limit> <text>                                      // Textentry with a limit of characters
 +
tooltip <clilocid>                                                                                          // popup a tooltip over a gump object (only for clients >= 4)
 +
radio <x> <y> <gump1> <gump2> <starting_state> <id>
 +
checkbox <x> <y> <gumpcheck> <gumpuncheck> <starting_state> <checkid>
 +
page <page_number>                                                                                          // for multi tab dialogs.
 +
group                                                                                                        // used to group groups of radio buttons - Group 1, Group 2, etc.
 +
nomove                                                                                                      // The gump cannot be moved around.
 +
noclose                                                                                                      // The gump cannot be closed
 +
nodispose                                                                                                    // not really used  (modal?)Yes, those look complicated now, and if you want to stick with easier scripting for a while, I don't blame you. As you can see, we have all of the required objects to make a nice form, like on a website, or even to make a website-type interface. I'll show you in a later chapter how make hidden buttons and such things like that. It's not as hard as it seems.</spherescript>
 +
 +
 +
Now, we have to discuss design. All gumps should start out like this:
 +
 +
 +
<spherescript>[DIALOG d_test_gump]
 +
0,0
 +
page 0
 +
... Some objects here ...
 +
page 1
 +
... More objects here ...</spherescript>
 +
 +
 +
0,0 is the position that the dialog will start on the screen. 0,0 means this dialog will appear with its upper left corner in the upper left corner of the game screen. It is possible to make a dialog start elsewhere, but it is really pointless unless the dialog is small.
 +
 +
 +
Dialogs are divided into pages, and only one page can be displayed at a given time. I'll show you later how to switch between pages with buttons. However, page 0 is always displayed under the other pages. If you have something that you don't want to change between pages (like a background or a title on top of the gump), you put it on page 0. Otherwise, it goes on another page. Page 1 is displayed by default when a dialog appears.
 +
 +
 +
Now, let's add a background to our gump. Since it's something we want to stay, we'll put it in page 0. Open up your InsideUO and we'll find a good background. The piece that you're looking for is that top left corner piece. (Most things in gumps deal with the top left corner of an object.) Find the one numbered A3C in the gump list of InsideUO. That's the background we're going to use. Actually this is a background you'll use a lot, because it's plain black with a gold border. Translating that number into hexadecimal, we get 2620. Remember that number, it's important.
 +
 +
 +
The command used for backgrounds is resizepic. Look at the chart above, and you'll see what information we need to give it for a resizepic: an x coordinate, a y coordinate, a gump id, a width, and a height. We have all of those things. We'll put it at (0,0) for coordinates, and let's say we make it 500 width and 300 height. Here's the new script:
 +
 +
 +
<spherescript>[DIALOG d_test_gump]
 +
0,0
 +
page 0
 +
resizepic 0 0 2620 500 300
 +
page 1</spherescript>
 +
 +
 +
That's all. Now put that into a script and type <font color="darkred">.dialog d_test_gump</font> in-game. You'll see that we have a nice black background. It's good to be in-game while you're creating gumps, because you can test it after each new addition. Sometimes if you're off by as little as 25 in your coordinates, things will look strange. It's much easier to fix things one at a time than it is to type the entire gump script, then find out you screwed up somewhere.
 +
 +
 +
Now, let's add some text to our gump. We'll say "Hello World" because that seems to be the standard for making new things in programming! There are two ways to store text, either inside the dialog or in the TEXT section. If your text is going to be used often, it's better to put it in the [DIALOG d_test_gump TEXT] section so you don't have to edit the same word every single time you want to change it. Otherwise, you can just add the text directly into the main dialog section. Here is an example of both:
 +
 +
 +
'''Using the TEXT section:'''<br />
 +
<spherescript>[DIALOG d_test_gump TEXT]
 +
<VAR.BLANKLINE>
 +
Hello World</spherescript>
 +
 +
 +
Each line has an index, starting with zero. For the first line, I always like to make a string that will evaluate to nothing, because sometimes you want empty text. I'll show you why later. Also, it makes it easier to think of your first line of text as 1 rather than 0. In our case, because Hello World is in position 1, we refer to it with text id 1. Here's what the whole script will look like now. Obviously, we're going to use that text object from the chart. We will put it at (50,50) and give it a color of 1152 (which happens to be white). We're also going to put it in page 1, because we don't want it to be there forever. Actually, I'll show you something else while we're at it.
 +
 +
 +
'''Using text inside the main gump:'''<br />
 +
It's much simpler than adding it to the TEXT section. Just use the <tt>dtext</tt> object:<br />
 +
<spherescript>dtext 50 50 1152 Hello World</spherescript>
 +
 +
 +
Much simpler! I'll be using both examples from here on. Here's what our whole script looks like now:
 +
 +
 +
<spherescript>[DIALOG d_test_gump]
 +
0,0
 +
page 0
 +
resizepic 0 0 2620 500 300
 +
page 1
 +
dtext 50 50 1152 Hello World
 +
text 50 70 3 1
 +
 +
[DIALOG d_test_gump TEXT]
 +
<LOCAL.BLANKLINE>
 +
Hello World
 +
 +
[DIALOG d_test_gump BUTTON]
 +
// Nothing here yet!</spherescript>
 +
 +
 +
See how easy it is to add text? You can also reuse text by using the same text id. If you look at this dialog in-game, you'll see that "Hello World" is written twice, because we have two text objects with Hello World. The second one is displayed 20 pixels (dots on the screen) below the first. As a general rule, all text should be assumed to be 20 pixels in height. (It's actually closer to 16, but some big letters take up more space.)
 +
 +
 +
You'll also see that they are in different colors. As a general rule, the color ID for dialog text is the color ID in-game minus 1. So black is 0, dark blue is 1, etc. New colors (like my hues.mul colors) will not display in any expected manner in a dialog, so stick to the default colors. Also, these colors are in DECIMAL, so you're going to need to convert things again. (Incidentally, color 1152 decimal is 0480 hexadecimal which happens to be that ice-blue color on an item.)
 +
 +
 +
Now that we've added text, we can experiment with a button. Obviously, we're going to use the button object to add a button to our gump. We need a lot of information for this button object, so I'll just copy the definition here for your reference. I'll go over each part in turn.
 +
 +
 +
<spherescript color="darkgreen">button <x> <y> <gump id (down)> <gump id (up)> <active> <page #> <index></spherescript>
 +
 +
 +
Here is what each does:
 +
 +
{|
 +
| '''&lt;x&gt; &lt;y&gt;''' || This is the position of the top left corner (see?) of the button image. Try to keep dialog pieces off one another, because they will overlap in the order they are placed in the script. We're going to put our button at (50, 90), right below the second line of text.
 +
|-
 +
| '''&lt;gump id&gt;'''    || When you press a button, it changes the picture to show that the button is in a "down" position. For our button IDs, we'll use 9A8 (2472) and 9A9 (2473). This is a red diamond shaped button that is rarely used. It has the same gold border as our background, so it'll look nice. Notice that the order is down, then up. The order of the images is up (2472), down (2473), so we'll have to switch the numbers in our script.
 +
|-
 +
| '''&lt;active&gt;'''      || This is a switch determining whether or not the button will return an event (1) or switch pages (0). Until we discuss pages in a later section, this will always be 1. (Thanks Belgar!)
 +
|-
 +
| '''&lt;page #&gt;'''      || If the button will be used to switch pages, this is the page that will be displayed. Keep in mind that you should put something on the other page to switch back to the first one. You don't want to frustrate your users with a crappy interface. Put 0 if the button doesn't switch pages.
 +
|-
 +
| '''&lt;index&gt;'''      || This is used in responding to events, as we'll see shortly. Make it a high number, probably starting in the thousands. Since this is our first button, we're going to call it button 1000. Index 0 is RESERVED, meaning you shouldn't use it for an ordinary button (we'll see why later).
 +
|}
 +
 +
 +
Here is the whole script now:
 +
 +
 +
<spherescript>[DIALOG d_test_gump]
 +
0,0
 +
page 0
 +
resizepic 0 0 2620 500 300
 +
page 1
 +
dtext 50 50 1152 Hello World
 +
text 50 70 3 1
 +
button 50 90 2473 2472 1 0 1000
 +
 +
[DIALOG d_test_gump TEXT]
 +
<LOCAL.BLANKLINE>
 +
Hello World
 +
 +
[DIALOG d_test_gump BUTTON]
 +
ON=1000
 +
SYSMESSAGE You pressed button 1000!</spherescript>
 +
 +
 +
Ooh! A new construct! The '''ON=1000''' you see in the button section of our dialog is how you respond to a button press. It acts just like any other ordinary event after that line. It means "When the button with ID 1000 is pressed, execute this event." In an ON event, SRC is the player operating the dialog and the default object is whatever the '''DIALOG''' command was used on. (On the sidenote, you can also use ONBUTTON= instead of ON=)
 +
 +
 +
Thus ends the first section on gumps and dialogs (which are the same thing). With this information you should be able to make just about any sort of gump you want, by playing with text and button positions. The possibilities are almost endless, and after you read Part 2, they will be endless. I have only used the information you will read in Part 2 twice in my entire long scripting career.

Revision as of 11:59, 2 June 2009

(WIP)

Skill Menus

One of the most common requests by newbie admins is the ability to create new things via the craft skills. I've noticed that it is also one of the first things that players check out about a shard. If your shard has awesome craftable items, chances are the player will stick around longer and gain skill so he can see them. Craftable houses are the ultimate in cool. And this section will show you how to make one. First, we'll just look at how the crafting system works.


There are about 9 built-in section names, for each of the various crafting skills. This script is called from within the server, and if those sections don't exist, you will receive many scary errors. Here is the list, which I grabbed from the top of sphereskill.scp.


// Hard coded ref names: (called directly form server)
// sm_alchemy = dclick on alch tools
// sm_summon
// sm_polymorph = polymorph menus
// sm_cartography = dclick on blank map
// sm_bowcraft = knife on wood
// sm_bolts = dclick on arrows or shafts
// sm_blacksmith = dclick on tool
// sm_carpentry = dclick on carp tool
// sm_tailor_leather = dclick on sewing kit
// sm_tailor_cloth
// sm_tinker = dclick on tinker tools.
// sm_inscription = dclick on blank scroll
// sm_cook = ??? NOT USED YET


Here is the syntax of a SKILLMENU section, like every other section in a SPHERE script:


[SKILLMENU sm_alchemy]


Now, a skill menu is the little box that pops up that contains the pictures of the items that you can scroll through and select. There are several attributes of this box which obviously need defined. The first is the title. It goes immediately underneath the [SKILLMENU] tag.


[SKILLMENU sm_alchemy]
What sort of potion do you want to make?


That line will be displayed across the top of the menu, as the title. In the case of the alchemy skill, we simply want to ask the user what type of potion he wishes to make. The next parts of the script are a little shaky, and contain some new constructs that you may or may not recognize. In reality, it's just a series of events, which occur depending on which menu item the user picks. Here's the part of the rest of the alchemy script:


[SKILLMENU sm_alchemy]
What sort of potion do you want to make?

ON=i_potion_Agility <name> (<resmake>)
    MAKEITEM=i_potion_Agility
    
ON=i_potion_AgilityGreat <name> (<resmake>)
    MAKEITEM=i_potion_AgilityGreat
    
ON=i_potion_CureLess <name> (<resmake>)
    MAKEITEM=i_potion_CureLess
    
ON=i_potion_Cure <name> (<resmake>)
    MAKEITEM=i_potion_Cure
    
ON=i_potion_CureGreat <name> (<resmake>)
    MAKEITEM=i_potion_CureGreat
    
ON=i_potion_ExplosionLess <name> (<resmake>)
    MAKEITEM=i_potion_ExplosionLess
    
ON=i_potion_Explosion <name> (<resmake>)
    MAKEITEM=i_potion_Explosion
    
ON=i_potion_ExplosionGreat <name> (<resmake>)
    MAKEITEM=i_potion_ExplosionGreat
    
ON=i_potion_HealLess <name> (<resmake>)
    MAKEITEM=i_potion_HealLess


As you can see, we still use the ON= event construction for these menus as well. The different is what follows. Let's dissect it:


ON=i_potion_HealLess <name> (<resmake>)


This line tells the server a number of things. The first parameter, immediately following the = sign, is the ID of the item to display. So, what will be displayed here is the DISPID of the i_potion_HealLess item. It happens to be a yellow potion. As soon as you specify this item, it becomes the default item for the rest of that line. The server knows that <NAME> refers to the name of the potion item, and that <RESMAKE> is a string which tells what it takes to make that item. Both of those are specified in the script for i_potion_HealLess (which is in sphere_item_provisions_potions.scp) and can easily be changed there (looks for NAME= to change the name and SKILLMAKE= to change the skill and difficulty).


MAKEITEM=i_potion_HealLess


Well if this isn't obvious, you shouldn't be reading this chapter. It simply begins the construction of the specific item. Wait, you may be asking, how does the server know which skill to use or how much skill is required, or even what to consume (1 empty bottle) when creating this item. Well, I'm glad you asked. To answer that, we need to look at the script for the item we're constructing. Ah, here it is....


[ITEMDEF i_potion_HealLess]
NAME=Lesser Heal
ID=i_bottle_YELLOW
RESOURCES=i_reag_ginseng, i_bottle_EMPTY
SKILLMAKE=ALCHEMY 0.1
TYPE=T_POTION
TDATA1=i_bottle_empty

ON=@Create
    MORE1 = s_heal
    MORE2 = 50.0


The two important lines are the RESOURCES and SKILLMAKE lines. These two lines work with the skill system to tell SPHERE what items are used to make this item. Basically, it says that when you create the item, you need 1 i_reag_ginseng and 1 i_bottle_empty. Incidentally, if you don't have the resources to make an item, it won't even appear on the list when you look at the SKILLMENU in-game. The next line tells the server which and how much skill is required to make this item. In this case, it says we need 0.1 in the alchemy skill. It IS just a lesser heal, after all.


Take your new i_potion_HealLess to a store and try to sell it. Magically, it seems to have a price. Where did that price come from? Well, it came from the RESOURCES. The value of a lesser heal potion is the combined value of the i_reag_ginseng and the i_bottle_EMPTY. Both of these are defined in sphere_item_resources.scp. This brings us to a point so important, I am going to put it in bold: An item MUST have either a VALUE or resources with a VALUE, or it will not appear in a SKILLMENU! Many newbie scripters ask on the boards about why their item is not appearing in an otherwise perfect SKILLMENU section. It has nothing to do with the SKILLMENU. Look at your item scripts before whining to us on the boards.


Another important point is this: You may have any number of lines between ON= events in a [SKILLMENU] section. It just happens that MAKEITEM does everything for us that we need it to do, so most scripts only have one line. However, you could print out a SYSMESSAGE or KILL a player within a SKILLMENU, just as easily as you could do it in any other event.


Now that we know this fact, let's build that craftable house I was referring to! First, we need to figure out what sort of RESOURCES we might want to use to craft a house. I would say a large amount of wood, maybe some metal for a doorknob, a deed to write on, and some magic just for the heck of it. We'll take a resources like that looks like this:


RESOURCES=1000 i_board, 100 i_ingot_iron, 5 i_reag_garlic, i_deed


We also need a SKILLMAKE definition, and for this we'll use the Carpentry skill. Say, 95.0. Then we'll put those lines into the ITEMDEF for the deed we want to make craftable:


[ITEMDEF i_craftable_deed]
ID=i_deed
NAME=Deed to a Small Stone House
RESOURCES=1000 i_board, 100 i_ingot_iron, 5 i_reag_garlic, i_deed
SKILLMAKE=CARPENTRY 95.0

CATEGORY=Provisions - Deeds
SUBSECTION=House Deeds
DESCRIPTION=Small Stone House

ON=@Create
    MORE1 = i_multi_house_stone_small


This, if you haven't figured it out, is a copy of item 04202, which has been renamed and edited. You can find the original script in sphere_item_deed.scp. Now, our item has a SKILLMAKE definition, and a VALUE definition (through the RESOURCES). It is craftable. We need to stick it into one of the existing Carpentry [SKILLMENU] sections now. Let's look at one of them:


[SKILLMENU sm_carpentry]
Carpentry

ON=i_board boards
    MAKEITEM=i_board
    
ON=i_chair_throne Chairs
    SKILLMENU=sm_wood_chairs
    
ON=i_chest_wooden_brass Containers & Shields
    SKILLMENU=sm_wood_containers_shields
    
ON=i_table_nightstand Table
    SKILLMENU=sm_wood_tables
    
ON=i_staff_gnarled Weapons & Tools
    SKILLMENU=sm_wood_weapons_tools
    
ON=i_armoir_dk Furniture
    SKILLMENU=sm_wood_furniture
    
ON=i_portrait_7 Paintings
    SKILLMENU=sm_wood_paintings
    
ON=i_trophy_deerhead Trophies
    SKILLMENU=sm_wood_trophies
    
ON=i_saddle Rancher Types
    SKILLMENU=sm_wood_rancher
    
ON=i_BED_9 Beds
    SKILLMENU=sm_wood_beds
    
ON=i_bulletin_board Miscellaneous
    SKILLMENU=sm_wood_misc


Like I said earlier, you can have any lines after an ON= section. In this case, it just happens to be a SKILLMENU line which opens up another menu. This is a hierarchical menu, because you choose from upper menu options like these, and go through lower menus, until you finally reach an item you can craft. Now, we're going to add the following two lines to the end of this script:


ON=i_craftable_deed <name> (<resmake>)
    MAKEITEM=i_craftable_deed


Guess what? We're done. That's all you need to do. Now, in most cases, you would make a new [SKILLMENU sm_houses] or something similar, and then add all of your items to that. In that case, the line you'd add to the main Carpentry menu (or one of the submenus) is the following:


ON=i_deed Craftable Houses
    SKILLMENU=sm_houses


That's all. Easy, isn't it? It's one of the easiest things to script, and one of the coolest. Unfortunately, it is so easy and repetitive that it takes FOREVER to make a good crafting system. If you are going to create one for your shard, start now. You should be finished in about a month. :)


Menus

If you paid attention in the previous section, this section should be very simple for you. It is so much easier to make a simple menu than a skillmenu. And, when you see how to read from buttons in a GUMP, you will see how similar it is to this. Basically, in SPHERE, there are occasions when you may want to bring up a menu for the user to choose from. Say, when they choose the "Help Desk from Hell" option on your help menu.


Do that. Right now. See how a menu pops up and asks if the user really wants to go to the help desk from hell? He can choose Yes, or No, and something different will happen in each case. Here's what the script for that menu might look like:


[MENU m_helpdesk]
Do you REALLY want to go to the Help Desk from Hell?  You will be stuck until a GM comes to free you!

ON=0 Yes
    SRC.GO Help Desk from Hell
    
ON=0 No
    SRC.SYSMESSAGE Help request cancelled.
    
ON=0 I'm a monkey.  Kill me.
    SRC.KILL


It looks awfully familiar, doesn't it? Here's what each part does. (I'll only take the first four lines, because the next ones are self-explanatory if you understand the first four.


[MENU m_helpdesk]
This is rather obvious. In a script, you would call this menu like this:


MENU m_helpdesk


Difficult eh?  :)


Do you REALLY want...
Like the skillmenu, this is the title of this section. The next thing I am about to discuss will determine where it is displayed.


ON=0 Yes
Aha, this is the new part. Remember what the first parameter to this section in a [SKILLMENU] was? Well, it's the same thing. That is the ITEM ID that the menu is supposed to display. However, we don't want a scrolling item-based menu, but rather a menu where we can select an option from a list. When you put a 0 for the ITEM ID, SPHERE will automatically assume that you want to create a text-based MENU. However, the catch is, you must put 0 for EVERY SINGLE OPTION in your menu, or else you will get a scrolling item menu like a SKILLMENU. In our case, we want to give the user options in text format, because our menu wouldn't make much sense with scrolling items for its purposes.


SRC.GO Help Desk of Hell
You know what this does. I just want to point out that the user of the menu is SRC, and the default object is whatever the MENU was called upon.


That's about all it takes to make a menu. Of course, you can put any commands you want after the ON= section, and there can be much more than one line. In fact, for most menus, there will be. That was easy, wasn't it? :)


InsideUO

UO comes with almost 4000 gumps. You aren't going to want to try each one in a script until you figure out which is which. You're going to need some sort of a program that shows you the gump. That program is InsideUO, which has come to be as useful to SPHERE scripting as a sword to a warrior. Here's a link to download it:


Download InsideUO


It's a zip file so you need WinZip or a similar tool to extract it. Unzip it to your main SPHERE directory (where SphereSvr.exe is). If you are running a Linux server, just unzip it to somewhere on your Windows computer. It doesn't run in Linux, sorry. Now, when you run the program, you will need to enter the paths of your MUL files. In most cases, that's your the folder where you installed UO (hopefully). Go to the View menu and select File Paths. Sometimes, it will automatically detect the location of your files, in which case you don't have to do anything.


Now, click on the GUMPS button along the sidebar and wait for it to load the index file. It will have a huge list of gumps from 00000001 to some other large number. Look down through them, write some interesting ones down, because you won't want to search back through the list every time you need a specific gump ID.


Also, you're going to be needing backgrounds, which come in 9 parts. I'll explain that when we get there, but if you see a series of items, which look like they'd fit together, write that down, because it would make an excellent background.


One more thing to note before we move on to the next section: The gump IDs you see here are in HEXADECIMAL. SPHERE will only accept gump IDs in decimal. This is one of those times when you need to break out the Windows Calculator and do some conversions.


Note: InsideUO is a popular tool for viewing the contents of the UO files but it is not the only one out there. Check out the Third Party Tools page for a list of other programs which you may want to use.


Gumps

Congratulations. If you've made it this far, you're way past where many scripters reach. Unfortunately, this is also where many scripters hit a brick wall. Gump scripting, especially gump designing, is one of the hardest things for a scripter to do. Rather than easy-to-remember scripting commands such as REMOVE and NEWITEM, you get cryptic looking strings of letters and numbers, which are made even more complex when they use variables. Due to the difficulty, I've split the Gump Scripting 101 section into two parts. The first part shows the setup and syntax of some of the commands. The second part shows the rest of them.


Part 1

First, we need to look at the setup of a gump script, which is different than any script you've seen so far. The tag SPHERE uses to recognize a gump script is DIALOG. I will use the words dialog and gump interchangeably throughout these sections. Unfortunately, GUMPs come in three parts: The dialog itself, the strings that go into the dialog, and the button responses. Those couldn't all be in one section, so SPHERE has divided things up like this:


[DIALOG d_test_dialog]
... Code for the dialog layout goes here ...

[DIALOG d_test_dialog TEXT]
... The text that will be displayed in the dialog goes here ...

[DIALOG d_test_dialog BUTTON]
... The events that are triggered when buttons are pressed goes here ...


Now, dialogs are made up of a number of different types of objects. You can have text boxes, buttons, checkboxes, text entry boxes (which you can change), and other various other things. They're each identified with a syntax that looks a lot like a function call. Here is the list of all the commands you can use with dialogs. I'll explain each of them in detail later.


Dialog Objects

resizepic <x> <y> <gumpback> <width> <height>                                // can come first if multi page. put up some background gump
dorigin <x> <y>                                                                                              // Sets a dynamic origin point
checkertrans <x> <y> <width> <height>                                                                        // add a trasparent layer (only for clients >= 3)
gumppic <x> <y> <gump> <hue>                                                                                 // put gumps in the dlg. (hue only for clients >= 3, otherwise ignored)
gumppictiled <x> <y> <width> <height> <gump>                                                                 // tile a gump
tilepic <x> <y> <item>                                                                                       // put item tiles in the dlg.
tilepichue <x> <y> <item> <hue>                                                                              // put colored item tiles in the dlg.
text <x> <y> <color> <stringindex>                                                                           // put some text here.
dtext <x> <y> <color> <text>                                                                                 // put some text here.
croppedtext <x> <y> <width> <height> <color> <stringindex>
dcroppedtext <x> <y> <width> <height> <color> <text>
htmlgump <x> <y> <width> <height> <stringindex> <hasbackgroud> <hasscrollbar>                                // add an html gump that show a text
dhtmlgump <x> <y> <width> <height> <hasbackgroud> <hasscrollbar> <text>                                      // add an html gump that show a text
xmfhtmlgump <x> <y> <width> <height> <clilocid> <hasbackgroud> <hasscrollbar>                                // add an html gump that show a cliloc text
button <x> <y> <Down_gump> <Up_gump> <pressable(1/0)> <pagedest> <id>
buttontileart <x> <y> <up_gump> <down_gump> <pressable> <page> <id> <tileid> <tilehue> <x offset> <y offset> // Add a button with tileart.
textentry <x> <y> <width> <height> <color> <id> <startstringindex>                                           // Height should be 20
dtextentry <x> <y> <width> <height> <color> <startstringindex> <text>                                        // Height should be 20
textentrylimited <x> <y> <width> <height> <color> <id> <startstringindex> <limit>                            // Textentry with a limit of characters
dtextentrylimited <x> <y> <width> <height> <color> <id> <limit> <text>                                       // Textentry with a limit of characters
tooltip <clilocid>                                                                                           // popup a tooltip over a gump object (only for clients >= 4)
radio <x> <y> <gump1> <gump2> <starting_state> <id>
checkbox <x> <y> <gumpcheck> <gumpuncheck> <starting_state> <checkid>
page <page_number>                                                                                           // for multi tab dialogs.
group                                                                                                        // used to group groups of radio buttons - Group 1, Group 2, etc.
nomove                                                                                                       // The gump cannot be moved around.
noclose                                                                                                      // The gump cannot be closed
nodispose                                                                                                    // not really used  (modal?)Yes, those look complicated now, and if you want to stick with easier scripting for a while, I don't blame you. As you can see, we have all of the required objects to make a nice form, like on a website, or even to make a website-type interface. I'll show you in a later chapter how make hidden buttons and such things like that. It's not as hard as it seems.


Now, we have to discuss design. All gumps should start out like this:


[DIALOG d_test_gump]
0,0
page 0
... Some objects here ...
page 1
... More objects here ...


0,0 is the position that the dialog will start on the screen. 0,0 means this dialog will appear with its upper left corner in the upper left corner of the game screen. It is possible to make a dialog start elsewhere, but it is really pointless unless the dialog is small.


Dialogs are divided into pages, and only one page can be displayed at a given time. I'll show you later how to switch between pages with buttons. However, page 0 is always displayed under the other pages. If you have something that you don't want to change between pages (like a background or a title on top of the gump), you put it on page 0. Otherwise, it goes on another page. Page 1 is displayed by default when a dialog appears.


Now, let's add a background to our gump. Since it's something we want to stay, we'll put it in page 0. Open up your InsideUO and we'll find a good background. The piece that you're looking for is that top left corner piece. (Most things in gumps deal with the top left corner of an object.) Find the one numbered A3C in the gump list of InsideUO. That's the background we're going to use. Actually this is a background you'll use a lot, because it's plain black with a gold border. Translating that number into hexadecimal, we get 2620. Remember that number, it's important.


The command used for backgrounds is resizepic. Look at the chart above, and you'll see what information we need to give it for a resizepic: an x coordinate, a y coordinate, a gump id, a width, and a height. We have all of those things. We'll put it at (0,0) for coordinates, and let's say we make it 500 width and 300 height. Here's the new script:


[DIALOG d_test_gump]
0,0
page 0
resizepic 0 0 2620 500 300
page 1


That's all. Now put that into a script and type .dialog d_test_gump in-game. You'll see that we have a nice black background. It's good to be in-game while you're creating gumps, because you can test it after each new addition. Sometimes if you're off by as little as 25 in your coordinates, things will look strange. It's much easier to fix things one at a time than it is to type the entire gump script, then find out you screwed up somewhere.


Now, let's add some text to our gump. We'll say "Hello World" because that seems to be the standard for making new things in programming! There are two ways to store text, either inside the dialog or in the TEXT section. If your text is going to be used often, it's better to put it in the [DIALOG d_test_gump TEXT] section so you don't have to edit the same word every single time you want to change it. Otherwise, you can just add the text directly into the main dialog section. Here is an example of both:


Using the TEXT section:

[DIALOG d_test_gump TEXT]
<VAR.BLANKLINE>
Hello World


Each line has an index, starting with zero. For the first line, I always like to make a string that will evaluate to nothing, because sometimes you want empty text. I'll show you why later. Also, it makes it easier to think of your first line of text as 1 rather than 0. In our case, because Hello World is in position 1, we refer to it with text id 1. Here's what the whole script will look like now. Obviously, we're going to use that text object from the chart. We will put it at (50,50) and give it a color of 1152 (which happens to be white). We're also going to put it in page 1, because we don't want it to be there forever. Actually, I'll show you something else while we're at it.


Using text inside the main gump:
It's much simpler than adding it to the TEXT section. Just use the dtext object:

dtext 50 50 1152 Hello World


Much simpler! I'll be using both examples from here on. Here's what our whole script looks like now:


[DIALOG d_test_gump]
0,0
page 0
resizepic 0 0 2620 500 300
page 1
dtext 50 50 1152 Hello World
text 50 70 3 1

[DIALOG d_test_gump TEXT]
<LOCAL.BLANKLINE>
Hello World

[DIALOG d_test_gump BUTTON]
// Nothing here yet!


See how easy it is to add text? You can also reuse text by using the same text id. If you look at this dialog in-game, you'll see that "Hello World" is written twice, because we have two text objects with Hello World. The second one is displayed 20 pixels (dots on the screen) below the first. As a general rule, all text should be assumed to be 20 pixels in height. (It's actually closer to 16, but some big letters take up more space.)


You'll also see that they are in different colors. As a general rule, the color ID for dialog text is the color ID in-game minus 1. So black is 0, dark blue is 1, etc. New colors (like my hues.mul colors) will not display in any expected manner in a dialog, so stick to the default colors. Also, these colors are in DECIMAL, so you're going to need to convert things again. (Incidentally, color 1152 decimal is 0480 hexadecimal which happens to be that ice-blue color on an item.)


Now that we've added text, we can experiment with a button. Obviously, we're going to use the button object to add a button to our gump. We need a lot of information for this button object, so I'll just copy the definition here for your reference. I'll go over each part in turn.


button <x> <y> <gump id (down)> <gump id (up)> <active> <page #> <index>


Here is what each does:

<x> <y> This is the position of the top left corner (see?) of the button image. Try to keep dialog pieces off one another, because they will overlap in the order they are placed in the script. We're going to put our button at (50, 90), right below the second line of text.
<gump id> When you press a button, it changes the picture to show that the button is in a "down" position. For our button IDs, we'll use 9A8 (2472) and 9A9 (2473). This is a red diamond shaped button that is rarely used. It has the same gold border as our background, so it'll look nice. Notice that the order is down, then up. The order of the images is up (2472), down (2473), so we'll have to switch the numbers in our script.
<active> This is a switch determining whether or not the button will return an event (1) or switch pages (0). Until we discuss pages in a later section, this will always be 1. (Thanks Belgar!)
<page #> If the button will be used to switch pages, this is the page that will be displayed. Keep in mind that you should put something on the other page to switch back to the first one. You don't want to frustrate your users with a crappy interface. Put 0 if the button doesn't switch pages.
<index> This is used in responding to events, as we'll see shortly. Make it a high number, probably starting in the thousands. Since this is our first button, we're going to call it button 1000. Index 0 is RESERVED, meaning you shouldn't use it for an ordinary button (we'll see why later).


Here is the whole script now:


[DIALOG d_test_gump]
0,0
page 0
resizepic 0 0 2620 500 300
page 1
dtext 50 50 1152 Hello World
text 50 70 3 1
button 50 90 2473 2472 1 0 1000

[DIALOG d_test_gump TEXT]
<LOCAL.BLANKLINE>
Hello World

[DIALOG d_test_gump BUTTON]
ON=1000
    SYSMESSAGE You pressed button 1000!


Ooh! A new construct! The ON=1000 you see in the button section of our dialog is how you respond to a button press. It acts just like any other ordinary event after that line. It means "When the button with ID 1000 is pressed, execute this event." In an ON event, SRC is the player operating the dialog and the default object is whatever the DIALOG command was used on. (On the sidenote, you can also use ONBUTTON= instead of ON=)


Thus ends the first section on gumps and dialogs (which are the same thing). With this information you should be able to make just about any sort of gump you want, by playing with text and button positions. The possibilities are almost endless, and after you read Part 2, they will be endless. I have only used the information you will read in Part 2 twice in my entire long scripting career.