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.

Items have defnames.

i_ingot_iron

...is shorthand for the number...

019b7

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>>>
//consume <eval blacksmith_amount1> <eval blacksmith_res1>
//consume 4 i_ingot_iron

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.

In the example above, if you tried to make the person emote something different for each item, you couldn't do this, for example:

[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_emote1 craft a deadly dagger //what they emote on success

on=@dclick
src.emote <eval blacksmith_emote1>
//*You see Tracker 0*

src.emote blacksmith_emote1
//*You see Tracker blacksmith_emote1*



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 it

[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.1

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.
1