Fudging around with GUMPS-

A tutorial by Tracker-Morgan of Shattered Alliance
http://gray-cat.com/alliance/
email me: morganmichaels@hotmail.com

Gumps and dialogs are the same thing, just for referance, and I use either word to mean the same thing. They are windows, text, or pictures that pop up onto someone's screen when you do:

dialog d_my_dialog

That is how you make a dialog pop up on someone's screen, by the way. I've been asked how to do that enough times to make sure to include it. To make a dialog pop up for someone when something is double-clicked, you would do:

on=@dclick
src.dialog d_my_dialog
return 1

You could also do anything similar to that:

on=@step
src.dialog d_my_dialog

on=@targon_char
src.targ.dialog d_my_dialog

on=@timer
link.dialog d_my_dialog
//or even
cont.dialog d_my_dialog

An interesting note is that any string variable can be used in the dialog calling like this:

src.dialog d_<tag.race>

This would pop up d_human if then were human, d_orc if they were an orc, or d_squirrel if they were a were-squirrel. I recommend using this instead of a on of IF statements that determines which race they are, and then pops up the right dialog. Of course, having a different gump for each race is inefficient when you could simply use one that was dynamic enough to change according to what you are.

To make a dialog appear in-game, you can type .dialog d_my_dialog. To make a dialog appear on someone else, you can type .xdialog d_my_dialog.

...for the rest of the basics, read Taran's tutorial at http://ithycaworld.com/  Read the whole damned site, actually, and practice some before doing any of this.

What did I mean by dynamic? Well, you can use variables in place of ANY number in a dialog.

text 14 147 0 <eval 0<tag.health>>

...is one example of the use of a tag. The last number is the "index" number, which points to which row of the TEXT portion of the dialog to look at. I had a TEXT portion like this:

[dialog d_health_bar TEXT]
( )( )( )( )( )( )(Healthy)
(X)( )( )( )( )( )(Bruised)
(X)(X)( )( )( )( )(Injured)
(X)(X)(X)( )( )( )(Wounded)
(X)(X)(X)(X)( )( )(Mauled)
(X)(X)(X)(X)(X)( )(Crippled)
(X)(X)(X)(X)(X)(X)(Incapacitated)

If tag.health was 2, for instance, it replaced:

text 14 147 0 <eval 0<tag.health>> with text 14 147 0 2

...which displayed to the user as:

(X)(X)( )( )( )( )(Injured)

The same could be done for something like race and class.

text 20 200 0 <eval 0<tag.race>>
text 20 220 0 <eval 0<tag.class>+5>
//I add +5 to it, so that it skips past the race section.
//If I wanted to add another one, I would have to make it skip past the class section.

[dialog d_character TEXT]
Race: Human
Race: Orc
Race: Troll
Race: Elf
Race: Dwarf
Race: Monkey
Class: Fighter
Class: Farmer
Class: Magician

The TEXT portion of the gump is not limited to simple things, believe it or not.  You can jsut as easily put...

[dialog d_character TEXT]
Race: Human

..as you can put...

[dialog d_character TEXT]
Race: <tag.racename>
AC: <eval (<findlayer(13).armor>/10)+(<findlayer(12).armor>/10)+(<findlayer(11).armor>/10)>
<findid.i_pet_timer.link.name>

Let's say that I want a dialog that shows a picture of what a person has in each hand, and tells me some info about each one. 
Now, how to get the information that I need?

[dialog d_wearing]
0,0
page 0
resizepic 0 0 5054 340 480
resizepic 8 8 3000 322 462

text 180 20 <eval <findlayer(1).color>> 1 //make the color the color of the item. Cute, eh?
text 180 40 <eval <findlayer(1).color>> 2 //Remember to always use eval because dialogs ALWAYS 
text 180 60 <eval <findlayer(1).color>> 3 //think in decimal, not hexadecimal.
text 180 80 <eval <findlayer(1).color>> 4 

tilepic 40 62 <eval <findlayer(1).id>>	//findlayer(1) points to what a person has in 
							//layer 1...the right hand.
text 180 120 <eval <findlayer(2).color>> 5 
text 180 140 <eval <findlayer(2).color>> 6 
text 180 160 <eval <findlayer(2).color>> 7 
text 180 180 <eval <findlayer(2).color>> 8 

tilepic 40 162 <eval <findlayer(2).id>>

[dialog d_wearing TEXT]
<var.blanknothingness>
Name: <findlayer(1).name>
Color: <findlayer(1).color>
Timer: <findlayer(1).timer>
UID: <findlayer(1).uid>
Name: <findlayer(2).name>
Color: <findlayer(2).color>
Timer: <findlayer(2).timer>
UID: <findlayer(2).uid>

That dialog is pretty innefficient, though. I already have 8 text statements, and I would need to add about 9 more lines of code for each other layer that I wanted to add info for. I need to make it more dynamic. I think I'll simply replace the "1" in "findlayer(1)" with "<tag.which_layer>", and add buttons to scroll through the different layers on a person.

First, I'll add the code for the button section.

[dialog d_wearing BUTTON]
onbutton=1150
tag.which_layer=<eval 0<tag.which_layer>+1>  	//add one
dialog d_wearing						//re-call the dialog

onbutton=1151
tag.which_layer=<eval 0<tag.which_layer>+(-1)>	//subtract one
dialog d_wearing						//re-call the dialog

Now I'll modify the text section to use <eval 0<tag.which_layer>> instead of findlayer(1 or 2). Notice that I'm using less code then before, but now I can show the info on any of the layers!

[dialog d_wearing TEXT]
<var.blanknothingness>
Name: <findlayer(<eval 0<tag.which_layer>>).name>
Color: <findlayer(<eval 0<tag.which_layer>>).color>
Timer: <findlayer(<eval 0<tag.which_layer>>).timer>
UID: <findlayer(<eval 0<tag.which_layer>>).uid>
Layer: <eval 0<tag.which_layer>>

Then I'll edit the dialog section to match. We end up with a hideously ugly dialog that is actually somewhat useful.

[dialog d_wearing]
0,0
page 0
resizepic 0 0 5054 340 480
resizepic 8 8 3000 322 462

text 180 20 <eval <findlayer(<eval 0<tag.which_layer>>).color>> 1 
text 180 40 <eval <findlayer(<eval 0<tag.which_layer>>).color>> 2 
text 180 60 <eval <findlayer(<eval 0<tag.which_layer>>).color>> 3 
text 180 80 <eval <findlayer(<eval 0<tag.which_layer>>).color>> 4 
text 180 120 0 5 	//Layer: 1

tilepic 40 62 <eval <findlayer(<eval 0<tag.which_layer>>).id>>

button 170 200 4502 4502 1 0 1150 		//next
button 20 200 4506 4506 1 0 1151 		//previous

Other things that are very useful:

<rescount *i_whatever*>
//A script that would count all of someone's reags would use this like this:
[dialog d_reag_count TEXT]
<rescount i_reag_garlic>
<rescount i_reag_ginseng>

<restest 1 *i_whatever*>
//A dialog that would tell a person if they had any common items would use this like this:
text 180 180 0 <restest 10 i_bandage> 
text 180 200 0 <restest 1 i_potion_healing>
text 180 220 0 <restest 1 i_spellbook>
text 180 240 0 <restest 20 i_arrow>
//restest returns 1 if they have that many of that item, 0 if they don't.

[dialog d_item_check TEXT]
NO
YES

<findlayer(*x*)>
//Can be used in an amazing number of ways.
//To show if they have anything equipped there, for example:
text 180 180 0 <findlayer(1)>
[dialog d_item_check TEXT]
NO
YES
//Would say yes if something is equipped, no if nothing is equipped.

<findlayer(*x*).(variablename)>
//Can be used aboslutely any way you can imagine. IE:
[dialog d_item_check TEXT]
Morex: <findlayer(1).morex>, Morey: <findlayer(1).morey>, Morez <findlayer(1).morez>

<findid.*i_whatever*.*item variable*>
//Great for checking variables on memory objects.
[dialog d_item_check TEXT]
Your long sword's morez: <findid.i_sword_long.morez>
The name of the object your memory object is linked to: <findid.i_memory_object.link.name>

What other creative uses for Gumps can I think of?

-People often ask how to set the light llevel for just one person...well...it's impossible. You could, however, "blind" a person by opening a screen-wide gump on them every second or so from a timer.
-You can cause text, tilepics, resizepiccs, and such to "move" by changing their x and y variables. This can be used to do things such as "hiding" images underneath other images, moving unwanted text off the screen, etc...

text <tag.textx> <tag.texty> 0 1

[dialog d_my_dialog BUTTON]
onbutton=1150
tag.textx=<eval 0<tag.textx>+1>  	//add one
tag.texty=<eval 0<tag.texty>+1>
dialog d_my_dialog

-Using tags, a person could design basicc gumps in-game by doing something to the effect of:
[dialog d_very_dynamic_gump]
0,0
page 0
resizepic <tag.rpicx1> <tag.rpicy1> <tag.rpicid1> <tag.rpicw1> <tag.rpich1> 
resizepic <tag.rpicx2> <tag.rpicy2> <tag.rpicid2> <tag.rpicw2> <tag.rpich2> 
resizepic <tag.rpicx3> <tag.rpicy3> <tag.rpicid3> <tag.rpicw3> <tag.rpich3> 

text <tag.textx1> <tag.texty1> <tag.textc1> <tag.textindex1>
text <tag.textx2> <tag.texty2> <tag.textc2> <tag.textindex2>
text <tag.textx3> <tag.texty3> <tag.textc3> <tag.textindex3>

tilepic <tag.tpicx1> <tag.tpicy1> <tag.tpicid1>
tilepic <tag.tpicx2> <tag.tpicy2> <tag.tpicid2>
tilepic <tag.tpicx3> <tag.tpicy3> <tag.tpicid3>

[dialog d_very_dynamic_gump TEXT]
<tag.gumptext1>
<tag.gumptext2>
<tag.gumptext3>

Of course, I would use eval and such so it would actually work. You could evn create a gump that let you create a gump...

What can you NOT do with gumps?

-You can't close a gump that someone hass open through script, only when a player right-clicks or presses a button.
-You cannot re-color a tilepic, resizepiic, etc...without editing your .mul files and adding a re-colored version of it in. You can make a new paperdoll, for instance, but you cannot change the colors of the tilepics for the items.

Fudging around with DEFNAMES-

A tutorial by Tracker/Morgan of Shattered Alliance
http://gray-cat.com/alliance/
email me: morganmichaels@hotmail.com

A defname is a global, static variable that is represented by a string of characters. You cannot change one in game, nor can you define one in game. They must be added and changed in script.

How can defnames be used to your advantage?

Any string can be used with <eval> to turn it from it's defname into a usable variable. Take this list, for instance:

[defname my_variables]
variableBLARG	i_ingot_iron

variable1	20
variable2	40
variable3	80
variable4	160

Then, on some random tester object (mine is called i_tester_object)

ON=@Dclick
src.tag.name=variable
src.tag.number=1

src.say <src.tag.name><src.tag.number>
//returns "variable01" which isn't what we want. We want it to return the value in "variable1".

src.say <src.tag.name><eval <src.tag.number>> 
//returns "variable1", not "20", like we want it to.
//This is because sphere is still treating it like a string.
//To make it EVALuate the string as a variable......we use EVAL!

src.say <eval <src.tag.name><eval <src.tag.number>>>
//returns "20", which is the number we wanted.
//What this is read as is:
//src.say <eval variable1>

This is incredibly useful when you want to have large lists of data that aren't stored on characters or items, and will be easily available globally. Imagine a custom crafting system that used lists of defnames instead of skillmenus.

You could do this:

[defname my_crafting]
blacksmith_item1		i_dagger		//the item you want to craft
blacksmith_res1		i_ingot_iron	//item needed to make it
blacksmith_amount1	4			//the amount of that resource needed

blacksmith_item2		i_sword_long	//the second item in the list
blacksmith_res2		i_ingot_iron
blacksmith_amount2	12

Then easily pull out that information like so:

src.tag.crafttype=blacksmith
src.tag.craftnumber=1	//or two if they chose to make the second item

if (<src.rescount <eval <src.tag.crafttype>_res<eval <src.tag.craftnumber>>> >= <eval <src.tag.crafttype>_amount<eval <src.tag.craftnumber>>>)
	//the huge line above breaks down to:
	//if (<src.rescount i_ingot_iron> >= 4)

	src.newitem <eval <src.tag.crafttype>_item<eval <src.tag.craftnumber>>>
	//this breaks down to <eval blacksmith_item1>
	//which then breaks down to i_dagger when <eval> is used on it

	src.consume <eval <src.tag.crafttype>_amount<eval <src.tag.craftnumber>>> <eval <src.tag.crafttype>_res<eval <src.tag.craftnumber>>> 
	src.sysmessage You finish crafting the <src.act.name>,
else
	src.sysmessage You do not have enough of the proper resources to make this!
endif

One problem with DEFNAMEs is that you can't store a real string in them, only things that evaluate to a number, meaning only other defnames and numbers. How can we get around this?

Well, in the above example, I DID do this...

src.sysmessage You finish crafting the <src.act.name>,

...after adding the object. Let's say that, in your custom crafting system, you wanted a person to emote something different for each item. You could create items like this:

[ITEMDEF i_blacksmith_emote1] //This is a defname, too!!
id=i_beeswax
type=t_normal
name=craft a super special dagger of doom

...then do:

src.newitem i_<src.tag.crafttype>_emote<eval <src.tag.craftnumber>>
//create i_blacksmith_emote1

src.emote <src.act.name>
//emote its name
//IE: *You see Tracker craft a super special dagger of doom*

src.act.remove
//remove it

Defname lists can be great for long lists of rarely-changed data. Let's give another situation in which they'd be useful. Let's say that you wanted to make an entirely new magic system, in which each spell required different reagents during every hour of the day. First, we'll get the syntax together. Each spell needs:

-a name
-an effect, which we'll just store as a  number that can be sent as <argn> to a function
-the casting difficulty of the spell-the list of reagents required to cast iit

[itemdef fire_name] //we'll use this to refer to it's name
id=i_beeswax
type=t_normal
name=Firey Death

[DEFNAME spell_list]
fire_effect		1 			//this will be sent to a function to determine what happens
fire_difficulty	300			//require a 30.0 skill to cast
fire_time1		i_reag_brimstone	//if it's hour one, this is the reag
fire_time2		i_reag_sulfur_ash	//if it's hour two, this is the reag
fire_time3		i_ingot_iron	//if it's hour three, this is the reag
fire_time4		i_dagger		//...you get the picture. One for each hour of the day.
fire_time5		i_paper_sack
fire_time6		i_monkey
fire_time7		i_blarg

This way, instead of having to say:

if (<src.tag.spellcast>==fire) 
 if (<eval <src.tag.skill>> > 300)
	if (<eval <var.time_of_day>>==1)
		if (<src.rescount i_wet_paper_sack> > 0)
			src.consume 1 i_wet_paper_sack
		endif
	endif
	if (<eval <var.time_of_day>>==2)
		if (<src.rescount i_monkey> > 0)
			src.consume 1 i_monkey
		endif
	endif
	if (<eval <var.time_of_day>>==4)
		if (<src.rescount i_blarg> > 0)
			src.consume 1 i_blarg
		endif
	endif
 endif
elif (//Twenty-four times for each damned spell...)
endif

You can just do ONE FUNCTION FOR ALL 95 new spells you made:

src.f_spell_cast_new fire

[function f_spell_cast_new]
if (<eval <tag.skill>> > <eval <args>_difficulty>)
//if their skill is greater then whatever the spell's difficulty is...

	if (<rescount <eval <args>_time<eval <var.time_of_day>>> > 0)
	//if they have more then one of <args>_time<var.time_of_day>
	//which is, let's say, fire_time7, since it's 7 o'clock
	
		consume 1 <eval <args>_time<eval <var.time_of_day>>
		//consume one fire_time7, which is an i_blarg in this case.
		newitem <eval <args>_name> 
		sysmessage You cast <act.name>.
		act.remove
		//in here you'd check what <args>_effect was, and
		//depending on it's effect, do something with it

	else
		newitem <eval <args>_time<eval <var.time_of_day>> 	
		//create an i_blarg
		sysmessage You don't have enough <act.name>.		
		//use it's name
		act.remove					
		//remove it
	endif
else
	newitem <eval <args>_name> 
	//newitem <eval fire_name>
	sysmessage You aren't yet skilled enough to cast <act.name>. 
	//sysmessage You aren't yet skilled enough to cast Firey Death.
	sysmessage You require <eval <args>_difficulty> skill to cast.
	 //sysmessage You require 300 skill to cast.
	act.remove
	//You're done with it, so remove it
endif

You could then do any other spell just by doing another set of defnames.

The custom skill system that I created worked like this:

[DEFNAME blacksmith_craftables]
blacksmith 		60				//number of items in the list 
blacksmithdelay 	5  				//time in seconds to make an item of this type
blacksmithsound 	02a 				//sounds made while crafting
blacksmithstat 	1  				//which stat is used to help craft
blacksmithtool	i_hammer_smith		//required tool, must be on person

blacksmith1 		i_shield_heater 	//itemdef of craftable item
blacksmithdiff1 		3			//skill needed to craft
blacksmithsucc1 		3			//any special things that happen on success
blacksmith1res1		i_ingot_iron	//first resource requirement(itemdef)
blacksmith1amount1	18			//amount of first resource used
blacksmith2res1		i_hides_cut		//second resource requirement(itemdef)
blacksmith2amount1	1			//amount of second resource used

blacksmith2 		i_sword_long
blacksmithdiff2 		3
blacksmithsucc2 		1
blacksmith1res2		i_ingot_iron
blacksmith1amount2	12
blacksmith2res2		i_log
blacksmith2amount2	1

I then have a single gump that I easily plug the defnames into, combined with a single recursive function that reads through to find and store the names of each item and its resources instead of having to have a different gump designed for each skill. When an item is chosen, a single function is called that performs the crafting action.

What else could be done with defnames?

Let's make a custom fishing script, which uses defnames to define areas in which there are fish.