Coding Class: Dagger III
From LSWiki
(diff) ←Older revision | Current revision | Newer revision→ (diff)
- include <item.h>
inherit "/std/item"; void configure() { ::configure(); weapon()->set_weapon_type(Weapon_Type_Dagger); set_craft(Craft_Good); add_description(([ Description_Type : Description_Type_Simple, Description_Content : ({ ({ 'v', 0 }), ({ "are", 0 }), ({ 'a', Description(Description_Type_Craftsmanship_Adjective) }), Description(Description_Type_Weapon_Type_Name), "with", ({ 'a', Description(Description_Type_Element_Name, ({ "sharp", "blade" }), ([ Element_Part : Part_Bulk ])) }), "and", ({ 'a', Description(Description_Type_Element_Name, ({ 0, "hilt" }), ([ Element_Part : Part_Base ])) }), "wrapped in", Description(Description_Type_Element_Name, 0, ([ Element_Part : Part_Wrap ])), 'b', ({ 'r', 0, "blade" }), "bears", Description(Description_Type_Element_Name, ({ "elegant", 0 }), ([ Element_Part: Part_Inlay ])), 'b', }), ])); set_readable(({ "writing" }), Skill_Anglic, "Heartpiercer"); add_proportion(([ Element_Type : Material_Steel, Element_Proportion : 1.0, ])); add_proportion(([ Element_Type : Material_Oak, Element_Proportion : 0.4, Element_Part : Part_Base, Element_Flags : Element_Flag_Secondary, ])); add_proportion(([ Element_Type : Material_Leather, Element_Proportion : 0.4, Element_Part : Part_Wrap, Element_Form : Form_Strips, Element_Color : "black", Element_Flags : Element_Flag_Secondary, ])); add_proportion(([ Element_Type : Material_Silver, Element_Proportion : 0.1, Element_Part : Part_Inlay, Element_Form : Form_Writing, ])); }
Important Header Files
- /lib/descriptors/description.h
- Description_*
Important Source Files
- /std/item.c
- /def/descriptor/description.c
Code Comments
Once the basic form of the dagger is set, its description can be expanded.
Setting the description for most objects can be accomplished via the add_description() function. The function add_description() should typically be passed a single argument -- the description descriptor of the description being added.
All description descriptors require the Description_Type field to be set, which defines its further behaviour. For example, Description_Type : Description_Type_Generic will produce a generic, pre-written description which contains some basic information about the item being described, and not much else. Likewise, Description_Type : Description_Type_Weapon_Type_Name produces the name of the weapon type assigned to the item. Description_Type_Simple, which is used in the description descriptor passed to the add_description() function above as the Description_Type, produces a description descriptor which displays the Description_Content when examined, typically regardless of any other conditions.
Most description descriptors will also have a Description_Content field set, which provides the content for the description. Description_Content should be an array, the content of which depends on the Description_Type and the desired content of the description being written. The Description_Content field may also include additional description descriptors, which will be parsed and added to the content of the main descriptor. When a description descriptor is placed inside of Description_Content, the descriptor should be initialized using the Description() macro.
The Description() macro may also be used to simplify the input of description descriptors, such as in the Description(Description_Type_Craftsmanship_Adjective) used in the example above. To make use of a descriptor macro, you should familiarize yourself with the order in which the variables are passed to the descriptor. In the case of the description descriptor macro, the argument order is Description_Type, Description_Content, Description_Index, Description_Identity, Description_Object, Description_Flags, Description_Info, Description_Order. Note that a variable number of arguments can be passed to the Description() macro, in which case any non-specified arguments will receive empty or default values. Descriptor macros can also be passed a mapping, in which case the macro will attempt to build a descriptor with the specific mapped values set. If a mapping is passed, descriptor arguments can be placed in any order, such as:
Description(([ Description_Content : ({ "foo" ]), Description_Type : Description_Type_Simple, ]))
The description for our dagger is contained in a single description descriptor of Description_Type_Simple. The Description_Content for this descriptor contains several elements which are compiled to form the full description for the item. The first few elements of the description are message binding arrays (see 'man message' for details concerning message bindings). Message bindings should be used in descriptions in order to ensure that the description is parsed correctly. In the description above, the array ({ 'v', 0 }) produces the word "this" -- the first element of the array is a character indicating the binding being called and the second element of the array is the thing the binding is being applied to ("0" in message bindings refers to the object in which the description/message is being called or applied to). The second binding array, ({ "are", 0 }) conjugates the word "are" as it is applied to the item being described.
The second element of a message binding may also be set as a string, descriptor, object, or array, with different results. In the example above, ({ 'a', Description(Description_Type_Craftsmanship_Adjective) }) produces "a well-crafted". Because of the message binding, if the craft of the object changes somehow to Craft_Exquisite, it will show up as "an exquisitely-crafted". Using a string as the second argument, ({ 'a', "exquisitely-crafted" }) would produce the same output as the second example, but would not update with the new craftsmanship adjective if the craft of the weapon changed.
The example above also contains several description descriptors of Description_Type_Element_Name, such as Description(Description_Type_Element_Name, ({ "sharp", "blade" }), ([ Element_Part : Part_Bulk ])), which produces a descriptor with this basic structure:
([ Description_Type : Description_Type_Element_Name, Description_Content : ({ "sharp", "blade" }), Description_Index : ([ Element_Part : Part_Bulk ]), ])
The Description_Index field is variously used to pass additional information to the descriptor, typically in the form of a descriptor or mapping, as above where the description is being indexed to the element of the object set to Part_Bulk (its steel material). The use of the Description_Index field typically relies on the specific type of description being called.
In the context of some descriptor types such as Description_Type_Element_Name, the Description_Content array will be parsed so that the first array element is set prior to the description produced, while the second element is set after. If one of the elements is set to 0, it will not attempt to insert any additional wording in its position, so to omit "sharp" in the above description, the Description_Content would be set to ({ 0, "blade" }).
So, the above descriptor will produce the words "sharp steel blade" in the context of this dagger. If it were applied to an item whose Part_Bulk were made of Material_Copper, it would show a "sharp copper blade", and so on.
When examined, the base item above should display as:
This is a well-crafted dagger with a sharp steel blade and an oak hilt wrapped in black leather strips. Its blade bears elegant silver writing.
Why don't we just write this out rather than using descriptors and message bindings? Simply put, once this item goes out into the world, there are any number of effects which can change one or more of its properties (such as item infusion), and using proper bindings and descriptors allows this description to change with the item, rather than being static and unable to represent those changes. Additionally, if we wanted to randomize some aspect of the item (so that clones of the object can have various materials, craft qualities, weapon types, etc), using appropriate bindings and descriptors would be essential in order to produce a description for the cloned item.
Finally, since one of the dagger's elements is set as Form_Writing, let's add a readable using set_readable() so that we can know what is written on the blade. The set_readable() function contains three arguments - an array containing the words for which the readable should be displayed when reading/examining the dagger, an integer defining the language used (as a Skill_* macro), and a string containing the message, which in this case is the word "Heartpiercer". So, someone examining or reading the writing on this blade will be able to read the message (assuming they know Anglic and are literate).