/
com/planet_ink/coffee_mud/Abilities/
com/planet_ink/coffee_mud/Abilities/Common/
com/planet_ink/coffee_mud/Abilities/Diseases/
com/planet_ink/coffee_mud/Abilities/Druid/
com/planet_ink/coffee_mud/Abilities/Fighter/
com/planet_ink/coffee_mud/Abilities/Prayers/
com/planet_ink/coffee_mud/Abilities/Properties/
com/planet_ink/coffee_mud/Abilities/Skills/
com/planet_ink/coffee_mud/Abilities/Songs/
com/planet_ink/coffee_mud/Abilities/Spells/
com/planet_ink/coffee_mud/Abilities/Thief/
com/planet_ink/coffee_mud/Abilities/Traps/
com/planet_ink/coffee_mud/Areas/interfaces/
com/planet_ink/coffee_mud/Behaviors/
com/planet_ink/coffee_mud/CharClasses/interfaces/
com/planet_ink/coffee_mud/Commands/
com/planet_ink/coffee_mud/Commands/interfaces/
com/planet_ink/coffee_mud/Exits/interfaces/
com/planet_ink/coffee_mud/Items/Armor/
com/planet_ink/coffee_mud/Items/Basic/
com/planet_ink/coffee_mud/Items/MiscMagic/
com/planet_ink/coffee_mud/Items/Software/
com/planet_ink/coffee_mud/Items/Weapons/
com/planet_ink/coffee_mud/Libraries/interfaces/
com/planet_ink/coffee_mud/Locales/
com/planet_ink/coffee_mud/Locales/interfaces/
com/planet_ink/coffee_mud/MOBS/
com/planet_ink/coffee_mud/MOBS/interfaces/
com/planet_ink/coffee_mud/Races/
com/planet_ink/coffee_mud/Races/interfaces/
com/planet_ink/coffee_mud/WebMacros/
com/planet_ink/coffee_mud/WebMacros/interfaces/
com/planet_ink/coffee_mud/application/
com/planet_ink/coffee_mud/core/smtp/
com/planet_ink/siplet/applet/
lib/
resources/examples/
resources/fakedb/
resources/quests/delivery/
resources/quests/diseased/
resources/quests/drowning/
resources/quests/gobwar/
resources/quests/holidays/
resources/quests/robbed/
resources/quests/smurfocide/
resources/quests/stolen/
resources/quests/templates/
resources/quests/treasurehunt/
resources/quests/vengeance/
web/
web/admin.templates/
web/admin/images/
web/pub.templates/
web/pub/images/mxp/
web/pub/sounds/
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

  
                                             
  
  <title>Programming for CoffeeMud 5.2</title>
  <link rel="StyleSheet" href="style.css" type="text/css" media="screen" />
<!-- Modified by Josh Mueller, 2006-5-6, fix validation problems, reformat, fix spelling errors -->
</head>


<body>

            
<center>  
<table border="1" bordercolor="gray" cellpadding="10" cellspacing="0" width="90%">

       <tbody>

         <tr>

             <td colspan="2" align="left" bgcolor="#dfdfdf" width="100%">
                                           
      
      <h1>           Programming for CoffeeMud 5.2         </h1>

            </td>

         </tr>

         <tr>

           <td align="left" valign="top" width="20%">                   
                       
      
      <ul>

                <li>             <a href="#overview">Overview</a>       
    </li>

                <li>             <a href="#BUILD">Building</a>          
                                                         
          
          <ul>

                    <li>                 <a href="#buildwin">Windows</a>
              </li>

                    <li>                  <a href="#buildunix">Unix</a> 
             </li>

                    <li>                 <a href="#external">External Components</a> 
               </li>

                    <li>                 <a href="#IMPORTS">Default Import
List</a>                 </li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#TEXT">Text</a>               
                                                    
          
          <ul>

                    <li>                 <a href="#nametag">Target Info Tag</a> 
                </li>

                    <li>                 <a href="#textcolor">Color</a> 
             </li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#javascript">JavaScripting</a>
                                                                    
          
          <ul>

                    <li>                 <a href="#writingjavascript">Writing
 Your First                 Javascript</a>               </li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#DIG1">Core Topic 1: Message Passing</a> 
                                                                    
          
          <ul>

                    <li><a href="#majorcode">Major Code Bitmask</a></li>

                    <li><a href="#messagepreview">Message Previewing</a></li>

                    <li><a href="#messageflagging">Message Flagging and Modification</a></li>

                    <li><a href="#messageexecution">Message Execution</a></li>

                    <li><a href="#messagetrailers">Message Trailers</a></li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#DIG2">Core Topic 2: State Layers</a> 
                                                                    
          
          <ul>

                    <li><a href="#envstats">EnvStats fields</a></li>

                    <li><a href="#charstats">CharStats codes</a></li>

                    <li><a href="#charstate">CharState</a></li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#DIG3">Core Topic 3: Threading</a> 
          </li>

                <li>             <a href="#DIG4">Core Topic 4: Core Libraries</a> 
                                                                    
          
          <ul>

                    <li><a href="#corepurpose">Core class purposes</a></li>

                    <li><a href="#corelibrarymap">Library mappings</a></li>

                    <li><a href="#corecommon">Common Classes</a></li>

                                                                        
          
          </ul>

                </li>

                <li><a href="#DIG5">Core Topic 5: Adding Data</a><br />

                </li>

           <li><a href="#CMDS">Commands</a>           </li>

                <li>             <a href="#MOBS">MOBs</a>               
                                                    
          
          <ul>

                    <li><a href="#mobcoding">Coding a new MOB</a></li>

                    <li><a href="#moblife">Life and Death</a></li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#ITEMS">Items</a>             
                                                      
          
          <ul>

                    <li><a href="#itemlife">Creation and Destruction</a></li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#BEHAVS">Behaviors</a>        
  </li>

                <li>             <a href="#CLASSES">Character Classes</a>
          </li>

                <li>             <a href="#RACES">Races</a>           </li>

                <li>             <a href="#EXITS">Exits</a>           </li>

                <li>             <a href="#LOCALES">Locales</a>         
 </li>

                <li>             <a href="#AREAS">Areas</a>           </li>

                <li>             <a href="#PROPS">Properties</a>        
  </li>

                <li>             <a href="#SKILLS">Skills</a>           
                                                        
          
          <ul>

                    <li><a href="#skillquality">Skill Nature Flags</a></li>

                    <li><a href="#skillflags">Skill Affect Flags</a></li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#SPC">Spells, Prayers, and Chants</a> 
                                                                    
          
          <ul>

                   <li><a href="#spells">Spells</a></li>

                   <li><a href="#spelldomain">Spell Domains</a></li>

                   <li><a href="#prayers">Prayers</a></li>

                   <li><a href="#chants">Chants</a></li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#SONGS">Songs</a>           </li>

                <li>             <a href="#COMMON">Common Skills</a>    
                                                               
          
          <ul>

                    <li><a href="#skillgathering">Gathering Skill</a></li>

                    <li><a href="#skillcrafting">Crafting Skill</a></li>

                                                                        
          
          </ul>

                </li>

                <li>             <a href="#POISON">Poisons</a>          
        </li>

                <li>             <a href="#DISEASE">Diseases</a>        
  </li>

                <li>             <a href="#TRAPS">Traps &amp; Bombs</a> 
         </li>

                <li>             <a href="#LANGS">Languages</a>         
 </li>

                                                 
      
      </ul>

            </td>

           <td align="left" valign="top">         <img src="images/mug.jpg" alt="CoffeeMud logo" />
                                               
      
      <h2>           <a name="overview" id="overview">Overview</a>      
  </h2>

                                                 
      
      <p>           The purpose of this document is to assist those who wish
 to add           custom Items, MOBs, Behaviors, Properties, or other objects
 to           CoffeeMud. The reader should be familiar with Java programming,
 and           should be experienced with writing and compiling Java classes.
 The           object oriented notions of class inheritance and polymorphism,
 as           well as the Java constructs of interfaces should be at least 
           vaguely familiar to you before attempting to build classes for 
          CoffeeMud. Also, it is expected that all of the ideas presented
 in           the <a href="ArchonGuide.html">Archons Guide</a> 
 and <a href="GameBuildersGuide.html">Game Builders Guide</a> are completely familiar.
 The           difference between a GenItem and a StdItem, or a GenMob and
 a           GenPostman will not be explained in this document.         </p>

                                                 
      
      <p>           It is not expected that someone would wish to dive in
 and make           wholesale changes to the CoffeeMud system right away,
but is more           likely wanting to fill in a functional gap in the system
 for their           own needs. For this reason, this document is not organized
 as a           comprehensive guide to programming CoffeeMud. Instead, it
is           designed to be a quick reference for those who wish to create
the           spot MOB, Behavior, Item, or Property for use on their maps.
         </p>

                                                  
      
      <p>           With this in mind then, let's start out with some brief
 development           instructions, and then and in no particular order,
discuss the           several essential object types in CoffeeMud are presented. 
         </p>

           <img src="images/sprockets.jpg" alt="Recompiling" />
                                              
      
      <h2>           <a name="BUILD" id="BUILD">Rebuilding CoffeeMud</a> 
       </h2>

                                                 
      
      <h3>           <a name="buildwin" id="buildwin">In Microsoft Windows</a> 
          </h3>

                                                 
      
      <ul>

                <li>                                                    
               
          
          <p>               Go to your coffeemud directory and edit the make.bat,
 the first               line will be something like: <code>SET JAVACPATH= 
               C:\jdk1.5.0_05\bin\javac</code> This might be different for
 you               depending on where your java development package is installed. 
             </p>

                </li>

                <li>                                                    
                
          
          <p>               Save the bat file.             </p>

                </li>

                <li>                                                    
               
          
          <p>               Run the bat file by double clicking on it. This
 will compile               the mud, making all the .class files.       
     </p>

                </li>

                                                 
      
      </ul>

                                                  
      
      <h3>           <a name="buildunix" id="buildunix">In Unix</a>     
   </h3>

                                                 
      
      <ul>

                <li>                                                    
               
          
          <p>               Go to your coffeemud directory and edit the makeUNIX.sh,
 the               first line will be something like:               <code>Java_Home=/home/knoppix/j2sdk1.4.2</code>
 This might be               different for you depending on where your java
 development               package is installed.             </p>

                 </li>

                <li>                                                    
               
          
          <p>               Save the shell script.             </p>

                </li>

                <li>                                                    
               
          
          <p>               Issue this command: <code>chmod 755 makeUNIX.sh</code> 
              </p>

                </li>

                <li>                                                    
               
          
          <p>               Execute the shell script. This will compile the
 mud, making all               the .class files.             </p>

                </li>

                                                 
      
      </ul>

                                                 
      
      <h3>            <a name="external" id="external">Introducing External 
           Components</a>         </h3>

                                                 
      
      <p>           If you perused the coffeemud.ini file as mentioned in
 the           Installation Guide, you may have noticed and wondered about
 the           section at the end which lists the default load paths for
the            several CoffeeMud objects.         </p>

                                                 
      
      <p>           By default, the CoffeeMud engine dynamically loads the
 vast           majority of its object code at boot time by referring to
the  paths           specified in the coffeemud.ini file. The value     
           <code>%DEFAULT%</code> is always used as a substitute for the
          default CoffeeMud object path. For instance, if you installed 
         CoffeeMud at "<code>C:\CoffeeMud\</code>", then           "<code>BEHAVIORS=%DEFAULT%</code>"
 in the ini file would load           "<code>C:\CoffeeMud\com\planet_ink\coffee_mud\Behaviors\*.class</code>" 
           into its behavior set.         </p>

                                                  
      
      <p>           This default object boot paths may be removed or added-to
 using           semicolon delimited paths, or even replaced with your own
 object           boot directories. In fact, when adding objects to your
CoffeeMud            boot sequence, it is recommended that you place your
objects in  a           separate directory path inside your CoffeeMud folder
and add its           path to the coffeemud.ini file under the proper setting.
The order           in which you place multiple paths in a single entry is
also            significant, as the CoffeeMud ClassLoader will load the files
in            the order in which they appear listed. For instance:      
  </p>

                                                 
      
      <pre>MOBS=%DEFAULT%;/resources/examples/MyClass.class;/resources/otherclasses<br /></pre>

                                                 
      
      <p>           Will cause the default CoffeeMud versions of the mob
classes to be           loaded first, followed by MyClass.class, followed
by all the class           files in the resources/otherclasses folder in
your CoffeeMud           package. Also notice that the ClassLoader follows
the rules of the           CMFS described in the Archons Guide, meaning that
the forward slash           is always the proper path separator, and that
no folder outside of           your CoffeeMud package may be referenced.
Also bear in mind that           case is sensitive when naming Java class
files, even in these boot           paths.         </p>

                                                 
      
      <p>           When writing these custom classes for your special object
 boot           directory(s), it is important to keep a number of things
in  mind:         </p>

                                                  
      
      <ul>

                <li>                                                    
               
          
          <p>               Do not mix your object types in the same directory!
 Never try               to boot custom items from the same directory from
 which you               boot your custom mobs. It will only confuse you
and  CoffeeMud.             </p>

                </li>

                <li>                                                    
               
          
          <p>               Java Packaging is irrelevant, you may package
 your classes or               not.             </p>

                 </li>

                <li>                                                    
               
          
          <p>               Implement or extend a class that implements the
 proper               interfaces. If you are coding mobs, this would mean
the MOB               interface. If you are coding locales, the Room interface,
 etc,               etc. See the section on the object type you are coding
 for the               proper interface to implement. You may get around
this                requirement by extending one of the base classes, such
as               StdItem, StdMOB, StdContainer, StdRoom, StdAbility, GenMob, 
              GenItem, GenContainer, etc.             </p>

                </li>

                <li>                                                    
               
          
          <p>               Make sure the <code>ID()</code> method in your
 classes always               matches the name of your class. You will understand
 this better               as you reference the object sections below.  
          </p>

                 </li>

                <li>                                                    
               
          
          <p>               Try to make the <code>name()</code> methods in
 your classes               return name values unique among all objects,
especially  objects               of that type. This is not a hard fast rule,
and breaking  it               will not cause malfunction in the system,
but breaking this                rule WILL make writing help files impossible.
                      </p>

                </li>

                <li>                                                    
               
          
          <p>                Class files loaded directly in the CoffeeMud
 classpath can not               be reloaded at run-time using the <code>UNLOAD</code>
 and               <code>LOAD</code> commands. If you plan on making changes
 to               your classes during run-time, place them in their own 
             directories.             </p>

                </li>

                <li>                                                    
               
          
          <p>               As a general rule, you may import any       
       "<code>interfaces.*</code>" packages in the base CoffeeMud       
       structure, any core Java packages, the CoffeeMud               "<code>core.*</code>"
 package, and any single base CoffeeMud               class you may be extending.
 Do not import more than that. Use               the CMClass getter methods
 if you need to create new instances               of CoffeeMud classes,
and  use the CMLib methods to access her               code libraries.  
          </p>

                 </li>

                                                 
      
      </ul>

                                                 
      
      <h3>           <a name="IMPORTS" id="IMPORTS">Complete Default Import
 List</a>         </h3>

                                                 
      
      <pre>import com.planet_ink.coffee_mud.core.*;<br />import com.planet_ink.coffee_mud.core.interfaces.*;<br />import com.planet_ink.coffee_mud.Abilities.interfaces.*;<br />import com.planet_ink.coffee_mud.Areas.interfaces.*;<br />import com.planet_ink.coffee_mud.Behaviors.interfaces.*;<br />import com.planet_ink.coffee_mud.CharClasses.interfaces.*;<br />import com.planet_ink.coffee_mud.Commands.interfaces.*;<br />import com.planet_ink.coffee_mud.Common.interfaces.*;<br />import com.planet_ink.coffee_mud.Exits.interfaces.*;<br />import com.planet_ink.coffee_mud.Items.interfaces.*;<br />import com.planet_ink.coffee_mud.Locales.interfaces.*;<br />import com.planet_ink.coffee_mud.MOBS.interfaces.*;<br />import com.planet_ink.coffee_mud.Races.interfaces.*;<br />import com.planet_ink.coffee_mud.Libraries.interfaces.*;<br />import java.io.IOException;<br />import java.util.*;<br /></pre>

           <img src="images/rainbow.jpg" alt="Text" />
                                              
      
      <h2>            <a name="TEXT" id="TEXT">Text</a>         </h2>

                                                 
      
      <p>           Before we get started with objects, needs must the topic
 of text           display be covered. Throughout the system you will see
text being           sent to the user. Since a mud is a text producing engine,
 this           should be no great surprise. However, within that text you
 will           often see different kinds of codes and tags which affect
the            output. For instance, consider the following lines:      
  </p>

                                                 
      
      <pre>msg=CMClass.newMsg(mob,target,this,affectType,"&lt;S-NAME&gt; reach(es) for &lt;T-NAMESELF&gt;.");<br />mob.location().show(mob,null,CMMsg.MSG_OK_ACTION,"&lt;S-NAME&gt; regain(s) &lt;S-HIS-HER&gt; feet.");<br /><br /></pre>

                                                 
      
      <p>           Focusing only on the text for a moment, you will notice
 that           special tags are used to designate a player name, or the
name  of           the target of a spell. You will also notice that (s) and
(es)  is           used to modify the proper form of a verb. These are key
features  of           the CoffeeMud text engine. Here is a more complete
list of           available tags:         </p>

           <a name="nametag" id="nametag">&nbsp;</a>                    
                       
      
      <table bgcolor="#ffffcc" border="1">

                <tbody>

                  <tr>

                    <td>                 <code>&lt;S-HIS-HER&gt;</code> 
              </td>

                    <td>                 Outputs 'Your' if Observer=Source, 
otherwise 'His'/'Her'.               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;S-HIM-HER&gt;</code> 
             </td>

                     <td>                 Outputs 'You' if Observer=Source, 
otherwise 'Him'/'Her'.               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;S-NAME&gt;</code>    
          </td>

                    <td>                  Outputs 'You' if Observer=Source, 
otherwise the Name.               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;S-NAMESELF&gt;</code>
              </td>

                    <td>                 Outputs 'Yourself' if Observer=Source,
 otherwise the Name               </td>

                   </tr>

                  <tr>

                    <td>                 <code>&lt;S-NAMENOART&gt;</code>
              </td>

                    <td>                 Outputs 'You' if Observer=Source,
otherwise  the Name minus                 any prefix articles (a, an, some,
etc..).               </td>

                  </tr>

                   <tr>

                    <td>                 <code>&lt;S-HE-SHE&gt;</code>  
            </td>

                    <td>                 Outputs 'You' if Observer=Source,
otherwise  'He'/'She'               </td>

                  </tr>

                  <tr>

                     <td>                 <code>&lt;S-SIRMADAM&gt;</code>
              </td>

                    <td>                 Outputs 'Sir'/'Madam'          
    </td>

                  </tr>

                  <tr>

                    <td>                  <code>&lt;S-IS-ARE&gt;</code> 
             </td>

                    <td>                 Outputs 'Are' if Observer=Source,
otherwise  'Is'.               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;S-HAS-HAVE&gt;</code>
               </td>

                    <td>                 Outputs 'Have' if Observer=Source, 
otherwise 'Has'.               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;S-YOUPOSS&gt;</code> 
             </td>

                     <td>                 Outputs 'Your' if Observer=Source, 
otherwise the Name`s               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;S-HIM-HERSELF&gt;</code> 
              </td>

                    <td>                  Outputs 'Yourself' if Observer=Source,
 otherwise the                 'Himself'/'Herself'               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;S-HIS-HERSELF&gt;</code> 
              </td>

                    <td>                 Outputs 'Yourself' if Observer=Source,
 otherwise the                 'Hisself'/'Herself'               </td>

                   </tr>

                  <tr>

                    <td>                 <code>&lt;T-HIS-HER&gt;</code> 
             </td>

                    <td>                 Outputs 'You' if Observer=Target,
otherwise  'His'/'Her'.               </td>

                  </tr>

                   <tr>

                    <td>                 <code>&lt;T-HIM-HER&gt;</code> 
             </td>

                    <td>                 Outputs 'You' if Observer=Target,
otherwise  'Him'/'Her'.               </td>

                  </tr>

                  <tr>

                     <td>                 <code>&lt;T-NAME&gt;</code>   
           </td>

                    <td>                 Outputs 'You' if Observer=Target,
otherwise  the Name.               </td>

                  </tr>

                  <tr>

                    <td>                  <code>&lt;T-NAMESELF&gt;</code>
              </td>

                    <td>                 Outputs 'Yourself' if Observer=Target,
 otherwise the Name               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;T-NAMENOART&gt;</code>
               </td>

                    <td>                 Outputs 'You' if Observer=Target,
otherwise  the Name minus                 any prefix articles (a, an, some,
etc..).               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;T-HE-SHE&gt;</code>  
            </td>

                     <td>                 Outputs 'You' if Observer=Target, 
otherwise 'He'/'She'               </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;T-SIRMADAM&gt;</code>
              </td>

                    <td>                  Outputs 'Sir'/'Madam'         
                 </td>

                  </tr>

                  <tr>

                    <td>                 <code>&lt;T-IS-ARE&gt;</code>  
            </td>

                    <td>                 Outputs 'Are' if Observer=Target,
otherwise  'Is'.               </td>

                   </tr>

                  <tr>

                    <td>                 <code>&lt;T-HAS-HAVE&gt;</code>
              </td>

                    <td>                 Outputs 'Have' if Observer=Target, 
otherwise 'Has'.               </td>

                  </tr>

                   <tr>

                    <td>                 <code>&lt;T-YOUPOSS&gt;</code> 
             </td>

                    <td>                 Outputs 'Your' if Observer=Target, 
otherwise the Name with an                 '`s'               </td>

                  </tr>

                  <tr>

                     <td>                 <code>&lt;T-HIM-HERSELF&gt;</code> 
              </td>

                    <td>                 Outputs 'Yourself' if Observer=Source,
 otherwise the                 'Himself'/'Herself'               </td>

                  </tr>

                  <tr>

                    <td>                  <code>&lt;T-HIS-HERSELF&gt;</code> 
              </td>

                    <td>                 Outputs 'Yourself' if Observer=Source,
 otherwise the                 'Hisself'/'Herself'               </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                 
      
      <p>            Occasionally, you will find color/font codes embedded
 in system           strings. For instance:         </p>

                                                 
      
      <pre>msg.append("^!You are thirsty.^?\n\r");<br /></pre>

                                                 
      
      <p>           These codes are as follows:         </p>

           <a name="textcolor" id="textcolor">&nbsp;</a>                
                           
      
      <table bgcolor="#ccffff" border="1">

                <tbody>

                  <tr>

                     <td>                 <code>^N</code>               </td>

                    <td>                 Normal               </td>

                  </tr>

                  <tr>

                    <td>                  <code>^!</code>               </td>

                    <td>                 Bold               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^H</code>                </td>

                    <td>                 Highlight               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^_</code>               </td>

                     <td>                 Underline               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^*</code>               </td>

                    <td>                  Blink               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^/</code>               </td>

                    <td>                 Italics               </td>

                   </tr>

                  <tr>

                    <td>                 <code>^.</code>               </td>

                    <td>                 Reset (turns off reverse)      
        </td>

                  </tr>

                   <tr>

                    <td>                 <code>^^</code>               </td>

                    <td>                 Generates an untranslated "^" character 
               </td>

                  </tr>

                  <tr>

                     <td>                 <code>^?</code>               </td>

                    <td>                 Restores previous color        
      </td>

                  </tr>

                  <tr>

                    <td>                  <code>^f</code>               </td>

                    <td>                 You-Fight               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^e</code>                </td>

                    <td>                 Fight-You               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^F</code>               </td>

                     <td>                 Fight               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^S</code>               </td>

                    <td>                  Spell               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^E</code>               </td>

                    <td>                 Emote               </td>

                   </tr>

                  <tr>

                    <td>                 <code>^T</code>               </td>

                    <td>                 Talk               </td>

                  </tr>

                   <tr>

                    <td>                 <code>^Q</code>               </td>

                    <td>                 Channel Background             
 </td>

                  </tr>

                  <tr>

                     <td>                 <code>^q</code>               </td>

                    <td>                 Channel Foreground             
 </td>

                  </tr>

                  <tr>

                    <td>                  <code>^x</code>               </td>

                    <td>                 Important message 1            
  </td>

                  </tr>

                  <tr>

                    <td>                 <code>^X</code>                </td>

                    <td>                 Important message 2            
  </td>

                  </tr>

                  <tr>

                    <td>                 <code>^Z</code>               </td>

                     <td>                 Important message 3           
               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^O</code>               </td>

                    <td>                  Room Title               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^L</code>               </td>

                    <td>                 Room Description               </td>

                   </tr>

                  <tr>

                    <td>                 <code>^J</code>               </td>

                    <td>                 Weather               </td>

                  </tr>

                   <tr>

                    <td>                 <code>^D</code>               </td>

                    <td>                 Direction               </td>

                  </tr>

                  <tr>

                     <td>                 <code>^d</code>               </td>

                    <td>                 Door               </td>

                  </tr>

                  <tr>

                    <td>                  <code>^I</code>               </td>

                    <td>                 Item               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^M</code>                </td>

                    <td>                 MOB               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^U</code>               </td>

                     <td>                 Unexplored Direction          
    </td>

                  </tr>

                  <tr>

                    <td>                 <code>^u</code>               </td>

                    <td>                  Unexplored Door               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^w</code>               </td>

                    <td>                 White               </td>

                   </tr>

                  <tr>

                    <td>                 <code>^g</code>               </td>

                    <td>                 Green               </td>

                  </tr>

                   <tr>

                    <td>                 <code>^b</code>               </td>

                    <td>                 Blue               </td>

                  </tr>

                  <tr>

                     <td>                 <code>^r</code>               </td>

                    <td>                 Red               </td>

                  </tr>

                  <tr>

                    <td>                  <code>^y</code>               </td>

                    <td>                 Yellow               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^c</code>                </td>

                    <td>                 Cyan               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^p</code>               </td>

                     <td>                 Purple               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^W</code>               </td>

                    <td>                  Dark White               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^G</code>               </td>

                    <td>                 Dark Green               </td>

                   </tr>

                  <tr>

                    <td>                 <code>^B</code>               </td>

                    <td>                 Dark Blue               </td>

                  </tr>

                   <tr>

                    <td>                 <code>^R</code>               </td>

                    <td>                 Dark Red               </td>

                  </tr>

                  <tr>

                     <td>                 <code>^Y</code>               </td>

                    <td>                 Dark Yellow               </td>

                  </tr>

                  <tr>

                    <td>                  <code>^C</code>               </td>

                    <td>                 Dark Cyan               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^P</code>                </td>

                    <td>                 Dark Purple               </td>

                  </tr>

                  <tr>

                    <td>                 <code>^&lt;</code>             
 </td>

                     <td>                 &lt; character. Used for MXP tags 
only.                </td>

                  </tr>

                  <tr>

                    <td>                 <code>^&gt;</code>             
 </td>

                     <td>                 &gt; character. Used for MXP tags 
only.                </td>

                  </tr>

                  <tr>

                    <td>                 <code>^&amp;</code>            
  </td>

                     <td>                 &amp; character. Used for MXP tags 
only.                </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                 
      
      <p>           As you might have guessed, it is preferred that the system
 colors           (the last 16 codes) be used sparingly, in favor of the
more            customizable codes above.         </p>

           <img src="images/mozilla.jpg" alt="Mozilla Javascript" />
                                               
      
      <h2>           <a name="javascript" id="javascript">JavaScripting:</a> 
         </h2>

                                                 
      
      <p>           JavaScript is an interpreted scripting language which
 is used in           various parts of CoffeeMud. The CoffeeMud engine integrates
 the           Rhino Javascript interpretor package from Mozilla in such
places  as           the Scriptable behavior, the JRun command, the ClassLoader,
the           Quest engine, and the web server.         </p>

                                                 
      
      <p>           In lieu of a complete write up on the syntax of this
language, it           is suggested that you read the documentation available
from the           authors of the interpretor here: <a href="http://www.mozilla.org/js/">http://www.mozilla.org/js/</a> and   
       <a href="http://www.mozilla.org/rhino/">http://www.mozilla.org/rhino/</a>. 
         </p>

                                                  
      
      <p>           If you are familiar with writing Javascript for web browsers,
 there           are several differences you will need to adjust to when
using            Javascript in CoffeeMud. A minor difference is that the
Rhino           interpretor requires that all variables be declared before
use.  A           more important difference is that Javascript Strings are
not the           same as Java String objects, and that confusing them can
lead to           errors. To get around this problem, all of the implementations
of           Javascript in CoffeeMud, with the exception of the ClassLoader, 
           Javascript in CoffeeMud, with the exception of the ClassLoader, 
           provide a special method to convert Javascript strings into Java 
           Strings before passing them to Java methods or objects which will 
           require them. An example is below:         </p>

                                                 
      
      <pre>var javascriptstring=' this is a javascript string ';<br />var javastring=toJavaString(javascriptstring);<br />// and now javastring is a real-live Java-compliant and Java-friendly string<br /></pre>

                                                 
      
      <p>           When writing Java classes in JavaScript, however, this
 method is           only available through the CMLib object in the core
package.  This           is how you would access the <code>toJavaString()</code>
method  from           a class written in JavaScript:         </p>

                                                  
      
      <pre>var javascriptstring=' this is a javascript string ';<br />var javastring=Packages.com.planet_ink.coffee_mud.core.CMLib.toJavaString(javascriptstring);<br />// and now javastring is a real-live Java-compliant and Java-friendly string<br /></pre>

                                                 
      
      <p>           The most important difference between coding Javascript
 for           CoffeeMud and for browsers is that there is no HTML DOM (Document 
           Object Model), and therefore several of the libraries you are used
           to are probably missing, such as Math. For this reason, it is
          necessary for you to learn the CoffeeMud object packages in order
           to get access to useful data and useful libraries. And now you
          understand why the JavaScripting notes are kept in the Programming 
           guide. :)         </p>

                                                 
      
      <p>           To access the CoffeeMud object packages, you will need
 to make use           of the Packages object to reference external packages.
 So long as           the imported objects are in your CoffeeMud classpath,
 they can be           accessed and used. For instance, to use the CoffeeMud 
           <code>pow(x,y)</code> function in CMParms.java:         </p>

                                                  
      
      <pre>var lib=Packages.com.planet_ink.coffee_mud.core.CMLib;<br />// the above creates a reference to the CoffeeMud Library as a shortcut<br />var value=lib.math().pow(4,2);<br />// now we can access the math() library from our shortcut.<br /></pre>

                                                 
      
      <p>           Depending upon the context from which your script runs
 (the           Scriptable behavior, JRun command, the Quest engine, or the 
           http/web server), certain other objects are made available to 
         assist scripts in properly interacting with their environment. When
           writing Java classes in JavaScript for the ClassLoader, however, 
           you must always use the           <code>Packages.com.planet_ink.coffee_mud.core.CMLib</code> 
           reference to access special methods such as the toJavaString method 
           discussed above.         </p>

                                                 
      
      <p>           In the Scriptable behavior, several methods are made
available to           access objects which are related to the event which
triggered the           scripted code. These methods include <code>MOB source(),
           Environmental target(), Environmental host(), Item item1(), Item 
           item2(), String message(),</code> and <code>MOB monster()</code>. 
           The JRun command provides the methods <code>MOB mob(), int    
      numParms(), String getParm(int i),</code> and <code>String        
  getParms()</code>. The web server makes the           <code>ExternalHTTPRequests
 request()</code> object available, as           well as the method <code>void
 write(String s)</code>. The quest           engine makes the current running
 Quest object available from the           method <code>Quest quest()</code>
 and the current state of the           quest setup script available in a
custom QuestState object           referencing method called <code>QuestState
setupState()</code>          </p>

                                                 
      
      <p>           The last piece of general information about JavaScript
 in CoffeeMud           concerns writing Java classes for the CoffeeMud ClassLoader.
 Any           JavaScript file *.js included in the ClassLoader boot paths
 (see           the previous section) will be loaded and treated just like
 any Java           compiled *.class file. The JavaScript file would be parsed, 
           compiled, and loaded at boot time. For the most part, writing Java
           Classes in JavaScript is extremely similar to writing Java Classes
           in Java. Base classes may be extended (using the special CoffeeMud
           <code>//extends</code> command in your JavaScript), interfaces
may           be implemented (using the special CoffeeMud           <code>//implements</code>
command in your JavaScript), super class           variables and methods
may be accessed (using the           <code>this.variableName</code> and 
         <code>this.super$methodname()</code> syntax), and super class  
        methods may be overridden by JavaScript functions of the same name 
           and number of parameters. Class files written in Javascript *.js 
           files may also be loaded and unloaded at runtime using the LOAD
 and           UNLOAD Archon commands, which gives them a step up on native
 Java           classes in the JVM classpath.         </p>

                                                  
      
      <h3>           <a name="writingjavascript" id="writingjavascript">Writing
 your           first JavaScript</a>         </h3>

                                                 
      
      <p>           Below is an example of a Java Class written in JavaScript.
 Examples           of Embedded JavaScript in CoffeeMud Virtual Pages (cmvp)
 web files           can be found in the Web Server Guide. Examples of Embedded 
           JavaScript in a Scriptable MOBPROG script can be found in the 
         Scripting Guide.         </p>

                                                 
      
      <p>           Our Java Class example is called GenLemming.js. It is
 a sample MOB           class to demonstrate extending the GenMob class to
 create a type of           modifiable mob for your maps. In this example,
 we add functionality           to make all mobs in the world created from
 the GenLemming base           suicidal. To use this class, save the code
somewhere in our           CoffeeMud folder under the name "GenLemming.js",
and add an object           path reference to it in the MOBS entry in your
coffeemud.ini file,           as described in section one.         </p>

                                                  
      
      <pre>//extends com.planet_ink.coffee_mud.MOBS.GenMob<br /><br />function ID(){return "GenLemming";}<br /><br />var lib=Packages.com.planet_ink.coffee_mud.core.CMLib;<br /></pre>

                                                 
      
      <p>           The first lines of our class include the special //extends
 command           which informs the CoffeeMud ClassLoader that this JavaScript
 class           will extend GenMob, thereby inhereting all functionality
of the           maleable GenMob.         </p>

                                                 
      
      <p>           The <code>ID()</code> method is required in all CoffeeMud
 classes.           It must be the simple name of the class, and must match
 the name of           the JavaScript file containing it. For example, GenLemming.js 
           contains class GenLemming and returns an ID of "GenLemming". They 
           all match exactly.         </p>

                                                  
      
      <p>           Lastly, we define the variable "lib" to act as a shortcut
 to the           CoffeeMud core Libraries.         </p>

                                                 
      
      <p>           Now, moving on; since we don't have the ability to write 
           constructors in JavaScript, any initial fields we need to set 
         whenever a new instance of our class is created must be done in
 the           CoffeeMud <code>newInstance()</code> method as shown here: 
        </p>

                                                 
      
      <pre>function newInstance()<br />{<br />    var lemm=this.super$newInstance();<br />    lemm.setName("a generic lemming");<br />    lemm.setDisplayText("a generic lemming is waiting to commit suicide");<br />    return lemm;<br />}<br /></pre>

                                                  
      
      <p>           There are several interesting points to make here. One
 is to notice           that the function has no explicit return type, which
 is part of the           JavaScript standard of being "weakly typed". Also
 notice the syntax           for calling the SuperClass version of the  
        <code>newInstance()</code> method --           <code>this.super$newInstance()</code>.
 This is very different from           Java syntax and should be noted. 
       </p>

                                                 
      
      <p>           And now we move on to overriding our first GenMob method,
 tick.         </p>

                                                 
      
      <pre>var countdown = 10;<br /><br />function tick( host, tickID )<br />{<br />  if( !this.amDead() )<br />  {<br />    countdown--;<br />    if( countdown &lt;= 0 )<br />    {<br />      lib.combat().postDeath( null, this, null );<br />      countdown = 10;<br />    }<br />  }<br />  return this.super$tick( host, tickID );<br />}<br />      </pre>

                                                 
      
      <p>           The <code>public boolean tick(Tickable host, int tickID)</code> 
           method from the standard MOB interface is designed to be called 
           every CoffeeMud tick (about 4 seconds). Now, the tick method in 
           StdMOB, which is extended by GenMob, handles things like recovering 
           hit points, automatic combat rounds, and other important periodic 
           activities. It is explained further in Core Topic 3.         </p>

                                                 
      
      <p>           For our GenLemming, we create a variable to count down
 the ticks           from 10 to 0. When the countdown variable reaches 0,
we call the           <code>postDeath(MOB killer, MOB killed, CMMsg msg)</code>
 method,           which is part of the CombatLibrary in the core libraries.
 "lib" is           the variable we defined above as a shortcut to our core
 libraries.           The last thing we do is return control to the SuperClass
 version of           the tick method.         </p>

                                                  
      
      <p>           Now we'll get creative and implement a message previewer
 (see the           Core Topic 1 below for more information on message previewing
 and           handling). This method will be called when any event happens
 in the           same room as the GenLemming mob. We will use this fact
to  look for,           capture, and modify the message string which will
inform  the room           of our impending death. Since it is the previewing
method,  it will           be called BEFORE the activity actually takes place,
giving  us a           chance to make our modifications before anyone actually
sees  the           message strings.         </p>

                                                 
      
      <pre>function okMessage(host,msg)<br />{<br />  if( ( msg.isSource( this ) )<br />      &amp;&amp;( msg.isOthers( "DEATH" ) )<br />      &amp;&amp;( msg.othersMessage() != null )<br />    )<br />  {<br />    msg.setOthersMessage("&lt;S-NAME&gt; jumps off a cliff!!!");<br />  }<br /><br />  return this.super$okMessage(host,msg);<br />}<br /></pre>

                                                 
      
      <p>           In our message previewing method, we will check every
 message that           comes our way, acting only if this particular GenLemming
 is the           source of the message, that he appears to be dying to others
 in the           room <code>( isOthers( "DEATH" ) )</code> and that the
message            being given to others in the room is a non-null string.
In these            conditions, we modify the message which others in the
room see.            When our condition is not met, we return control to
the           SuperClass-GenMob version of okMessage.         </p>

           <img src="images/kiss.jpg" alt="Getting the Message" />
                                               
      
      <h2>           <a name="DIG1" id="DIG1">Core Topic 1: Getting the Message:</a> 
         </h2>

                                                 
      
      <p>           CoffeeMud is essentially a distributed message passing
 and handling           system, where the actions and events that occur in
 the system are           represented as messages (Common.interfaces.CMMsg)
 which are then           previewed, modified, cancelled, and/or reacted
to  by handlers.           Understanding this idea is key to fully understanding
 how CoffeeMud           really works, so let's take a second and peruse
this  concept in           more detail.         </p>

                                                 
      
      <p>           Messages in CoffeeMud, at least as we are talking about
 them here,           always represent Events. Events such as a mob picking
 up an item,           swinging a sword at an opponent, taking damage from
 a fireball, or           getting pricked by a poisonous needle. These events
 can never           actually occur in CoffeeMud unless a proper message
is  generated           for them first. These messages, in the code, implement
 the           interface <code>Common.interfaces.CMMsg</code>, and are typically 
           an instance of the class <code>Common.DefaultMessage</code>.  
      </p>

                                                  
      
      <p>           Messages are created at the moment that the event needs
 to occur.           This moment can be triggered by the player entering
a  command into           their telnet client and pressing Enter. It can
also  by triggered by           the mindless algorithms which animate the
mobs.  Either way, when           the moment has come, a message is created,
and  it looks like this:         </p>

                                                 
      
      <pre>CMMsg msg = CMClass.getMsg(mob, targetMOB, this,<br />     CMMsg.MSG_CAST_ATTACK_VERBAL_SPELL,"^S&lt;S-NAME&gt; invoke a spell at &lt;T-NAME&gt;s feet..^?",<br />     CMMsg.MSG_CAST_ATTACK_VERBAL_SPELL,"^S&lt;S-NAME&gt; invoke(s) a spell at your feet.^?",<br />     CMMsg.MSG_CAST_ATTACK_VERBAL_SPELL,"^S&lt;S-NAME&gt; invokes a spell at &lt;T-NAME&gt;s feet.^?"<br />     );<br /><br /></pre>

                                                 
      
      <p>           The above message was taken from the code for the Grease
 spell,           which calls the <code>core.CMClass.getMsg</code> method
to           construct a CMMsg object. Constructing the           CMMsg object
 does not actually make anything happen,           but it is the vital first
 step. The message we constructed here, in           this case, utilizes
every  major component of a message. These           components are, in order:
        </p>

                                                 
      
      <ul>

                 <li>Source                                             
                      
          
          <p>               The source of any message must always be a valid
 reference to               an instance of the MOB interface. In short, all 
               events that occur in the system are a direct result of the 
              activity of a MOB. This is on the theory that the          
    universe is controlled and governed by sentience. In the            
  extremely rare instances where a mob is not readily available         
     to provide a message source, one should be instantiated -- even    
          if it is just a blank, new StdMOB.             </p>

                </li>

                <li>Target                                               
                    
          
          <p>                The target of a message may be null, or any
valid reference to               an instance of the Environmental interface,
which               includes Items, MOBs, Rooms, Exits, etc. The type   
           and context of message you wish to generate will typically tell
               you intuitively whether the source is doing something to 
             someone or something else, or is acting independently. This
is                usually another mob or an item, but you will find examples
of               all kinds of targets in the code.             </p>

                </li>

                <li>Tool                                                
                   
          
          <p>               The tool of a message may be null, or any valid
 reference to an               instance of the Environmental interface, which 
               includes Items, Abilities, MOBs, Rooms, Exits,            
  etc. The tool represents something which the source is               utilizing
 to accomplish the task or generate the event. This is               typically
 either an Ability object (like a               Spell or Skill being used),
 or an               Item object (like a weapon in an attack event).    
        </p>

                 </li>

                <li>Source Code                                         
                          
          
          <p>               This is an encoded integer which represents what
 the source               MOB is actually doing. We'll break down this code 
               below.             </p>

                </li>

                <li>Source Message                                      
                             
          
          <p>               This is the string which the source MOB will
see               should the event occur successfully.             </p>

                 </li>

                <li>Target Code                                         
                          
          
          <p>               This is an encoded integer which represents what
 is happening               to the target. If there is no target, this number
 will               typically have the value of 0 (CMMsg.NOEFFECT).     
       </p>

                </li>

                <li>Target Message                                      
                             
          
          <p>               This is the string which the target MOB (if it
 is               a MOB) will see should the event occur               successfully.
 If there is no target, this string is null.             </p>

                 </li>

                <li>Others Code                                         
                          
          
          <p>               This is an encoded integer which represents how
 any other               objects (such as MOBs, Items, Rooms, Exits) other 
               than the source and target, in the same room, perceive the 
              event. If the event is completely imperceptible by anything 
              other than the source, it may be 0               (CMMsg.NOEFFECT) 
             </p>

                </li>

                <li>Others Message                                      
                             
          
          <p>                This is the string which other MOBs in the same 
               room as the source and target MOBs will see should        
      the event occur successfully. If the event is completely          
    imperceptible by other MOBs, it may be null.             </p>

                </li>

                                                 
      
      </ul>

                                                 
      
      <p>           The Source Code, Target Code, and Others Code is easily
 the most           complicated aspect of a Message. For this reason, numerous 
           pre-configured message codes have been created in the         
 CMMsg interface, all of which begin with the           characters MSG_.
 Although we will not go into the meaning of each           of these messages
 (that will be left to the reader to search the           code for instances
 of messages which use the codes, and learn from           the context in
which they are used), we can at least break down           these codes so
that they can be better understood.         </p>

                                                  
      
      <p>           These coded integers all have two parts, the Major aspect
 (or the           Major Code) and the Minor aspect (or the Minor Code).
They  may be           referenced off of an already constructed CMMsg object
          using such methods as <code>sourceMajor()</code> and          
      <code>sourceMinor()</code>.  These methods will automaticallyy break
          down a <code>sourceCode()</code>  into the components we will 
         discuss.         </p>

                                                 
      
      <p>            The Major code is a series of significant bits in the
 integer, each           of which gives some new meaning to the message.
These  bits are as           follows:         </p>

               <a name="majorcode" id="majorcode">&nbsp;</a>            
                               
      
      <table bgcolor="#ffccff" border="1">

                <thead>             <tr>

                    <th width="15%">                 Bit mask           
             </th>

                    <th width="30%">                 CMMsg Equate Variable(s) 
              </th>

                    <th>                 Meaning               </th>

                  </tr>

                </thead>            <tbody>

                  
                  <tr>

                    <td>                 2048               </td>

                    <td>                                                
                                 
            
            <p>                   MASK_HANDS                 </p>

                    </td>

                    <td>                 Message includes small movements.
              </td>

                  </tr>

                  <tr>

                    <td>                 4096               </td>

                    <td>                                                
                                 
            
            <p>                   MASK_MOVE                 </p>

                    </td>

                    <td>                 Message includes large, full-body
movements.                </td>

                  </tr>

                  <tr>

                    <td>                 8192               </td>

                    <td>                 MASK_EYES               </td>

                    <td>                 Message includes visual information. 
              </td>

                  </tr>

                  <tr>

                    <td>                 16384               </td>

                    <td>                 MASK_MOUTH               </td>

                    <td>                 Message include mouth movement,
or consumption.                </td>

                  </tr>

                  <tr>

                    <td>                 32768               </td>

                    <td>                 MASK_SOUND,<br />

                      MASK_SOUNDEDAT               </td>

                    <td>                 Message includes auditory information. 
               </td>

                  </tr>

                  <tr>

                    <td>                 65536               </td>

                    <td>                 MASK_ALWAYS               </td>

                    <td>                 Override mask which flags the message
 as something which Must                 occur, regardless of the state of
 the source or target.               </td>

                  </tr>

                  <tr>

                    <td>                 131072               </td>

                    <td>                 MASK_MAGIC               </td>

                    <td>                 Message has a magical nature.  
            </td>

                  </tr>

                  <tr>

                    <td>                 262144               </td>

                    <td>                 MASK_DELICATE               </td>

                    <td>                 Message includes very fine, delicate
 movements, such as thief                 skills.               </td>

                  </tr>

                  <tr>
            <td>524288</td>
            <td>MASK_MALICIOUS</td>
            <td>Message represents an attack of some sort.</td>
          </tr>
          <tr>

                    <td>                 1048576               </td>

                    <td>                 MASK_CHANNEL               </td>

                    <td>                 Message is part of public channel
conversation.                </td>

                  </tr>

                  <tr>

                    <td>                 2097152               </td>

                    <td>                 MASK_OPTIMIZE               </td>

                    <td>                 Message implementation should be
optimized  for repetition.               </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                  
      
      <p>           The above masks can be quite confusing. It is best to
 examine the           several MSG_ equates in the CMMsg interface to see
how they are           properly or improperly used. Remember a MSG_ equate
is a completely           constructed Code, complete with the appropriate
Major and Minor           aspects.         </p>

                                                  
      
      <p>           The Minor Code represents the more specific activity
being           performed, and is a simple integer ranging from 0 (NO EFFECT)
to           2047. The officially recognized Minor codes are exhaustively
listed           in the CMMsg interface, and all begin with the prefix TYP_.
These           types cover every sort of major event which occurs in the
CoffeeMud           engine, including getting items, casting spells, entering
or           leaving rooms, etc, etc..         </p>

                                                  
      
      <pre>CMMsg msg = CMClass.getMsg(attacker,target,weapon,CMMsg.MSG_WEAPONATTACK,<br />          "&lt;S-NAME&gt;attack(s) &lt;T-NAME&gt;!");<br /></pre>

                                                  
      
      <p>           The core.CMClass has many different getMsg signatures
 to make           message construction quick and painless. The above is
an  example           where only a single Code and a single message text
are provided. In           constructors where only one Code or message text
field are           provided, it is assumed that the code and message texts
will be the           same for source, target (if any) and others.      
  </p>

                                                  
      
      <p>           CMMsg objects also have <code>value()</code> and <code>setValue(int)</code>
 methods for           modifying an integer not found in the constructor.
This number is           used for several different purposes in message construction,
 from           the amount of damage in a TYP_DAMAGE message, to the amount
 of           experience in a TYP_EXPCHANGE message. This number is also
used  to           determine whether or not a standard saving throw was made.
Value            defaults to 0, but, after running through a message which
contains            a savable event, the value will be &gt;0 if the save
was made.         </p>

                                                  
      
      <h3><a name="messagepreview" id="messagepreview">Message Previewing</a></h3>

                                                  
      
      <p>           Once a Message has been constructed, it is time     
     to actually put the message out into the system. There is a        
  standard form for the sending of almost all messages. If the source   
       of the message is a MOB called "SourceMOB", this standard form   
       looks like this:         </p>

                                                  
      
      <pre>CMMsg msg = CMClass.getMsg(SourceMOB,TargetMOB,weapon,CMMsg.MSG_WEAPONATTACK,<br />          "&lt;S-NAME&gt;attack(s) &lt;T-NAME&gt;!");<br /><br />if(SourceMOB.location().okMessage(SourceMOB,msg))<br />{<br />     SourceMOB.location().send(SourceMOB,msg);<br />}<br /></pre>

                                                 
      
      <p>           The <code>location()</code> field on a MOB refers to
the Room in which the mob           is. Room's are always the top level at
which messages are           previewed, and then executed or sent. The first
line           (where the message is constructed) has already been examined.
The           second line, in which the Room method <code>okMessage()</code>
is called, is the           preview step. In this step, the message is evaluated
 before           it actually happens. The first parameter to <code>okMessage()</code>
 is called           the "host" object, and it refers to the object to which
 the one you           are sending the message should refer back to. This
parameter is           rarely used, except by Behaviors, and it is always
safe to use the           source of your message as this value. The second
parameter to           <code>okMessage()</code> is the message we constructed.
The third line, where           the Room <code>send()</code> method is called,
 is the execution step.         </p>

                                                  
      
      <p>           In the preview step, the room object will examine the
 message to           see if there is anything which it might not like, wish
 to modify,           or wish to flag about the Message it has been handed.
 If the Room           object does not like the message, it will return false.
 Returning           false from <code>okMessage()</code> is always an order
 to cancel, and not           execute the message. Under any other circumstances,
 true may be           returned to allow the message to go forward. The Room
 will also           make calls to the <code>okMessage()</code> methods on
 every other MOB in the           room, Exit from the room, Item in the room,
 spell effects which may           be on the room, and behaviors of the room.
 The MOB who receives the           <code>okMessage()</code> call will, in
 turn, pass the Message to the <code>okMessage()</code>           methods
in every Item the MOB is carrying or wearing, every spell           effect
on the MOB, and every behavior of the MOB. Items wills also           make
      <code>okMessage()</code> calls on their spell effects. Any of these
calls           may modify or flag the message they receive. Any of these
calls may           also return false. If any object which previews a message
returns           false, the Room <code>okMessage()</code> method will also
return false, ordering           the message to be totally canceled. For
this reason,       <code>okMessage()</code>           methods are careful
about returning true unless they have a really           good reason not
to.         </p>

                                                  
      
      <p>           Inside the <code>okMessage()</code> methods of every
Item, MOB, Behavior,           Ability (spell effect), Exit, and Room the
Messages may (as we           mentioned) be examined and modified, flagged,
or canceled. As we           have already covered how Messages are canceled
(by returning           false). Let us turn now to the manner in which Messages
are           modified or flagged.         </p>

                                                  
      
      <h3><a name="messageflagging" id="messageflagging">Message Flagging
 and Modification</a></h3>

                                                  
      
      <p>           Message modification is very rare. When it happens though,
 it is           done by calling one of the several <code>modify()</code>
methods on the           Common.interfaces.CMMsg object. These methods allow
the source,           target, and all other fields to be updated. Message
modification           should also happen during the preview step so that
any changes made           to the message are made before the message is
executed. It is also           often wise, after making a change to a message,
to recursively call           the okMessage method on the room again so that
the modifications           can be previewed, but this is not always necessary.
         </p>

                                                  
      
      <p>           Message flagging is somewhat less rare. Messages    
      may be flagged when a combat strike is successful, or when a saving 
           throw is made against a spell Effect, or for any other reason the
           Message constructing code may wish. Flagging is done by calling
 the           aforementioned <code>CMMsg.setValue(int)</code> method, and
 using           it to change the value to something other than the default
 of 0.           Flagging using the <code>setValue()</code> method lets the
 code which constructed           the Message know that something significant
 with relation to the           Message has occurred. The meaning of this
value will vary depending           upon the type of message being generated,
 and upon the purpose to           which the creator of the message wishes
to put it. The value is           read using the <code>int value()</code>
method on CMMsg.         </p>

                                                  
      
      <h3><a name="messageexecution" id="messageexecution">Message Execution</a></h3>

                                                  
      
      <p>           Once the <code>okMessage()</code> method on a Room object
 has           returned true, and any code which may need to check or handle 
           modifications to the Message have executed, the Message is sent. 
           The proper way to send a Message is through the Room objects, by
           calling one of the following Messages:           <code>Room.send(MOB
 SourceMOB, CMMsg msg)</code>           or           <code>Room.sendOthers(MOB
 SourceMOB, CMMsg msg)</code>.           The first method handles a     
     standard Execution, while the second allows every relevant object  
        except the SourceMOB to handle Execution. The first method should
          almost always be called.         </p>

                                                  
      
      <p>           The <code>send()</code> methods will then begin calling
 other           methods in other objects. These other methods are called
the           <code>executeMsg()</code> methods, and are usually of the form
      <code>public           void executeMsg(Environmental           myHost,
 CMMsg msg);</code>. These methods are responsible for           Executing
 the contents of the message. The Room method will make           <code>executeMsg()</code>
 method calls on itself, and on every Exit, Item, MOB,           spell effects
 (Ability object), and Behavior associated with that           Room. As in
 the <code>okMessage()</code> case, the MOBs will in turn call the      
    <code>executeMsg()</code> methods on their own Items and spell effects.
 Items           will then call the <code>executeMsg()</code> methods on
their  own spell effects,           and so on.         </p>

                                                  
      
      <p>           Of course, not every object in your game will handle
and react to           the Execution of every Message sent. Most of the time,
 a given           object will be ignoring the Message altogether. However,
 each           object knows precisely which Messages are important for it,
 and           watch carefully for them in both their <code>okMessage()</code>
 and <code>executeMsg()</code>           methods. In general, every Message
 which is previewed in an objects           <code>okMessage()</code> method
 is handled in the <code>executeMsg()</code> method of the           same
object, though this is by no means always true. In general,           the
following object types handle the following types of Messages:         </p>

                                                  
      
      <ul>

                <li>MOBs                                                
                 
          
          <p>             Any Message which has the mob instance as a target
 is both             Previewed and Executed. Any Message which has the mob
 as a source             is typically Previewed, and (lacking a target) may
 also be             Executed.           </p>

                </li>

                <li>Items                                               
                  
          
          <p>             Any Message which has the item instance as a target. 
           </p>

                </li>

                <li>Exits                                               
                  
          
          <p>             Any Message which has the exit instance as a target
 or             tool.           </p>

                </li>

                <li>Rooms                                               
                  
          
          <p>             Any Message which has the room instance as a target. 
           </p>

                </li>

                <li>Ability(spell effects)                              
                                   
          
          <p>             Any Message pertaining to the MOB or Item     
       which is affected by the spell or skill.           </p>

                </li>

                <li>Behavior                                             
                    
          
          <p>             Any Message pertaining to the object instance which
 has             this behavior.           </p>

                </li>

                                                 
      
      </ul>

                                                  
      
      <p>           Now that you are completely confused, it will       
   make you at least a bit happier to know that Room objects have       
   several short-cut methods for creating, previewing, and executing    
      messages. They include the following:         </p>

                                          
      
      <pre>public boolean show( MOB source,<br />                     Environmental target,<br />                     int allCode,<br />                     String allMessage<br />                   );<br /><br />public boolean show( MOB source,<br />                     Environmental target,<br />                     Environmental tool,<br />                     int allCode,<br />                     String allMessage<br />                   );<br /><br />public boolean show( MOB source,<br />                     Environmental target,<br />                     Environmental tool,<br />                     int srcCode,<br />                     int tarCode,<br />                     int othCode,<br />                     String allMessage<br />                   );<br /><br />public boolean show( MOB source,<br />                     Environmental target,<br />                     Environmental tool,<br />                     int srcCode,<br />                     String srcMessage,<br />                     int tarCode,<br />                     String tarMessage,<br />                     int othCode,<br />                     String othMessage<br />                   );<br /><br />public boolean show( MOB source,<br />                     Environmental target,<br />                     Environmental tool,<br />                     int allCode,<br />                     String srcMessage,<br />                     String tarMessage,<br />                     String othMessage<br />                   );<br /><br />public boolean showOthers( MOB source,<br />                           Environmental target,<br />                           int allCode,<br />                           String allMessage<br />                         );<br /><br />public boolean showOthers( MOB source,<br />                           Environmental target,<br />                           Environmental tool,<br />                           int allCode,<br />                           String allMessage<br />                         );<br /><br />public boolean showSource( MOB source,<br />                           Environmental target,<br />                           int allCode,<br />                           String allMessage<br />                         );<br /><br />public boolean showSource( MOB source,<br />                           Environmental target,<br />                           Environmental tool,<br />                           int allCode,<br />                           String allMessage<br />                         );<br /><br />public void showHappens(int allCode, String allMessage);<br /><br />public void showHappens( int allCode,<br />                         Environmental like,<br />                         String allMessage<br />                       );<br /></pre>

                                                  
      
      <p>           The first methods (show) is very commonly used; it constructs
 a           message with the given source and target (no tool), and with
the           given Code and text message applying to source, target, and
others.           The <code>showHappens()</code> methods will do the same,
but will also construct a           blank MOB object to act as the source,
for those instances where a           source MOB is not readily available.
The <code>showOthers()</code> methods behave           like the first, but
do not allow the source MOB to preview or           execute the message,
while the <code>showSource()</code> methods ONLY allows the           source
MOB to preview and execute the message.         </p>

                                                  
      
      <p>           All four of those methods will construct a CMMsg object,
 give the           Message to the Room object for previewing ("okMessage"),
 and then,           if the Message is not canceled, will call the Room "send"
 method           for execution and return true. If the Message was canceled,
 false           will be returned.         </p>

                                                  
      
      <h3><a name="messagetrailers">Message Trailers</a></h3>

                                                  
      
      <p>           The final subject we will discuss in the area of    
      Messages and Message handling regards another rare technique called 
           Message Trailer adding. Message Trailers are CMMsg objects which 
           have been added to another CMMsg instance using the           
     <code>CMMsg.addTrailerMsg(CMMsg msg)</code> method. The Message passed 
to this method is           constructed in the usual way.           This method
          may be properly called at any point during the Preview or Execution
          stage of Message handling, by any Previewing or Executing object.
          When it is performed is not important, because any Messages added
          using this method are not Previewed or Executed until after the
          Room object has completely finished sending the host Message to
all           interested objects.         </p>

                                                  
      
      <p>           Constructing and adding messages which act as message
 trailers can           serve many purposes, but the most important of which
 is that the           trailer messages only happen IF the host message also
 happens, and           only happen AFTER the host message happens. This
can  be useful for           the timing of subsequent messages which are
dependent  on           others.         </p>

               <img src="images/temple.jpg" alt="The State of Things" />
                                               
      
      <h2><a name="DIG2" id="DIG2">Core Topic 2: The State of Things:</a></h2>

                                                  
      
      <p>           In most systems, it is typical for all of the data variables
 which           describe a particular object to be coded directly inside
that           object. While this is also true in CoffeeMud, many important
data           fields, along with the appropriate "getter" and "setter" methods, 
           are stored in separate special data-storage, or state         
 objects. These data-storage objects provide access to numerous         
 important properties for those objects. These storage/state objects    
      are routinely copied and then the copies are modified by other    
      objects which have a spacial relationship with them. For instance, 
         a MOB object may copy one or more of its state objects, and then 
           allow the local Room object, or his inventory Item objects, or 
          spell Effect objects to modify the copy, The copied state object 
           modifications are stacked on each other. Confused? Well, keep 
         reading!         </p>

                                                  
      
      <p>           Each instance of the several Environmental          
objects (MOBs, Items, Exits, Rooms) have a particular storage/state     
     object called their Environmental Stats. This object implements the
          Common.interfaces.EnvStats interface, and is typically an instance
           of the Common.DefaultEnvStats class. Access to this state object
is           available through each core.interfaces.Environmental objects
           <code>EnvStats baseEnvStats()</code>           and <code>EnvStats
 envStats()</code> method calls. Since Rooms, MOBS, Items,           Exits,
 and Areas are all Environmental objects, that means that           they
all  have baseEnvStats and envStats methods as well.         </p>

                                                  
      
      <h3><a name="envstats" id="envstats">EnvStats state object fields</a></h3>

                                                  
      
      <table bgcolor="#ccccff" border="1">

                <thead>             <tr>

                    <th>                 Field name               </th>

                    <th>                 Relevant objects               </th>

                    <th>                 Meaning               </th>

                  </tr>

                </thead>           <tbody>

                  <tr>

                    <td>                 level               </td>

                    <td>                 Item, MOB, Exit               </td>

                     <td>                 Experience level (see Archon's
Guide)                </td>

                  </tr>

                  <tr>

                    <td>                 ability               </td>

                    <td>                 Item, MOB               </td>

                     <td>                 Magical level (see Archon's Guide) 
              </td>

                  </tr>

                  <tr>

                    <td>                 rejuv               </td>

                    <td>                 Item, MOB               </td>

                     <td>                 Rejuvenation rate (see Archon's
Guide)                </td>

                  </tr>

                  <tr>

                    <td>                 weight               </td>

                    <td>                 Item, MOB               </td>

                     <td>                 Weight of the object          
    </td>

                  </tr>

                  <tr>

                    <td>                 height               </td>

                    <td>                 Armor, MOB               </td>

                     <td>                 Size of the object            
  </td>

                  </tr>

                  <tr>

                    <td>                 armor               </td>

                    <td>                 Item, MOB               </td>

                     <td>                 Protection level (see Archon's
Guide)                </td>

                  </tr>

                  <tr>

                    <td>                 damage               </td>

                    <td>                 Item, MOB               </td>

                     <td>                 Damaging ability              
            </td>

                  </tr>

                  <tr>

                    <td>                 speed               </td>

                    <td>                 Item, MOB               </td>

                     <td>                 Attack speed               </td>

                  </tr>

                  <tr>

                    <td>                 attackAdjustment               </td>

                    <td>                 Item, MOB               </td>

                     <td>                 Attack level               </td>

                  </tr>

                  <tr>

                    <td>                 replacementName               </td>

                    <td>                 Item, MOB, Exit               </td>

                     <td>                 New displayable name of the object 
              </td>

                  </tr>

                  <tr>

                    <td>                 sensesMask               </td>

                    <td>                 Item, MOB, Exit, Room          
    </td>

                     <td>                 Bit mask of relevant sensory abilities. 
               </td>

                  </tr>

                  <tr>

                    <td>                 disposition               </td>

                    <td>                 Item, MOB, Exit, Room          
    </td>

                     <td>                 Bit mask of relevant disposition
state                </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                  
      
      <p>           Although most of these fields are better described in
 the Archon's           Guide, there are two whose nature may not be readily
 apparent: the           sensesMask and the disposition. These two integers
 are bitmaps. The           value of each bit is defined by equates in the 
           Common.interfaces.EnvStats interface. The equates which refer to
           the bits for sensesMask all begin with "CAN_", while the equates 
           which refer to the bits for disposition all begin with "IS_". 
       </p>

                                                  
      
      <p>           Now, as mentioned previously, all Environmental     
     objects have two methods for accessing their EnvStats. One         
 is           <code>core.interfaces.Environmental.baseEnvStats()</code> 
         and the other is           <code>core.interfaces.Environmental.envStats()</code>. 
           The difference between these two methods is very           significant.
 The EnvStats state object           returned by the "baseEnvStats" method
 refers to the permanent,           unmodified, "base" state of the Environmental
 object. The           "envStats" method, however, returns the modified,
less  permanent,           "current" state of the Environmental object. The
EnvStats  object           returned by the "envStats" method is always copied
and derived  from           the "baseEnvStats" values, after all relevant
modifications  have           been made to it. How the current state object
goes from its  base           values (baseEnvStats) to its current values
(envStats) is our next           topic.         </p>

                                                  
      
      <p>           We must now introduce two other Environmental       
   interface methods significant to this topic. One is the           <code>recoverEnvStats()</code>
 method,           while the other is the           <code>affectEnvStats(Environmental
 affected, EnvStats           affectableStats)</code> method. The "recoverEnvStats"
 method           is also located on every Environmental (Item, MOB, Exit,
 etc)           object and is the method which turns the <code>baseEnvStats()</code>
 values into           their current <code>envStats()</code> values. This
method call works by           copying the base values into the current values
and then           allowing certain other objects to have an opportunity
to affect the           copy. Only after all opportunities to modify the
copied values have           been exhausted, does the <code>recoverEnvStats()</code>
method return. In           essence, <code>recoverEnvStats()</code> allows
the Environmental objects           <code>baseEnvStats()</code> to be updated,
with that updated state object made           available through <code>envStats()</code>.
         </p>

                                                  
      
      <p>           The way in which the current EnvStats state         
 object is modified by the <code>recoverEnvStats()</code> method call is
by           making repeated internal calls to the           <code>affectEnvStats(Environmental
 affected, EnvStats           affectedStats)</code> methods on other relevant
 objects.           These methods will then have the opportunity to change
 the values           in the current state object (affectedStats parameter)
 however they            wish. The relevant objects which may change the
state  of an           Environmental are as follows:         </p>

                                                  
      
      <ul>

                <li>MOBs                                                
                 
          
          <p>             Room object being occupied, something being Ridden,
 the MOBs             Character Class object, the MOBs Race object, the Items
 in the MOBs             inventory, and finally the Ability objects which
are affecting the             MOB (spell effects).           </p>

                </li>

                <li>Items, Exits, Areas                                  
                               
          
          <p>             Ability objects which are affecting it (spell 
           effects).           </p>

                </li>

                <li>Rooms                                               
                  
          
          <p>           Area object which this room is a part of, Ability
 objects             which are affecting it (spell effects), Items in the
Room, and MOBs             in the Room.           </p>

                </li>

                                                 
      
      </ul>

                                                  
      
      <p>           Here is an example:         </p>

                                                  
      
      <p>           Gunker the Thief wears Full Plate Armor (Item),     
     and has the Shield spell cast on him. His base Armor rating is 100.
          When he puts on the Plate Armor, the "recoverEnvStats" method is 
           called on Gunker's MOB object. That method in turn calls the  
        "affectEnvStats" method on the Plate Armor and the Shield spell 
         Effect. Both of those methods improve the Armor rating on Gunker's 
           MOB's current EnvStats by some number. Thus, Gunker becomes harder 
           to hit in combat. Also, when Gunker picked up the Plate armor,
 the           weight of the armor was added to Gunker's overall carried
weight  by           increasing the weight value in Gunker's           EnvStats
object.          </p>

                                                  
      
      <p>           I know, this is probably still confusing.         </p>

                                                  
      
      <p>           Confusing or not, however, we still have to consider
two other           state objects, both of which are only available from
the MOB           object. One of which is the CharStats object, and the other
 of           which is the CharState object.         </p>

                                                  
      
      <p>           The CharStats objects are most closely analogous    
      to the EnvStats objects. For instance, there are           <code>CharStats
 baseCharStats()</code>           and <code>CharStats           charStats()</code>
 method calls from a MOB object, as well as           a           <code>recoverCharStats()</code>
 method call. All           of these work similarly to the ones described
above for EnvStats.           The fields on a Common.interfaces.CharStats
object are somewhat           more straight forward however. Most of the
fields of a CharStats           object are referenced using the         
 <code>int getStat(int)</code> and           <code>setStat(int,int)</code>
methods on a           CharStats object. Both of these methods require, as
their first           parameter, an integer code which corresponds to the
specific stat           being set or read. These stat parameters are defined
as equates           within the CharStats interface, and include:       
   </p>

                                                    
      
      <p><a name="charstats" id="charstats">&nbsp;</a>           STAT_STRENGTH, 
           STAT_INTELLIGENCE, STAT_DEXTERITY, STAT_CONSTITUTION,         
 STAT_CHARISMA, STAT_WISDOM, STAT_GENDER, STAT_SAVE_PARALYSIS,          
STAT_SAVE_FIRE, STAT_SAVE_COLD, STAT_SAVE_WATER, STAT_SAVE_GAS,         
 STAT_SAVE_MIND, STAT_SAVE_GENERAL, STAT_SAVE_JUSTICE,           STAT_SAVE_ACID,
 STAT_SAVE_ELECTRIC, STAT_SAVE_POISON,           STAT_SAVE_UNDEAD, STAT_SAVE_MAGIC,
 STAT_SAVE_DISEASE,           STAT_SAVE_TRAPS, STAT_MAX_STRENGTH_ADJ, STAT_MAX_INTELLIGENCE_ADJ, 
           STAT_MAX_DEXTERITY_ADJ, STAT_MAX_CONSTITUTION_ADJ,           STAT_MAX_CHARISMA_ADJ,
 STAT_MAX_WISDOM_ADJ, STAT_AGE,           STAT_SAVE_DETECTION, STAT_SAVE_OVERLOOKING. 
           </p>

                                                    
      
      <p>           In addition to these equates defined and read       
   through the <code>getStat()</code> and <code>setStat()</code> methods,
there is also the Race           object available through <code>getMyRace()</code>
 and <code>setMyRace()</code> methods, as           well as Character Class
 and Character Class level methods. See the           Common.interfaces.CharStats
 java file for more information on those           methods and how they work. 
         </p>

                                                  
      
      <p>           Like the EnvStats above, those objects listed as    
      able to modify the EnvStats current state object are the same     
     objects which are able to modify the CharStats state objects.      
    Rereading the section on EnvStats will make clear how the CharStats 
         objects are modified in the same analogous manner, using repeated 
           calls to<code>affectCharStats(MOB           affected, CharStats
 affectedStats)</code> methods on related           objects.         </p>

                                                  
      
      <p><a name="charstate" id="charstate">&nbsp;</a>           The last
 state object to consider is the           Common.interfaces.CharState objects
 on MOBs. The CharState object           represents those fields which are
 constantly in flux: Hit Points,           Mana, Movement, Hunger, Fatigue,
 and Thirst.         </p>

                                                  
      
      <p>           Unlike EnvStats and CharStats, there are three      
    CharState objects to consider for MOBs: the base CharState object   
       (available through<code>CharState           baseState()</code> method,
 the adjusted base CharState (or           max state) object available through
 the           <code>CharState maxState()</code> method and           modified
 by <code>recoverMaxState(MOB           affected, CharState affectedState)</code>
 methods on related           objects, and lastly the current CharState object
 available through           the <code>CharState           curState()</code>
 and refreshed or reset to maximums using           the MOBs           <code>resetToMaxState()</code>
 method.         </p>

                                                  
      
      <p>           The relationship between the above objects is as follows:
 The base           CharState object represents the maximum values for the
 state           variables BEFORE modification by magical armor or spells.
 The           adjusted base CharState object (Max State) represents the
maximum            values for the state variables AFTER modification by magical
armor            or spells. The current CharState object (curState) represents 
the            current hit points, mana points, etc available to the MOB. 
        </p>

                                                  
      
      <p>           In the case of the CharState objects, adjustment    
      by relevant objects is initiated by calling the MOBs           <code>recoverMaxState()</code>
 method.           This method allows the same objects who modify the EnvStats
 and           CharStats above to modify the maximum CharState values as
          well.         </p>

                                                  
      
      <p>           Once again, to understand one of them fully is to understand
 them           all.         </p>

               <img src="images/time.jpg" alt="Tick Tock" />
                                               
      
      <h3><a name="DIG3" id="DIG3">Core Topic 3: Tick Tock</a></h3>

                                                  
      
      <p>           Our last Core Topic will cover the ability of the   
       mobs, items, exits, abilities, spell effects, behaviors, and other 
           objects to perform tasks on a regular, timed, basis. The tasks
 to           be performed are always located within an method called   
       <code>boolean tick(Tickable ticking, int tickID)</code>.         
 All Environmental objects define this method, and Behavior           objects
do as well.         </p>

                                                  
      
      <p>           These methods are called on a regular, timed        
  basis whenever the object instance in question has been properly      
    set up to do so, and at a defined frequency and interval. The       
   "ticking" parameter is usually a reference to the object itself, or  
        to the host object in the case of Behaviors. The "tickID" parameter 
           describes what sort of regular timed event is occurring. These 
          events are defined as equates in the core.interfaces.Tickable  
        interface, and include IDs such as TICKID_MOB, TICKID_AREA,     
     TICKID_EXIT_REOPEN and others. See           the java file of that interface
for more defined tickID           values.         </p>

                                                  
      
      <p>           Before we get into the methods by which an object instance
 are           properly set up for regular calls to its <code>tick()</code>
 method, it may be           worthwhile to discuss which regular ticks are
 setup by the system           by default. These tick events cover the most
 commonly used objects           under the most common circumstances, and
so may be just the events           you already needed! They include:   
     </p>

                                                  
      
      <ul>

              <li>MOBs                                                  
             
          
          <p>           All MOBs have their <code>tick()</code> method called
 once per           core.interfaces.MudHost.TIME_TICK (4 seconds), with the
 "tickID"           defined by Host.MOB_TICK. MOBs will, in turn, call the
           <code>tick()</code>           methods on their own Behaviors,
and  Ability objects affecting them.           If any of these dependent
objects  return "false" from their own           tick methods, then the object
will  cease to receive any further           tick method calls.         </p>

              </li>

               <li>Exits, Items, Rooms                                  
                             
          
          <p>           Whenever a Behavior is           added to any of
these objects, they will begin to have their tick           methods called
once per MudHost.TIME_TICK (4 seconds), with the           tickID defined
by Tickable.TICKID_ITEM_BEHAVIOR, TICKID_EXIT_BEHAVIOR,           or TICKID_ROOM_BEHAVIOR.
Deletion of the last behavior from the host           object will stop this
tick event from occurring again.         </p>

              </li>

               <li>Areas                                                
               
          
          <p>           All Area objects have their tick methods        
  called once per core.interfaces.MudHost.TIME_TICK,           with the tickID
 defined by Tickable.TICKID_AREA.         </p>

              </li>

               <li>Ability                                              
                 
          
          <p>           Whenever an Ability object is added as an Effect
(using           the <code>addEffect()</code> Environmental method) to a
non-MOB object by using           the proper Ability invoke procedure (see
below), then the Ability           object itself will gain it's own regular
calls to its tick method.           The tickID for this call is also Tickable.TICKID_MOB,
 so as to make           consistant the tickID for all spell and similar
effects.          </p>

              </li>

                                               
      
      </ul>

                                                   
      
      <p>           To sum up, MOBs have regular tick calls which they use
 to perform           their own periodic tasks, as well as to allow their
Behavior and           spell effects to perform tasks. The other objects
have           circumstantial ticks in certain instances.         </p>

                                                  
      
      <p>           Now, to add a new periodic call to the "tick" method
on an           Environmental object, one needs only to make a method call
like           this:         </p>

                                                  
      
      <pre>CMClass.threads().startTickDown(theEnvObject,Tickable.MY_TICK_ID,TIME_TICK,NUM_TICKS);<br /></pre>

                                                  
      
      <p>           The second parameter is the tickID which will be used
 when the           <code>tick()</code> method on the "theEnvObject" object
 is called. The third           parameter is the time interval, in milliseconds,
 between each           event. The fourth parameter is the number of time
intervals between           each call to the <code>tick()</code> method.
The total time between each call to           the <code>tick()</code> method,
therefore, will be TIME_TICK * NUM_TICKS.         </p>

                                                  
      
      <p>           Now, the above version of <code>startTickDown()</code>
 can be used to create timed           events of any duration. However, all
 objects in the base           distribution of CoffeeMud operate on a single
 default time interval           of 4000 milliseconds as defined by Tickable.TIME_TICK.
 For this           reason, a different version of the <code>startTickDown()</code>
 method is called           which does not include the TIME_TICK parameter,
 utilizing the           standard 4 second delay instead:         </p>

                                                  
      
      <pre>CMClass.ThreadEngine().startTickDown(theEnvObject,Host.MY_TICK_ID,NUM_TICKS);<br /></pre>

                                                  
      
      <p>           Stopping any of these tick calls can be done by simply
 returning           "false" from the tick method itself, or manually using
 the           following:         </p>

                                                  
      
      <pre>CMClass.ThreadEngine().deleteTick(theEnvObject,Host.MY_TICK_ID);<br /></pre>

                                                  
      
      <p>           You may also stop tick calls to an object by        
  using the Environmental objects           <code>destroy()</code> method. 
         </p>

               <img src="images/books.jpg" alt="Core Libraries" />
                                               
      
      <h2><a name="DIG4" id="DIG4">Core Topic 4: Core Libraries</a></h2>

                                                  
      
      <p>           The CoffeeMud engine contains numerous Java classes whose
 purpose           is to perform much of the underlying game functionality.
 Some of           these Java classes are Core classes, some are Library
          classes, and some are Common classes.         </p>

                                                  
      
      <p>           Core classes are those classes found in the         
 com.planet_ink.coffee_mud.core package. Like the interfaces, they      
    may not be extended or overwritten without risking problems. The    
      core classes, and their general purpose is:<br />

              </p>

               <a name="corepurpose" id="corepurpose">&nbsp;</a>        
                                   
      
      <table bgcolor="#ffffcc" border="1">

                <thead>             <tr>

                    <th>                 Core Class Name               </th>

                    <th>                 Purpose               </th>

                  </tr>

                </thead>           <tbody>

                  <tr>

                    <td>                 B64Encoder               </td>

                    <td>                 Encode and decode text&lt;-&gt;binary
 using Base64               </td>

                  </tr>

                  <tr>

                    <td>                 CMath               </td>

                    <td>                 Converting strings to numbers, performing
 bit-wise and other                 arithmetic operations               </td>

                  </tr>

                  <tr>

                    <td>                 CMClass               </td>

                    <td>                 Main ClassLoader -- get all your
objects  from methods                 here!               </td>

                  </tr>

                  <tr>

                    <td>                 CMFile               </td>

                    <td>FileSystem manager, get all your file data from this 
class                </td>

                  </tr>

                  <tr>

                    <td>                 CMLib               </td>

                    <td>                 The non-core library reference object. 
                 *                 See below for more information.       
       </td>

                  </tr>

                  <tr>

                    <td>                 CMParms               </td>

                    <td>                 Methods for parsing strings and
determining  parameter values                 in many different ways.   
           </td>

                  </tr>

                  <tr>

                    <td>                 CMProps               </td>

                    <td>                 Properties manager, for reading
INI file values from                 coffeemud.ini and other places.    
          </td>

                  </tr>

                  <tr>

                    <td>                 CMSecurity               </td>

                    <td>                 The security manager, for evaluating
 player and system                 security flags.               </td>

                  </tr>

                  <tr>

                    <td>                 CMStrings               </td>

                    <td>                 Methods to manipulate, pad, and
filter  strings.               </td>

                  </tr>

                  <tr>

                    <td>                 Directions               </td>

                    <td>                 Methods to handle the different
compass  directions.               </td>

                  </tr>

                  <tr>

                    <td>                 DVector               </td>

                    <td>                 A multi-dimensional version of java.util.Vector 
               </td>

                  </tr>

                  <tr>

                    <td>                 Log               </td>

                    <td>                 The file and console logging manager. 
               </td>

                  </tr>

                  <tr>

                    <td>                 Resources               </td>

                    <td>                 The object-resource manager, usually
 with lots of                 StringBuffers keyed by String names.      
        </td>

                  </tr>

                  <tr>

                    <td>                 Scripts               </td>

                    <td>                 The human-language readable strings 
loader.                </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                  
      
      <p>           You should check out the javadocs for those classes for
 more           information on the core classes.         </p>

                                                  
      
      <p>           * CMLib also refers to some of the sub-core classes,
such as the           Database access objects, and the Threading engine.
While they are           considered core, they are accessed through CMLib
as if they were           non-core libraries. Most core classes can also
be accessed through           CMLib methods, making it a one-stop shop. 
       </p>

                                                  
      
      <p>           Now, non-core libraries, or Libraries proper, are located
 in the           com.planet_ink.coffee_mud.Libraries package, and each one 
           implements a unique interface from the           com.planet_ink.coffee_mud.Libraries.interfaces
 package. This is           unique, that each class in the Libraries package
 implements a           unique interface all its own, but that is not the
only unique thing           about this package. Libraries are also singletons
-- there is never           more than 1 instance of each Library. Moreover,
these singletons           are all accessed from a single accessor class,
CMLib, which we           mentioned earlier.         </p>

                                                  
      
      <p>           Here is a map of how the classes, interfaces, and CMLib
 methods are           all mapped together:         </p>

                <a name="corelibrarymap" id="corelibrarymap">&nbsp;</a> 
                                          
      
      <table bgcolor="#99ff99" border="1">

                <thead>             <tr>

                    <th>                 Library class name<br />

                      <code>...Libraries.*</code>               </th>

                    <th>                 Library interface name<br />

                      <code>...Libraries.interfaces.*</code>            
  </th>

                    <th>                 CMLib method name<br />

                      <code>...core.CMLib</code>               </th>

                    <th>               Purpose of the Library           
             </th>

                  </tr>

                </thead>           <tbody>

                  <tr>

                    <td>                 BeanCounter               </td>

                    <td>                  MoneyLibrary               </td>

                    <td>                 <code>beanCounter()</code>     
         </td>

                    <td>                 Handle money and currency.     
          </td>

                  </tr>

                  <tr>

                    <td>                 CharCreation               </td>

                    <td>                 CharCreationLibrary            
               </td>

                    <td>                 <code>login()</code>           
               </td>

                    <td>                 Login and create new players.  
            </td>

                  </tr>

                   <tr>

                    <td>                 Clans               </td>

                    <td>                 ClanManager               </td>

                    <td>                  <code>clans()</code>          
    </td>

                    <td>                 Handle all clans.              
            </td>

                  </tr>

                  <tr>

                    <td>                  CMAble               </td>

                    <td>                 AbilityMapper               </td>

                    <td>                 <code>ableMapper()</code>      
         </td>

                    <td>                 Maps CharClasses to Skills/Abilities. 
               </td>

                  </tr>

                  <tr>

                    <td>                 CMChannels                </td>

                    <td>                 ChannelsLibrary               </td>

                    <td>                 <code>channels()</code>        
      </td>

                    <td>                  Handles public channels.      
        </td>

                  </tr>

                  <tr>

                    <td>                 CMColor               </td>

                    <td>                  ColorLibrary               </td>

                    <td>                 <code>color()</code>           
               </td>

                    <td>                 ANSI and color code conversions.
               </td>

                  </tr>

                  <tr>

                    <td>                 CMEncoder               </td>

                    <td>                 TextEncoders                </td>

                    <td>                 <code>encoder()</code>         
                 </td>

                    <td>                 Compression library.           
               </td>

                  </tr>

                   <tr>

                    <td>                 CMJournals               </td>

                    <td>                 JournalsLibrary               </td>

                    <td>                  <code>journals()</code>       
       </td>

                    <td>                 Handles public journal commands.
              </td>

                  </tr>

                  <tr>

                    <td>                  CMLister               </td>

                    <td>                 ListingLibrary               </td>

                    <td>                 <code>lister()</code>          
                 </td>

                    <td>                 Handles listing tables nicely. 
             </td>

                  </tr>

                  <tr>

                    <td>                 CMMap                </td>

                    <td>                 WorldMap               </td>

                    <td>                 <code>map()</code>             
 </td>

                    <td>                  Find areas and rooms.         
                 </td>

                  </tr>

                  <tr>

                    <td>                 CoffeeFilter               </td>

                    <td>                  TelnetFilter               </td>

                    <td>                 <code>coffeeFilter()</code>    
          </td>

                    <td>                 Filters/transforms text going to
and  from a player.                </td>

                  </tr>

                  <tr>

                    <td>                 CoffeeLevels               </td>

                    <td>                 ExpLevelLibrary                </td>

                    <td>                 <code>leveler()</code>         
                 </td>

                    <td>                 Leveling and Experience gaining
functionality.                </td>

                  </tr>

                   <tr>

                    <td>                 CoffeeMaker               </td>

                    <td>                 CMObjectBuilder               </td>

                    <td>                  <code>coffeeMaker()</code>    
          </td>

                    <td>                 Generic Mob/Item and CoffeeXML generators. 
               </td>

                  </tr>

                  <tr>

                    <td>                  CoffeeShops               </td>

                    <td>                 ShoppingLibrary               </td>

                    <td>                 <code>coffeeShops()</code>     
          </td>

                    <td>                 Handles manipulation of shop inventories. 
               </td>

                  </tr>

                  <tr>

                    <td>                 CoffeeTables                </td>

                    <td>                 StatisticsLibrary              
            </td>

                    <td>                 <code>coffeeTables()</code>    
          </td>

                    <td>                  Maintains player usage stats. 
             </td>

                  </tr>

                  <tr>

                    <td>                 CoffeeTime               </td>

                    <td>                  TimeManager               </td>

                    <td>                 <code>time()</code>            
  </td>

                    <td>                 Real-life data/time display.   
            </td>

                  </tr>

                  <tr>

                    <td>                 CoffeeUtensils               </td>

                    <td>                 CMMiscUtils                </td>

                    <td>                 <code>utensils()</code>        
      </td>

                    <td>                 Misc stuff-- law, traps, titles,
resets.                </td>

                  </tr>

                   <tr>

                    <td>                 CommonMsgs               </td>

                    <td>                 CommonCommands               </td>

                    <td>                  <code>commands()</code>       
       </td>

                    <td>                 Methods for getting, talking, common-stuff 
               </td>

                  </tr>

                  <tr>

                    <td>                  Dice               </td>

                    <td>                 DiceLibrary               </td>

                    <td>                 <code>dice()</code>            
               </td>

                    <td>                 Random number generator.       
       </td>

                  </tr>

                  <tr>

                    <td>                 EnglishParser                </td>

                    <td>                 EnglishParsing               </td>

                    <td>                 <code>english()</code>         
                 </td>

                    <td>                  Player command line parsing helpers. 
               </td>

                  </tr>

                  <tr>

              <td>ColumbiaUniv</td>

              <td>ExpertiseLibrary</td>

              <td><span style="font-family: monospace;">expertise()</span></td>

              <td>Maintains expertise skill flags</td>

            </tr>

            <tr>

                    <td>                 Factions               </td>

                    <td>                  FactionManager               </td>

                    <td>                 <code>factions()</code>        
      </td>

                    <td>                 Handles the factions and faction
system.                 </td>

                  </tr>

                  <tr>

             <td>MUDLaw</td>

             <td>LegalLibrary</td>

             <td>l<span style="font-family: monospace;">aw()</span></td>

             <td>Handles legal and property matters.</td>

           </tr>

           <tr>

                    <td>                 MUDFight               </td>

                    <td>                 CombatLibrary                </td>

                    <td>                 <code>combat()</code>          
    </td>

                    <td>                 Combat and Death routines.     
         </td>

                  </tr>

                   <tr>

                    <td>                 MUDHelp               </td>

                    <td>                 HelpLibrary               </td>

                    <td>                  <code>help()</code>           
               </td>

                    <td>                 Handling help-file entries.    
          </td>

                  </tr>

                  <tr>

                    <td>                  MUDTracker               </td>

                    <td>                 TrackingLibrary               </td>

                    <td>                 <code>tracking()</code>        
       </td>

                    <td>                 Methods for NPC movement, and for
tracking.                </td>

                  </tr>

                  <tr>

                    <td>                 MUDZapper                </td>

                    <td>                 MaskingLibrary               </td>

                    <td>                 <code>masking()</code>         
                 </td>

                    <td>                  Zapper-mask parsing and evaluation. 
              </td>

                  </tr>

                  <tr>

                    <td>                 Polls               </td>

                    <td>                  PollManager               </td>

                    <td>                 <code>polls()</code>           
               </td>

                    <td>                 Handle the public polls.       
        </td>

                  </tr>

                  <tr>

                    <td>                 Quests               </td>

                    <td>                 QuestManager                </td>

                    <td>                 <code>quests()</code>          
    </td>

                    <td>                 Quest Manager system.          
    </td>

                  </tr>

                   <tr>

              <td>RawCMaterials</td>

              <td>MaterialLibrary</td>

              <td><span style="font-family: monospace;">materials()</span></td>

              <td>Manipulate/Create raw resource objects</td>

            </tr>

            <tr>

                    <td>                 Sense               </td>

                    <td>                 CMFlagLibrary               </td>

                    <td>                  <code>flags()</code>          
    </td>

                    <td>                 Sensory and Disposition bitmap/flag 
handling.                </td>

                  </tr>

                  <tr>

                    <td>                  Sessions               </td>

                    <td>                 SessionsList               </td>

                    <td>                 <code>sessions()</code>        
       </td>

                    <td>                 Container for player connection
objects.                </td>

                  </tr>

                  <tr>

                    <td>                 SlaveryParser                </td>

                    <td>                 SlaveryLibrary               </td>

                    <td>                 <code>slavery()</code>         
                 </td>

                    <td>                  Geas and Slavery order parsing
and execution.                </td>

                  </tr>

                  <tr>

                    <td>                 SMTPclient               </td>

                    <td>                  SMTPLibrary               </td>

                    <td>                 <code>smtp()</code>            
  </td>

                    <td>                 E-Mail sending routines.       
        </td>

                  </tr>

                  <tr>

                    <td>                 Socials               </td>

                    <td>                 SocialsList                </td>

                    <td>                 <code>socials()</code>         
                 </td>

                    <td>                 Socials container and parser.  
            </td>

                  </tr>

                   <tr>

                    <td>                 StdLibrary               </td>

                    <td>                 NONE               </td>

                    <td>                 NONE               </td>

                    <td>                 SuperClass of other libraries. 
             </td>

                  </tr>

                  <tr>

                    <td>                 TimsLibrary               </td>

                    <td>                 ItemBuilderLibrary             
 </td>

                    <td>                 <code>itemBuilder()</code>     
         </td>

                    <td>                 Methods for normalized item evaluation. 
               </td>

                  </tr>

                  <tr>

                    <td>                 XMLManager               </td>

                    <td>                 XMLLibrary               </td>

                    <td>                 <code>xml()</code>             
 </td>

                    <td>                 General XML parsing.           
               </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                  
      
      <p>           Libraries are           lastly unique in that it is almost
 useless to write new ones,           unless you are doing the most serious
 additions and enhancements to           your system. However, they are designed
 especially so they they can           be extended and overridden. They have
 their own entry in the           coffeemud.ini file called LIBRARY. By writing
 classes that extend           the base CoffeeMud library classes, and overriding
 their methods,           you can make changes to the most basic CoffeeMud
 algorithms, even           at run-time! Libraries also have an entry in
the  coffeemud.ini           file, LIBRARY, so that you can specify your
custom  extended           versions of them after the %DEFAULT% string, thus
allowing  your           changes to be loaded at boot-time.         </p>

                                                  
      
      <p>           The last set of classes to discuss under this topic are
 neither           Core class or Libraries, but form parts of the cores of
 other           classes, including many of the Libraries. These are the
Common            classes. They are part of the com.planet_ink.coffee_mud.Common 
          package. Like the Libraries, they each implement their own unique 
           interface from the com.planet_ink.coffee_mud.Common.interfaces 
          package. However, unlike the Libraries, numerous instances of each 
           class will exist in your mud, and they are created from the core 
           CMClass loader, much like MOBs, Items, Rooms, and so forth. The 
           javadocs are also a good place to learn about these classes, but 
           here is a brief list of them to wrap up our last Core Topic.  
      </p>

               <a name="corecommon" id="corecommon">&nbsp;</a>          
                                 
      
      <table bgcolor="#ccccff" border="1">

                <thead>             <tr>

                    <th>                 Common Class               </th>

                    <th>                 Description               </th>

                  </tr>

                </thead>           <tbody>

                  <tr>

                    <td>                 DefaultArrestWarrant           
               </td>

                    <td>                 An object created every time a law 
is broken.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultCharState              
            </td>

                    <td>                 Contains a mobs hit points, mana,
movement,  fatigue, hunger,                 and thirst.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultCharStats              
            </td>

                    <td>                 Contains a mobs class, race, saving 
throws, and basic stat                 scores.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultClan               </td>

                    <td>                 Represents a single Clan.      
        </td>

                  </tr>

                  <tr>

                    <td>                  DefaultClimate               </td>

                    <td>                 A single climatary system for a
given  area.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultCMIntegerGrouper       
       </td>

                    <td>                 An object for maintaining a players 
room visitation                 memory.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultCoffeeShop             
 </td>

                    <td>                 Represents a single shop store inventory. 
               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultCoffeeTableRow         
                 </td>

                    <td>                 Represents a days worth of game
player  usage                 statistics.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultEnvStats               </td>

                    <td>                 Contains an objects attack bonus,
armor  bonus, weight,                 height, rejuv rate.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultFaction               </td>

                    <td>                 Represents a single faction.   
           </td>

                  </tr>

                  <tr>

                    <td>                  DefaultLawSet               </td>

                    <td>                 Represents a single set of laws
and legal policies.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultMessage               </td>

                    <td>                 A CoffeeMud event message (CMMsg). 
              </td>

                  </tr>

                  <tr>

                    <td>                  DefaultPlayerStats            
  </td>

                    <td>                 Represents player-specific fields
like  prompts, friends,                 alias, etc.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultPoll               </td>

                    <td>                 A single poll object.          
    </td>

                  </tr>

                  <tr>

                    <td>                  DefaultQuest               </td>

                    <td>                 Container for a single timed quest. 
              </td>

                  </tr>

                  <tr>

                    <td>                  DefaultRoomnumberSet          
    </td>

                    <td>                 Container for a players area visitation
 memory.               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultSession               </td>

                    <td>                 Connection object for handling a
players  telnet session with                 the mud               </td>

                  </tr>

                  <tr>

                    <td>                  DefaultSocial               </td>

                    <td>                 Object for a single social command. 
              </td>

                  </tr>

                  <tr>

                    <td>                  DefaultTimeClock              
            </td>

                    <td>                 Object representing a single calendar/time
 system that spans                 areas, possibly the whole world.     
         </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

               <br />

         <br />

         <img src="images/stat.jpg" alt="Core Libraries" height="70" width="87" />
                                               
      
      <h2><a name="DIG5" id="DIG4">Core Topic 5: Stat</a></h2>

                                                  
      
      <p>In the uncoming sections, you will learn about the layout and design 
of each of the several major CoffeeMud class types. &nbsp; Sometimes, however, 
you may want to expand or extend the classes to include new or extraneous 
data. &nbsp;If so, this last core topic is for you.<br />

         </p>

                       
      
      <p>All of the classes which implement the Environmental interface (including 
Abilities, Exits, Areas, Rooms, MOBs, and Items) or the PlayerStats interface 
(Player MOBs) or several others, will include the following methods for accessing 
and modifying certain internal data fields:<br />

         </p>

                       
      
      <p><tt>&nbsp;&nbsp;&nbsp; public String[] getStatCodes();<br />

   &nbsp;&nbsp;&nbsp; public int getSaveStatIndex();<br />

   &nbsp;&nbsp;&nbsp; public String getStat(String code);<br />

   &nbsp;&nbsp;&nbsp; public void setStat(String code, String val);</tt><br />

         </p>

                       
      
      <p>The<tt> getStatCodes() </tt>method returns a string array of the 
"names" of the internal data fields which this class makes available to the 
outside world. &nbsp; These names can then be used in the <tt>getStat(String)</tt> 
method to retreive the string-rendered values of those data fields, and the 
      <tt>setStat(String,String)</tt> method can be used to change them. &nbsp;This
is a very versitile way of reading and writing the particular aspects of
a data object, especially when you don't know for sure what kind of object
it is (or you don't care).<br />

         </p>

                       
      
      <p>However, the reason this might interest you is because of the method 
we havn't mentioned yet: <tt>getSaveStatIndex()</tt>. &nbsp;The purpose of 
this method is quite simple: It returns the number of stat code names (from 
      <tt>getStatCodes()</tt> ) that are already handled by the existing database
code. &nbsp;This means that, for a stock CoffeeMud system, this method will
return the same number as <tt>getStatCodes().length</tt> would. &nbsp;However,
should you decide to add to the stat name strings defined by getStatCodes()
and then extend getStat and setStat methods to manage your own internal variables,
you have only to make sure your new name is at the end, and that getSaveStatIndex()
stops short of that number, to make sure that CoffeeMud will go ahead and
save your new data to the database (and restore it, of course). &nbsp;Exporting
to cmare files and other features are also included this way.<br />

         </p>

                       
      
      <p>Here is an example:<br />

         </p>

                       
      
      <p><tt>public class MySpecialGenMob extends GenMOB<br />

   {<br />

   &nbsp;&nbsp;&nbsp; public String ID(){return "</tt><tt>MySpecialGenMob</tt><tt>";}<br />

   &nbsp;&nbsp;&nbsp; <br />

   &nbsp;&nbsp;&nbsp; private String myvariable="";<br />

   &nbsp;&nbsp;&nbsp; <br />

   &nbsp;&nbsp;&nbsp; public String[] getStatCodes()<br />

   &nbsp;&nbsp;&nbsp; {<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List L=java.util.Arrays.asList(super.getStatCodes());<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; L.add("MYVALUE"); <br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (String[])L.toArray();<br />

   &nbsp;&nbsp;&nbsp; } <br />

   &nbsp;&nbsp;&nbsp; public String getStat(String code)<br />

   &nbsp;&nbsp;&nbsp; {<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(code.equalsIgnoreCase("MYVALUE"))<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 
myvariable;<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.getStat(code);<br />

   &nbsp;&nbsp;&nbsp; }<br />

   &nbsp;&nbsp;&nbsp; public void setStat(String code, String value)<br />

   &nbsp;&nbsp;&nbsp; {<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(code.equalsIgnoreCase("MYVALUE"))<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myvariable=value;<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />

   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.setStat(code,value);<br />

   &nbsp;&nbsp;&nbsp; }<br />

   &nbsp;&nbsp;&nbsp; public int getSaveStatIndex(){return super.getStatCodes().length;}</tt></p>

                       
      
      <p><br />

   You'll notice above that the getStatCodes() method is extended to add
a new stat code name "MYVALUE" which will appear at the end of the string
list. &nbsp;The getStat and setStat methods are adjusted accordingly to support 
the new code. &nbsp;Lastly, the getSaveStatIndex method is overridden to return
the length of the base classes codes instead of mine, that way the getSaveStatIndex
for <tt>MySpecialGenMob </tt>will return one less than the getSaveStatIndex
for GenMOB, the super class.</p>

                       
      
      <p>And just by doing those simple things, we now have a new variable 
which the CoffeeMud engine will ensure is written to the database. &nbsp;However, 
this capability is limited to the following types of objects: generic mobs, 
generic items, playerstats, or any exits, rooms, or area classes. &nbsp;Since 
players are technically implemented as StdMOB objects, you will need to modify 
the appropriate methods in the DefaultPlayerStats object to achieve the same 
effect for players.</p>

         <br />

         <img src="images/pencil.jpg" alt="commands" />
                                               
      
      <h2><a name="CMDS" id="CMDS">Commands</a></h2>

                                                  
      
      <p>           Commands are exactly what they sound like: LOOK, QUIT,
 KILL, GET,           and all the other things you type into the mud are
handled  by           CoffeeMud Commands.         </p>

                                                  
      
      <p>           A Custom Command may or may not belong to any particular
 package,           though it is important that the <code>ID()</code> of
the  Command be unique in           the system. A custom Command imports
the same  packages mentioned in           the first section of this document
under Complete Default Import           List as well as com.planet_ink.coffee_mud.Commands.StdCommand. 
         </p>

                                                  
      
      <pre>public class DoNothing extends com.planet_ink.coffee_mud.Commands.StdCommand<br />{<br />  public DoNothing(){}<br /><br />  private String[] access={ "DONOTHING" };<br />  public String[] getAccessWords(){ return access; }<br /></pre>

                                                 
      
      <p>           All Commands should extend StdCommand for conformity's
 sake, though           it is not required so long as your class implements
 the           com.planet_ink.coffee_mud.core.interfaces.Command interface.
 In our           example above, we have an empty constructor, but we do
define  some           access words.         </p>

                                                  
      
      <p>           Access words are what you think they are: the       
   words which, when typed, allow the users to activate the command.    
      We define a string array containing one such access word in this  
        case, and then define our Command interface method getAccessWords() 
           to return that array. Our String array may contain as many strings 
           as you would need to provide sufficient words to activate this 
          command.         </p>

                                                  
      
      <pre>public double actionsCost(){ return 1.0; }<br />public double combatActionsCost(){ return 1.0; }<br /><br />public boolean canBeOrdered(){ return true; }<br /></pre>

                                                 
      
      <p>           The next two methods, <code>actionsCost()</code> and 
         <code>combatActionsCost()</code>, designate how LONG it takes to 
           execute this command. A value of 0 means that the command always 
           happens instantly. A value greater than 0 will always take that 
           many free actions to complete. A standard player may perform 1 
          action in a given 4 second period, or 2 actions during combat in 
           the default combat system -- they retain their 1 action per tick
 in           other combat systems). Action costs may be partial as well,
costing           0.5 (1/2 action) or other values.         </p>

                                                  
      
      <p>           The <code>canBeOrdered()</code> method designates whether
 this command           represents an action which a creature or player might
 reasonably be           ordered to do by another player. Archons and those
 with the "ORDER"           security code are exempt from this flag.    
    </p>

                                                  
      
      <pre>  public boolean securityCheck( MOB mob )<br />  {<br />    return CMSecurity.isAllowed( mob, mob.location(), "IMMORT");<br />  }<br /></pre>

                                                 
      
      <p>           And speaking of security, this method returns whether
 or not the           given mob may even have access to this command. If
the            <code>securityCheck()</code> method returns false, the command
 and its access           words will behave as if they do not even exist,
returning "Huh?"           should a player attempt to use it. Returning true,
however, means           only that the execute method below may be accessed.
Any further           security would have to be implemented there.      
  </p>

                                                  
      
      <p>           In the above example, we call the <code>isAllowed()</code>
 method in CMSecurity           with the mob reference, the room in which
the mob is located, and           the security code "IMMORT". This asks the
Security module whether           this mob, at this location, is authorized
to perform functions           designated by the "IMMORT" security code.
        </p>

                                                  
      
      <pre>  public boolean preExecute(MOB mob, Vector commands, int secondsElapsed, double actionsRemaining)<br />    throws java.io.IOException;<br />  {<br />    if( secondsElapsed == 0 )<br />    {<br />      mob.tell( "You are preparing to do nothing." );<br />    }<br /><br />    if( secondsElapsed == 3 )<br />    {<br />      mob.tell( "You almost ready to do nothing." );<br />    }<br />  }<br /></pre>

                                                 
      
      <p>           The <code>preExecute()</code> method is very rarely implemented, 
           but it is important to mention in light of the <code>actionsCost()</code>
 and           <code>combatActionsCost()</code> values above. The purpose
of the method is to           give the player or the room status messages
when the player does           not yet have enough actions to execute the
command. The method will           be called immediately if a player does
not have enough actions to           execute the command, and will present
a secondsElapsed value of 0.           It will then be called again every
second or so with updated values           until the player has enough actions
to proceed.         </p>

                                            
      
      <pre>  public boolean execute( MOB mob, Vector commands )<br />    throws java.io.IOException<br />  {<br />    String parameters = CMParms.combine( commands, 1 );<br />    if( parameters.length() == 0 )<br />    {<br />      mob.tell( "Nothing done." );<br />    }<br />    else<br />    {<br />      mob.tell( "Nothing, not even '" + parameters + "', done." );<br />    }<br />    return false;<br /><br />  }<br />  </pre>

                                                  
      
      <p>           Our last method is where the command actually does its
 work. The           mob given would be the MOB object trying to execute
this  command,           while commands is a Vector of parameters.      
  </p>

                                                  
      
      <p>           The parameter commands is never null, and by convention
 is a Vector           of strings starting with the access word used to execute
 the           command. For instance, if the user entered:         </p>

                                                  
      
      <pre>donothing never "and always" never<br />        </pre>

                                                  
      
      <p>           The commands Vector would be size 4, and contain "donothing", 
           "never", "and always", and "never" respectively. In the case of 
           this command, we use one of the String utilities to recombine the
           last 3 parameters back into one string "never and always never", 
           and then issue a message to the mob depending upon whether there 
           were any parameters at all. Since this command requires a command 
           word to access it, it is reasonable to assume that the 0th element 
           in the commands vector is the word "donothing", which means we
 can           safely ignore it.         </p>

               <img src="images/smurf.jpg" alt="MOBs" />
                                               
      
      <h2><a name="MOBS" id="MOBS">MOBs</a></h2>

                                                  
      
      <p>           MOBs, or "Moveable OBjects", are the creatures and characters
 which           the players fight. In CoffeeMud, they are among the simpler
 objects           to code. This is not because they are uncomplex. In fact,
 they are           MOST complex. However, this complexity comes due to the
 myriad of           Items, Behaviors, Properties, and Abilities that are
added to them.           Short of these numerous additions, a MOB by himself
is rather           simple!         </p>

                                                  
      
      <p>           This simplicity is important however, and should be carefully 
           considered before you run off to create new MOBs. If you are  
        creating a new MOB because you want a creature to have some new 
         kind of ability, then are you sure it is not a new Ability you want
           to write? If the new MOBs behavior is complex and unique, are
you            sure it's not a new Behavior you wish to code? Otherwise, the
best            reasons to be coding MOBs are actually three: because you
have a           particular kind of monster that is used prolifically in
your world,           and you want to save memory by coding him as a special 
mob that           extends StdMOB, or because you want to code special player 
           capabilities by creating your own class that both extends StdMOB 
           and has an <code>ID()</code> of "StdMOB", or because you want to
add special NPC           monster capabilities by creating your own class
 that extends GenMob           and has an <code>ID()</code> of "GenMob".
        </p>

                                                  
      
      <p>           So, if you are sure this is what you want to do, carry
 on! The           directory for your custom coded MOB objects should be
specified            using the "MOBS" entry in the coffeemud.ini file. See
the section            above on Rebuilding CoffeeMud for more information
on this feature.          </p>

                                                  
      
      <h3><a name="mobcoding" id="mobcoding">Coding a new MOB</a></h3>

                                                  
      
      <p>           A Custom MOB may or may not belong to any particular
package,           though it is important that the ID() of the MOB be unique
in the           system. A custom MOB imports the same packages         
 mentioned in the first section of this document under Complete         
 Default Import List as well as (in this case)           com.planet_ink.coffee_mud.MOBS.StdMOB
 because our sample mob           extends it.         </p>

                                                  
      
      <p>           A MOB class must extend either StdMOB or GenMob,    
      StdShopKeeper or GenShopKeeper,           StdRideable or GenRideable
 depending on the basic           capabilities, and customizability you would
 like. Although Generic           objects are more customizable at run-time,
 they also take a long           time for the system to load and build, and
 take up a lot of           database disk space, and more memory. For this
 reason, using           Standard instead of Generic wherever possible is
always good.           Another reason for extending StdMOB is because all
players in the           game use the "StdMOB" class as a basis, which means
that special           player fields and capabilities can be coded by both
extending the           StdMOB class, and also giving your custom class an
      <code>ID()</code> of           "StdMOB". If you do this, however, make
sure your class is loaded           after the %DEFAULT% list in your coffeemud.ini
file.         </p>

                                                  
      
      <p>           As was stated, each unique MOB must also have a custom
       <code>ID()</code>           method as shown below. Notice that the
      <code>ID()</code> is the same as the name           of the class. This
 is no accident -- this is required!         </p>

                                                  
      
      <pre>public class MyNewMOB extends com.planet_ink.coffee_mud.MOBS.StdMOB<br />{<br />  public String ID(){ return "MyNewMOB";}<br /></pre>

                                                 
      
      <p>           All of your customizing will be done inside the     
     constructor: name, displayText, description, etc, etc.         </p>

                                          
      
      <pre>  public MyNewMOB()<br />  {<br />    super();<br /><br />    setName( "a new mob" );<br />    setDescription( "It`s furry with 2 legs" );<br />    setDisplayText( "My new mob is standing here." );<br /><br />    Factions.setAlignment( this, Faction.ALIGN_NEUTRAL );<br />    setMoney( 0 );<br />    setWimpHitPoint( 2 );<br />    baseEnvStats().setDamage( 4 );<br /><br />    baseEnvStats().setAbility( 0 );<br />    baseEnvStats().setLevel( 1 );<br />    baseEnvStats().setArmor( 30 );<br />    baseEnvStats().setSpeed( 1.0 );<br />    baseEnvStats().setAttackAdjustment( 30 );<br />    baseEnvStats().setWeight( 85 );<br />    baseEnvStats().setSensesMask( EnvStats.CAN_SEE_DARK|EnvStats.CAN_SEE_INFRARED );<br />    baseEnvStats().setDisposition( EnvStats.IS_FLYING );<br />    baseCharStats().setCurrentClass( CMClass.getCharClass( "Fighter" ) );<br /><br />    baseCharStats().setMyRace( CMClass.getRace( "Dog" ) );<br />    baseCharStats().getMyRace().startRacing( this, false );<br />    baseCharStats().setStat( CharStats.STAT_GENDER, (int)'F' );<br />    baseCharStats().setStat( CharStats.STAT_STRENGTH, 18 );<br />    baseCharStats().setStat( CharStats.STAT_INTELLIGENCE, 14 );<br />    baseCharStats().setStat( CharStats.STAT_WISDOM, 13 );<br />    baseCharStats().setStat( CharStats.STAT_DEXTERITY, 15 );<br />    baseCharStats().setStat( CharStats.STAT_CONSTITUTION, 12 );<br />    baseCharStats().setStat( CharStats.STAT_CHARISMA, 13 );<br />    baseCharStats().setStat( CharStats.STAT_SAVE_COLD, 50 );<br /><br />    baseState.setHitPoints( CMLib.dice().roll( baseEnvStats().level(), 20, 20 ) );<br />    baseState.setMana( CMLib.dice().roll( baseEnvStats().level(), 50, 100 ) );<br /><br />    recoverMaxState();<br />    resetToMaxState();<br />    recoverEnvStats();<br />    recoverCharStats();<br />  }<br /></pre>

                                                 
      
      <p>           You can see here that the basic stats have been filled
 out, from           level to attack speed, alignment and weight. For numeric
 values,           higher is always better, except for Armor, which is always
 best           low, and comes down from 100. You'll notice above that two
 commands           are required to set the Race of the creature. Also, you
 should           realize that the numerous saving throws, and senses as
well  as           dispositions (sneaking, hiding) are not represented above,
but  can           easily be added using the format shown.         </p>

                                                  
      
      <p>           It is very important to note the last four commands.
These commands           "reset" the MOB, and "implement" the scores which
are given in the           several areas. <code>recoverEnvStats()</code>,
for instance, must be called           whenever a change is made to the <code>baseEnvStats()</code>
 object. Ditto for           "CharStats" and "MaxState".         </p>

                                                  
      
      <p>           Now, suppose we wanted to add an Effect or Behavior or
 Ability to           your MOB. The proper place for such a           statement
 would be in the same above constructor, among the other           commands.
 Preferably before the several "recover" commands, but           after the
 several stat definitions. Of course, all of this is           unnecessary
 for a new GenMOB object.         </p>

                                                  
      
      <pre>    addNonUninvokableEffect( CMClass.getAbility( "Fighter_Berzerk" ) );<br /><br />    Ability A = CMClass.getAbility( "Prop_Resistance" );<br />    if( A != null )<br />    {<br />      A.setMiscText( "Fire 200%" );<br />      addNonUninvokableEffect( A );<br />    }<br /><br />    addAbility( CMClass.getAbility( "Poison" ) );<br /><br />    addBehavior( CMClass.getBehavior( "MudChat" ) );<br />    addBehavior( CMClass.getBehavior( "Mobile" ) );<br />    addBehavior( CMClass.getBehavior( "CombatAbilities" ) );<br /></pre>

                                                  
      
      <p>           The commands above will make the MOB permanently Berzerk,
 gives it           the ability to Poison folks while in combat, allows the
 MOB to Chat           with other players, and to walk around in its area.
 The last           behavior gives the MOB the wisdom to use its Poison ability
 while           in combat.         </p>

                                                  
      
      <p>           If your MOB extends StdShopKeeper, you will need    
      to add your inventory manually through the <code>getShop()</code> object
 access           method as shown below. The <code>getShop()</code> method
 returns an instance of           the com.planet_ink.coffee_mud.Common.interfaces.CoffeeShop 
           interface, which stores inventory for the shopkeepers. In creating 
           the shopkeepers, you will also need to specify the type of    
      ShopKeeper.         </p>

                                                  
      
      <pre>    setWhatIsSold( ShopKeeper.ONLYBASEINVENTORY );<br /><br />    Weapon sword = (Weapon)CMClass.getWeapon( "Longsword" );<br />    getShop().addStoreInventory( sword, 35, -1, this );<br />    Armor mail = (Armor)CMClass.getArmor( "FullPlate" );<br />    getShop().addStoreInventory( mail, 35, -1, this );<br />    Item waterskin = CMClass.getItem( "Waterskin" );<br />    getShop().addStoreInventory( waterskin, 35, -1, this );<br /></pre>

                                                 
      
      <p>           You'll recall from the Archon's Guide that there are
many different           types of ShopKeepers, including trainers, pet sellers, 
           weaponsmiths, and others.         </p>

                                                  
      
      <p>           StdRideable MOBs will require a few other settings  
        as well!         </p>

                                                  
      
      <pre>    setRideBasis( Rideable.RIDEABLE_LAND );<br />    setMobCapacity( 2 );<br /></pre>

                                                  
      
      <p>           The last thing is to give the MOB equipment, armor, and
 weapons.           The following commands will do the trick!         </p>

                                                  
      
      <pre>    Weapon sword = (Weapon)CMClass.getWeapon( "Longsword" );<br />    addInventory( sword );<br />    sword.wearIfPossible( this );<br /><br />    Armor mail = (Armor)CMClass.getArmor( "FullPlate" );<br />    addInventory( mail );<br />    mail.wearIfPossible( this );<br /><br />    Item sack = (Item)CMClass.getItem( "StdContainer" );<br />    addInventory( sack );<br /><br />    Item waterskin = (Item)CMClass.getItem( "Waterskin" );<br />    addInventory( waterskin );<br />    waterskin.setContainer( sack );<br /></pre>

                                                 
      
      <p>           And that's all there is to creating a new standard MOB.
 Easy, huh?           Well, obviously, the real complexity of MOBs comes
when  the           Behaviors and Abilities are programmed, but that is not
covered            here, of course.         </p>

                                                  
      
      <p>           There is also the advanced topic of extending the capabilities
 of           the existing MOB classes. As mentioned previously, this consists
 in           creating your own java classes with the same class name and
      <code>ID()</code>           string methods as the base CoffeeMud MOB
 classes, and the adding           the reference to your custom class to
the  coffeemud.ini file's MOBS           enter after the %DEFAULT% entry.
Now,  adding or extending the           capabilities of these classes typically
 means both adding your own           methods, and extending the importing
 existing methods in those           classes. The most important of those
existing methods are discussed           above in the Core Topics, namely
okMessage, executeMsg, and tick.           However, there are many other
methods which might be extended to           the end of altering or enhancing
basic aspects of the mud. Those           are numerated both in the classes
you are extending, and in           com.planet_ink.coffee_mud.MOBS.interfaces.MOB.java.
Consult the           CoffeeMud java docs for more information.         </p>

                                                  
      
      <h3><a name="moblife" id="moblife">Bringing MOBs to Life, and Taking
 That Life Away</a></h3>

                                                  
      
      <p>           The following instructions are supplemental, and unnecessary.
 Once           you have created your new MOB, modified your INI file, and
 rebooted           your CoffeeMud server, you need only use the CREATE and
 other           Archon commands to make use of him. If, for some reason,
you want           to know HOW these commands do their work, however, here
it is.         </p>

                                                  
      
      <p>           To bring a MOB into existence, a MOB must have somewhere
 to exist!           Presumably, this is some room on your map. Rooms on
the  map are           classes which implement the interface           com.planet_ink.coffee_mud.Locales.interfaces.Room.
 If a MOB is to           have a permanent existence, it must also have a
starting room, or a           place to rejuvenate into when necessary. If
a MOB does not have a           starting room, then its death, when that
death comes, will be           forever.         </p>

                                                  
      
      <pre>MOB mob = CMClass.getMOB( "MyNewMOB" );<br />Room room = CMLib.map().getRoom( "Midgaard#3504" );<br /><br />mob.setStartRoom( room ); // this mob will rejuvenate into this room.<br />mob.baseEnvStats().setRejuv( 500 ); // 30 minutes rejuvenation time<br />mob.recoverEnvStats(); // remember this command?!<br /><br />mob.bringToLife( room, true ); // tadah!<br /></pre>

                                                 
      
      <p>           And THAT's all there is to bring a standard mob to life.
 Now,           generic items require an additional step:         </p>

                                                  
      
      <pre>Item item = CMClass.getItem( "GenItem" );<br />Room room = CMLib.map().getRoom( "Midgaard#3504" );<br /><br />item.text();<br />item.recoverEnvStats();<br />room.addItem( item );<br />room.recoverRoomStats();<br /></pre>

                                                 
      
      <p>           The call to the <code>text()</code> method and the seemingly
 redundant call to           <code>Item.recoverEnvStats()</code> (which we
 know is already in the item           constructor), ensures that some of
the internal structures of the           Generic MOB are properly set. Of
course, you may want to save this           room to the database to make
the situation permanent, but all of           this is usually done from inside
CoffeeMud using the CREATE,           MODIFY, and DESTROY commands anyway.
Speaking of destroy,           destroying a mob for good is even easier than
creating one:         </p>

                                                  
      
      <pre>Room room = CMLib.map().getRoom( "Midgaard#3504" );<br />for( int i = 0; i &lt; room.numInhabitants(); i++ )<br />{<br />  MOB mob = room.fetchInhabitant( i );<br />  mob.destroy();<br />}<br /></pre>

              <img src="images/sword.jpg" alt="Items" />
                                               
      
      <h2><a name="ITEMS" id="ITEMS">Items:</a></h2>

                                                  
      
      <p>           A Custom Item may or may not belong to any          
particular package, though it is important that the <code>ID()</code> of
the           Item be unique in the system. A custom Item           imports
the same packages mentioned in the           first section of this document
under Complete Default Import List           as well as (in this case)  
        com.planet_ink.coffee_mud.Items.Weapons.StdWeapon because our first
           sample item extends it.         </p>

                                                  
      
      <p>           An Item class must extend either           StdItem or
 GenItem, StdWeapon or           GenWeapon, StdRideable or GenRideable, 
         StdArmor or GenArmor depending on the basic           capabilities,
 and customizability you would like. Although Generic           objects are
 more customizable at run-time, they also take a long           time for
the  system to load and build, and take up a lot of           database disk
space.  For this reason, using Standard instead of           Generic wherever
possible  is always good. There are generally           two good reasons
to be coding  your own           Items: because you have a particular kind
of item that  is used           prolifically in your world, and you want
to save memory  by coding           it as a special item that extends StdItem
or StdWand,  or because           you want to code special item capabilities
by creating  your own           class that both extends one of the base item
classes and  has the           same <code>ID()</code> string of that class.
          The           directory for your custom coded Item objects should
be specified            using the "ITEMS", "WEAPONS", "ARMOR", "CLANITEMS",
or "MISCMAGIC"            entries in the coffeemud.ini file. See the section
above on           Rebuilding CoffeeMud for more information on this feature.
        </p>

                                                  
      
      <p>           Each Item must also have a custom <code>ID()</code> method
 as shown below.           Notice that the <code>ID()</code> is the same
as  the name of the class. This is           no accident -- this is required! 
         </p>

                                                  
      
      <pre>public class MyNewSword extends com.planet_ink.coffee_mud.Items.Weapons.StdWeapon<br />{<br />  public String ID(){ return "MyNewSword"; }<br /><br />  public MyNewSword()<br />  {<br />    super();<br />  }<br />}<br /></pre>

                                                 
      
      <p>           All of your customizing will be done inside the constructor:
 name,           displayText, description, etc, etc.         </p>

                                                  
      
      <pre>  public MyNewSword()<br />  {<br />    super();<br /><br />    setName( "a super sword" );<br />    setDescription( "A long super duper sword!" );<br />    setDisplayText( "Someone left their super sword here." );<br />    setSecretIdentity( "" );<br />    setMaterial( RawMaterial.RESOURCE_STEEL );<br />    setWeaponType( Weapon.TYPE_SLASHING );<br />    setWeaponClassification( Weapon.CLASS_SWORD );<br /><br />    setBaseValue( 500 );<br />    baseEnvStats().setDisposition( EnvStats.IS_GLOWING );<br />    baseEnvStats.setWeight( 25 );<br />    baseEnvStats.setAttackAdjustment( 10 );<br />    baseEnvStats.setDamage( 15 );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           What is shown above is entirely sufficient for the creation
 of a           normal StdWeapon . The material, weight, attack         
 and damage describe it completely. You'll even notice that by          
setting  a disposition flag, we have made the sword glow! Now, what     
     if we  wanted a missile weapon?         </p>

                                                  
      
      <pre>  public MyNewBow()<br />  {<br />    super();<br /><br />    setName( "a super bow" );<br />    setDescription( "A long super duper bow!" );<br />    setDisplayText( "Someone left their super bow here." );<br />    setSecretIdentity( "" );<br /><br />    setMaterial( RawMaterial.RESOURCE_OAK );<br />    setBaseValue( 5000 );<br />    baseEnvStats.setWeight( 15 );<br />    baseEnvStats.setAttackAdjustment( 20 );<br />    baseEnvStats.setDamage( 5 );<br />    setWeaponType( Weapon.TYPE_PIERCING );<br />    setWeaponClassification( Weapon.CLASS_RANGED );<br />    setRanges( 1, 5 );<br />    setAmmunitionType( "arrows" );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           You'll notice we added two new methods, <code>setRanges()</code>,
 and           <code>setAmmunitionType()</code>. With the former, we specify
 that this is a           ranged-only weapon, usable from range 1 (0=melee)
 to range 5. The           ammunition type specifies that it uses arrows.
Other classes,           however, have different requirements altogether.
For instance, if           class extends com.planet_ink.coffee_mud.Items.Armor.StdArmor: 
         </p>

                                                  
      
      <pre>  public MyNewArmor()<br />  {<br />    super();<br /><br />    setName( "a super bracer" );<br />    setDescription( "A super duper bracer" );<br />    setDisplayText( "Someone left their super bracer here." );<br />    setSecretIdentity( "" );<br /><br />    setMaterial( RawMaterial.RESOURCE_STEEL );<br />    setBaseValue( 100 );<br />    baseEnvStats.setWeight( 5 );<br />    baseEnvStats.setArmor( 5 );<br />    setRawProperLocationBitmap( Item.WORN_LEFT_WRIST|Item.WORN_RIGHT_WRIST );<br />    setRawLogicalAnd( false );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           In this case, we made a bracer wearable on both left
and right           wrists. If it were something that could only be worn
on both wrists           at the same time (like handcuffs), then the RawLogicalAnd
 value           would have been true. Now, a class extending           com.planet_ink.coffee_mud.Items.Basic.StdContainer: 
         </p>

                                                  
      
      <pre>  public MyNewBag()<br />  {<br />    super();<br /><br />    setName( "a super bag" );<br />    setDescription( "A super duper bag" );<br />    setDisplayText( "Someone left their super bag here." );<br />    setSecretIdentity( "" );<br /><br />    setBaseValue( 50 );<br />    setLidsNLocks( false, true, false, false );<br />    setKeyName( "" );<br />    setMaterial( RawMaterial.RESOURCE_LEATHER );<br />    baseEnvStats.setWeight( 1 );<br />    setCapacity( 100 );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           When setting the capacity of a container,           remember
 that it must also be able to hold its own weight! Also,           note the
 lids and locks flags have made this container lidless and           lockless
 and always open. Of course, without a lock, setting a key           would
 be silly! Now, a class extending           com.planet_ink.coffee_mud.Items.Basic.StdDrink 
           will create a drinkable container:         </p>

                                                  
      
      <pre>  public MyNewCup()<br />  {<br />    super();<br /><br />    setName( "a super cup" );<br />    setDescription( "A super duper cup" );<br />    setDisplayText( "Someone left their super cup here." );<br />    setSecretIdentity( "" );<br /><br />    setMaterial( RawMaterial.RESOURCE_LEATHER );<br />    setBaseValue( 5 );<br />    setLiquidHeld( 2000 );<br />    setLiquidRemaining( 2000 );<br />    setThirstQuenched( 500 );<br />    setLiquidType( RawMaterial.RESOURCE_MILK );<br />    baseEnvStats.setWeight( 1 );<br />    setCapacity( 0 );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           The StdDrink created above is an           enormous cup
 of milk! You'll notice the capacity is 0, meaning that           mundane
objects cannot be stored in it. Now, a class           extending        
  com.planet_ink.coffee_mud.Items.Basic.StdFood:         </p>

                                                  
      
      <pre>  public MyNewFood()<br />  {<br />    super();<br /><br />    setName( "a super crumb" );<br />    setDescription( "A super duper crumb" );<br />    setDisplayText( "Someone left their super crumbs." );<br />    setSecretIdentity( "" );<br /><br />    setBaseValue( 1 );<br />    setMaterial( RawMaterial.RESOURCE_MEAT );<br />    setNourishment( 500 );<br />    baseEnvStats.setWeight( 1 );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           Now, the items extending           com.planet_ink.coffee_mud.Items.Basic.StdRideable 
           resemble the MOB of the same name, and thus, have identical   
       modifications.         </p>

                                                  
      
      <pre>  public MyNewBed()<br />  {<br />    super();<br /><br />    setName( "a bed" );<br />    setDescription( "A bed" );<br />    setDisplayText( "A bed is here" );<br />    setSecretIdentity( "" );<br /><br />    setBaseValue( 100 );<br />    setMobCapacity( 2 );<br />    setRideBasis( Rideable.RIDEABLE_SLEEP );<br />    baseEnvStats.setWeight( 100 );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                  
      
      <p>           A pile of money extends class           com.planet_ink.coffee_mud.Items.Basic.StdCoins, 
           and is simplest of all:         </p>

                                                  
      
      <pre>  public MyNewMoney()<br />  {<br />    super();<br /><br />    setName( "a pile of coins" );<br />    setDescription( "A pile of coins" );<br />    setDisplayText( "Someone left their money here." );<br />    setSecretIdentity( "" );<br /><br />    setBaseValue( 0 );<br />    setMaterial( RawMaterial.RESOURCE_GOLD );<br />    setNumberOfCoins( 1000 ); // 1000 coins!<br />    setDenomination( 1.0 ); // each coin worth 1.0 basic gold<br />    baseEnvStats.setWeight( 1 );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           Notice that the base value of the coins is 0,       
   it's the other methods that truly determine its value. Now, to       
   make a magical pill, our class should extend           com.planet_ink.coffee_mud.Items.MiscMagic.StdPill: 
         </p>

                                                  
      
      <pre>  public MyNewPill()<br />  {<br />    super();<br /><br />    setName( "a super pill" );<br />    setDescription( "A super duper pill" );<br />    setDisplayText( "Someone left their super pill." );<br />    setSecretIdentity( "" );<br /><br />    setBaseValue( 1 );<br />    setMaterial( RawMaterial.RESOURCE_MEAT );<br />    setNourishment( 500 );<br />    baseEnvStats.setWeight( 1 );<br />    setSpellList( "Spell_Sleep;Prayer_CureLightWounds" );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           The spells cast on the eater are listed by their    
      Class names, separated by semicolons. The secret identity is also 
         trimmed out, since the system will handle that automaticallyy. Also 
           notice that the StdPill resembles           StdFood except for
 the addition of the           setSpellList method. In the exact same way,
 the           com.planet_ink.coffee_mud.Items.MiscMagic.StdPotion      
    class resembles the StdDrink class except that it           has an identical
 setSpellList method added to IT. So, in the           interests of saving
 a little sand for future generations, I would           enumerate the StdPotion.
 We can, however, show off           another class which extends        
  com.planet_ink.coffee_mud.Items.MiscMagic.StdScroll:         </p>

                                                  
      
      <pre>  public MyNewScroll()<br />  {<br />    super();<br /><br />    setName( "a super scroll" );<br />    setDescription( "A super duper scroll" );<br />    setDisplayText( "Someone left their super scroll." );<br />    setSecretIdentity( "" );<br />    setBaseValue( 100 );<br /><br />    setMaterial( RawMaterial.RESOURCE_PAPER );<br />    setUsesRemaining( 50 );<br />    baseEnvStats.setWeight( 1 );<br />    setScrollSpells( "Spell_Sleep;Prayer_CureLightWounds" );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           Not too difficult, right? Looks like the other      
    two, but the spell setting method has a different name. Now, let's  
        look at a sample of a class extending           com.planet_ink.coffee_mud.Items.MiscMagic.StdWand: 
         </p>

                                                  
      
      <pre>  public MyNewWand()<br />  {<br />    super();<br /><br />    setName( "a wand" );<br />    setDescription( "A magic wand" );<br />    setDisplayText( "Someone left their magic wand." );<br />    setSecretIdentity( "" );<br /><br />    setBaseValue( 1000 );<br />    setMaterial( RawMaterial.RESOURCE_OAK );<br />    baseEnvStats.setWeight( 1 );<br />    setSpell( CMClass.getAbility( "Spell_Fireball" ) );<br />    setUsesRemaining( 50 );<br />    recoverEnvStats();<br />  }<br /></pre>

                                                 
      
      <p>           In this case, we made use of the "uses remaining"   
       field to set the number of charges for the wand. The way the spell 
           is set is also different. A wand may only have one spell, and the
           actual Ability object for the spell must be passed in, instead
 of           just the class name as we did before. You will find that this
 is           also how the classes extending           com.planet_ink.coffee_mud.Items.MiscMagic.StdStaff 
           work. The StdStaff resembles the           StdWeapon we did above,
 except that the additional           setSpell and setUsesRemaining calls
become appropriate to the           constructor.         </p>

                                                  
      
      <p>           The next thing we will look at is adding effects and
behaviors to           Items. Behavior addition (despite the fact that there
is really           only one behavior that works with Items) will look familiar.
The           only difference between this and the MOB example above is the
fact           that we are setting a parameter on the Behavior before adding
it.         </p>

                                                  
      
      <pre>Behavior B = CMClass.getBehavior( "Emoter" );<br />B.setParms( "min=1 max=20 chance=75;makes strange sounds" );<br />addBehavior( B );<br /></pre>

                                                  
      
      <p>           Adding normal effects as properties is also similar to
 mobs...         </p>

                                                  
      
      <pre>Ability A = CMClass.getAbility( "Prop_HaveResister" );<br />A.setMiscText( "fire acid 50%" );<br />A.addNonUninvokableEffect( A );<br /></pre>

                                                 
      
      <p>           The above Effect will allow anyone who owns the item
to resist fire           and acid at 50%! And again, as with mobs, these
commands are best           put in the constructor of the item before the
recoverEnvStats()           call.         </p>

                                                  
      
      <p>           There is also the advanced topic of extending the capabilities
 of           the existing Item classes. As mentioned previously, this consists 
           in creating your own java classes with the same class name and
 ID()           string methods as the base CoffeeMud Item classes, and the
 adding           the reference to your custom class to the relevant coffeemud.ini 
           file's entries after the %DEFAULT% string. Now, adding or extending 
           the capabilities of these classes typically means both adding your
           own methods, and extending the importing existing methods in those
           classes. The most important of those existing methods are discussed
           above in the Core Topics, namely okMessage and executeMsg. However,
           there are many other methods which might be extended to the end
of           altering or enhancing basic aspects of the mud. Those are numerated
           both in the classes you are extending, in           com.planet_ink.coffee_mud.Items.interfaces.Item.java,
and in other           interface files in that directory. Consult the CoffeeMud
java docs           for more information.         </p>

                                                  
      
      <h3><a name="itemlife" id="itemlife">Creating and Destroying Items</a></h3>

                                                  
      
      <p>           As with mobs, the following instructions are supplemental,
 and           unnecessary. Once you have created your new Item, modified
your INI           file, and rebooted your CoffeeMud server, you need only
use the           CREATE and other Archon commands to make use of it. If,
for some           reason, you want to know HOW these commands do their work,
 however,           here it is.         </p>

                                                  
      
      <p>           To bring an Item into existence, an item must have somewhere
 to           exist! Items can belong to either Rooms, as mobs are, or they
 can           belong to mobs themselves. This means that Items actually
have  two           different creation mechanisms. Here is an example of
each, starting           with the creation of an Item in a Room:        
      </p>

                                                  
      
      <pre>Item item = CMClass.getItem( "MyNewItem" );<br />Room room = CMLib.map().getRoom( "Midgaard#3504" );<br /><br />room.addItem( item );<br />room.recoverRoomStats();<br /></pre>

                                                 
      
      <p>           A room is grabbed off the map, and the item is added
to the room           using the <code>addItem()</code> method. Then the room
 recover is called to make           the room react to the addition of the
 item. Now, generic items           require an additional step:         </p>

                                                  
      
      <pre>Item item = CMClass.getItem( "GenItem" );<br />Room room = CMLib.map().getRoom( "Midgaard#3504" );<br /><br />item.text();<br />item.recoverEnvStats();<br />room.addItem( item );<br />room.recoverRoomStats();<br /></pre>

                                                 
      
      <p>           The call to the <code>text()</code> method and the seemingly
 redundant call to           <code>Item.recoverEnvStats()</code> (which we
 know is already in the item           constructor), ensures that some of
the internal structures of the           Generic Item are properly set. Of
course, these items are one-shot           items, meaning that they are not
generated to exist on the map           forever and ever.         </p>

                                                  
      
      <pre>Item item = CMClass.getItem( "MyNewItem" );<br />Room room = CMLib.map().getRoom( "Midgaard#3504" );<br /><br />item.baseEnvStats().setRejuv( 500 ); // 30 minutes rejuvenation time<br />item.recoverEnvStats();<br />room.addItem( item );<br />room.recoverRoomStats();<br />room.startItemRejuv();<br /></pre>

                                                  
      
      <p>           In this case, we wanted the item to be rejuvenating.
That means           that, when the item is removed from the room by a player,
 the item           will reset at some point in the future. If the rejuv
ticks  count is           set to 0, the item will not reset. In the example
above,  the count           is set to 500 so that the item will reset. However,
the            rejuvenation is not actually activated until the room item
rejuvs            are set. This is done with the last method call to    
      <code>startItemRejuv()</code>,  which handles the rejuv resets on all
items in           the room.         </p>

                                                  
      
      <p>           In the previous section, we saw how items are given to
 mobs by           simply calling the <code>addInventory()</code> method,
so this will not be           repeated. Regardless of where or how the item
is created, however,           it is destroyed the same way. With a simple
call to the <code>destroy()</code>           method on the item. Here is
an example of destroying all the items           in a room.         </p>

                                                  
      
      <pre>Room room = CMLib.map().getRoom( "Midgaard#3504" );<br /><br />for( int i = room.numItems() - 1; i &gt;= 0; i-- )<br />{<br />  Item item = room.fetchItem( i );<br />  item.destroy();<br />}<br /></pre>

              <img src="images/clown.jpg" alt="Behaviors" />
                                               
      
      <h2><a name="BEHAVS" id="BEHAVS">Behaviors</a></h2>

                                                  
      
      <p>           A Behavior is defined as a property of an item,     
     mob, exit, or room which takes proactive (as opposed to REactive)  
        steps on behalf of its host. Examples of Behaviors include      
    aggressiveness, mobility, auto-emoting, and scripting.           Behaviors
 import the same           packages mentioned in the first section of this
 document under           Complete Default Import List as well as (in this
 case)           com.planet_ink.coffee_mud.Behaviors.StdBehavior because
our  sample           behavior extends it. Custom           behaviors are
loaded  at boot-time by adding references to them to           the BEHAVIORS
entry  in your coffeemud.ini file. Let's take a look           at a sample
Behavior  and see how they are put together:         </p>

                                                  
      
      <pre>public class Ravenous extends com.planet_ink.coffee_mud.Behaviors.StdBehavior<br />{<br />  public String ID(){ return "Ravenous"; }<br />  public String name(){ return "Ravenous Eater"; }<br /></pre>

                                                  
      
      <p>           Our first step, as seen above, is to make sure we define
 an <code>ID()</code>           method with the classes name, just as we
do  in other CoffeeMud           objects. Notice that the <code>ID()</code>
is  the same as the name of the class.           This is no accident -- this
is required! The next step is to give           the Behavior a name, which
is entirely unimportant to players, but           helpful for Archons.  
      </p>

                                                  
      
      <pre>  protected int canImproveCode(){ return Behavior.CAN_MOBS; }<br />  public long flags(){ return 0; }<br />  public boolean grantsAggressivenessTo( MOB M ){ return false; }<br /></pre>

                                                 
      
      <p>           Next are some important flags that tell the CoffeeMud
 system some           important things about your behavior. The first method 
           (<code>canImproveCode()</code>) tells the           behavior whether
 it is properly used on Mobs, or Items, Rooms,           Exits, or all of
these. In this case, our behavior only affects           mobs. The next method
(<code>flags()</code>) tells the system certain things about           the
behavior by returning values such as Behavior.FLAG_MOBILITY, or         
 Behavior.FLAG_TROUBLEMAKING. The last method           (<code>grantsAggressivenessTo()</code>)
says whether or not this method would           necessary cause the host
mob to attack the mob (M) in the           parameter.         </p>

                                                  
      
      <pre>  public void startBehavior( Environmental forMe )<br />  {}<br /></pre>

                                                  
      
      <p>           The next method, seldom used, is still quite important. 
           startBehavior receives as its parameter the brand new host of this
           behavior. If the behavior instance needs to do any variable or
          other preparation to either the behaving object host (forMe) or
          itself, it should do so here.         </p>

                                                  
      
      <pre>  public String getParms(){ return super.getParms(); }<br />  public void setParms( String parameters )<br />  {<br />    super.setParms( parameters );<br />  }<br /></pre>

                                                 
      
      <p>           These methods, part of the StdBehavior and          
Behavior interface, are shown here just to make you aware of how        
  parameter strings passed to behaviors are accessed. Sometimes         
 prepatory code is also executed inside a setParms method, for          
instance. Normally these methods would not appear in your own           instance
of a Behavior.         </p>

                                                  
      
      <pre>  public boolean tick( Tickable ticking, int tickID )<br />  {<br />    MOB mob = getBehaversMOB( ticking ); // returns mob, if ticking is a mob. Returns mob owner, if ticking is an item<br />    Room room = getBehaversRoom( ticking ); // whatever the ticking object is, this will return its location<br />    if( ( mob == null ) || ( room == null ) || ( tickID != Host.MOB_TICK ) )<br />    {<br />      return super.tick( ticking, tickID );<br />    }<br /></pre>

                                                 
      
      <p>           Now we get to the nitty gritty of the Behaviors work.
 A behavior           gets all or almost all of its work done in a tick method.
 If you           have not read the Core Topic above about the tick method,
 you           should definitely do so! In this example, we call two internal 
           StdBehavior methods to get some important starting information 
          about the behaving object host of the behavior. In this example, 
           our behaving object host will be a mob. However, these methods
 may           still intelligently return Item owners, or Exit rooms if the
 host           is other than a mob. The ticking parameter will always be
the           behaving object host.         </p>

                                                  
      
      <p>           The next line checks to see if our host mob exists, and
 is in a           room. We also check to see if the tickID is the valid
mob  ticking           id. If our host had been an Item, Exit, or Room, this
tickID  would           no longer be Tickable.TICKID_MOB, but would be  
        Tickable.TICKID_ITEM_BEHAVIOR, Tickable.TICKID_ROOM_BEHAVIOR, or
          Tickable.TICKID_EXIT_BEHAVIOR. Since our host, in this case, is
a           Mob, we check for Tickable.TICKID_MOB.         </p>

                                                  
      
      <pre>    if( ( !canActAtAll( mob ) )<br />        ||( !canFreelyBehaveNormal( mob ) )<br />      )<br />    {<br />      return super.tick( ticking, tickID );<br />    }<br /></pre>

                                                  
      
      <p>           Our next step is to call a couple more internal StdBehavior 
           methods. The first (<code>canActAtAll()</code>) returns true if
 the mob is alive,           awake, and mobile. The second method (<code>canFreelyBehaveNormal()</code>) 
           returns true if the mob is not currently in combat, not charmed
 or           following anyone, and is not severely injured. We want our
ravenous            mob to follow this behavior only in the best of health
and mood.          </p>

                                                  
      
      <pre>    Item eatible = null;<br />    for( int i = 0; i &lt; mob.inventorySize(); i++ )<br />    {<br />      Item I = mob.fetchInventory( i );<br />      if( ( I != null ) &amp;&amp; ( I instanceof Food ) )<br />      {<br />        eatible=I;<br />      }<br />    }<br /></pre>

                                                  
      
      <p>           Next, we iterate through the mob's inventory to find
the last           instance of a piece of food.         </p>

                                                  
      
      <pre>    if( eatible != null)<br />    {<br />      room.show( mob, eatible, null, "&lt;S-NAME&gt; gobble(s) up &lt;T-NAMESELF&gt;." );<br />      return true;<br />    }<br /></pre>

                                                 
      
      <p>           If some food was found, the mob will eat it. Now, practically 
           speaking, the mob will quickly devour and use up any and all food 
           which it may have had to begin with. What we decide to do when
 the           mob does NOT have food, therefore, is just as important. 
       </p>

                                                  
      
      <pre>    int randMob = CMLib.dice().roll( 1, room.numInhabitants(), -1 );<br />    MOB mobToHitUp = room.fetchInhabitant( randMob );<br />    if( ( mobToHitUp == null )<br />        ||( mobToHitUp == mob )<br />        ||( CMLib.dice().rollPercentage() &gt; 75 )<br />      )<br />    {<br />      return true;<br />    }<br /></pre>

                                                  
      
      <p>           Since our mob is hungry, and another mob is the most
likely source           of food, we will pick a random inhabitant of the
room, which is not           ourselves, 25% of the time. Otherwise, we just
return true, and try           again on the next tick.         </p>

                                                  
      
      <pre>    int randItem = CMLib.dice().roll( 1, mobToHitUp.inventorySize(), -1 );<br />    Item I = mobToHitUp.fetchInventory( randItem );<br />    if( ( I != null ) &amp;&amp; ( I instanceof Food ) )<br />    {<br />      eatible = I;<br />    }<br /><br />    if( eatible == null )<br />    {<br />      return true;<br />    }<br />    </pre>

                                                  
      
      <p>           Next we will pick a random piece of inventory from that
 mob, and           see if it is food. If not, we return true and try again
 on the next           tick.         </p>

                                                  
      
      <pre>    CMLib.commands().postSay( mob, mobToHitUp, "May I have some of your " + eatible.name() + "?" , false, false );<br /><br />    return true;<br />  }<br /></pre>

                                                 
      
      <p>           And lastly, since we have picked a random mob in the
room, and seen           that he has food, we will ask him for it! If it's
a player, then           perhaps he might even give us some. If we are given
food, we will           eat it on the next tick for sure!         </p>

                                                  
      
      <pre>  public void executeMsg( Environmental affecting, CMMsg msg )<br />  {}<br /><br />  public boolean okMessage( Environmental oking, CMMsg msg )<br />  {<br />    return true;<br />  }<br />}<br /></pre>

                                                 
      
      <p>           The above two methods are shown here just to remind you
 that,           although a behavior's PRIMARY purpose is to be proactive
in a tick           method, a behavior also has the ability to preview and
respond to           messages affecting the host behaving object. That object
will           always be identified in the affecting and oking parameters
           respectively. If these two methods mean nothing to you, you should 
           definitely go back and read the Core Topic on message passing. 
        </p>

               <img src="images/cloak.jpg" alt="Character Classes" />
                                               
      
      <h2><a name="CLASSES" id="CLASSES">Character Classes</a></h2>

                                                  
      
      <p>           A Character Class, in CoffeeMud, is the carreer     
     being followed by the player. Armor and weapon choices, skill and  
        spell access, as well as score advancements all depend on the   
       Character Class chosen by the player. Thankfully, despite all this 
           weighty responsibility, Character Classes are not difficult to 
          code. CharClasses import           the same packages mentioned in
the first section of this document           under Complete Default Import
 List as well as (in this case)           com.planet_ink.coffee_mud.CharClasses.StdCharClass
 because our           sample class extends it. Your           custom classes
 need to be listed in your coffeemud.ini file under           the CHARCLASSES
 entry. Aside from making custom classes, you can           also extend an
 existing class, return an identical <code>ID()</code> string, and      
    then list it at the end of the aforementioned entry in the          
coffeemud.ini  file. Now, let's take a look at a simple one           here:
        </p>

                                                  
      
      <pre>public class NormalGuy extends com.planet_ink.coffee_mud.CharClasses.StdCharClass<br />{<br /></pre>

                                                 
      
      <p>           Our Normal Guy character class will define all of the
 basic           elements of a filled-out character class.         </p>

                                                  
      
      <pre>  public String ID()<br />  {<br />    return "NormalGuy";<br />  }<br /><br />  public String baseClass()<br />  {<br />    return ID();<br />  }<br /></pre>

                                                  
      
      <p>           The first methods above are the unique Character Class
 ID and the           Base Class ID of the class. The Class ID must be a
unique            identifier. The <code>baseClass()</code> method takes a
bit of  explaining. If your           CoffeeMud system is using the default
SubClassing  system, the           baseClass will define which classes may
be switched  between by a           player, as well as which classes are
available to choose from when           a new player is created. Fighter,
Monk, Paladin, Ranger, and           Barbarian, for instance, all have a
baseClass of "Fighter".  This           means that the Fighter class is one
of the classes which may  be           chosen by a new player (since it's
      <code>ID()</code> and <code>baseClass()</code>  are the           same),
and that any of the baseClass() "Fighter" classes  may switch           amongst
each other. If your CoffeeMud system is using  the           multi-class
or single classing system, this method is irrelevant.          </p>

                                                  
      
      <pre>  public String name()<br />  {<br />    return "Normal Guy";<br />  }<br /><br />  public String name( int classLevel )<br />  {<br />    return name();<br />  }<br /></pre>

                                                  
      
      <p>           Our next method, <code>name()</code>, is the default
displayable name of your           class. The next method <code>name( int
classLevel )</code> is, in this case,           simply returning the default
name again. However, if you like, your           character classes may have
different names at different class           levels. Simply check the classLevel
and return a different string!           As standard practice, however, class
 level 0 should always return           the default name. Remember that Class
 Levels are different from           Player Levels. A Player may, in a multi-classing
 system, have           numerous levels in numerous classes. The Class Level
 represents how           many levels the player has gained in this character
 class ONLY!         </p>

                                                  
      
      <pre>  protected String[] names = null;<br /><br />  public String[] nameSet()<br />  {<br />    if( names != null )<br />    {<br />      return names;<br />    }<br /><br />    names = new String[1];<br />    names[0] = name();<br />    return names;<br />  }<br /></pre>

                                                 
      
      <p>           The <code>nameSet()</code> method really only needs to
 be extended and           re-implemented when there are more than 1 available
 names for your           class. Its purpose is to return a string list of
 all the names that           this class may go by. As you can see from the
 above code, by           default, the StdCharClass will nicely handle classes
 with just one           name. However, the code above will need to be altered
 in your own           character class if you choose to make one with multiple
 names.         </p>

                                                  
      
      <pre>  public int getHPDivisor()<br />  {<br />    return 3;<br />  }<br /><br />  public int getHPDice()<br />  {<br />    return 1;<br />  }<br /><br />  public int getHPDie()<br />  {<br />    return 6;<br />  }<br /></pre>

                                                 
      
      <p>           Next come the hit point ranges. When a player with this
 class gains           a level,these values will determine hit points gained
 based on           class and constitution.         </p>

                                                  
      
      <pre>  public int getPracsFirstLevel()<br />  {<br />    return 3;<br />  }<br /><br />  public int getTrainsFirstLevel()<br />  {<br />    return 1;<br />  }<br /><br />  public int getBonusPracLevel()<br />  {<br />    return 0;<br />  }<br /></pre>

                                                 
      
      <p>           The next two methods define the starting Training and
 Practice           points for this Character Class. The BonusPracLevel method
 tells us           how many bonus practices (above the number determined
the WISDOM/4           formula) which the player will receive every level.
         </p>

                                                  
      
      <pre>  public int getAttackAttribute()<br />  {<br />    return CharStats.STAT_STRENGTH;<br />  }<br /><br />  public int getBonusAttackLevel()<br />  {<br />    return 1;<br />  }<br /></pre>

                                                 
      
      <p>           And here is an method defining which of the 6 primary
 Character           Attributes (Strength, Intelligence, Wisdom, Dexterity, 
           Constitution, or Charisma) are used to determine any attack bonuses 
           whenever the player gains a level. Usually this is Strength. The 
           number of bonus attack points received by a player when a level
 is           gained is determined by dividing the players score in this
          attribute by 6, and then adding the value returned by         
       <code>getBonusAttackLevel()</code>.         </p>

                                                  
      
      <pre>  public int getManaDivisor()<br />  {<br />    return 3;<br />  }<br /><br />  public int getManaDice()<br />  {<br />    return 1;<br />  }<br /><br />  public int getManaDie()<br />  {<br />    return 6;<br />  }<br /></pre>

                                                  
      
      <p>           These methods determines how much mana a player receives
 when they           gain a level in this class.         </p>

                                                  
      
      <pre>  public int getLevelsPerBonusDamage()<br />  {<br />    return 25;<br />  }<br /></pre>

                                                 
      
      <p>           This score determines how many levels a player must make,
 in this           class, before they will gain a bonus point of damage to
 all damage           rolls.         </p>

                                                  
      
      <pre>  public int getMovementMultiplier()<br />  {<br />    return 2;<br />  }<br /></pre>

                                                  
      
      <p>           And lastly for our scores, this method will determine
 how many           movement points a player receives when they gain a level.
 The           formula is determined by dividing the player's strength score
 by 9,           and multiplying the result by this value.         </p>

                                                  
      
      <pre>  public int allowedArmorLevel()<br />  {<br />    return CharClass.ARMOR_CLOTH;<br />  }<br /></pre>

                                                 
      
      <p>           The CharClass interface defines a method called "armorCheck"
 which           returns true if the player is in compliance with armor 
         requirements. This method does its work by checking the        
        <code>allowedArmorLevel()</code> method. This method returns an equate 
defined in           the CharClass interface which may specify ANY armor, 
CLOTH level,            armor, LEATHER (or worse) armor, or NON-METAL armor. 
You should            check the CharClass interface for any other ARMOR_* 
definitions            which may be added from time to time.         </p>

                                                  
      
      <pre>  public int allowedArmorLevel()<br />  {<br />    return CharClass.ARMOR_CLOTH;<br />  }<br /><br />  protected int requiredArmorSourceMinor()<br />  {<br />    return -1;<br />  }<br /><br />  protected String armorFailMessage()<br />  {<br />    return "&lt;s-name&gt; fumble(s) &lt;s-his-her&gt; &lt;skill&gt; due to &lt;s-his-her&gt; armor!";<br />  }<br /></pre>

                                                  
      
      <p>           The The StdCharClass will automaticallyy enforce armor
 requirements           whenever a class skill is used, provided these methods
 are defined.           The <code>allowedArmorLevel()</code> method returns
 an equate defined in the           CharClass interface which may specify
ANY armor, CLOTH level,           armor, LEATHER (or worse) armor, METAL-ONLY,
 or NON-METAL armor.           You should check the CharClass interface for
 any other ARMOR_*           definitions which may be added from time to
time.          </p>

                                                  
      
      <p>           While the <code>armorFailMessage()</code> method is pretty
 self explanatory, the           requiredArmorSourceMinor may not be. The
later method returns the           MINOR code of the SOURCE code of the message
 generating the skill           use. Typically this method will either return
 -1 for non spell           casters, or CMMsg.TYP_CAST_SPELL for spell casters.
 See the Core           Topics for more information on what the heck a source
 code of a           message might be.         </p>

                                                  
      
      <pre>  public int allowedWeaponLevel()<br />  {<br />    return CharClass.WEAPONS_THIEFLIKE;<br />  }<br /><br />  private HashSet disallowedWeapons = buildDisallowedWeaponClasses();<br />  public HashSet disallowedWeaponClasses( MOB mob )<br />  {<br />    return disallowedWeapons;<br />  }<br /><br />  private HashSet requiredWeaponMaterials = buildRequiredWeaponMaterials();<br />  public HashSet requiredWeaponMaterials()<br />  {<br />    return requiredWeaponMaterials;<br />  }<br /></pre>

                                                 
      
      <p>           The StdCharClass will automaticallyy enforce weapon restrictions 
           whenever a weapon attack is made, provided these methods are  
        defined. The <code>allowedWeaponLevel()</code> method returns an
 equate defined           in the CharClass interface which may specify ANY
 weapons, DAGGER           only, THIEF-like weapons, WOODEN weapons, and
several  others. You           should check the CharClass interface for other
WEAPONS_*            definitions which may be added from time to time.  
      </p>

                                                  
      
      <p>           The <code>disallowedWeaponClasses( MOB mob )</code> and
       <code>requiredWeaponMaterials()</code>           methods return HashSet
 objects which, due to the method calls in           StdCharClass seen above,
 are totally derivative of the value you           already put in <code>allowedWeaponLevel()</code>.
 In other words, so long as you           include the <code>allowedWeaponLevel()</code>
 method, you should also include           those next four methods, exactly
 as you see them.         </p>

                                                  
      
      <pre>  public int availabilityCode()<br />  {<br />    return Area.THEME_FANTASY;<br />  }<br /></pre>

                                                 
      
      <p>           The method <code>availabilityCode()</code> defines how
 players can access this           race. Possible values for this constant
 include:           'Area.THEME_FANTASY' (makes the class available for players
 to           choose when creating fantasy characters),           'Area.THEME_FANTASY|Area.THEME_SKILLONLYMASK'
 (makes the class           available to spells or Skills, but not for player
 creation), or '0'           (the class is not available to spells or for
player creation.)         </p>

                                                  
      
      <pre>  public NormalGuy()<br />  {<br />    super();<br />    maxStat[CharStats.STAT_CHARISMA] = 10;<br />  }<br /><br />  public void initializeClass()<br />  {<br />      CMLib.ableMapper().addCharAbilityMapping( ID(),<br />                                                   1,<br />                                                   "Skill_Write",<br />                                                   50,<br />                                                   "",<br />                                                   true,<br />                                                   false,<br />                                                   new Vector(),<br />                                                   ""<br />                                                  );<br /><br />      CMLib.ableMapper().addCharAbilityMapping( ID(),<br />                                                   1,<br />                                                   "Skill_Recall",<br />                                                   0,<br />                                                   "",<br />                                                   true,<br />                                                   false,<br />                                                   new Vector(),<br />                                                   ""<br />                                                 );<br /><br />      CMLib.ableMapper().addCharAbilityMapping( ID(),<br />                                                   1,<br />                                                   "Skill_Climb",<br />                                                   0,<br />                                                   "",<br />                                                   true,<br />                                                   false,<br />                                                   new Vector(),<br />                                                   ""<br />                                                 );<br /><br />      CMLib.ableMapper().addCharAbilityMapping(<br />        ID(),         // class/race to assign the skill to<br />        1,            // level the skill is qualified for<br />        "Skill_Swim", // the java ID of the ability to qualify for<br />        0,            // default proficiency to give after gaining<br />        "",           // any misc parameters to pass to the Skill_Swim skill<br />        false,        // true for the class to gain automatically, false to qualify<br />        false,        // whether this skill is unlisted for this class<br />        CMParms.parseSemicolons(<br />                                 "Skill_Climb;Skill_Write",<br />                                 true<br />                               ), //  list of skills required to gain this one<br />        "-LOCALE +UNDERWATER" // mask to apply to class members wanting this skill<br />      );<br />    }<br />  }<br />  </pre>

                                                 
      
      <p>           And now, after a few methods to flag our construction,
 work, we           come to our constructor! The Constructor for every character
 class defines any special           maximums for the primary attributes.
This is done by setting the           appropriate value in the <code>maxStat[]</code>
 array for the class. By default,           18 is the maximum score for all
 primary attributes.         </p>

                                                  
      
      <p>           The second method is found in all CMObject, and is the
 initializeClass() method. &nbsp;This method is called after all classes
have  been loaded, but before the map is loaded. &nbsp;The method is called
once  on every class, but only during initialization. &nbsp;In Character
classes,  it establishes the qualifying and bonus skills for the        
  class. This  is done through repeated calls to one of the several     
     <code>CMLib.ableMapper().addCharAbilityMapping()</code>  methods. The
first           parameter of the method is the <code>ID()</code>  value of
the Character Class           itself, followed by the level at which  this
class gains or           qualifies for the skill. Next is the <code>ID()</code>
 value of the Ability to           allow this class to qualify for, followed
 by the default           proficiency which this class displays in the skill
 (typically 0).           The next parameter are any special parameters that
 affects the way           this class uses the skill, followed by a boolean
 which establishes           whether the player will receive this skill automaticallyy
 when he or           she gains the appropriate level, or whether they merely
 qualify for           the skill. The next parameter, almost always false,
 determines           whether the skill is "secret" for this class. Secret
 skills are           qualified for (or gained), but do not appear on Qualify
 lists,           Class information, or Help files. Secret skills are never
 taught by           Guildmasters (MOBTeachers) unless specifically told
to.  The next           parameter is a Vector of Strings, representing a
list of skills           which must be known by this class before he can
learn the skill in           question. The last parameter is a String representing
a mask which           must be passed by the person who wants to gain this
skill.         </p>

                                                  
      
      <pre>  public Vector getSecurityGroups( int classLevel )<br />  {<br />    if( classLevel &gt; 1000 )<br />    {<br />      Vector V = new Vector();<br />      V.addElement( "ABOVELAW" );<br />      V.addElement( "LISTADMIN" );<br />      return V;<br />    }<br />    else<br />    {<br />      return new Vector();<br />    }<br />  }<br /></pre>

                                                 
      
      <p>           The purpose of this method is to allow you to assign
CoffeeMud           Security Flags or CoffeeMud Security Groups to your players
based           on their Character Class and Character Class Level. This
is a           rather obscure feature that is really only meant for special
           Character Classes you may design for your admins and builders.
Your           player <code>getSecurityGroups()</code> methods will normally
just return an           empty Vector regardless of classLevel. In this case,
however, we           are demonstrating how a player who gains 1001 levels
in our           NormalGuy Class will become immune to the CoffeeMud legal
system           (ABOVELAW flag) and gain access to the Archon LIST command
           (LISTADMIN flag). See the Archon's Guide for more information
on            the CoffeeMud security system.         </p>

                                                  
      
      <pre>  public String statQualifications()<br />  {<br />    return "Warm body, breathe.";<br />  }<br /><br />  public boolean qualifiesForThisClass( MOB mob, boolean quiet )<br />  {<br />    if( !CMLib.flags().canBreathe( mob ) )<br />    {<br />      if( !quiet )<br />      {<br />        mob.tell( "You need to be breathing to be a normal guy." );<br />      }<br /><br />      return false;<br />    }<br /><br />    return super.qualifiesForThisClass( mob, quiet );<br />  }<br /></pre>

                                                 
      
      <p>           The next method is a display string, for the benefit
of some of the           web macros, which describes in plain english any
attribute, or           other numeric qualifications to become this class.
The           <code>qualifiesForThisClass()</code> method would actually
check and enforce the           qualifications described by <code>statQualifications()</code>.
 In our example           above, there are no stat qualifications, only a
check to see if the           idiot is still breathing. Also note that a
quiet boolean exists to           allow qualifications to be checked without
sending any messages to           the player in question.         </p>

                                                  
      
      <pre>  public String otherBonuses()<br />  {<br />    return "Receives a mortgage, but no home.";<br />  }<br /></pre>

                                                 
      
      <p>           The next method, like <code>statQualifications above()</code>,
 is for the benefit           of the web macros. It describes any special
bonuses received due to           being this class.         </p>

                                                  
      
      <pre>  public Vector outfit( MOB myChar )<br />  {<br />    if( outfitChoices == null )<br />    {<br />      outfitChoices = new Vector();<br />      Weapon w = (Weapon)CMClass.getWeapon( "a mortgage" );<br />      outfitChoices.addElement( w );<br />    }<br />    return outfitChoices;<br />  }<br /></pre>

                                                 
      
      <p>           The outfit method should return a Vector of any Class-Specific
 Item           object equipment they may need. Clothing and so forth is
actually            covered by Races.         </p>

                                                  
      
      <pre>  public void grantAbilities( MOB mob, boolean isBorrowedClass )<br />  {<br />    super.grantAbilities( mob, isBorrowedClass );<br />    if( mob.isMonster() )<br />    {<br />      Vector V = CMLib.abilityMapping().getUpToLevelListings( ID(),<br />        mob.charStats().getClassLevel( ID() ),<br />        false,<br />        false<br />      );<br /><br />      for( Enumeration a = V.elements(); a.hasMoreElements(); )<br />      {<br />        Ability A = CMClass.getAbility( (String)a.nextElement() );<br />        if( ( A != null )<br />            &amp;&amp; ( ( A.classificationCode()&amp;Ability.ALL_ACODES) != Ability.ACODE_COMMON_SKILL )<br />            &amp;&amp; ( !CMLib.abilityMapping().getDefaultGain( ID(), true, A.ID() ) )<br />          )<br />        {<br />          giveMobAbility( mob,<br />            A,<br />            CMLib.abilityMapping().getDefaultproficiency( ID(), true, A.ID() ),<br />            CMLib.abilityMapping().getDefaultParm( ID(), true, A.ID() ),<br />            isBorrowedClass<br />          );<br />        }<br />      }<br />    }<br />  }<br /></pre>

                                                 
      
      <p>           This important method is called whenever a player gains
 a level in           this class, or when an NPC mob is being "outfitted"
with this class           via one of the following Behaviors: CombatAbilities,
 Fighterness,           Druidness, Bardness, Clericness, Thiefness, Mageness. 
         </p>

                                                  
      
      <p>           The <code>grantAbilities()</code> method has the important
 job of making sure           that players receive their autogained skills
 or any other options           skills when they level. The StdCharClass
version  of grantAbilities           (called by <code>super.grantAbilities(...)</code>)
 takes care of any autogained           skills up to the player or mobs current
 level in the class. Each           char class which extends this, however,
 needs to take care of any           skills or abilities for NPC mobs which
 are not automaticallyy           gained. This is to make up for the fact
that npc mobs will not be           lining up at your guildmasters to spend
their trains on skills they           merely qualify for. In the sample code
above, we give the mobs           every skill the class qualifies for up
to the mobs level in the           class, except for any common skills. Those
would still need to be           given by hand to each mob.         </p>

                                                  
      
      <pre>  public boolean okMessage( Environmental myHost, CMMsg msg )<br />  {<br />    if( !( myHost instanceof MOB ) )<br />    {<br />      return super.okMessage( myHost, msg );<br />    }<br /><br />    MOB myChar = (MOB)myHost;<br /><br />    if( ( msg.amITarget( myChar ) )<br />        &amp;&amp;( msg.targetMinor() == CMMsg.TYP_DAMAGE )<br />        &amp;&amp;( ( msg.sourceMinor() == CMMsg.TYP_COLD )<br />                    || ( msg.sourceMinor() == CMMsg.TYP_WATER )<br />                  )<br />      )<br />    {<br />      int recovery = myChar.charStats().getClassLevel( this );<br />      msg.setValue( msg.value() - recovery );<br />    }<br />    else if( ( msg.amITarget( myChar ) )<br />             &amp;&amp;( msg.targetMinor() == CMMsg.TYP_DAMAGE )<br />             &amp;&amp;( msg.sourceMinor() == CMMsg.TYP_FIRE )<br />           )<br />    {<br />      int recovery = msg.value();<br />      msg.setValue( msg.value() + recovery );<br />    }<br /><br />    return super.okMessage( myChar, msg );<br />  }<br />}<br /></pre>

                                                 
      
      <p>           And lastly, just as I'm sure you were wondering how useful
 those           three Core Topics above would really be, we see them in
active  use.           Some classes contain methods such as these to enforce
some  of the           benefits for the class. In the <code>okMessage()</code>
method, which we discussed           in the first Core Topic, we see messages
messages containing the           type of damage taken by the player being
intercepted. TYP_DAMAGE           messages always have their damage amounts
stored in the <code>.value()</code>           method of a message, so it
is these values which are modified,           based on the type of damage
taken.               </p>

                                                  
      
      <p>           And not least, although we won't go into it in detail
 here, there           are two other methods which may be of use for the
advanced            Character Class programmer. They are the level and unLevel
methods.            These methods are called when a player gains or loses
          (respectively) a level in the class. If there are any extra skills
          or bonus scores the player may wish to gain and lose with levels,
          that would be the place for such code. Also, in some cases (Mages 
           and Clerics come to mind), the gaining of qualifying skills may
 be           somewhat complex. In those cases, overriding the gainAbilities 
           method may be in order. Check the Mage and Cleric classes for more
           information.         </p>

               <img src="images/dragon.jpg" alt="Races" />
                                               
      
      <h2><a name="RACES" id="RACES">Races</a></h2>

                                                  
      
      <p>           A Race, in CoffeeMud, contributes very little to    
      functionality, but quite a bit to the role playing and other "soft" 
           aspects of the game.. For this reason, everyone is encouraged to
           code as many races as humanly possible. The more, the better! 
         Races import the same           packages mentioned in the first
 section of this document under           Complete Default Import List as
well as (in this case)           com.planet_ink.coffee_mud.Races.StdRace
because our sample class           extends it.           Your custom races
need to be listed in your coffeemud.ini           file under the RACES entry.
Aside from making custom race classes,           you can also extend an existing
 race class, return an identical           ID() string, and then list it
at  the end of the aforementioned           entry in the coffeemud.ini file.
Now,           let's take a look at a simple one here:         </p>

                                                  
      
      <pre>public class Grumbler extends com.planet_ink.coffee_mud.Races.StdRace<br />{<br /></pre>

                                                 
      
      <p>           Our Grumbler race will define all of the basic elements
 of a           filled-out race.         </p>

                                                  
      
      <pre>  public String ID()<br />  {<br />    return "Grumbler";<br />  }<br /><br />  public String name()<br />  {<br />    return "Grumbler";<br />  }<br /><br />  public String racialCategory()<br />  {<br />    return "Grumbler";<br />  }<br /><br />  protected static Vector resources = new Vector();<br /><br />  public int availabilityCode()<br />  {<br />    return Area.THEME_FANTASY;<br />  }<br /></pre>

                                                 
      
      <p>           The first methods return the unique ID of the Race (which
 must           always match the java/class file name) and the <code>name()</code>
 method is the           displayable name of the Race. The third method is
 very important,           as it defines the category into which this race
 falls. There is no           hard rule to determine when a new category
should  be created versus           using an old one. Some of the uses of
racial categories include the           Ranger Favored Enemy skill, as well
as most of the race-based           restrictions on doors and with shopkeepers.
In many ways, the           racial category is more important than the name
of the race itself,           if functionality is considered.         </p>

                                                  
      
      <p>           The last method list above, availabilityCode, defines
 how players           can access this race. Possible values for this constant
 include:           'Area.THEME_FANTASY' (makes the race available for players
 to           choose when creating fantasy characters),           'Area.THEME_FANTASY|Area.THEME_SKILLONLYMASK'
 (makes the race           available to spells such as Polymorph or Wish,
but not for player           creation), or '0' (the race is not available
to spells or for           player creation.)         </p>

                                                  
      
      <pre>  protected int shortestMale()<br />  {<br />    return 84;<br />  }<br /><br />  protected int shortestFemale()<br />  {<br />    return 78;<br />  }<br /><br />  protected int heightVariance()<br />  {<br />    return 80;<br />  }<br /><br />  protected int lightestWeight()<br />  {<br />    return 2000;<br />  }<br /><br />  protected int weightVariance()<br />  {<br />    return 500;<br />  }<br /></pre>

                                                 
      
      <p>           These methods, as you might have guessed, establish parameters
 for           the base height and weight of a typical monster of this type.
 A           random number from 0-<code>heightVariance()</code> will be added
 to the           <code>shortedMale()</code>/<code>shortestFemale()</code>
 value to determine height, while a           random number from 0-<code>weightVariance()</code>
 will be added to <code>lightestWeight()</code>           to determine that. 
         </p>

                                                  
      
      <pre>  protected long forbiddenWornBits()<br />  {<br />    return Item.WORN_WIELD<br />           |Item.WORN_WAIST<br />           |Item.WORN_ABOUT_BODY<br />           |Item.WORN_FEET<br />           |Item.WORN_HANDS;<br />  }<br /></pre>

                                                  
      
      <p>           This method establishes where a creature of this type
 may NOT wear           something. In this case, we forbid any wielded items,
 or anything           worn around the waist, on hands or feet, or about
the  body.           Anywhere else is fine. Return 0 if you do not wish any
restrictions            on wearing.         </p>

                                                  
      
      <pre>  private static final int[] parts = {0,2,2,1,1,0,0,1,4,4,1,0,1,1,1,2};<br />  public int[] bodyMask()<br />  {<br />    return parts;<br />  }<br /></pre>

                                                 
      
      <p>           The <code>bodyMask()</code> method defines and returns
 an array of integers which           defines the types and number of particular
 body parts normally           retained by the race. Each position in the
array is defined by the           equates BODY_ in the Race interface. These
equates are (starting           from 0): BODY_ANTENEA, BODY_EYE, BODY_EAR,
BODY_HEAD,           BODY_NECK, BODY_ARM, BODY_HAND, BODY_TORSO, BODY_LEG,
BODY_FOOT,           BODY_NOSE, BODY_GILL, BODY_MOUTH, BODY_WAIST, BODY_TAIL,
           BODY_WING. Remember that these can be found in the Race      
    interface for you to reference. In the above example, we find no    
      antenea, 2 eyes, 2 ears, a head, neck, no arms or hands, a torso, 4
          legs, 4 feet, a nose, but no gill, and then a mouth, waist, tail,
           and 2 wings.         </p>

                                                  
      
      <pre>  private String[] racialAbilityNames = { "Skill_Trip", "Fighter_Whomp" };<br />  private int[] racialAbilityLevels = { 1, 3 };<br />  private int[] racialAbilityProficiencies = { 75, 50 };<br />  private boolean[] racialAbilityQuals = { false, false };<br /><br />  protected String[] racialAbilityNames()<br />  {<br />    return null;<br />  }<br /><br />  protected int[] racialAbilityLevels()<br />  {<br />    return null;<br />  }<br /><br />  protected int[] racialAbilityProficiencies()<br />  {<br />    return null;<br />  }<br /><br />  protected boolean[] racialAbilityQuals()<br />  {<br />    return null;<br />  }<br /><br />  public Vector racialAbilities( MOB mob )<br />  {<br />    Vector V = super.racialAbilities( mob );<br />    return V;<br />  }<br /></pre>

                                                 
      
      <p>           Our next section here deals with Racial Abilities, which
 are           defined as follows: A racial ability is a skill that has a
command           word, and is not autoinvoked. A racial ability may be qualified
 for           or automaticallyy gained. If the skill is qualified for, then
 upon           reaching the designated player level, the player may GAIN
the           skill, and will have a default proficiency as designated. If
the           skill is not qualified for, then it is automaticallyy gained.
This           means that all mobs or players of this race, who have obtained
the           necessary player level, will have access to the use of the
skill as           if they had learned it, and at the proficiency designated.
Racial           Abilities are available to any mob or player of this race,
even           those affected by Shape Shift, Polymorph, or similar skills.
         </p>

                                                  
      
      <p>           The first four methods define these skills. The data
in all four           variables are ordered with relative to each other.
The           <code>racialAbilityNames</code> is a list of the Ability class
ID. The           <code>racialAbilityLevels</code> is the level at which
the skill is qualified           for or gained. The <code>racialAbilityProficiencies()</code>
 is the proficiency           of skills automaticallyy gained. The <code>racialAbilityQuals()</code>
 tells           whether or not the skill is automaticallyy gained (false)
 or is only           qualified for (true).         </p>

                                                  
      
      <p>           The method above (<code>racialAbilities()</code>) will
 return a Vector of Ability           objects, with proficiency already set,
 appropriate to the mob           passed in. This vector should consist only
 of automaticallyy gained           abilities appropriate to the level of
the mob. If the four           variables are set properly, the programmer
will not need to           override the method from StdRace unless there
other gender-based or           other special qualifications for skills not
defined by those four           variables.         </p>

                                                  
      
      <pre>  public Vector outfit( MOB myChar )<br />  {<br />    if( outfitChoices == null )<br />    {<br />      outfitChoices = new Vector();<br />      Weapon w = (Weapon)CMClass.getItem( "GenPants" );<br />      outfitChoices.addElement( w );<br />    }<br /><br />    return outfitChoices;<br />  }<br /></pre>

                                                 
      
      <p>           The outfit method should return a Vector of any Race-Specific
 Item           object equipment they may need.         </p>

                                          
      
      <pre>  private String[] culturalAbilityNames = { "Dwarven", "Mining" };<br />  private int[] culturalAbilityProficiencies = { 100, 50 };<br /><br />  public String[] culturalAbilityNames()<br />  {<br />    return culturalAbilityNames;<br />  }<br /><br />  public int[] culturalAbilityProficiencies()<br />  {<br />    return culturalAbilityProficiencies;<br />  }<br /></pre>

                                                 
      
      <p>           Cultural Abilities are defined as those skills which
a mob or           player of this race would know through upbringing in the
 culture of           that race, such as language. Players Shape Shifted
or  Polymorphed           into the race, since they did not grow up in the
culture,  would not           have automatic access to these skills per se.
These two  methods are           defined similarly to the Racial Abilities
above.         </p>

                                                  
      
      <pre>  public void affectEnvStats( Environmental affected, EnvStats affectableStats )<br />  {<br />    super.affectEnvStats( affected, affectableStats );<br /><br />    affectableStats.setSensesMask(<br />      affectableStats.sensesMask() | EnvStats.CAN_SEE_INFRARED<br />    );<br />  }<br /></pre>

                                                 
      
      <p>           This sample of the <code>affectEnvStats()</code> method
 we discussed in the Core           Topics above makes sure that all creatures
 of this race can see in           the infrared spectrum.         </p>

                                                  
      
      <pre>  public void affectCharStats( MOB affectedMOB, CharStats affectableStats )<br />  {<br />    super.affectCharStats( affectedMOB, affectableStats );<br />    affectableStats.setStat( CharStats.STAT_STRENGTH, 15 );<br />    affectableStats.setStat( CharStats.STAT_DEXTERITY, 25 );<br />    affectableStats.setStat( CharStats.STAT_INTELLIGENCE, 5 );<br />  }<br /></pre>

                                                 
      
      <p>           This sample of the affectCharStats method we discussed
 in the Core           Topics above establishes a base strength, dexterity,
 and           intelligence for all creatures of this race. As this is the
 ONLY           way to modify a MOBs stats short of magical equipment, it
should be           used with care!         </p>

                                                 
      
      <pre>  public void startRacing( MOB mob, boolean verifyOnly )<br />  {<br />    super.startRacing( mob, verifyOnly );<br />  }<br /></pre>

                                                 
      
      <p>           startRacing is called whenever a player of this race
logs on, or a           mob of this race is created. If there are any special
properties of           the mob or player which must be set due to their
being this race,           this would be the appropriate method in which
to do so. This method           is not called for Polymorph, Shape Shift,
or similar changes in           race, but only for those whose permanent
race is this one.         </p>

                                                  
      
      <pre>  public Weapon myNaturalWeapon()<br />  {<br />    if( naturalWeapon == null )<br />    {<br />      naturalWeapon = CMClass.getWeapon( "StdWeapon" );<br />      naturalWeapon.setName( "huge claws" );<br />      naturalWeapon.setWeaponType( Weapon.TYPE_PIERCING );<br />    }<br /><br />    return naturalWeapon;<br />  }<br /></pre>

                                                 
      
      <p>           This method allows you to create (see item creation above)
 a           special weapon to serve the creature whenever they are not wielding 
           something. Since our Grumbler cannot wield weapons anyway, it is
           important to give them some big piercing claws.         </p>

                                                  
      
      <pre>  public String healthText( MOB viewer, MOB mob )<br />  {<br />    double pct = ( CMath.div( mob.curState().getHitPoints(),<br />                              mob.maxState().getHitPoints()<br />                            )<br />                 );<br /><br />    if( pct &lt; .10 )<br />    {<br />      return "^r" + mob.displayName(viewer) + "^ris raging in bloody pain!^N";<br />    }<br />    else if( pct &lt; .20 )<br />    {<br />      return "^r" + mob.displayName(viewer) + "^ris covered in blood.^N";<br />    }<br />    else if( pct &lt; .30 )<br />    {<br />      return "^r" + mob.displayName(viewer) + "^r is bleeding badly from lots of wounds.^N";<br />    }<br />    else if( pct &lt; .50 )<br />    {<br />      return "^y" + mob.displayName(viewer) + "^y has some bloody wounds and gashed scales.^N";<br />    }<br />    else if( pct &lt; .60 )<br />    {<br />      return "^p" + mob.displayName(viewer) + "^p has a few bloody wounds.^N";<br />    }<br />    else if( pct &lt; .70 )<br />    {<br />      return "^p" + mob.displayName(viewer) + "^p is cut and bruised heavily.^N";<br />    }<br />    else if( pct &lt; .90 )<br />    {<br />      return "^g" + mob.displayName(viewer) + "^g has a few bruises and scratched scales.^N";<br />    }<br />    else if( pct &lt; .99 )<br />    {<br />      return "^g" + mob.displayName(viewer) + "^g has a few small bruises.^N";<br />    }<br />    else<br />    {<br />      return "^c" + mob.displayName(viewer) + "^c is in perfect health.^N";\<br />    }<br />  }<br /></pre>

                                                 
      
      <p>           Although the programmer is welcome to skip the above
method and use           the defaults from the StdRace class, this allows
you to set special           health messages for creatures of this type.
        </p>

                                                
      
      <pre>  public Vector myResources()<br />  {<br />    synchronized( resources )<br />    {<br />      if( resources.size() == 0 )<br />      {<br />        resources.addElement( makeResource( "a " + name().toLowerCase() + "claw",<br />                                            RawMaterial.RESOURCE_BONE<br />                                          )<br />                            );<br /><br />        for( int i = 0; i &lt; 10; i++ )<br />        {<br />          resources.addElement( makeResource( "a strip of " + name().toLowerCase() + " hide",<br />                                              RawMaterial.RESOURCE_SCALES<br />                                            )<br />                              );<br />        }<br /><br />        for( int i = 0; i &lt; 10; i++ )<br />        {<br />          resources.addElement( makeResource( "a pound of " + name().toLowerCase() + " meat",<br />                                              RawMaterial.RESOURCE_MEAT<br />                                            )<br />                              );<br />        }<br /><br />        resources.addElement( makeResource( "some " + name().toLowerCase() + " blood",<br />                                            RawMaterial.RESOURCE_BLOOD<br />                                          )<br />                            );<br />      }<br />    }<br /><br />    return resources;<br />  }<br />}<br /></pre>

                                                 
      
      <p>           The above method allows you to determine what sorts of
 materials           are gotten from this creature whenever the dead corpse
 is           Butchered.         </p>

                                                  
      
      <p>           Now, in addition to the methods above which are     
     good to include in your custom races, there are also several       
   methods which are not normally extended or overridden, but which is  
        may be good to do so in special cases. These methods include    
      <code>public void level( MOB mob )</code>, which is called        
  whenever a player of that race gains a level, public void           <code>agingAffects(
 MOB mob, CharStats baseStats, CharStats charStats )</code>           , which
 is called to           enforce how aging effects this race, and <code>public
 DeadBody           getCorpseContainer( MOB mob, Room room )</code>, which
 is           called to create a corpse for members of           this race. 
         </p>

               <img src="images/chomper.jpg" alt="Exits" />
                                               
      
      <h2><a name="EXITS" id="EXITS">Exits</a></h2>

                                                  
      
      <p>           Exits are the connecting points between two rooms, and
 tend to be           rather simple. If two rooms, A &amp; B, are connected
 to each           other, there are always two exits associated with that
connection.           One from room A to room B, and the other from room
B to room A.         </p>

                                                  
      
      <p>           Exits import the same packages mentioned in the first
 section of           this document under Complete Default Import List as
well as (in           this case) com.planet_ink.coffee_mud.Exits.StdExit
because our           sample class extends it.           Here is an example
exit:         </p>

                                                  
      
      <pre>public class SlidingDoor extends com.planet_ink.coffee_mud.Exits.StdExit<br />{<br />  public String ID()<br />  {<br />    return "SlidingDoor";<br />  }<br /><br />  public SlidingDoor()<br />  {<br />    super();<br />    Ability A = CMClass.getAbility( "Prop_ReqHeight" );<br />    A.setMiscText( "30" );<br />    addNonUninvokableEffect( A );<br />  }<br /><br />  public String name()<br />  {<br />    return "a sliding door";<br />  }<br /><br />  public String displayText()<br />  {<br />    return "";<br />  }<br /><br />  public String closedText()<br />  {<br />    return "a closed sliding door";<br />  }<br /><br />  public String doorName()<br />  {<br />    return "door";<br />  }<br /><br />  public String openName()<br />  {<br />    return "slide";<br />  }<br /><br />  public String closeName()<br />  {<br />    return "slide";<br />  }<br /><br />  public boolean hasADoor()<br />  {<br />    return true;<br />  }<br /><br />  public boolean hasALock()<br />  {<br />    return false;<br />  }<br /><br />  public boolean defaultsLocked()<br />  {<br />    return false;<br />  }<br /><br />  public boolean defaultsClosed()<br />  {<br />    return true;<br />  }<br /><br />  public int openDelayTicks()<br />  {<br />    return 45;<br />  }<br />}<br /></pre>

                                                 
      
      <p>           As you can see, exits are very simple. A set of variables
 and           parameters are sufficient to establish every function of an
 exit,           and these are already well defined in the Archon's Guide.
 This is           due primarily to the fact that several Properties and
Behaviors            give an exit most of its color and complexity.     
   </p>

                                                  
      
      <p>           Exits, like all other Environmental objects, get to preview
 and           execute messages. They will only tend to listen for messages 
           dealing with OPENING or CLOSING where the exit is the target, or
           ENTERING and LEAVING where the exit is the tool. If a player is
           going from room A to room B. The player message will note that
 he           or she is ENTERING the exit in room A and LEAVING the exit
in  room           B. Although this makes perfect sense to me, it may sound
a  little           backwards from the intuitive way. Since Room objects
(Locales)  are           almost always the target of ENTER and LEAVE messages,
exits  are           subordinated to being the tools of such messages.  
      </p>

                                                  
      
      <p>           Exits will never tick, by and large, unless they have
 a door that           defaults closed and the door is opened, or they gain
 some sort of           Behavior (such as Emoter).         </p>

               <img src="images/scenery.jpg" alt="Locales" />
                                               
      
      <h2><a name="LOCALES" id="LOCALES">Locales</a></h2>

                                                  
      
      <p>           Locales are the stuff rooms are           made of, and
 so they implement the interface Room. There are           actually four
different  general types of locales: the standard           room, the standard
grid,  the "thin" grid, and the standard maze.           Each of those respectively
 is a functional superset of the former           respectively. Rooms import
 the same packages mentioned in the first section of           this document
 under Complete Default Import List as well as (in           this case) com.planet_ink.coffee_mud.Rooms.StdGrid, 
           com.planet_ink.coffee_mud.Rooms.StdRoom, or com.planet_ink.coffee_mud.Rooms.StdMaze, 
           because our sample classes           extends them.         </p>

                                                  
      
      <p>           Let's looks at an example of a standard grid room, which
 has much           of the functionality we are interested in:         </p>

                                                  
      
      <pre>public class RoadGrid extends com.planet_ink.coffee_mud.Locales.StdGrid<br />{<br />  public String ID()<br />  {<br />    return "RoadGrid";<br />  }<br /><br />  public RoadGrid()<br />  {<br />    super();<br />    name = "a road";<br />    baseEnvStats.setWeight( 1 );<br />    recoverEnvStats();<br />  }<br /><br />  public String getGridChildLocaleID()<br />  {<br />    return "Road";<br />  }<br /><br />  public Vector resourceChoices()<br />  {<br />    return Road.roomResources;<br />  }<br /><br />  public int domainType()<br />  {<br />    return Room.DOMAIN_OUTDOORS_PLAINS;<br />  }<br /><br />  public int domainConditions()<br />  {<br />    return Room.CONDITION_NORMAL;<br />  }<br />}<br /></pre>

                                                 
      
      <p>           Here we see the standard RoadGrid. It's effects, behaviors, 
           displaytext, description, and (since it is a grid type) size in
 the           x and y are all defined by the builder. The features (and
they            aren't many) which are available to the coder can be seen
here.  We           see the base weight being set to "1" here. This is the
default            number of movement points consumed by crossing this room.
For           Grids, we see the Locale ID of the child-rooms inside the grid.
 We           also see the standard room settings methods for the domain
type            (the type of locale it is) and the domain conditions (the
quality            of the weather, or the air, wetness, dryness, etc).  
      </p>

                                                  
      
      <p>           The Resource choices for this room are borrowed from
the Road           itself, though this will never be used. Players will never
 actually           be inside the Grid room itself, but will always occupy
 one of the           child rooms, each of which will take direction from
the parent           Grid. If you wish to define resources, however, be aware
 that the           resourceChoices vector returned may not be null, and
must  only           contain Integer objects representing the Resource (see
the            Items.interfaces.RawMaterial.java interface) available there. 
Use            the RESOURCE_* static integer values from RawMaterial interface. 
         </p>

                                                  
      
      <p>           Here are another set of useful methods:         </p>

                                                  
      
      <pre>  public String roomTitle()<br />  public String roomDescription()<br /></pre>

                                                 
      
      <p>           These methods return the title           and description
 of the room respectively. These methods are           responsible for making
 the title and description into a proper           displayable format. They
 draw on the values of the room object           <code>displayText()</code>
 and <code>description()</code> methods respectively, then parse        
  that data for any special display codes, though often that data is    
      simply passed through.         </p>

                                                  
      
      <p>           The <code>executeMsg()</code>, and <code>okMessage()</code>
 methods on rooms are also available,           as they are in all Environmental
 objects, for customized message           handling as described in the Core
 Topics above.         </p>

               <img src="images/area.jpg" alt="Areas" />
                                               
      
      <h2><a name="AREAS" id="AREAS">Areas</a></h2>

                                                  
      
      <p>           The Area objects, which represent areas in the game,
are the most           difficult to advise about regarding programming. 
       </p>

                                                  
      
      <p>           However, an attempt must be made. Therefore, we     
     will go over some of the methods and features available on the Area
          object, which might be overridden for some other use. Areas   
       import the same packages           mentioned in the first section
of  this document under Complete           Default Import List.         </p>

                                                  
      
      <pre>public class StdArea implements Area<br />{<br />  public String ID()<br />  {<br />    return "StdArea";<br />  }<br /><br />  [...]<br /><br />  public Climate getClimateObj(){...}<br />  public int climateType(){...}<br />  public void setClimateType( int newClimateType ){...}<br /></pre>

                                                 
      
      <p>           Of course, like every Environmental object, the Area
must define an           <code>ID()</code>. Notice that the <code>ID()</code>
is the same as the name of the class.           This is no accident -- this
is required! The name, display text,           description, and others are
all handled by the builder, or           Properties or behaviors, and aren't
pertinent to this discussion of           Areas.         </p>

                                                  
      
      <p>           The weather, however, is a relative function of each
area. Each           area knows its current weather object (see the Climate
interface)           as well as the next weather change "in the que". These
can be read           and set by the methods in the Climate object. Each
area also knows           it climatic "tendencies", and this also can be
set and read from           the area itself. Lastly, a method exists on the
Climate object to           force the area to cycle through its weather,
which will force the           "next" weather code to become current, and
establish a new "next"           weather code.         </p>

                                                  
      
      <pre>  public int getTechLevel()<br />  public void setTechLevel( int level )<br /></pre>

                                                 
      
      <p>           These will return the technical level allowed in the
area, whether           it be magic, technology, or both.         </p>

                                                  
      
      <pre>  public String getArchivePath()<br />  public void setArchivePath( String pathFile )<br /></pre>

                                                 
      
      <p>           The Archive name of the area is set and read from   
       the area, though it's more properly set by the           builder.
        </p>

                                                 
      
      <pre>  public TimeClock getTimeObj()<br /></pre>

                                                 
      
      <p>           Similar to Climate above, each area has a reference to
 a TimeClock           object which contains information about local time.
 Unlike the           Climate, however, StdAreas all share the same Time
object,  meaning           that time is global. However, the object exists
here in  case you           want local time areas.         </p>

                                                  
      
      <pre>  public void toggleMobility( boolean onoff )<br />  public boolean getMobility()<br /></pre>

                                                 
      
      <p>           These methods define whether Mobile mobs will move around.
 By           toggling mobility off, no mob or player in the whole area will
 move           from room to room for any reason, allowing a good base state
 for           builders to work from.         </p>

                                                  
      
      <pre>  public StringBuffer getAreaStats()<br /></pre>

                                                 
      
      <p>           If the data, appearance, or format of the HELP provided
 for areas           needs to be changed, the <code>getAreaStats()</code>
method is where to generate           a new one.         </p>

                                                  
      
      <pre>  public Enumeration getMetroMap()<br />  public int metroSize()<br />  public Room getRandomMetroRoom()<br /></pre>

                                                  
      
      <p>           These methods provide access to all of the rooms in the
 given area,           plus all of the rooms in any child areas, plus any
rooms in their           children areas and so forth.         </p>

                                                  
      
      <pre>  public void fillInAreaRooms()<br />  public void fillInAreaRoom( Room R )<br /><br />  public Enumeration getProperMap()<br />  public int properSize()<br />  public Room getRandomProperRoom()<br />  public void clearMetroCache()<br /></pre>

                                                  
      
      <p>           The first two methods are called in order to perform
finalizing           clean-up or resetting of room structures. The remaining
methods           provide access to the set of rooms which are directly a
part of           this area. The last method is one which should be called
if any           proper rooms are ever added, since it clears and "re-calculates" 
           the metro rooms list.         </p>

                                                  
      
      <pre>  public void addSubOp( String username )<br />  public void delSubOp( String username )<br />  public boolean amISubOp( String username )<br />  public String getSubOpList()<br />  public void setSubOpList( String list )<br />  public Vector getSubOpVectorList()<br /></pre>

                                                 
      
      <p>           And lastly, the list of staff (Area Archons they are
also sometimes           called), can be managed from here. Changing these
methods would           modify how staff are handled by Areas.         </p>

               <img src="images/house.jpg" alt="Properties" />
                                               
      
      <h2><a name="PROPS" id="PROPS">Properties</a></h2>

                                                  
      
      <p>           Properties are the simplest of the objects which implement
 the           Ability interface, and are defined as effects which can be 
          permanently tacked-on to items, mobs, and other Environmental  
        objects. Properties are Abilities, but they are never qualified for
           by classes, never gained as skills, and never wear off or disappear
           when a mob dies. They are always added to a mob, item, room, etc
           using the Environmental interface method           <code>addNonUninvokableEffect(
 Ability )</code> method either inside a custom           coded Environmental
 object, or at run-time to a GenMob, GenItem,           Room, or similar
type  object.         </p>

                                                  
      
      <p>           Properties and Behaviors are often the basic building
 blocks of the           customized GenMob and GenItem in CoffeeMud, and
differ  from each           other in this basic respect: Properties tend
to have a smaller           memory footprint and tend to react to events
affecting their hosts           rather than cause their hosts to take proactive
actions. Properties           make heavy use of the message handlers and
stat affecting methods.           If you have not read the Core Topics above
already, you should do           so now.         </p>

                                                  
      
      <p>           A Custom property may or may not belong to any      
    particular package, though it is important that the ID() of the     
     property be unique in the system. Properties           import the same
 packages mentioned in the           first section of this document under
Complete Default Import List           as well as (in this case)        
  com.planet_ink.coffee_mud.Properties.Property because our sample      
    class extends it.         </p>

                                                  
      
      <p>           A customized property class must extend the Property
class           implemented in the aforementioned package. This Property
class           already implements the Ability interface, and already has
dummy           methods for most of the Ability interface methods which are
           unnecessary or are unused in a Property.         </p>

                                                  
      
      <p>           Each property must also have custom <code>ID()</code>,
 and <code>name()</code> methods as           shown below. Notice that the
       <code>ID()</code> is the same as the name of the           class.
This  is no accident -- this is required!         </p>

                                                  
      
      <pre>public class Prop_AstralSpirit extends com.planet_ink.coffee_mud.Abilities.Properties.Property<br />{<br />  public String ID()<br />  {<br />    return "Prop_AstralSpirit";<br />  }<br /><br />  public String name()<br />  {<br />    return "Astral Spirit";<br />  }<br /></pre>

                                                  
      
      <p>           Above we see the aforementioned methods defined. The
Property does           not differ from other Abilities, or indeed other
Environmental           objects in this respect. A unique <code>ID()</code>,
and <code>name()</code> method must be           defined for each new class.
         </p>

                                                  
      
      <pre>  protected int canAffectCode()<br />  {<br />    return Ability.CAN_MOBS;<br />  }<br /><br />  public String accountForYourself()<br />  {<br />    return "an astral spirit";<br />  }<br /></pre>

                                                 
      
      <p>           Here are two important support methods you will     
     also find in Skills and the other more standard Abilities. The     
     first method tells what type of objects (Areas, MOBs, Items, Rooms,
          or Exits) can be affected by this property. In this case, this
          property only affects MOBS. A value like           Ability.CAN_MOBS|Ability.CAN_ITEMS 
           would denote one that affects MOBs or Items.         </p>

                                                  
      
      <p>           The second method is a string which is returned whenever
 this           property appears on an Item which is Identified. This string
 would           appear in addition to any secretIdentity defined for the
item.         </p>

                                                  
      
      <pre>  /** this method defines how this thing responds<br />  * to environmental changes.  It may handle any<br />  * and every msg listed in the CMMsg class<br />  * from the given Environmental source */<br />  public boolean okMessage( Environmental myHost, CMMsg msg )<br />  {<br />    if( ( affected == null ) || ( !( affected instanceof MOB ) ) )<br />    {<br />      return true;<br />    }<br /><br />    MOB mob = (MOB)affected;<br /><br />    if( ( msg.amISource( mob ) )<br />        &amp;&amp; ( !CMath.bset( msg.sourceMajor(), CMMsg.MASK_ALWAYS ) )<br />      )<br />    {<br />      if( ( msg.tool() != null )<br />          &amp;&amp;( msg.tool().ID().equalsIgnoreCase( "Skill_Revoke" ) )<br />        )<br />      {<br />        return super.okMessage( myHost, msg );<br />      }<br />      else if( msg.targetMinor() == CMMsg.TYP_WEAPONATTACK )<br />      {<br />        mob.tell( "You are unable to attack in this incorporeal form." );<br />        peaceAt( mob );<br />        return false;<br />      }<br />      else if( ( CMath.bset( msg.sourceMajor(), CMMsg.MASK_HANDS ) )<br />               || ( CMath.bset( msg.sourceMajor(), CMMsg.MASK_MOUTH ) )<br />             )<br />      {<br />        if( CMath.bset( msg.sourceMajor(), CMMsg.MASK_SOUND ) )<br />        {<br />          mob.tell( "You are unable to make sounds in this incorporeal form." );<br />        }<br />        else<br />        {<br />          mob.tell( "You are unable to do that this incorporeal form." );<br />        }<br /><br />        peaceAt( mob );<br />        return false;<br />      }<br />    }<br />    else if( ( msg.amITarget( mob ) )<br />             &amp;&amp;( !msg.amISource( mob ) )<br />             &amp;&amp;( !CMath.bset( msg.targetMajor(), CMMsg.MASK_ALWAYS ) )<br />           )<br />    {<br />      mob.tell( mob.name() + " doesn't seem to be here." );<br />      return false;<br />    }<br /><br />    return true;<br />  }<br /></pre>

                                                 
      
      <p>           As discussed in the Core Topics above, here is an example
 of an           okMessage method. In this case, we intercept attack and
other  vocal           or hand movement messages where the source of the
action is the mob           whose property this is. We then return false,
effectively            canceling those messages, after telling the poor bloke
why we are            doing it. The rest of the method prevents any messages
from           targeting the mob with this property. This saves him from
being           attacked by aggressives, or arrested by cityguards -- since
          technically he isn't even there.         </p>

                                                  
      
      <pre>  public void affectEnvStats( Environmental affected, EnvStats affectableStats )<br />  {<br />    super.affectEnvStats( affected, affectableStats );<br />    // when this spell is on a MOBs Affected list,<br />    // it should consistantly put the mob into<br />    // a sleeping state, so that nothing they do<br />    // can get them out of it.<br /><br />    affectableStats.setWeight( 0 );<br />    affectableStats.setHeight( -1 );<br /><br />    affectableStats.setDisposition(<br />      affectableStats.disposition()|EnvStats.IS_GOLEM<br />    );<br /><br />    affectableStats.setDisposition(<br />      affectableStats.disposition()|EnvStats.IS_INVISIBLE<br />    );<br /><br />    affectableStats.setDisposition(<br />      affectableStats.disposition()|EnvStats.IS_NOT_SEEN<br />    );<br /><br />    affectableStats.setSensesMask(<br />      affectableStats.sensesMask()|EnvStats.CAN_NOT_SPEAK<br />    );<br />  }<br />}<br /></pre>

                                                 
      
      <p>           Last but not least, here is another example from the
Core Topics,           an <code>affectEnvStats()</code> method. This method
will always have the host mob           passed in the "affected" parameter,
and a copy of his current           EnvStats objects in the affectableStats
parameter. This method then           sets the mob as being both invisible,
and totally unseen. It makes           him unviewable to infrared, and prevents
him from speaking. The two           methods above then combine to produce
our desired results, an           Astral Spirit.         </p>

               <img src="images/monk.jpg" alt="Skills" />
                                               
      
      <h2><a name="SKILLS" id="SKILLS">Introduction to Skill Abilities</a></h2>

                                                  
      
      <p>           Abilities are easily the most complicated and varied
of all the           objects in CoffeeMud. They encompass everything from
invoked skills           and spell, like TRIP or MAGIC MISSILE, to natural
abilities, like           NONDETECTION. A Skill Ability then is an object
which implements           the Ability interface fully, unlike the Property
above, which           implements only certain parts.         </p>

                                                  
      
      <p>           An Ability is known in the mud as any of the following:
 A Spell,           Song, Dance, Skill, Common Skill, Thief Skill, Poison,
 Disease,           Prayer, Chant, or Trap. They all implement the Ability
 interface,           which in turn extends the Environmental interface discussed 
           throughout the rest of this document. Abilities make extensive
 use           of the okMessage and executeMsg, tick, and stat affecting
methods            discussed above in the Core Topics. If you have not read
the Core            Topics, you should do so now.         </p>

                                                  
      
      <p>           Abilities will all tend to extend the basic StdAbility
 class found           in the Abilities package, and sometimes they will
further  extend a           class more specific to their type, such as Spell,
StdSkill,  Song,           BardSkill, Prayer, FighterSkill, ThiefSkill, Chant,
or some  other           basic types found in the standard CoffeeMud distribution
packages.         </p>

                                                  
      
      <p>           Abilities are added to mob objects using the addAbility
 method on           MOBs. From there, through casting or by autoInvocation
 (discussed           below), they may end up in the effects list of a mob,
 item, room,           area, or exit via the addEffect method.         </p>

                                                  
      
      <p>           A Custom ability may or may not belong to any       
   particular package, though it is important that the           <code>ID()</code>
 of the ability be           unique in the system. A custom ability     
     imports the same packages mentioned in the           first section of
this document under Complete Default Import List           as well as (in
this case)           com.planet_ink.coffee_mud.Abilities.StdAbility because
our sample           class extends it.         </p>

                                                  
      
      <p>           A customized ability class usually extends the StdAbility
 class           implemented in the aforementioned package. This StdAbility
 class           already implements the Ability interface, and already has
 numerous           support methods which aid in the creation of custom abilities. 
         </p>

                                                  
      
      <p>           Each ability must also have custom <code>ID()</code>
and       <code>name()</code> methods as           shown below. Notice that
the        <code>ID()</code> is the same as the name of the           class.
This  is no accident -- this is required!         </p>

                                                  
      
      <pre>public class Skill_Trip extends com.planet_ink.coffee_mud.Abilities.StdAbility<br />{<br />  public String ID()<br />  {<br />    return "Skill_Trip";<br />  }<br /><br />  public String name()<br />  {<br />    return "Trip";<br />  }<br /></pre>

                                                  
      
      <p>           Above we see the aforementioned methods defined. This
 skill does           not differ from other Abilities, or indeed other Environmental 
           objects in this respect. A unique <code>ID()</code> and <code>name()</code>
 method must be           defined for each new class.         </p>

                                                  
      
      <pre>  public String displayText()<br />  {<br />    return "(Tripped)";<br />  }<br /></pre>

                                                  
      
      <p>           The display text on an Ability always refers to the text
 shown in           the "You are affected by" section shown by the SCORE
and  AFFECTS           commands in the MUD. In this case, someone affected
by trip will           see (Tripped). If this method does not leave any information
 for           those affected by it, it should return "".         </p>

                                                  
      
      <pre>  protected int canAffectCode()<br />  {<br />    return CAN_MOBS;<br />  }<br /><br />  protected int canTargetCode()<br />  {<br />    return CAN_MOBS;<br />  }<br /></pre>

                                                 
      
      <p>           These two methods assist the MUDGrinder, and the HELP
 files in           classifying the several skills and spells.         </p>

                                                  
      
      <p>           The first method, <code>canAffectCode()</code>, returns
 what type of objects, if           any, this ability class may find itself
 in the effects list of.           Since our Trip skill effects the tripped
 mob, we list mobs. Other           possible values include any combination
 of CAN_ROOMS, CAN_EXITS,           CAN_ITEMS, or CAN_AREAS. If a skill may
 Effect more than one, they           can be combined using the | operator.
 An example skill that affects           both mobs and items might return
CAN_MOBS|CAN_ITEMS, for instance.         </p>

                                                  
      
      <p>           The second method, <code>canTargetCode()</code>, above
 tells the system what           type of objects can be targeted by this
skill.  Some skills will           target items (like the Enchant Weapon
spell), or rooms (like the           Darkness spell), or exits (like the
Knock spell).  In a similar           fashion to canAffectCode, this method
can return any  combination of           valid objects to notify the system
of proper targets.          </p>

                                                  
      
      <pre>  public int abstractQuality()<br />  {<br />    return Ability.QUALITY_MALICIOUS;<br />  }<br /></pre>

                                                 
      
      <p>           This MOST important method tells the system quite a bit
 about the           nature of the skill, as well as how mobs with behaviors
 like           CombatAbilities should use it. In this case, we return  
        Ability.QUALITY_MALICIOUS, which tells the system that the skill
is            always malicious to others, and that it will most likely anger
 the           target. It tells mobs to target this skill at enemies in combat 
         </p>

                                                  
      
      <p>           Other possible values include:         </p>

               <a name="skillquality" id="skillquality">&nbsp;</a>      
                                     
      
      <table border="1">

                <tbody>

                  <tr>

                    <td>                 Ability.QUALITY_BENEFICIAL_SELF
              </td>

                    <td>                 always helpful to oneself when used 
              </td>

                  </tr>

                  <tr>

                    <td>                 Ability.QUALITY_BENEFICIAL_OTHERS
              </td>

                    <td>                 can be targeted to other people,
and  is always beneficial               </td>

                  </tr>

                  <tr>

                    <td>                 Ability.QUALITY_OK_SELF        
      </td>

                    <td>                 targets oneself, but is only useful 
in certain circumstances,                 or it has complicated parameters 
that mobs won't find useful               </td>

                  </tr>

                  <tr>

                    <td>                 Ability.QUALITY_OK_OTHERS      
        </td>

                    <td>                 targets other people, but is only
useful  under certain                 circumstances, or it also has complicated
parameters                </td>

                  </tr>

                  <tr>

                    <td>                 Ability.QUALITY_INDIFFERENT    
          </td>

                    <td>                 targets items, or rooms, and is
only  useful in certain                 circumstances               </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                  
      
      <p>           Only skills marked as           Ability.QUALITY_BENEFICIAL_*
 orAbility.QUALITY_MALICIOUS will be           used in combat or by most
behaviors.          </p>

                                                  
      
      <pre>  public int castingQuality( MOB invoker, Environmental target )<br />  {<br />    return super.castingQuality( invoker, target );<br />  }<br /></pre>

                                                 
      
      <p>           This second most important method is similar to the 
         <code>abstractQuality()</code> method above, but it tells the system
 what the           quality of the skills or spell is if it is specifically
 used by the           given invoker against the given target at this given
 time. If your           skill is only useful in water or against elves,
it  might be good to           check to see if the invoker is in water or
the  target is an elf           before returning a value. The same kinds
of values  may be returned           from this method as are returned by
abstractQuality,  except for           QUALITY_OK_OTHERS and Ability.QUALITY_OK_SELF,
which  are           meaningless in this context.         </p>

                                                  
      
      <pre>  public boolean isAutoInvoked()<br />  {<br />    return false;<br />  }<br /></pre>

                                                 
      
      <p>           All skills are either autoInvoking, or they must be invoked
 by a           player or mob. The value returned by this method determines
 which           sort this ability is. If it is autoinvoking, it will not
have an           invoke( method as described below, nor will it have trigger 
           strings, nor will it return anything other than "" from it's  
        <code>displayText()</code> method. An example of an autoInvoking
 ability would           be Blind Fighting or Two Weapon Fighting. In our
case, however,           Trip is not autoinvoking, but requires a player
to invoke it.         </p>

                                                  
      
      <pre>  private static final String[] triggerStrings = { "TRIP" };<br />  public String[] triggerStrings()<br />  {<br />    return triggerStrings;<br />  }<br /><br />  public double castingTime()<br />  {<br />    return 0.25;<br />  }<br /><br />  public double combatCastingTime()<br />  {<br />    return 1.0;<br />  }<br /></pre>

                                                 
      
      <p>           For skills which are not autoinvoking, like this one,
 we must           define an array of strings which constitute the command
 words to           use this skill. Each entry in the array must be only
one  word. If           more than one skill is found with the same trigger
words  (such as           the spells, which all share the trigger word "CAST"),
then the name           of the specific ability will be the required next
parameter. Trip,           however, has a unique trigger word, which is defined
by this           method.         </p>

                                                  
      
      <p>           Skills can also define how many actions they take to
execute when           the caster or user of the skill is in combat, or not
in combat. The           next two methods define this. A value of 0 means
that the skill or           spell is always instantaneous. A higher value
means that the skill           requires a full action to perform. Typical
players have 1 action           per tick (4 second period) to use.      
  </p>

                                                  
      
      <pre>  public int classificationCode()<br />  {<br />    return Ability.ACODE_SKILL;<br />  }<br /></pre>

                                                 
      
      <p>           This important method defines which category an ability
 falls into.           Possible values include: SKILL, PRAYER, SONG, TRAP,
 SPELL,           THIEF_SKILL, LANGUAGE, CHANT, COMMON_SKILL, DISEASE, or
POISON.         </p>

                                                  
      
      <pre>  public long flags()<br />  {<br />    return Ability.FLAG_MOVING;<br />  }<br /></pre>

                                                 
      
      <p>           This method returns a value consisting of one or more
 flags,           separated by | symbols in the same way that canAffectCode
 does           above. Each flag has a specific meaning and imparts information
 to           the engine about the ability. Possible values, which may be
used           alone or together in any combination, include:         </p>

               <a name="skillflags" id="skillflags">&nbsp;</a>          
                                 
      
      <table border="1" cellpadding="1" cellspacing="1" width="75%">

                <tbody>

                  <tr>

                    <td>                 FLAG_BINDING               </td>

                    <td>                 Binds and or limits movement and
the  use of hands.               </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_MOVING               </td>

                    <td>                 Changes the position of the target 
or affected one.               </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_TRANSPORTING              
            </td>

                    <td>                 Changes the room of the target,
requires  that the performer                 of the skill be present.   
                       </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_WEATHERAFFECTING          
    </td>

                    <td>                 Changes the weather.           
               </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_SUMMONING               </td>

                    <td>                 Changes the room of the target,
where  the performer of the                 skill is not present. May also
bring  new creatures into                 existence.               </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_CHARMING               </td>

                    <td>                 Charms the target.             
 </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_TRACKING               </td>

                    <td>                 Results in the target tracking something. 
               </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_HEATING               </td>

                    <td>                 Makes the target hot.          
    </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_BURNING               </td>

                    <td>                 Makes the target on fire.      
        </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_HOLY               </td>

                    <td>                 Means that the skill is GOOD aligned,
 unless FLAG_UNHOLY is                 also set, in which case it makes the
 skill NEUTRAL.               </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_UNHOLY               </td>

                    <td>                 Means that the skill is EVIL aligned,
 unless FLAG_UNHOLY is                 also set, in which case it makes the
 skill NEUTRAL.               </td>

                  </tr>

                  <tr>

                    <td>                 FLAG_PARALYZING               </td>

                    <td>                 Makes the target or affected one
unable  to move their                 muscles.               </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                  
      
      <pre>  public void affectEnvStats( Environmental affected, EnvStats affectableStats )<br />  {<br />    super.affectEnvStats( affected, affectableStats );<br />    if( !doneTicking )<br />    {<br />      affectableStats.setDisposition( affectableStats.disposition()<br />                                      | EnvStats.IS_SITTING<br />                                    );<br />    }<br />  }<br /></pre>

                                                  
      
      <p>           This is an example of the <code>affectEnvStats()</code>
 method described in the           Core Topics. In the case of our Trip skill,
 it forces the affected           target into a sitting position.       
       </p>

                                                  
      
      <pre>  public boolean okMessage( Environmental myHost, CMMsg msg )<br />  {<br />    if( ( affected == null ) || ( !( affected instanceof MOB ) ) )<br />    {<br />      return true;<br />    }<br /><br />    MOB mob = (MOB)affected;<br />    if( doneTicking &amp;&amp; msg.amISource( mob ) )<br />    {<br />      unInvoke();<br />    }<br />    else if( msg.amISource( mob )<br />             &amp;&amp; ( msg.sourceMinor() == CMMsg.TYP_STAND )<br />           )<br />    {<br />      return false;<br />    }<br /><br />    return true;<br />  }<br /></pre>

                                                 
      
      <p>           This is an example of the <code>okMessage()</code> method
 described in the Core           Topics. In this case, it intercepts messages
 where the affected mob           is trying to stand and cancels the message,
 without comment, by           returning false.         </p>

                                                  
      
      <pre>  public void unInvoke()<br />  {<br />    if( ( affected == null ) || ( !( affected instanceof MOB ) ) )<br />    {<br />      return;<br />    }<br /><br />    MOB mob = (MOB)affected;<br />    if( canBeUninvoked() )<br />    {<br />      doneTicking = true;<br />    }<br /><br />    super.unInvoke();<br /><br />    if( !mob.amDead() )<br />    {<br />      if( mob.location() != null )<br />      {<br />        CMMsg msg = CMClass.getMsg( mob,<br />                                    null,<br />                                    CMMsg.MSG_NOISYMOVEMENT,<br />                                    "&lt;S-NAME&gt; regain(s) &lt;S-HIS-HER&gt; feet."<br />                                  );<br /><br />        if( mob.location().okMessage( mob, msg ) )<br />        {<br />          mob.location().send( mob, msg );<br />          CMLib.commands().postStand( mob, true );<br />        }<br />      }<br />      else<br />      {<br />        mob.tell( "You regain your feet." );<br />      }<br />    }<br />  }<br /></pre>

                                                 
      
      <p>           All standard abilities include an <code>unInvoke()</code>
 method, which is           called when the Effect caused by the ability
is  dispelled, or the           duration of the ability expires. The <code>super.unInvoke()</code>
 method, which           is located in StdAbility.java, actually does the
work of removing           the Effect from the affected object (stored in
the variable           affected), and then setting affected to null. In this
particular           <code>unInvoke()</code> method, we also see the code
trying to force the mob           back to his feet.         </p>

                                                  
      
      <pre>  public boolean preInvoke( MOB mob,<br />                            Vector commands,<br />                            Environmental givenTarget,<br />                            boolean auto,<br />                            int asLevel,<br />                            int secondsElapsed,<br />                            double actionsRemaining<br />                          )<br />  {<br />    return true;<br />  }<br /></pre>

                                                 
      
      <p>           The <code>preInvoke()</code> method is an optional method
 that normally just           returns true. Unless you have reason to do
so,  you do not need to           override the standard preInvoke method
in StdAbility.java.  The           preInvoke method must return true before
the <code>invoke()</code>  method (below)           is executed. The difference
between the two is that  the preInvoke           method is called at the
moment the skill command words are entered,           even if the skill is
coded, via the <code>castingTime()</code>  or           <code>combatCastingTime()</code>
methods, to invoke at some later time. If your           skill does invoke
at a later time, it is generally  useful to use           the preInvoke method
to scan the commands Vector,  which contains           the command parameter
strings minus any trigger words, for errors.           You may also give
the user a message that their skill will invoke           later on. The preInvoke
method will continue to be called, at 1           second intervals, until
the player is able to invoke the           command.         </p>

                                                  
      
      <pre>  public boolean invoke( MOB mob,<br />                         Vector commands,<br />                         Environmental givenTarget,<br />                         boolean auto,<br />                         int asLevel<br />                       )<br />  {<br /></pre>

                                                  
      
      <p>           If an ability is not autoinvoked, it will always have
 a functional           invoke method. This invoke method includes the following 
           parameters: the mob invoking the ability and a vector of command 
           parameter strings (which does not include any trigger words). The
           givenTarget parameter, which is null on normal ability invocations, 
           will have the value of a target to the skill if one is available. 
           Calls to the invoke method where the givenTarget is not null are 
           typically from potions, wands, traps, or other automatic      
    invocations. Which brings us to the last parameter, auto. Auto is   
       false on normal invocations of the skill, and true whenever the  
        skill should always invoke no matter what. Setting auto to true not
           only changes the output string for the skill, but overrides  
        proficiency checks as well.         </p>

                                                  
      
      <pre>    MOB target = this.getTarget( mob, commands, givenTarget );<br />    if( target == null )<br />    {<br />      return false;<br />    }<br /></pre>

                                                 
      
      <p>           Our first step in Trip is to get our target. There are
 several           <code>getTarget()</code> methods built into StdAbility
for determining a target           object based on the command parameters
passed in, as well as the           <code>abstractQuality()</code> value
for the ability. The StdAbility method call           to <code>getTarget()</code>
 is smart enough to know that if a target name is not           specified
by givenTarget, and also one is not specified in the           commands Vector
 passed in, that it should choose whoever the mob is           fighting,
since  the ability isAbility.QUALITY_MALICIOUS.           Non-malicious skills
would  not follow this reasoning, but would           choose the caster himself
as default.         </p>

                                                  
      
      <p>           All of the several <code>getTarget()</code> methods will
 generate their own error           messages to the user if a target is not
 specified, or found, or           cannot be determined. For this reason,
we need only to check to see           if a target has been returned. If
not, we can return false from           <code>invoke()</code>, telling the
system that the ability failed to invoke.         </p>

                                                  
      
      <pre>    if( CMLib.flags().isSitting( target )<br />        || CMLib.flags().isSleeping( target )<br />      )<br />    {<br />      mob.tell( target,<br />                null,<br />                null,<br />                "&lt;S-NAME&gt; is already on the floor!"<br />              );<br /><br />      return false;<br />    }<br /><br />    if( !CMLib.flags().aliveAwakeMobile( mob, true )<br />        ||( CMLib.flags().isSitting( mob ) )<br />      )<br />    {<br />      mob.tell( "You need to stand up!" );<br />      return false;<br />    }<br /><br />    if( mob.isInCombat() &amp;&amp; ( mob.rangeToTarget() &gt; 0 ) )<br />    {<br />      mob.tell( "You are too far away to trip!" );<br />      return false;<br />    }<br /><br />    if( target.riding() != null )<br />    {<br />      mob.tell( "You can't trip someone "<br />                + target.riding().stateString( target )<br />                + " "<br />                + target.riding().name()<br />                + "!"<br />              );<br /><br />      return false;<br />    }<br /><br />    if( CMLib.flags().isFlying( target ) )<br />    {<br />      mob.tell( target.name() + " is flying and can't be tripped!" );<br />      return false;<br />    }<br /></pre>

                                                 
      
      <p>           Here are numerous checks to see if the invoking mob is
 able to           trip, and the target is able to be tripped.         </p>

                                                  
      
      <pre>    if( !super.invoke( mob, commands, givenTarget, auto ) )<br />    {<br />      return false;<br />    }<br /></pre>

                                                 
      
      <p>           The <code>invoke()</code> method back up in StdAbility
 is called now. This           method will check mana requirements, and subtract
 mana if           necessary. It should be called AFTER all other preliminary
 checks           have been made.         </p>

                                                  
      
      <pre>    int levelDiff = target.envStats().level() - mob.envStats().level();<br />    if( levelDiff &gt; 0 )<br />    {<br />      levelDiff = levelDiff * 5;<br />    }<br />    else<br />    {<br />      levelDiff = 0;<br />    }<br /><br />    Double temp = new Integer(<br />                               target.charStats().getStat(<br />                                                           CharStats.STAT_DEXTERITY<br />                                                         )<br />                             ).doubleValue()<br />                             - 9.0;<br /><br />    int adjustment =<br />    (-levelDiff) + (-( 35 + ( (int)Math.round( temp * 3.0 ) ) ) );<br /><br />    boolean success = proficiencyCheck( mob, adjustment, auto );<br /></pre>

                                                  
      
      <p>           The <code>proficiencyCheck()</code> method called at
the end here will determine           of the user of the skill has passed
their proficiency check. The           first parameter of this method is
the invoking mob, followed by           either a positive (or helpful) adjustment,
or a negative (not           helpful) adjustment. The second parameter is
the auto flag           mentioned above, to allow overrides of the normal
proficiency. In           the case of Trip, we calculate an adjustment based
both on level           and the dexterity of the target. We store whether
or not the           proficiency check failed or passed into the variable
success.         </p>

                                                  
      
      <pre>    success = success &amp;&amp; ( target.charStats().getBodyPart( Race.BODY_LEG ) &gt; 0 );<br /><br />    if( success )<br />    {<br />      CMMsg msg = CMClass.getMsg( mob,<br />                                  target,<br />                                  this,<br />                                  CMMsg.MSK_MALICIOUS_MOVE|CMMsg.TYP_JUSTICE|( auto ? CMMsg.MASK_ALWAYS : 0 ),<br />                                  auto ? "&lt;T-NAME&gt; trip(s)!" : "^F&lt;S-NAME&gt; trip(s) &lt;T-NAMESELF&gt;!^?"<br />                                );<br /><br />      if( mob.location().okMessage( mob, msg ) )<br />      {<br />        mob.location().send( mob, msg );<br />        int durationTicks = ( msg.value() &gt; 0 ) ? 1 : 2;<br />        maliciousAffect( mob, target, asLevel, durationTicks, -1 );<br />        target.tell( "You hit the floor!" );<br />      }<br />    }<br />    else<br />    {<br />      return maliciousFizzle( mob,<br />                              target,<br />                              "&lt;S-NAME&gt; attempt(s) to trip &lt;T-NAMESELF&gt;, but fail(s)."<br />                            );<br />    }<br /><br />    return success;<br />  }<br />}<br /></pre>

                                                 
      
      <p>           The rest of the <code>invoke()</code> method actually
 does the work of sending           the trip message and affecting the target
 if necessary, or sending           the "fizzle" message if the proficiency
 check failed (success was           false).         </p>

                                                  
      
      <p>           Of special note are some of the other StdAbility method
 calls in           this section of code. You'll notice that the message
constructed            (as per the Core Topics discussion in a previous section)
in this            case uses a TYP_JUSTICE message (meaning an attack on
dignity),            with the malicious and movement flags set. If this message
gets            sent, a call to <code>maliciousAffect()</code> is made. The
first  parameter is the           invoker, and the second parameter is the
one its  being invoked           upon. The third parameter is the level of
the affect,  or 0 for           default values. The forth parameter is the
duration of  the Effect           in ticks, which you can see is dependent
in this case  upon whether           the message came back with a <code>value()
&gt; 0</code>  (meaning the saving throw           was made). If the forth
parameter is 0, then the default duration           formula will be used.
All other positive  values, such as in this           case, denote a number
of ticks of duration.  The last parameter,           normally -1, asks <code>maliciousAffect()</code>
 to give the target one more           saving throw, against any of the valid
 saving throw type messages,           such as TYP_FIRE, TYP_ACID, TYP_GAS,
 etc. The value of -1 means not           to make any further saving throw
 attempts before affecting the           target.         </p>

                                                  
      
      <p>           If this skill had not been malicious, we could have made
 a call to           the <code>beneficialAffect()</code> method instead.
That  method has the same           parameters as <code>maliciousAffect()</code>,
 though it lacks the final parameter           for a further saving throw,
 since beneficial affects require no           saving throw.         </p>

                                                  
      
      <p>           Now, if the success variable had been false, then we
made a call to           the <code>maliciousFizzle()</code> method. In addition
 to a display in the room,           this method will make sure the target
 knows that the invoking mob           was trying to do something bad to
him  or her, so that the target           will get angry and start fighting.
Had  this not been a malicious           ability, we would have made calls
instead  to either the          <code> beneficialWordsFizzle()</code> method,
or the        <code>beneficialVisualFizzle()</code> method,           depending
upon  whether the skill is verbal or somantic based. Most           spells
are verbal based, for instance, while most skills are           somantic.
        </p>

                                                  
      
      <p>           Finally, we return the results of the success variable
 from the           <code>invoke()</code> method, to let the system know
whether  or not the ability           succeeded. If it did, the target will
now be  affected by this           ability, and will have to stay on the
ground for  a few ticks while           the source mob pounds on him or her.
              </p>

               <img src="images/fireball.jpg" alt="Spells" />
                                               
      
      <h2><a name="SPC" id="SPC">Spells, Prayers, and Chants</a></h2>

                                                  
      
      <p>           Spells, Prayers, and Chants are all special forms of
Abilities. For           this reason, it is required that you go back and
read the previous           section on Skill Abilities before proceeding.
You will also be           required to poke through the Core Topics elsewhere
in this document           as well.         </p>

                                                  
      
      <h3><a name="spells" id="spells">Spells</a></h3>

                                                  
      
      <p>           Spells will follow all the rules mentioned above in the
 Skill           Abilities section, with a few differences:         </p>

                                                  
      
      <pre>public class Spell_ResistFire extends com.planet_ink.coffee_mud.Abilities.Spells.Spell<br />{<br />  public String ID()<br />  {<br />    return "Spell_ResistFire";<br />  }<br /><br />  public String name()<br />  {<br />    return "Resist Fire";<br />  }<br /><br />  public String displayText()<br />  {<br />    return "(Resist Fire)";<br />  }<br /><br />  public int abstractQuality()<br />  {<br />    return Ability.QUALITY_BENEFICIAL_OTHERS;<br />  }<br /><br />  protected int canAffectCode()<br />  {<br />    return CAN_MOBS;<br />  }<br /><br />  public int classificationCode()<br />  {<br />    return Ability.ACODE_SPELL|Ability.DOMAIN_ABJURATION;<br />  }<br /></pre>

                                                 
      
      <p>           The first difference you will notice above is that spells
 extend           the base class Spell.java found in the Abilities/Spells
directory           instead of StdAbility. Spell.java also extends StdAbility
as well.           The second difference is in the <code>classificationCode()</code>
 method. You           will notice that the domain of the spell is also specified.
 In           addition to the normal classification code of Ability.ACODE_SPELL, 
           the domain may be added using the | symbol. Possible domains  
        include:         </p>

               <a name="spelldomain" id="spelldomain">&nbsp;</a>        
                                   
      
      <table border="1">

                <tbody>

                  <tr>

                    <td>                 DOMAIN_DIVINATION              
            </td>

                    <td>                 Spells that grant knowledge.   
           </td>

                  </tr>

                  <tr>

                    <td>                 DOMAIN_ABJURATION              
            </td>

                    <td>                 Spells that protect.           
               </td>

                  </tr>

                  <tr>

                    <td>                 DOMAIN_ILLUSION               </td>

                    <td>                 Spells that fool the senses.   
           </td>

                  </tr>

                  <tr>

                    <td>                 DOMAIN_EVOCATION               </td>

                    <td>                 Spells that bring forth the elements. 
               </td>

                  </tr>

                  <tr>

                    <td>                 DOMAIN_ALTERATION              
            </td>

                    <td>                 Spells that change things.     
         </td>

                  </tr>

                  <tr>

                    <td>                 DOMAIN_TRANSMUTATION           
               </td>

                    <td>                 Spells that change people.     
         </td>

                  </tr>

                  <tr>

                    <td>                 DOMAIN_ENCHANTMENT             
 </td>

                    <td>                 Spells that enchant items or the
mind.                </td>

                  </tr>

                  <tr>

                    <td>                 DOMAIN_CONJURATION             
 </td>

                    <td>                 Spells that transport people or
items.                </td>

                  </tr>

                                                             
        
        </tbody>                                            
      
      </table>

                                                  
      
      <pre>  public boolean invoke( MOB mob,<br />                         Vector commands,<br />                         Environmental givenTarget,<br />                         boolean auto,<br />                         int asLevel<br />                       )<br />  {<br />    MOB target = getTarget( mob, commands, givenTarget );<br />    if( target == null )<br />    {<br />      return false;<br />    }<br /><br />    if( !super.invoke( mob, commands, givenTarget, auto ) )<br />    {<br />      return false;<br />    }<br /><br />    boolean success = proficiencyCheck( mob, 0, auto );<br />    if( success )<br />    {<br />      CMMsg msg = CMClass.getMsg( mob,<br />                                  target,<br />                                  this,<br />                                  affectType( auto ),<br />                                  auto ?<br />                                    "&lt;T-NAME&gt; feel(s) cooly protected."<br />                                  : "^S&lt;S-NAME&gt; invoke(s) a cool field of protection around &lt;T-NAMESELF&gt;.^?"<br />                                );<br /><br />      if( mob.location().okMessage( mob, msg ) )<br />      {<br />        mob.location().send( mob, msg );<br />        beneficialAffect( mob, target, asLevel, 0 );<br />      }<br />    }<br />    else<br />    {<br />      beneficialWordsFizzle( mob,<br />                             target,<br />                             "&lt;S-NAME&gt; attempt(s) to invoke fire protection, but fail(s)."<br />                           );<br />    }<br /><br />    return success;<br />  }<br />}<br /></pre>

                                                 
      
      <p>           The <code>invoke()</code> method above follows the one
 in Skill_Abilities very           closely. You will see that no adjustment
 is made to the           proficiency check, and that, since this is not
          aAbility.QUALITY_MALICIOUS ability, calls are made to         
       <code>beneficialAffect()</code> and <code>beneficialWordsFizzle()</code>
 instead of           <code>maliciousAffect()</code> and <code>maliciousFizzle()</code>.
 The main difference to notice           here, however, is the line constructing
 the evoking message. You           will notice that where the message code
 should be specified, a           method call to <code>affectType()</code>,
 which is a method located in           Spell.java, is made. This call will
 automaticallyy construct the           proper message type for a spell,
taking  into           accountAbility.QUALITY_MALICIOUSness, and whether
the auto  flag is           set. You will also notice that different message
strings  are           constructed depending upon whether the auto flag is
set.         </p>

                                                  
      
      <h3><a name="prayers" id="prayers">Prayers</a></h3>

                                                  
      
      <p>           Prayers will follow all the rules mentioned above in
the Skill           Abilities section, with a few differences:         </p>

                                                  
      
      <pre>public class Prayer_Anger extends com.planet_ink.coffee_mud.Abilities.Prayers.Prayer<br />{<br />  public String ID()<br />  {<br />    return "Prayer_Anger";<br />  }<br /><br />  public String name()<br />  {<br />    return "Anger";<br />  }<br /><br />  public int abstractQuality()<br />  {<br />    return Ability.QUALITY_MALICIOUS;<br />  }<br /><br />  public long flags()<br />  {<br />    return Ability.FLAG_UNHOLY;<br />  }<br /><br />  public boolean invoke( MOB mob,<br />                         Vector commands,<br />                         Environmental givenTarget,<br />                         boolean auto,<br />                         int asLevel<br />                       )<br />  {<br />    if( !super.invoke( mob, commands, givenTarget, auto ) )<br />    {<br />      return false;<br />    }<br /><br />    boolean success = proficiencyCheck( mob, 0, auto );<br /><br />    boolean someoneIsFighting = false;<br />    for( int i = 0; i &lt; mob.location().numInhabitants(); i++ )<br />    {<br />      MOB inhab = mob.location().fetchInhabitant( i );<br />      if( ( inhab != null ) &amp;&amp; ( inhab.isInCombat() ) )<br />      {<br />        someoneIsFighting = true;<br />      }<br />    }<br /><br />    if( success<br />        &amp;&amp;( !someoneIsFighting )<br />        &amp;&amp;( mob.location().numInhabitants() &gt; 3 )<br />      )<br />    {<br />      // it worked, so build a copy of this ability,<br />      // and add it to the effects list of the<br />      // affected MOB.  Then tell everyone else<br />      // what happened.<br />      CMMsg msg = CMClass.getMsg( mob,<br />                                  null,<br />                                  this,<br />                                  affectType( auto ),<br />                                  auto ? "A feeling of anger descends" : "^S&lt;S-NAME&gt; rage(s) for anger.^?"<br />                                );<br /><br />      if( mob.location().okMessage( mob, msg ) )<br />      {<br />        mob.location().send( mob, msg );<br /><br />[.......]<br />}<br /></pre>

                                                 
      
      <p>           The first difference you may notice between this and
the Skill           Ability discussed in the previous section is that this
skill           extends the Prayer.java class instead of StdAbility. Prayer.java 
           will make sure that the <code>classificationCode()</code> method
 returns the           proper value.         </p>

                                                  
      
      <p>           You should also take note of the <code>flags()</code>
 method. All Prayers must           return a value from <code>flags()</code>
 where either the FLAG_UNHOLY is set           (meaning the Prayer is EVIL
 aligned), FLAG_HOLY is set (meaning the           Prayer is GOOD aligned),
 or BOTH are set, in which case the Prayer           is NEUTRAL.        
      </p>

                                                  
      
      <p>           The last special note is down in the message construction
 in the           <code>invoke()</code> method. The <code>invoke()</code>
method above           follows the one in Skill_Abilities very closely. You
will see that           no adjustment is made to the proficiency check, for
instance. The           main difference to notice here, however, is the line
constructing           the evoking message. You will notice that where the
message code           should be specified, a method call to <code>affectType()</code>,
 which is a           method located in Prayer.java, is made. This call will 
           automaticallyy construct the proper message type for a prayer, 
          taking into accountAbility.QUALITY_MALICIOUSness, and whether the 
           auto flag is set. You will also notice that different message 
         strings are constructed depending upon whether the auto flag is 
         set.         </p>

                                                  
      
      <h3><a name="chants" id="chants">Chants</a></h3>

                                                  
      
      <p>           Chants will follow all the rules mentioned above in the
 Skill           Abilities section, with a few differences:         </p>

                                                  
      
      <pre>public class Chant_AlterTime extends com.planet_ink.coffee_mud.Abilities.Druid.Chant<br />{<br />  public String ID()<br />  {<br />    return "Chant_AlterTime";<br />  }<br /><br />  public String name()<br />  {<br />    return "Alter Time";<br />  }<br /><br />  public String displayText()<br />  {<br />    return "";<br />  }<br /><br />  public int overrideMana()<br />  {<br />    return 100;<br />  }<br /><br />  public int abstractQuality()<br />  {<br />    return Ability.QUALITY_INDIFFERENT;<br />  }<br /><br />  protected int canAffectCode()<br />  {<br />    return 0;<br />  }<br /><br />  protected int canTargetCode()<br />  {<br />    return 0;<br />  }<br /><br />  public boolean invoke( MOB mob,<br />                         Vector commands,<br />                         Environmental givenTarget,<br />                         boolean auto,<br />                         int asLevel<br />                       )<br />  {<br />    if( !super.invoke( mob, commands, givenTarget, auto ) )<br />    {<br />      return false;<br />    }<br /><br />    boolean success = proficiencyCheck( mob, 0, auto );<br />    if( success )<br />    {<br />      // it worked, so build a copy of this ability,<br />      // and add it to the effects list of the<br />      // affected MOB.  Then tell everyone else<br />      // what happened.<br />      CMMsg msg = CMClass.getMsg( mob,<br />                                  null,<br />                                  this,<br />                                  affectType( auto ),<br />                                  auto ? "" : "^S&lt;S-NAME&gt; chant(s), and reality seems to start blurring.^?"<br />                                );<br /><br />      if( mob.location().okMessage( mob, msg ) )<br />      {<br />        mob.location().send( mob, msg );<br />        int x = CMath.s_int( text() );<br />        while( x == 0 )<br />        {<br />          x = CMLib.dice().roll( 1, 3, -2 );<br />        }<br /><br />        if( x &gt; 0 )<br />        {<br />          mob.location().showHappens( CMMsg.MSG_OK_VISUAL, "Time moves forwards!" );<br />        }<br />        else<br />        {<br />          mob.location().showHappens( CMMsg.MSG_OK_VISUAL, "Time moves backwards!" );<br />        }<br /><br />        if( CMLib.map().numAreas() &gt; 0 )<br />        {<br />          CMLib.map().getFirstArea().tickTock( x );<br />        }<br />      }<br />    }<br />    else<br />    {<br />      return beneficialWordsFizzle( mob,<br />                                    null,<br />                                    "&lt;S-NAME&gt; chant(s), but the magic fades"<br />                                  );<br />    }<br /><br />    // return whether it worked<br />    return success;<br />  }<br />}<br /></pre>

                                                 
      
      <p>           The first difference you may notice between this    
      and the Skill Ability discussed in the previous section is that   
       this skill extends the Chant.java class instead of StdAbility.   
       Chant.java will make sure that the <code>classificationCode()</code>
 method           returns the proper value.         </p>

                                                  
      
      <p>           You should also take note that the <code>overrideMana()</code> 
           method is actually returning a value here of 100. This method 
         allows your ability to always cost the same amount of mana,    
      regardless of the invokers level. This method may be used in any  
        ability, not just chants. Also, this is not a method that is    
      normally found in chants. This particular chant, being deemed to be 
           especially powerful, happens to return a value for it. Normally 
           this method would not be found.         </p>

                                                  
      
      <p>           The last special note is down in the message        
  construction in the <code>invoke()</code> method. The <code>invoke()</code> 
           method above follows the one in Skill_Abilities very closely. You
           will see that no adjustment is made to the proficiency check, for
           instance. The main difference to notice here, however, is the
line            constructing the evoking message. You will notice that where
the            message code should be specified, a method call to <code>affectType()</code>, 
           which is a method located in Chant.java, is made. This call will 
           automaticallyy construct the proper message type for a chant, taking
           into accountAbility.QUALITY_MALICIOUSness, and whether the auto
           flag is set. You will also notice that different message strings
           are constructed depending upon whether the auto flag is      
    set.         </p>

                <img src="images/elvis.jpg" alt="Songs" />
                                               
      
      <h2><a name="SONGS" id="SONGS">Songs</a></h2>

                                                  
      
      <p>           Although Songs also follow the Skill Abilities      
    rules above, they are the most unique of skills. More than any      
    other skill, they rely very heavily on basic functionality provide  
        by their appropriate superclasses. For your sanity, I recommend 
         that ALL of your coded songs extend either           com.planet_ink.coffee_mud.Abilities.Songs.Song, 
           com.planet_ink.coffee_mud.Abilities.Songs.Dance,           or com.planet_ink.coffee_mud.Abilities.Songs.Play.
This is because           those classes provide very important basic functionality
unique to           songs, and save you as the coder from having to worry
about coding           that unique functionality yourself.         </p>

                                                  
      
      <p>           By unique functionality, I am referring to the      
    way songs behave when invoked in particular. They are always        
  invoked upon groups, and always require the invoker to remain in      
    the room for the song to remain in effect.         </p>

                                          
      
      <pre>public class Song_Protection extends com.planet_ink.coffee_mud.Abilities.Songs.Song<br />{<br />  public String ID()<br />  {<br />    return "Song_Protection";<br />  }<br /><br />  public String name()<br />  {<br />    return "Protection";<br />  }<br /></pre>

                                                  
      
      <p>           Like the skill abilities above, <code>ID()</code> and
       <code>name()</code>           are implemented. The <code>name()</code>
 will get intermingled into the           invocation text, so name your songs
 carefully, so they sound right           when invoked!         </p>

                                                  
      
      <pre>  public int abstractQuality()<br />  {<br />    return Ability.QUALITY_BENEFICIAL_OTHERS;<br />  }<br />        </pre>

                                                  
      
      <p>           This method, discussed above for skill abilities,   
       is absolutely vital for Songs, as it tells the Song superclass   
       whether to invoke the song upon all your enemies, or upon all your 
           group members. Make sure you implement this method!         </p>

                                                  
      
      <pre>  public void affectEnvStats( Environmental affected, EnvStats affectableStats )<br />  {<br />    super.affectEnvStats( affected, affectableStats );<br />    if( invoker == null )<br />    {<br />      return;<br />    }<br /><br />    affectableStats.setAttackAdjustment( affectableStats.attackAdjustment() - 5 );<br />  }<br />        </pre>

                                                  
      
      <p>           This particular song uses affectEnvStats to lower   
       the attack rating of everyone that hears the song. Although this is 
           not a malicious song, it is the price of using it.         </p>

                                          
      
      <pre>  public void affectCharStats( MOB affected, CharStats affectableStats )<br />  {<br />    super.affectCharStats( affected, affectableStats );<br />    if( invoker == null )<br />    {<br />      return;<br />    }<br /><br />    affectableStats.setStat( CharStats.STAT_DEXTERITY,<br />                             affectableStats.getStat( CharStats.STAT_DEXTERITY ) - 1 );<br /><br />    affectableStats.setStat( CharStats.STAT_SAVE_ACID,<br />                             affectableStats.getStat( CharStats.STAT_SAVE_ACID )<br />                             + (<br />                                 invoker.charStats().getStat(<br />                                                              CharStats.STAT_CHARISMA<br />                                                            ) * 4<br />                               )<br />                           );<br /><br />    affectableStats.setStat( CharStats.STAT_SAVE_COLD,<br />                             affectableStats.getStat( CharStats.STAT_SAVE_COLD )<br />                             + (<br />                                 invoker.charStats().getStat(<br />                                                              CharStats.STAT_CHARISMA<br />                                                            ) * 4<br />                               )<br />                           );<br /><br />    affectableStats.setStat( CharStats.STAT_SAVE_ELECTRIC,<br />                             affectableStats.getStat( CharStats.STAT_SAVE_ELECTRIC )<br />                             + (<br />                                 invoker.charStats().getStat(<br />                                                              CharStats.STAT_CHARISMA<br />                                                            ) * 4<br />                               )<br />                           );<br /><br />    affectableStats.setStat( CharStats.STAT_SAVE_FIRE,<br />                             affectableStats.getStat( CharStats.STAT_SAVE_FIRE )<br />                             + (<br />                                 invoker.charStats().getStat(<br />                                                              CharStats.STAT_CHARISMA<br />                                                            ) * 4<br />                               )<br />                           );<br /><br />    affectableStats.setStat( CharStats.STAT_SAVE_GAS,<br />                             affectableStats.getStat( CharStats.STAT_SAVE_GAS )<br />                             + (<br />                                 invoker.charStats().getStat(<br />                                                              CharStats.STAT_CHARISMA<br />                                                            ) * 4<br />                               )<br />                           );<br />  }<br />}<br /></pre>

                                                    
      
      <p>           The most important thing our sample           song does
 is improve the saving throws of everyone who hears it.           The <code>affectCharStats()</code>
 method makes that happen by modifying the           appropriate saving throws
 in affectableStats.         </p>

               <img src="images/fun.jpg" alt="Common Skills" />
                                               
      
      <h2><a name="COMMON" id="COMMON">Common Skills</a></h2>

                                                  
      
      <p> There are actually 3 unique kinds of common skills. One type is
simply a normal skill, just like the ones shown above. Another type is the
gathering skill, which is used to collect resources, and extends com.planet_ink.coffee_mud.Abilities.Common.GatheringSkill.
The last type is the crafting skill, which extends com.planet_ink.coffee_mud.Abilities.Common.CraftingSkill.
In general, common skills have this in common: they invoke immediately, but
take a long time to complete. They give messages of progress to the user,
and they immediately unInvoke themselves if the user leaves the room, enters
combat, or some other canceling condition arises. </p>

                                                  
      
      <p><a name="skillgathering" id="skillgathering">&nbsp;</a>        
  Let's look at a Gathering skill. Although Crafting skills are much    
      more involved, especially in the way they select the items they   
       create, and in the way they fill-in the variables for what they are 
           creating, you will find them remarkably similar to gathering  
        skills.         </p>

                                                  
      
      <pre>public class Fishing extends com.planet_ink.coffee_mud.Abilities.Common.GatheringSkill<br />{<br />  public String ID()<br />  {<br />    return "Fishing";<br />  }<br /><br />  public String name()<br />  {<br />    return "Fishing";<br />  }<br />        </pre>

                                                  
      
      <p>           If you've read the Skill Abilities section above, you
 will           recognize these methods and their importance. As always,
the        <code>ID()</code>           must match the class name, while the
      <code>name()</code>  can be whatever you           want to call the
skill.         </p>

                                                  
      
      <pre>  private static final String[] triggerStrings = { "FISH" };<br />  public String[] triggerStrings()<br />  {<br />    return triggerStrings;<br />  }<br />        </pre>

                                                  
      
      <p>           And again, like a normal skill, the common skills create
 and return           their invocation words (or "trigger strings" as they
 are called in           skills).         </p>

                                                  
      
      <pre>  public long flags()<br />  {<br />    return FLAG_GATHERING;<br />  }<br /><br />  public String supportedResourceString()<br />  {<br />    return "FLESH";<br />  }<br />        </pre>

                                                  
      
      <p>           The <code>flags()</code> method you will also recognize
 from the Skill Abilities           section. However, we've provided the
system  at large with a flag to           let it know that this skill is
for gathering  resources, and not for           crafting.         </p>

                                                  
      
      <p>           The <code>supportedResourceString()</code> is a great
 supplementary method that           is unique to Common Skills. It's purpose
 is to inform the system           what kinds of MATERIALS and RESOURCES
are  utilized by this skill.           Fishing is for catching fish, so we'll
notify the system that we           deal in meat (flesh). Appropriate strings
to return from this           method are listed in           com.planet_ink.coffee_mud.Items.interfaces.RawMaterial.java.
 If           there is more than one resource or material type, they are
          separated with the pipe | character.         </p>

                                                  
      
      <pre>  protected Item found = null;<br />  protected String foundShortName = "";<br />        </pre>

                                                  
      
      <p>           Almost all the common skills create the item that they
 will           generate in the invoke method, store it in the skill, and
then           provide it when the skill is unInvoked. For this reason, we'll
need           some variables to store the object we will create, and a string
 for           its name.         </p>

                                                  
      
      <pre>  public Fishing()<br />  {<br />    super();<br />    displayText = "You are fishing...";<br />    verb = "fishing";<br />  }<br />        </pre>

                                                  
      
      <p>           Our constructor sets the variable "verb", which is part
 of the           CommonSkill superclass. It is used when constructing sentences 
           which let the user and others around them know what they are doing. 
           displayText serves the same purpose described by the Skill    
      Abilities section above.         </p>

                                                  
      
      <pre>  public boolean tick( Tickable ticking, int tickID )<br />  {<br />    if( ( affected != null )<br />        &amp;&amp; ( affected instanceof MOB )<br />        &amp;&amp; ( tickID == Tickable.TICKID_MOB )<br />      )<br />    {<br />      MOB mob = (MOB)affected;<br />      if( tickUp == 6 )<br />      {<br />        if( found != null )<br />        {<br />          commonTell( mob, "You got a tug on the line!" );<br />        }<br />        else<br />        {<br />          StringBuffer str = new StringBuffer( "Nothing is biting around here.\n\r" );<br />          commonTell( mob, str.toString() );<br />          unInvoke();<br />        }<br />      }<br />    }<br /><br />    return super.tick( ticking, tickID );<br />  }<br />        </pre>

                                                  
      
      <p>           Although our common skill super classes do most of the
 hard work of           maintaining the task being performed, you will still
 find that they           are often extended by individual common skills
in  other to give           more appropriate messages to the user. If you
don't  know what a           tick method is fore, read the Core Topic on
the subject  first. In           this case, before calling the superclasses
tick method  and letting           it do most of our work, we take a moment
to check the  tickUp           integer maintained by CommonSkill.java. That
variable is            incremented every 4 seconds after the skill is invoked.
in this            case, after 24 seconds (6*4), we let the user know whether
or not            an item was generated by the invoke method. If an an item 
was           invoked, we tell them they have hooked a fish. If an item was 
not            generated, we tell them that nothing is biting and immediately 
          <code>unInvoke()</code> the skill.         </p>

                                                  
      
      <p>           The <code>commonTell()</code> method is another feature
 unique to common skills.           Since common skills are often found on
 hireling mobs, we wanted a           special method which would tell players
 who invoke the skill about           the progress of our task, even if it
 is a follower that is actually           DOING the task. For instance, <code>commonTell()</code>
 would tell a player who is           fishing "You got a tug on the line!".
 However, commonTell would           force an NPC follower of a player to
SAY "I got a tug on the           line!".         </p>

                                                  
      
      <pre>  public void unInvoke()<br />  {<br />    if( canBeUninvoked() )<br />    {<br />      if( ( affected != null ) &amp;&amp; ( affected instanceof MOB ) )<br />      {<br />        MOB mob = (MOB)affected;<br />        if( ( found != null )<br />            &amp;&amp; ( !aborted )<br />            &amp;&amp;( !helping )<br />          )<br />        {<br />          int amount = CMLib.dice().roll( 1, 5, 0 ) * ( abilityCode() );<br />          String s = "s";<br />          if( amount == 1 )<br />          {<br />            s = "";<br />          }<br /><br />          mob.location().show( mob,<br />                               null,<br />                               CMMsg.MSG_NOISYMOVEMENT,<br />                               "&lt;S-NAME&gt; manage(s) to catch "<br />                                 + amount<br />                                 + " pound"<br />                                 + s<br />                                 + " of "<br />                                 + foundShortName<br />                                 + "."<br />                              );<br /><br />          for( int i = 0; i &lt; amount; i++ )<br />          {<br />            Item newFound = (Item)found.copyOf();<br />            mob.location().addItemRefuse( newFound, Item.REFUSE_PLAYER_DROP );<br /><br />            if( ( mob.riding() != null )<br />                &amp;&amp; ( mob.riding() instanceof Container )<br />              )<br />            {<br />              newFound.setContainer( (Container)mob.riding() );<br />            }<br /><br />            CMLib.commands().postGet( mob, null, newFound, true );<br />          }<br />        }<br />      }<br />    }<br /><br />    super.unInvoke();<br />  }<br />        </pre>

                                                  
      
      <p>           As mentioned above, the <code>unInvoke()</code> method
 is where the final work           is done. So long as the skill has not
been  aborted (the aborted           variable), or the skill was invoked
only to  help ANOTHER player           (the helping variable), we go ahead
and create  several copies of           our target item, put them in the
room using addItemRefuse,  and           force the player to get them into
their inventory (if they can).         </p>

                                                  
      
      <pre>  public boolean invoke( MOB mob,<br />                         Vector commands,<br />                         Environmental givenTarget,<br />                         boolean auto,<br />                         int asLevel<br />                       )<br />  {<br />    bundling = false;<br />    if( (!auto)<br />        &amp;&amp; ( commands.size() &gt; 0 )<br />        &amp;&amp; ( ( (String)commands.firstElement() ).equalsIgnoreCase( "bundle" ) )<br />      )<br />    {<br />      bundling = true;<br />      if( super.invoke( mob, commands, givenTarget, auto, asLevel ) )<br />      {<br />        return super.bundle( mob, commands );<br />      }<br /><br />      return false;<br />    }<br />        </pre>

                                                  
      
      <p>           The <code>invoke()</code> method is where common skills
 do 99% of their work,           namely determining what the user wants to
 do and whether they have           the resources and are in the right place
 to do it, and then           actually generating the target item and filling
 it out. Then the           invoke method actually places the filled-out
common  skill on the           player as an "effect", allowing it to receive
"tick"  calls until it           completes.         </p>

                                                  
      
      <p>           In this case, right off the bat we check to see if the
 user is           trying to use the Fishing skill to bundle up a pile of
fish. If so,           we call a superclass helper method to do the bundling
for us. The           bundle method which will happily use the <code>supportedResourceString()</code> 
           method above to determine what the player is allowed to       
   bundle.         </p>

                                                  
      
      <pre>    int foundFish = -1;<br />    boolean maybeFish = false;<br />    if( mob.location() != null )<br />    {<br />      for( int i = 0; i &lt; RawMaterial.FISHES.length; i++ )<br />      {<br />        if( mob.location().myResource() == RawMaterial.FISHES[i] )<br />        {<br />          foundFish = RawMaterial.FISHES[i];<br />          maybeFish = true;<br />        }<br />        else if( ( mob.location().resourceChoices() != null )<br />                 &amp;&amp; ( mob.location().resourceChoices().contains(<br />                                                                         new Integer(<br />                                                                                      RawMaterial.FISHES[i]<br />                                                                                    )<br />                                                                       )<br />                            )<br />               )<br />        {<br />          maybeFish = true;<br />        }<br />      }<br />    }<br />        </pre>

                                                  
      
      <p>           Our next step is to initialize a variable for the   
       com.planet_ink.coffee_mud.Items.interfaces.RawMaterial.java      
    (resource) code which will represent the type of fish we have       
   caught here. We also set a variable saying whether or not ANY fish   
       are even POSSIBLY available here.         </p>

                                                  
      
      <pre>    if( !maybeFish )<br />    {<br />      commonTell( mob, "The fishing doesn't look too good around here." );<br />      return false;<br />    }<br />        </pre>

                                                  
      
      <p>           If maybeFish is false, we are in a location where no
fish are even           possibly available (such as a Desert room).     
   </p>

                                                  
      
      <pre>    verb = "fishing";<br />    found = null;<br />    playSound = "fishreel.wav";<br />        </pre>

                                                  
      
      <p>           Otherwise, we re-initialize the "verb" and "found" variables
 we           mentioned above, and set a CommonSkill string called "playSound" 
           which will be used to give our skill a little sound effect while
 it           is working.         </p>

                                                  
      
      <pre>    if( !super.invoke( mob, commands, givenTarget, auto, asLevel ) )<br />    {<br />      return false;<br />    }<br />        </pre>

                                                  
      
      <p>           Next we call the GatherSkill superclass invoke method.
 It is           important to note that several qualifying checks are made
 in that           method, such as whether the player is able to perform
the  skill. It           also subtracts the necessary mana or movement points
for using the           skill.         </p>

                                                  
      
      <pre>    if( ( proficiencyCheck( mob, 0, auto ) )<br />        &amp;&amp; ( foundFish &gt; 0 )<br />      )<br />    {<br />      found = (Item)CMLib.materials().makeResource( foundFish, mob.location().domainType(), false );<br />      foundShortName = "nothing";<br />      if( found != null )<br />      {<br />        foundShortName = RawMaterial.RESOURCE_DESCS[ found.material()&amp;RawMaterial.RESOURCE_MASK ].toLowerCase();<br />      }<br />    }<br />        </pre>

                                                  
      
      <p>           Now we check to see if two important conditions have
occurred; the           first being whether the player has passed his or
her proficiency           check, and the second being whether the foundFish
variable was           assigned. Remember that the foundFish variable represents
the           material &amp; resource code for the type of fish we will catch.
 If           both of those are true, we make use of a very useful method
in the           <code>utensils()</code> library called makeResource to generate
 our item for us.           We also properly set the name of what we have
caught based on the           material type of the foundFish.         </p>

                                                  
      
      <pre>    int duration = 35 - mob.envStats().level();<br />    if( duration &lt; 10 )<br />    {<br />      duration=10;<br />    }<br /><br />    CMMsg msg = CMClass.getMsg( mob,<br />                                found,<br />                                this,<br />                                CMMsg.MSG_NOISYMOVEMENT,<br />                                "&lt;S-NAME&gt; start(s) fishing."<br />                              );<br /><br />    if( mob.location().okMessage( mob, msg ) )<br />    {<br />      mob.location().send( mob, msg );<br />      found = (Item)msg.target();<br />      beneficialAffect( mob, mob, asLevel, duration );<br />    }<br />    return true;<br />  }<br />}<br />        </pre>

                                                  
      
      <p>           Our last step is to calculate the amount of time (duration)
 that it           will take to catch the fish, create a coffeemud message
 to declare           the start of our finishing adventure, and send the
message  out.           After doing so, notice that we re-set the found variable
to            <code>msg.target()</code>. This may seem strange, since, in
the  getMsg method,           we already declared found to be our message
target.  So isn't that           like saying that A=A? Actually no! Remember
that the okMessage           method may preview or *modify* a message. Re-setting
the found           variable to <code>msg.target()</code> is done to support
code which may have           modified our target to something else.    
    </p>

                                                  
      
      <p><a name="skillcrafting" id="skillcrafting">&nbsp;</a>          
Now we'll take a look at a proper crafting skill. They are more         
 complicated than gathering skills, but you'll be able to apply         
 almost all you learned by reviewing the gathering skill to build a     
     good picture of the way crafting skills work. The first difference 
         is that the crafting skills extend           com.planet_ink.coffee_mud.Abilities.Common.CraftingSkill.
 Many of           them also implement the           com.planet_ink.coffee_mud.Abilities.interfaces.ItemCrafter 
           interface, which allows them to provide items to other parts of 
           coffeemud instantly!         </p>

                                                  
      
      <pre>public class GlassBlowing extends CraftingSkill implements ItemCraftor<br />{<br />  public String ID()<br />  {<br />    return "GlassBlowing";<br />  }<br /><br />  public String name()<br />  {<br />    return "Glass Blowing";<br />  }<br />        </pre>

                                                  
      
      <p>           If you've read the Skill Abilities section above, you
 will           recognize these methods and their importance. As always,
the        <code>ID()</code>           must match the class name, while the
      <code>name()</code>  can be whatever you           want to call the
skill.         </p>

                                                  
      
      <pre>  private static final String[] triggerStrings = { "GLASSBLOW", "GLASSBLOWING" };<br />  public String[] triggerStrings()<br />  {<br />    return triggerStrings;<br />  }<br />        </pre>

                                                  
      
      <p>           And again, like a normal skill, the common skills create
 and return           their invocation words (or "trigger strings" as they
 are called in           skills).         </p>

                                                  
      
      <pre>  public String supportedResourceString()<br />  {<br />    return "GLASS|SAND";<br />  }<br />        </pre>

                                                  
      
      <p>           The <code>supportedResourceString()</code> is a great
 supplementary method that           is unique to Common Skills. It's purpose
 is to inform the system           what kinds of MATERIALS and RESOURCES
are  utilized by this skill.           GlassBlowing is for turning sand into
glass,  so we'll notify the           system that we deal in sand and glass
resources.  Appropriate           strings to return from this method are
listed in           com.planet_ink.coffee_mud.Items.interfaces.RawMaterial.java.
If           there is more than one resource or material type, they are 
         separated with the pipe | character.         </p>

                                                  
      
      <pre>  protected static final int RCP_FINALNAME = 0;<br />  protected static final int RCP_LEVEL     = 1;<br />  protected static final int RCP_TICKS     = 2;<br />  protected static final int RCP_WOOD      = 3;<br />  protected static final int RCP_VALUE     = 4;<br />  protected static final int RCP_CLASSTYPE = 5;<br />  protected static final int RCP_MISCTYPE  = 6;<br />  protected static final int RCP_CAPACITY  = 7;<br />  protected static final int RCP_SPELL     = 8;<br />        </pre>

                                                  
      
      <p>           This list is at the core of the crafting skills     
     It represents the name and function of each column of the crafting 
         skill's text file. Later on, we will use these constants to index 
           into a Vector that represents the particular row from the crafting 
           skill's text file that the player is building.         </p>

                                                  
      
      <pre>  protected Item building    = null;<br />  protected Item fire        = null;<br />  protected boolean messedUp = false;<br />        </pre>

                                                  
      
      <p>           As in the gathering skill, we need to set up our    
      global variables to remember the object we are crafting, since it 
         will be constructed below in our invoke method, but not sent out 
           into the world until the unInvoke method. We also need a reference 
           to the fire object we are using, so we can watch and see if it
 goes           out.         </p>

                                                  
      
      <pre>  public boolean tick( Tickable ticking, int tickID )<br />  {<br />    if( ( affected != null )<br />        &amp;&amp; ( affected instanceof MOB )<br />        &amp;&amp; ( tickID == Tickable.TICKID_MOB )<br />      )<br />    {<br />      MOB mob = (MOB)affected;<br />      if( ( building == null )<br />          || ( fire == null )<br />          || ( !CMLib.flags().isOnFire( fire ) )<br />          || ( !mob.location().isContent( fire ) )<br />          || ( mob.isMine( fire ) )<br />        )<br />      {<br />        messedUp = true;<br />        unInvoke();<br />      }<br />    }<br />    return super.tick( ticking, tickID );<br />  }<br />        </pre>

                                                  
      
      <p>           Unlike the gathering skill, we will let the         
 superclass tick method do all the talking to the player. The only      
    job being done here is to make sure the fire didn't go out. If it   
       did, we declare the project messed up, and immediately unInvoke  
        it.         </p>

                                                  
      
      <pre>  protected Vector loadRecipes()<br />  {<br />    return super.loadRecipes( "glassblowing.txt" );<br />  }<br />        </pre>

                                                  
      
      <p>           Overriding the <code>loadRecipes()</code> method is absolutely 
           necessary for any crafting skill, as it specifies the recipes list.
           A recipes list is a comma-delimited file where each row is linefeed
           delimited. Each columns meaning is defined by the constants above.
           The loadRecipes(String) method will automaticallyy look in   
       $coffeemud-install-path/resources/skills for the file           specified.
         </p>

                                                  
      
      <pre>  public void unInvoke()<br />  {<br />    if( canBeUninvoked() )<br />    {<br />      if( ( affected != null ) &amp;&amp; ( affected instanceof MOB ) )<br />      {<br />        MOB mob = (MOB)affected;<br /><br />        if( ( building != null ) &amp;&amp; ( !aborted ) )<br />        {<br />          if( messedUp )<br />          {<br />            commonTell( mob,<br />                        CMStrings.capitalizeAndLower(<br />                                                      building.name())<br />                                                      + " explodes!"<br />                      );<br />          }<br />          else<br />          {<br />            mob.location().addItemRefuse( building, Item.REFUSE_PLAYER_DROP );<br />          }<br />        }<br /><br />        building = null;<br />      }<br />    }<br />    super.unInvoke();<br />  }<br />        </pre>

                                                  
      
      <p>           Just like in the gathering skill, the <code>unInvoke()</code> 
           method is where we actually give our product to the world. Its
 been           saved in the 'building' variable reference, so its just a
matter of           checking whether everything went ok and adding it to
the room if           things did. Since common skills work by adding themselves
as           affects on the player/mobs performing the skill, we need only
check           the StdAbility.affected reference variable to find our  
        craftor.         </p>

                                                  
      
      <pre>  public boolean invoke( MOB mob,<br />                         Vector commands,<br />                         Environmental givenTarget,<br />                         boolean auto,<br />                         int asLevel<br />                       )<br />  {<br />    int autoGenerate = 0;<br /><br />    if( ( auto )<br />        &amp;&amp; ( givenTarget == this )<br />        &amp;&amp; ( commands.size() &gt; 0 )<br />        &amp;&amp; ( commands.firstElement() instanceof Integer )<br />      )<br />    {<br />      autoGenerate = ( (Integer)commands.firstElement() ).intValue();<br />      commands.removeElementAt( 0 );<br />      givenTarget = null;<br />    }<br />        </pre>

                                                 
      
      <p>           Crafting skills are all outfitted with the          
ability to allow the rest of the system to use the skill class as       
   an automatic item generator. By convention, this is done by sending  
        in a commands vector (which is normally the parameter strings   
       entered by a user) with the first element as an Integer object   
       instead. This object then represents the material out of which the
           item should be made, and maps back to one of the           RawMaterial.RESOURCE_*
constants.         </p>

                                                  
      
      <pre>    randomRecipeFix( mob,<br />                     addRecipes( mob, loadRecipes() ),<br />                     commands,<br />                     autoGenerate<br />                   );<br />        </pre>

                                                 
      
      <p>           This complex line does the most important work      
    related to the autoGenerate flag we set above, and also to handle   
       the case where mobs are initiating this skill on their own.      
    Embedded are three method calls: one to get a vector of vectors     
     representing the skill row matrix (<code>loadRecipes()</code>), another
 to           append to this vector any recipe Items in the mobs inventory 
           (<code>addRecipes(..)</code>), and lastly, to randomly select a
recipe based on           the autoGenerate flag or if the invoker is an NPC
           (<code>randomRecipeFix()</code>). <code>randomRecipeFix()</code>
 can handle things like           modifying the parameter list (commands)
so that it has the name of           the random recipe selected.        
      </p>

                                                  
      
      <pre>    if( commands.size() == 0 )<br />    {<br />      commonTell( mob, "Make what? Enter \"glassblow list\" for a list." );<br />      return false;<br />    }<br /><br />    if( ( !auto )<br />        &amp;&amp; ( commands.size() &gt; 0 )<br />        &amp;&amp;( ( (String)commands.firstElement() ).equalsIgnoreCase( "bundle" ) )<br />      )<br />    {<br />      bundling = true;<br />      if( super.invoke( mob, commands, givenTarget, auto, asLevel ) )<br />      {<br />        return super.bundle( mob, commands );<br />      }<br /><br />      return false;<br />    }<br />        </pre>

                                                  
      
      <p>           Now we can finally start dealing the the           parameter
 list typed by the player, or generated by the system. The           parameter
 list (minus the command invoking word) is in the           "commands" vector
 as a set of strings. The first thing we do is           check the parameters
 to see if they want to generate a bundle of           raw resources. If
they  do, we call a superclass helper method to do           so and exit
-- this  is identical to the way it was done in the           gathering skill
above.          </p>

                                                  
      
      <pre>    Vector recipes = addRecipes( mob, loadRecipes() );<br />        </pre>

                                                  
      
      <p>           We're going to need that final recipes list so we   
       can search for the one the player entered into the command line. 
         Therefore we call <code>loadRecipes()</code> to get the list from
 our text file,           and then addRecipes to tack on any Recipe Items
in the mobs           inventory. What comes back is our vector of vectors,
representing           the rows and columns in the text file. Each vector
in the 'recipes'           vector can be index by the RCP_* constants above.
         </p>

                                                  
      
      <pre>    String str = (String)commands.elementAt( 0 );<br />    String startStr = null;<br />    bundling = false;<br />    int completion = 4;<br />        </pre>

                                                  
      
      <p>           Next we initialize a few important variables,       
   such as setting a variable for the first word in the parameters      
    (str), setting a default completion ticks (4), and initializing a   
       bundling flag to false. Even if the player did not explicitly use
          the word bundle in the parameters, they may still have selected
a           bundle item from the recipes list, so we need that flag to notify 
           the rest of the code of that fact.         </p>

                                                  
      
      <pre>    if( str.equalsIgnoreCase( "list" ) )<br />    {<br />      StringBuffer buf = new StringBuffer(<br />                                           CMStrings.padRight( "Item", 16 )<br />                                           + " Lvl Sand required\n\r"<br />                                         );<br /><br />      for( int r = 0; r &lt; recipes.size(); r++ )<br />      {<br />        Vector V = (Vector)recipes.elementAt( r );<br />        if( V.size() &gt; 0 )<br />        {<br />          String item = replacePercent( (String)V.elementAt( RCP_FINALNAME ), "" );<br />          int level = CMath.s_int( (String)V.elementAt( RCP_LEVEL ) );<br />          int wood = CMath.s_int( (String)V.elementAt( RCP_WOOD ) );<br />          if( level &lt;= mob.envStats().level() )<br />          {<br />            buf.append(<br />                        CMStrings.padRight( item, 16 )<br />                        + " "<br />                        + CMStrings.padRight( "" + level, 3 )<br />                        + " "<br />                        + wood<br />                        + "\n\r"<br />                      );<br />          }<br />        }<br />      }<br /><br />      commonTell( mob, buf.toString() );<br />      return true;<br />    }<br />        </pre>

                                                  
      
      <p>           If the player entered "list" as the first word in   
       the parameters, we display the recipes to them.         </p>

                                                  
      
      <pre>    fire = getRequiredFire( mob, autoGenerate );<br />    if( fire == null )<br />    {<br />      return false;<br />    }<br /><br />    building = null;<br />    messedUp = false;<br />        </pre>

                                                  
      
      <p>           Now we know we are definitely building something,   
       so we can initialize some more variables, such as the global     
     messedUp flag and the global building reference item. The global   
       fire reference item is also set here by calling a superclass helper 
           method <code>getRequiredFire(..)</code> which also has the benefit
 of giving the           user an error message if it fails to find a fire
to use. The           autoGenerate flag is sent in to tell the method to
skip the check           if we are simply using the invoke method to automaticallyy
 generate           an item.         </p>

                                                  
      
      <pre>    int amount = -1;<br />    if( ( commands.size() &gt; 1 )<br />        &amp;&amp; ( CMath.isNumber( (String)commands.lastElement() ) )<br />      )<br />    {<br />      amount = CMath.s_int( (String)commands.lastElement() );<br />      commands.removeElementAt( commands.size() - 1 );<br />    }<br />        </pre>

                                                  
      
      <p>           Our next step is to check the parameters list to    
      see if the player is specifying how much raw material they want to
          use in the construction of this item. The recipe list mentions
the            minimum amount of material, but the user is allowed to specify
 more           if they like. We'll save this override amount and confirm
its           validity later.         </p>

                                                  
      
      <pre>    String recipeName = CMParms.combine( commands, 0 );<br />    Vector foundRecipe = null;<br />    Vector matches = matchingRecipeNames( recipes, recipeName, true );<br />    for( int r = 0; r &lt; matches.size(); r++ )<br />    {<br />      Vector V = (Vector)matches.elementAt( r );<br />      if( V.size() &gt; 0 )<br />      {<br />        int level = CMath.s_int( (String)V.elementAt( RCP_LEVEL ) );<br />        if( ( autoGenerate &gt; 0 ) || ( level &lt;= mob.envStats().level() ) )<br />        {<br />          foundRecipe = V;<br />          break;<br />        }<br />      }<br />    }<br />        </pre>

                                                  
      
      <p>           Now we can actually get to the important part of    
      making sure that the recipe name entered by the players into the  
        command line is actually a valid recipe. We do that by combining
          the remaining strings on the command line into a single variable 
           "recipeName", and then calling a superclass helper method called 
           "matchingRecipeNames" to generate a subset of the master recipe 
           list which matches that name. Once we have this list of matching 
           recipes, we can select the winner based on level (unless we are 
           performing an auto-generation, in which case level doesn't matter). 
           Our winning recipe is stored in a single vector of strings called 
           foundRecipe, which we can index by the RCP_*           constants. 
         </p>

                                                  
      
      <pre>    if( foundRecipe == null )<br />    {<br />      commonTell( mob,<br />                  "You don't know how to make a '"<br />                    + recipeName<br />                    + "'. Try \"glassblow list\" for a list."<br />                );<br />      return false;<br />    }<br />        </pre>

                                                  
      
      <p>           Of course, if no recipe matched, or none met the    
      level requirements, our matched row vector will be null, in which 
         case we error out.         </p>

                                                  
      
      <pre>    int woodRequired = CMath.s_int( (String)foundRecipe.elementAt( RCP_WOOD ) );<br />    if( amount &gt; woodRequired )<br />    {<br />      woodRequired = amount;<br />    }<br /><br />    String misctype = (String)foundRecipe.elementAt( RCP_MISCTYPE );<br />    bundling = misctype.equalsIgnoreCase( "BUNDLE" );<br />    int[] pm = { RawMaterial.RESOURCE_SAND,<br />                 RawMaterial.RESOURCE_CRYSTAL,<br />                 RawMaterial.RESOURCE_GLASS<br />               };<br /><br />    int[][] data = fetchFoundResourceData( mob,<br />                                           woodRequired,<br />                                           "sand",<br />                                           pm,<br />                                           0,<br />                                           null,<br />                                           null,<br />                                           bundling,<br />                                           autoGenerate<br />                                         );<br />    if( data == null )<br />    {<br />      return false;<br />    }<br /><br />    woodRequired = data[0][FOUND_AMT];<br />        </pre>

                                                  
      
      <p>           However, if we did find a matching row, its time to start
 pulling           information out of that row and start using it. The first
 thing we           check is the minimum required raw materials (woodRequired)
 which           can be modified by a larger "amount" variable by the player
 if they           entered one. We also draw out the general modifier string 
           "misctype", which can be used to specify parameters on the item 
           being generated. For instance, is the misctype column says    
      "bundle", we know that we are bundling raw resources and can set  
        our bundling flag to true.         </p>

                                                  
      
      <p>           The next step is a bit more complicated. The pm     
     array is constructed of RawMaterial.RESOURCE_* constants which     
     represent those material or resource types valid for making the    
      items in this common skill. Next we call the powerful superclass  
        method fetchFoundResourceData which will return to us the amount
          and specific type of valid resources found, and give an error if 
           none are found. Of course it doesn't really matter with the   
       autoGenerate flag, so it will take that into account as          
well. The returned array "data"           has two dimensions, 0 for the primary
resource,           and 1 for a secondary resource if applicable (its not
applicable           here). Each dimension can be dereferenced using superclass
FOUND_*           constants. For instance, we can get a final "woodRequired"
value           from the data integer array.         </p>

                                                  
      
      <pre>    if( !super.invoke( mob, commands, givenTarget, auto, asLevel ) )<br />    {<br />      return false;<br />    }<br />        </pre>

                                                  
      
      <p>           Just like for gathering skills, the superclass      
    invoke method is called to take care of mana consumption, and to    
      make sure the person trying to do the crafting is not asleep or   
       dead.         </p>

                                                  
      
      <pre>    int lostValue = destroyResources( mob.location(),<br />                                      woodRequired,<br />                                      data[0][FOUND_CODE],<br />                                      0,<br />                                      null,<br />                                      autoGenerate<br />                                    );<br /><br />    building = CMClass.getItem( (String)foundRecipe.elementAt( RCP_CLASSTYPE ) );<br /><br />    if( building == null )<br />    {<br />      commonTell( mob,<br />                  "There's no such thing as a "<br />                    + foundRecipe.elementAt( RCP_CLASSTYPE )<br />                    + "!!!" );<br />      return false;<br />    }<br />        </pre>

                                                 
      
      <p>           Our next step is to call another superclass         
 method <code>destroyResources()</code> which will remove the resources from
 the           room which are used to construct the item. After that, we
can            actually initialize the building item reference so we can
begin  to           fill it out. The building variable will remain referenced
only  by           the common skill class until the <code>unInvoke()</code>
method  is called, when it           will be given to the craftor.      
  </p>

                                                  
      
      <pre>    completion = CMath.s_int(<br />                              (String)foundRecipe.elementAt( RCP_TICKS )<br />                            )<br />                            - (<br />                                (<br />                                  mob.envStats().level()<br />                                  - CMath.s_int(<br />                                                 (String)foundRecipe.elementAt( RCP_LEVEL )<br />                                               )<br />                                ) * 2<br />                              );<br /><br />    String itemName = replacePercent(<br />                                      (String)foundRecipe.elementAt( RCP_FINALNAME ),<br />                                      RawMaterial.RESOURCE_DESCS[<br />                                        (data[0][FOUND_CODE]&amp;RawMaterial.RESOURCE_MASK)<br />                                                                ]<br />                                    ).toLowerCase();<br /><br />    if( bundling )<br />    {<br />      itemName = "a " + woodRequired + "# " + itemName;<br />    }<br />    else<br />    {<br />      itemName = CMStrings.startWithAorAn( itemName );<br />    }<br /><br />    building.setName( itemName );<br />    startStr = "&lt;S-NAME&gt; start(s) blowing " + building.name() + ".";<br />    displayText = "You are blowing " + building.name();<br />    verb = "blowing " + building.name();<br />    playSound = "fire.wav";<br />    building.setDisplayText( itemName + " is here" );<br />    building.setDescription( itemName + ". " );<br />    building.baseEnvStats().setWeight( woodRequired );<br />    building.setBaseValue( CMath.s_int( (String)foundRecipe.elementAt( RCP_VALUE ) ) );<br />        </pre>

                                                  
      
      <p>           Now that we have a reference to the item object     
     we are building, we can start filling in some fields, such as its  
        name, display text, weight, and base value, usually from columns
in           our recipe text file. We can also derive the final completion
           variable, representing the number of ticks it will take to complete 
           the item.         </p>

                                                  
      
      <pre>    if( data[0][FOUND_CODE] == RawMaterial.RESOURCE_SAND )<br />    {<br />      building.setMaterial( RawMaterial.RESOURCE_GLASS );<br />    }<br />    else<br />    {<br />      building.setMaterial( data[0][FOUND_CODE] );<br />    }<br /><br />    building.baseEnvStats().setLevel(<br />                                      CMath.s_int(<br />                                                   (String)foundRecipe.elementAt( RCP_LEVEL )<br />                                                 )<br />                                    );<br /><br />    building.setSecretIdentity( "This is the work of " + mob.Name() + "." );<br />    int capacity = CMath.s_int( (String)foundRecipe.elementAt( RCP_CAPACITY ) );<br />    String spell = ( foundRecipe.size() &gt; RCP_SPELL ) ?<br />                     ( (String)foundRecipe.elementAt( RCP_SPELL ) ).trim()<br />                     : "";<br /><br />    addSpells( building, spell );<br />        </pre>

                                                  
      
      <p>           Continuing with our mission of filling out the      
    building object, we set the material type, level, and secret        
  identity. We also add any properties to it that are listed in the     
     recipe text file by calling the superclass helper method           <code>addSpells()</code>.
 There is also a column in the recipe file for the           capacity of
the  item if it is a container.         </p>

                                                  
      
      <pre>    if( building instanceof Container )<br />    {<br />      if( capacity &gt; 0 )<br />      {<br />        ( (Container)building ).setCapacity( capacity + woodRequired );<br />      }<br /><br />      if( misctype.equalsIgnoreCase( "LID" ) )<br />      {<br />        ( (Container)building ).setLidsNLocks( true, false, false, false );<br />      }<br />      else if( misctype.equalsIgnoreCase( "LOCK" ) )<br />      {<br />        ( (Container)building ).setLidsNLocks( true, false, true, false );<br />        ( (Container)building ).setKeyName(<br />                                            new Double(<br />                                                        Math.random()<br />                                                      ).toString()<br />                                          );<br />      }<br /><br />      ( (Container)building ).setContainTypes( Container.CONTAIN_ANYTHING );<br />    }<br />        </pre>

                                                  
      
      <p>           If, in fact, the item we are building is a          
container, we'll set the capacity of the container, and use our         
 general purpose "misctype" column from the table to determine          
whether a lit or lock needs to be made.         </p>

                                                  
      
      <pre>    if( building instanceof Drink )<br />    {<br />      if( CMLib.flags().isGettable( building ) )<br />      {<br />        ( (Drink)building ).setLiquidRemaining( 0 );<br />        ( (Drink)building ).setLiquidHeld( capacity * 50 );<br />        ( (Drink)building ).setThirstQuenched( 250 );<br /><br />        if( ( capacity * 50 ) &lt; 250 )<br />        {<br />          ( (Drink)building ).setThirstQuenched( capacity * 50 );<br />        }<br />      }<br />    }<br /><br />    if( bundling )<br />    {<br />      building.setBaseValue( lostValue );<br />    }<br />        </pre>

                                                  
      
      <p>           If the item is a Drinkable, then we have a few      
    more fields to fill out, based on the capacity column. The last     
     line makes sure that the gold value of the item reflects the sum of
          the materials used, in case we are bundling.         </p>

                                                  
      
      <pre>    building.recoverEnvStats();<br />    building.text();<br />    building.recoverEnvStats();<br />        </pre>

                                                  
      
      <p>           The filling out of the item is complete, so we      
    call <code>recoverEnvStats()</code>, populate the miscText field if the
 item is           Generic, and then recover the env stats again in case
that  changed           anything.         </p>

                                                  
      
      <pre>    messedUp =! proficiencyCheck( mob, 0, auto );<br />    if( completion &lt; 4 )<br />    {<br />      completion = 4;<br />    }<br /><br />    if( bundling )<br />    {<br />      messedUp = false;<br />      completion = 1;<br />      verb = "bundling "<br />             + RawMaterial.RESOURCE_DESCS[<br />             ( building.material()&amp;RawMaterial.RESOURCE_MASK)<br />             ].toLowerCase();<br /><br />      startStr = "&lt;S-NAME&gt; start(s) " + verb + ".";<br />      displayText = "You are " + verb;<br />    }<br />        </pre>

                                                  
      
      <p>           Now we can set our messedUp flag based on a         
 proficiency check, and change our common skill player-message          
strings based on whether we are bundling.         </p>

                                                  
      
      <pre>    if( autoGenerate &gt; 0 )<br />    {<br />      commands.addElement( building );<br />      return true;<br />    }<br />        </pre>

                                                  
      
      <p>           If the invoke method was called simply to           generate
 the item, we are done -- we can add the item to the           commands vector
 (where it will be expected), and           return.         </p>

                                                  
      
      <pre>    CMMsg msg = CMClass.getMsg( mob,<br />                                building,<br />                                this,<br />                                CMMsg.MSG_NOISYMOVEMENT,<br />                                startStr<br />                              );<br /><br />    if( mob.location().okMessage( mob, msg ) )<br />    {<br />      mob.location().send( mob, msg );<br />      building = (Item)msg.target();<br />      beneficialAffect( mob, mob, asLevel, completion );<br />    }<br />    else if( bundling )<br />    {<br />      messedUp = false;<br />      aborted = false;<br />      unInvoke();<br />    }<br />    return true;<br />  }<br />}<br />        </pre>

                                                  
      
      <p>           Last but not least, we do exactly what we did in    
      our gathering skill, namely generate a message for this event, and
          add the common skill as an effect to the invoker of it. The   
       completion time is used to determine how long it will take to    
      generate the item.         </p>

                <img src="images/prayer.jpg" alt="poisons" />
                                               
      
      <h2><a name="POISON" id="POISON">Poisons</a></h2>

                                                  
      
      <pre>public class Poison_BeeSting extends com.planet_ink.coffee_mud.Abilities.Poisons.Poison<br />{<br />  public String ID()<br />  {<br />    return "Poison_BeeSting";<br />  }<br /><br />  public String name()<br />  {<br />    return "Bee Sting";<br />  }<br /></pre>

                                                 
      
      <p>           The Poison base class in the Poisons package provides
 a tidy           template upon which your more common, mundane poisons can
 be based.           The first three methods are those required by any Environmental 
           class. The fact that none of the other preliminary methods normally 
           found in skill abilities are present is a testimony to the    
      homogeneous nature of Poisons.         </p>

                                                  
      
      <pre>  private static final String[] triggerStrings = { "POISONSTING" };<br />  public String[] triggerStrings()<br />  {<br />    return triggerStrings;<br />  }<br /></pre>

                                                 
      
      <p>           Poisons have the feature of having their own trigger
commands,           meaning they can be added as attack abilities to monsters
(like a           Bee in this case).         </p>

                                                  
      
      <pre>  protected String POISON_DONE()<br />  {<br />    return "The stinging poison runs its course.";<br />  }<br /><br />  protected String POISON_START()<br />  {<br />    return "^G&lt;S-NAME&gt; turn(s) green.^?";<br />  }<br /><br />  protected String POISON_CAST()<br />  {<br />    return "^F&lt;S-NAME&gt; sting(s) &lt;T-NAMESELF&gt;!^?";<br />  }<br /><br />  protected String POISON_FAIL()<br />  {<br />    return "&lt;S-NAME&gt; attempt(s) to sting &lt;T-NAMESELF&gt;, but fail(s).";<br />  }<br /></pre>

                                                 
      
      <p>           In this set of methods, strings are defined for the invocation
 of           the poison, all the way through its recovery string.      
        </p>

                                                  
      
      <pre>  protected int POISON_TICKS()<br />  {<br />    return 10; // 0 means no adjustment!<br />  }<br /></pre>

                                                 
      
      <p>           Poisons can have a variable duration dependent upon level
 (by           returning 0) or can have a set duration on the poisoned creature. 
         </p>

                                                  
      
      <pre>  protected int POISON_DELAY()<br />  {<br />    return 2;<br />  }<br /><br />  protected int POISON_DAMAGE()<br />  {<br />    return ( invoker != null ) ? 2 : 0;<br />  }<br /><br />  protected String POISON_AFFECT()<br />  {<br />    return "&lt;S-NAME&gt; cringe(s) from the poisonous itch.";<br />  }<br /></pre>

                                                 
      
      <p>           Poisons can also be set to cause the poisoned creature
 to emote on           a regular basis, and to take damage as well. Here
you  can see three           methods being used to designate how often the
emote/damage  cycle           occurs (in ticks) as well as the amount of
damage, and the  text of           the emote.         </p>

                                                  
      
      <pre>  public void affectCharStats( MOB affected, CharStats affectableStats )<br />  {<br />    affectableStats.setStat(<br />                              CharStats.STAT_CONSTITUTION,<br />                              affectableStats.getStat(<br />                                                       CharStats.STAT_CONSTITUTION<br />                                                     ) - 1<br />                           );<br /><br />    affectableStats.setStat(<br />                              CharStats.STAT_STRENGTH,<br />                              affectableStats.getStat(<br />                                                       CharStats.STAT_STRENGTH<br />                                                     ) - 1<br />                           );<br /><br />    if( affectableStats.getStat( CharStats.STAT_CONSTITUTION ) &lt;= 0 )<br />    {<br />      affectableStats.setStat( CharStats.STAT_CONSTITUTION, 1 );<br />    }<br /><br />    if( affectableStats.getStat( CharStats.STAT_STRENGTH ) &lt;= 0 )<br />    {<br />      affectableStats.setStat( CharStats.STAT_STRENGTH, 1 );<br />    }<br />  }<br />}<br /></pre>

                                                 
      
      <p>           And lastly, as described under the Core Topic on state
 affects, we           have the code which lowers the poisoned creatures
constitution  and           strength while the poison is in effect. We even
have a few lines to           make sure the values don't fall below 0.  
      </p>

               <img src="images/disease.jpg" alt="Diseases" />
                                               
      
      <h2><a name="DISEASE" id="DISEASE">Diseases</a></h2>

                                                  
      
      <p>           Like Poison, the Disease base class in the Diseases package 
           provides a tidy template upon which your more common, mundane 
         diseases can be based.         </p>

                                                  
      
      <pre>public class Disease_Cold extends com.planet_ink.coffee_mud.Abilities.Diseases.Disease<br />{<br />  public String ID()<br />  {<br />    return "Disease_Cold";<br />  }<br /><br />  public String name()<br />  {<br />    return "Cold";<br />  }<br /><br />  public String displayText()<br />  {<br />    return "(Cold Virus)";<br />  }<br /><br />  protected int canAffectCode()<br />  {<br />    return CAN_MOBS;<br />  }<br /><br />  protected int canTargetCode()<br />  {<br />    return CAN_MOBS;<br />  }<br /><br />  public int abstractQuality()<br />  {<br />    return Ability.QUALITY_MALICIOUS;<br />  }<br /><br />  public boolean putInCommandlist()<br />  {<br />    return false;<br />  }<br /></pre>

                                                 
      
      <p>           The Disease base class provides many important base services
 that           allows CoffeeMud to interact properly with your disease.
For  this           reason, making a disease that extends the Disease base
class  is           highly recommended. In the first half dozen methods,
we see the           important values of a standard skill being defined.
See the            introduction to Skill Abilities if you need more details
on these            methods.         </p>

                                                  
      
      <pre>  protected String DISEASE_DONE()<br />  {<br />    return "Your cold clears up.";<br />  }<br /><br />  protected String DISEASE_START()<br />  {<br />    return "^G&lt;S-NAME&gt; come(s) down with a cold.^?";<br />  }<br /></pre>

                                                 
      
      <p>           In this set of methods, strings are defined for the invocation
 of           the disease as well as its recovery string.         </p>

                                                  
      
      <pre>  protected int DISEASE_TICKS()<br />  {<br />    return 24;<br />  }<br /></pre>

                                                 
      
      <p>           Diseases can have a variable duration dependent upon
level (by           returning 0) or can have a set duration on the diseased
creature.         </p>

                                                  
      
      <pre>  protected int DISEASE_DELAY()<br />  {<br />    return 5;<br />  }<br /><br />  protected String DISEASE_AFFECT()<br />  {<br />    return "&lt;S-NAME&gt; sneeze(s). AAAAAAAAAAAAAACHOOO!!!!";<br />  }<br /></pre>

                                                 
      
      <p>           Diseases can also be set to cause the poisoned creature
 to emote on           a regular basis. Here you can see a pair of methods
 being used to           designate how often the emote/damage cycle occurs
 (in ticks) as           well as the text of the emote. Any damage or other
 consequences of           the disease are defined later.         </p>

                                                  
      
      <pre>  public int abilityCode()<br />  {<br />    return DiseaseAffect.SPREAD_CONSUMPTION<br />           |DiseaseAffect.SPREAD_PROXIMITY<br />           |DiseaseAffect.SPREAD_CONTACT<br />           |DiseaseAffect.SPREAD_STD;<br />  }<br /></pre>

                                                 
      
      <p>           This important method is used to define how the disease
 is spread.           Some aspects of disease catching must be coded by the
 programmer of           the disease. Some aspects are handled by the engine,
 while most are           handled by the Disease base class. This method
is  used to           coordinate the efforts on behalf of the disease by
the CoffeeMud           engine as a whole. Different bit values are defined
by the           DiseaseAffect interface.         </p>

                                                  
      
      <pre>  public boolean tick( Tickable ticking, int tickID )<br />  {<br />    if( !super.tick( ticking,tickID ) )<br />    {<br />      return false;<br />    }<br /><br />    if( affected == null )<br />    {<br />      return false;<br />    }<br /><br />    if( !( affected instanceof MOB ) )<br />    {<br />      return true;<br />    }<br /><br />    MOB mob = (MOB)affected;<br />    MOB diseaser = invoker;<br />    if( diseaser == null )<br />    {<br />      diseaser = mob;<br />    }<br /></pre>

                                                 
      
      <p>           If a disease does anything during its delay cycle (defined
 above by           <code>DISEASE_DELAY()</code>), then the programmer must
 implement a tick method           to take care of this functionality. These
 first few lines of the           method are error and state checking, as
well as defining some           useful variables, such as who caused the
disease (diseaser), and           who has the disease (mob)         </p>

                                                  
      
      <pre>    if( ( getTickDownRemaining() == 1 )<br />        &amp;&amp;( CMLib.dice().rollPercentage() &gt; mob.charStats().getSave( CharStats.STAT_SAVE_COLD ) )<br />        &amp;&amp;( CMLib.dice().rollPercentage() &lt; 25 - mob.charStats().getStat( CharStats.STAT_CONSTITUTION ) )<br />        &amp;&amp;( !mob.amDead() )<br />        &amp;&amp;( !mob.isMonster() )<br />      )<br />    {<br />      mob.delEffect( this );<br />      Ability A = CMClass.getAbility( "Disease_Pneumonia" );<br />      A.invoke( diseaser, mob, true );<br />    }<br /></pre>

                                                 
      
      <p>           One of the things we have decided to do in the disease
 Cold is to           make it so that, if the creature does not cure the
disease  before           it expires naturally, they will almost certainly
catch Pneumonia.            By checking <code>getTickDownRemaining()</code>,
we check out counter which runs           downwards from <code>DISEASE_TICKS()</code> 
to 0. At a value of 1, we make a           saving throw check for the creature 
with the cold, and potentially           give them another disease to enjoy 
when the Cold expires 1 tick           later.         </p>

                                                  
      
      <pre>    else if( ( !mob.amDead() ) &amp;&amp; ( ( --diseaseTick ) &lt;= 0 ) )<br />    {<br />      diseaseTick = DISEASE_DELAY();<br />      mob.location().show( mob, null, CMMsg.MSG_NOISE, DISEASE_AFFECT() );<br />      if( mob.curState().getHitPoints() &gt; ( ( 2 * diseaser.envStats().level() ) + 1 ) )<br />      {<br />        int damage = CMLib.dice().roll( 2, diseaser.envStats().level(), 1 );<br />        CMLib.combat().postDamage( diseaser,<br />                                   mob,<br />                                   this,<br />                                   damage,<br />                                   CMMsg.MASK_ALWAYS|CMMsg.TYP_DISEASE,<br />                                   -1,<br />                                   null<br />                                 );<br />      }<br /><br />      catchIt( mob );<br />      return true;<br />    }<br />    return true;<br />  }<br /></pre>

                                                 
      
      <p>           The last thing we do in this method is, every <code>DISEASE_DELAY()</code>
 ticks,           we emote our DISEASE_AFFECT string, and then allow the
creature  to           take a few points of disease damage by calling the
                <code>MUDFight.postDamage()</code> method. After this, we
also call the           <code>catchIt(MOB mob)</code> method up in the Disease
base class. This           important method spreads the disease among those
in the same room           as the creature, thereby handling any diseases
spread by proximity            as defined in <code>abilityCode()</code> above.
        </p>

                                                  
      
      <pre>  public void affectCharStats( MOB affected, CharStats affectableStats )<br />  {<br />    if( affected == null )<br />    {<br />      return;<br />    }<br /><br />    affectableStats.setStat(<br />                              CharStats.STAT_CONSTITUTION,<br />                              affectableStats.getStat(<br />                                                       CharStats.STAT_CONSTITUTION<br />                                                     ) - 2<br />                           );<br /><br />    affectableStats.setStat(<br />                              CharStats.STAT_STRENGTH,<br />                              affectableStats.getStat(<br />                                                       CharStats.STAT_STRENGTH<br />                                                     ) - 3<br />                           );<br /><br />    if( affectableStats.getStat( CharStats.STAT_CONSTITUTION ) &lt;= 0 )<br />    {<br />      affectableStats.setStat( CharStats.STAT_CONSTITUTION, 1 );<br />    }<br /><br />    if( affectableStats.getStat( CharStats.STAT_STRENGTH ) &lt;= 0 )<br />    {<br />      affectableStats.setStat( CharStats.STAT_STRENGTH, 1 );<br />    }<br />  }<br />}<br /></pre>

                                                 
      
      <p>           And lastly, as described under the Core Topic on state
 affects, we           have the code which lowers the diseased creatures
constitution  and           strength while the disease is in effect. We even
have a few  lines           to make sure the values don't fall below 0. 
       </p>

               <img src="images/traps.jpg" alt="Traps" />
                                               
      
      <h2><a name="TRAPS" id="TRAPS">Traps</a></h2>

                                                  
      
      <p>           Traps and Bombs are so similar, that the           differences
 are not worth mentioning. However, although they are           classified
 as skill abilities, they are different from normal Skill           Abilities
 mentioned above in that they rely very heavily on their           superclass
 bases, which are           com.planet_ink.coffee_mud.Abilities.Traps.StdTrap,
 and           com.planet_ink.coffee_mud.Abilities.Traps.StdBomb        
  respectively. Making a proper and compliant trap is helped           considerably
 by following that advice. Otherwise, so long as your           trap implements
 the           com.planet_ink.coffee_mud.Abilities.interfaces.Trap interface,
 it           will be ok.         </p>

                                                  
      
      <pre>public class Trap_ElectricShock extends com.planet_ink.coffee_mud.Abilities.Traps.StdTrap<br />{<br />  public String ID()<br />  {<br />    return "Trap_ElectricShock";<br />  }<br /><br />  public String name()<br />  {<br />    return "electric shock";<br />  }<br />        </pre>

                                                  
      
      <p>           If you've read the Skill Abilities section above,   
       you will recognize these methods and their importance. As always,
          the <code>ID()</code> must match the class name, while the <code>name()</code>
 can be           whatever you want to call the skill.         </p>

                                                  
      
      <pre>  protected int canAffectCode()<br />  {<br />    return Ability.CAN_ITEMS|Ability.CAN_EXITS;<br />  }<br /><br />  protected int canTargetCode()<br />  {<br />    return 0;<br />  }<br />        </pre>

                                                  
      
      <p>           It is very important, even more so than normal      
    skills, to make sure that your StdAbility <code>canAffectCode()</code>
 method           returns a proper value. Some traps can be placed on rooms
 (floors),           and some on items, and others on exits. Make sure your
 method           informs StdAbility what your trap will do.         </p>

                                                  
      
      <pre>  protected int trapLevel()<br />  {<br />    return 19;<br />  }<br />        </pre>

                                                  
      
      <p>           The <code>trapLevel()</code> is the class level of your
 trap.           In general, a player needs this many levels in their trap-laying 
           class before they can create this trap.         </p>

                                                  
      
      <pre>  public String requiresToSet()<br />  {<br />    return "10 pounds of metal";<br />  }<br />        </pre>

                                                  
      
      <p>           This is another trap-specific method which is       
   used by the Set Traps skill to inform the user of what kinds of      
    extra-materials are required by the user before they can lay this   
       particular trap. It will be enforced below in the canSetTrap and 
         setTrap methods.         </p>

                                                  
      
      <pre>  public Trap setTrap( MOB mob,<br />                       Environmental E,<br />                       int trapBonus,<br />                       int qualifyingClassLevel,<br />                       boolean permanent<br />                     )<br />  {<br />    if( E == null )<br />    {<br />      return null;<br />    }<br /><br />    if( mob != null )<br />    {<br />      Item I = findMostOfMaterial( mob.location(), RawMaterial.MATERIAL_METAL );<br />      if( I != null )<br />      {<br />        super.destroyResources( mob.location(), I.material(), 10 );<br />      }<br />    }<br />    return super.setTrap( mob, E, trapBonus, qualifyingClassLevel, permanent );<br />  }<br />        </pre>

                                                  
      
      <p>           This method is used to actually set the trap,       
   well before the trap is sprung. Springing is handles by the StdTrap  
        superclass system, and is based on what is returned by the      
    <code>canAffectCode()</code> method. The setTrap method received the
mob/player           setting the trap, the item onto which the trap is being
set (E -- I           know, very descriptive; sue me), the trapBonus of the
trap setter, if any, and at what level they first qualified for         
 this trap. In this particular method, we use some helper methods       
   from StdTrap to find all of the metal in the room, and then use      
    another StdTrap superclass method to remove the found metal from    
      the room.       <code>findMostOfMaterial()</code> will look for any
raw material Metals           in the room, and return an example Item representing
the specific           type (bronze, iron, gold) of metal that is most numerous
in the           room. The <code>destroyResources()</code> method then will
remove 10 of those from           the room.         </p>

                                                  
      
      <pre>  public boolean canSetTrapOn( MOB mob, Environmental E )<br />  {<br />    if( !super.canSetTrapOn( mob, E ) )<br />    {<br />      return false;<br />    }<br /><br />    if( mob != null )<br />    {<br />      Item I = findMostOfMaterial( mob.location(), RawMaterial.MATERIAL_METAL );<br />      if( ( I == null )<br />          || ( super.findNumberOfResource( mob.location(), I.material() ) &lt; 10 )<br />        )<br />      {<br />        mob.tell( "You'll need to set down at least 10 pounds of metal first." );<br />        return false;<br />      }<br />    }<br />    return true;<br />  }<br />        </pre>

                                                  
      
      <p>           This method is called before the <code>setTrap()</code>
 method           to determine whether the given player/mob is allowed or
able to set           the trap on the given object (E). Just as we did in
setTrap above,           we use <code>findMostOfMaterial()</code> to determine
what the most numerous metal           resource on the room is, then call
another StdTrap superclass           method, <code>findNumberOfResource()</code>,
 to make sure there is enough of this           particular metal resource
to do the job. If not, we inform the user           and return false from
the method. If everything is fine, we return           true. Notice that
we were careful to call the superclass version of           this method --
it does important things for us also, so it should           definitely be
called!         </p>

                                                  
      
      <pre>  public void spring( MOB target )<br />  {<br />    if( ( target != invoker() ) &amp;&amp; ( target.location() != null ) )<br />    {<br />      if( ( !invoker().mayIFight( target ) )<br />          || ( CMLib.dice().rollPercentage() &lt;= target.charStats().getSave( CharStats.STAT_SAVE_TRAPS) )<br />        )<br />      {<br />        target.location().show( target,<br />                                null,<br />                                null,<br />                                CMMsg.MASK_ALWAYS|CMMsg.MSG_NOISE,<br />                                "&lt;S-NAME&gt; avoid(s) setting off a shocking trap!"<br />                              );<br />      }<br />      else if( target.location().show( target,<br />                                       target,<br />                                       this,<br />                                       CMMsg.MASK_ALWAYS|CMMsg.MSG_NOISE,<br />                                       "&lt;S-NAME&gt; set(s) off an shocking trap!"<br />                                     )<br />             )<br />      {<br />        super.spring( target );<br />        CMLib.combat().postDamage( invoker(),<br />                                   target,<br />                                   null,<br />                                   CMLib.dice().roll( trapLevel(), 8, 1 ),<br />                                   CMMsg.MASK_ALWAYS|CMMsg.TYP_ELECTRIC,<br />                                   Weapon.TYPE_STRIKING,<br />                                   "The shock &lt;DAMAGE&gt; &lt;T-NAME&gt;!"<br />                                    + CMProps.msp( "shock.wav",30 )<br />                                  );<br /><br />        if( ( canBeUninvoked() ) &amp;&amp; ( affected instanceof Item ) )<br />        {<br />          disable();<br />        }<br />      }<br />    }<br />  }<br />}<br />        </pre>

                                                  
      
      <p>           The spring method is where the action is at. If the code
 in StdTrap           determines that the trap has been sprung, then this
method will be           called with only one parameter, namely the mob who
sprung it. After           making sure we aren't springing the trap on the
thief who set it,           we make sure that the thief who set the trap
is not breaking PK           rules by hurting the player. We do this using
the <code>invoker()</code> method           from StdAbility, which will return
a reference to the thief MOB who           set the trap. We also give the
poor bloke who sprung the trap a           saving throw. If both checks fail,
we let the room know that the           trap has gone off. Notice that it
is inside this condition that we           call <code>super.spring()</code>.
This is because, normally, the spring method           is only supposed to
hurt people. Since we have lots of conditions           by which the mob
can get out of being hurt, we need to wrap our           call to <code>super.spring()</code>.
Anyway, since the trap has gone off, we           make a library call to
the <code>combat()</code> engine's <code>postDamage()</code> method.    
      That method has lots of very complicated parameters, so you'll have
           to read up on the Library section for more information on it,
but            suffice to say that it posts the damage message that takes
hit           points away from the player. Lastly, if the trap is allowed
to be            uninvoked, we call the special StdTrap <code>disable()</code>
method, which           makes the trap unviable FOREVER. It effectively destroys
the           trap.         </p>

               <img src="images/language.jpg" alt="Languages" />
                                               
      
      <h2><a name="LANGS" id="LANGS">Languages</a></h2>

                                                  
      
      <p>           Of all skills, you will find that Languages are the easiest
 to           code. Although they fall into the category of Ability, and
are  a           far derivative of StdAbility, you will need very little
of that            extended knowledge if you follow the K.I.S.S. principle
and use  the           simple template provided by the Language base class
in the           Languages package.         </p>

                                                  
      
      <pre>public class Elvish extends com.planet_ink.coffee_mud.Abilities.Languages.Language<br />{<br />  public String ID()<br />  {<br />    return "Elvish";<br />  }<br /><br />  public String name()<br />  {<br />    return "Elvish";<br />  }<br /></pre>

                                                 
      
      <p>           Like all Abilities, the Language requires an ID which
 is the same           as its class name, and a readable name. In the case
 of Elvish, they           are identical.         </p>

                                                  
      
      <pre>  private static boolean mapped = false;<br />  public Elvish()<br />  {<br />    super();<br />    if( !mapped )<br />    {<br />      mapped = true;<br />      CMAble.addCharAbilityMapping( "All", 1, ID(), false );<br />    }<br />  }<br /></pre>

                                                 
      
      <p>           The constructor of this language is worth noting. Under
 the section           on Character Classes, we learned how to make classes
 qualify for           skills. Languages, like Common Skills, are available
 to ALL           classes. For this reason, we save ourselves the trouble
by having           the language declare its qualifications itself by accessing
 the           same CMAble method we saw up in Character Class creation.
        </p>

                                                  
      
      <pre>  public static Vector wordLists = null;<br />  public Vector translationVector()<br />  {<br />    if(wordLists==null)<br />    {<br />      String[] one = { "a", "e",<br />                      "i", "o",<br />                      "&aacute;", "&eacute;",<br />                      "&iacute;", "&oacute;"<br />                    };<br /><br />      String[] two = { "os", "vi",<br />                      "ne", "vo",<br />                      "li", "eh",<br />                      "no", "ai",<br />                      "by", "et",<br />                      "ce", "un",<br />                      "il"<br />                    };<br /><br />      String[] three = { "&aacute;na", "cil",<br />                        "sar", "tan",<br />                        "hel", "loa",<br />                        "sir", "hep",<br />                        "yur", "nol",<br />                        "hol", "qua",<br />                        "&eacute;th"<br />                      };<br /><br />      String[] four = { "s&eacute;ya", "qual", "quel",<br />                       "lara", "uqua", "sana",<br />                       "yava", "masse", "yanna",<br />                       "quettaparma", "manna", "manan",<br />                       "merme", "carma", "harno",<br />                       "harne", "varno", "essar",<br />                       "saira", "cilta", "veuma",<br />                       "norta", "turme", "saita"<br />                     };<br /><br />      String[] five = { "cuiva", "cuina", "nonwa",<br />                       "imire", "nauta", "cilta",<br />                       "entuc", "norta", "latin",<br />                       "l&ograve;tea", "veuya", "veuro",<br />                       "apama", "hampa", "nurta",<br />                       "firta", "saira", "holle",<br />                       "herwa", "uquen", "arcoa",<br />                       "calte", "cemma", "hanta",<br />                       "tanen"<br />                     };<br /><br />      String[] six = { "mahtale", "porisalque", "hairie",<br />                      "tararan", "ambarwa", "latina",<br />                      "ol&ograve;tie", "amawil", "apacen",<br />                      "yavinqua", "apalume", "linquilea",<br />                      "menelwa", "alassea", "nurmea",<br />                      "parmasse", "ceniril", "heldasse",<br />                      "imirin", "earina", "calatengew",<br />                      "lapselunga", "rianna", "eneques"<br />                    };<br /><br />      wordLists=new Vector();<br />      wordLists.addElement( one );<br />      wordLists.addElement( two );<br />      wordLists.addElement( three );<br />      wordLists.addElement( four );<br />      wordLists.addElement( five );<br />      wordLists.addElement( six );<br />    }<br />    return wordLists;<br />  }<br /></pre>

                                                 
      
      <p>           The first, often only, and certainly most important Language
 method           is <code>translationVector()</code>, which returns a Vector
 object containing a           set of String arrays. Each String array is
designated by the size           of the Common language words which will
be used by the array for           translation. That is to say, whenever
a Common word of three           letters is being translated into Elvish,
the String array three           will have a word randomly chosen from it.
         </p>

                                                  
      
      <p>           The words which are placed into these string arrays is
 arbitrary,           and may actually contain as many or few letters as
you  like.           Keeping the number of letters close or the same as the
Common  word           equivalent provides a certain symmetry, however, and
makes  it fun           for the players who don't speak a language to try
and guess  what is           being said by counting letters.         </p>

                                                  
      
      <pre>  private static final Hashtable hashwords = new Hashtable();<br />  public Hashtable translationHash()<br />  {<br />    if( ( hashwords != null ) &amp;&amp; ( hashwords.size() &gt; 0 ) )<br />    {<br />      return hashwords;<br />    }<br /><br />    hashwords.put( "ABANDON", "avarta" );<br />    hashwords.put( "ABLE", "pol" );<br />    hashwords.put( "ACCOMMODATE", "camta" );<br />    hashwords.put( "ACT", "car" );<br /><br />    ...<br /><br />    hashwords.put( "WRONG", "raic&euml;" );<br />    hashwords.put( "YES", "y&eacute;" );<br />    hashwords.put( "YESTERDAY", "tellaur&euml;" );<br />    return hashwords;<br />  }<br />}<br /></pre>

                                                 
      
      <p>           The last Language method is <code>translationHash()</code>. 
           This method is entirely optional and may be left out of a language 
           definition. In fact, it usually IS left out. However, when it is
           not, it provides a hashtable which can be used to translate exact
           english matches back to the fantasy language. The First word in
           each hashtable entry is the English word (and it MUST MUST MUST
be           in UPPERCASE) as the key, and the translation word as the entry
           value. Correct casing is taken care of by the Language base  
        class.         </p>

      	</td>

         </tr>

                   
  
  </tbody>  
</table>

     </center>

        <br />

     <br />

   <br />

</body>
</html>