dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
<html><!-- #BeginTemplate "/Templates/Body Text.dwt" -->
<head>
<title> Discworld Documentation </title>
</head>
<body bgcolor="#ffffff" TEXT="#000030" LINK="#4a529c" VLINK="#b57339">
<table width="75%" border="0">
  <tr>
    <td><font face="arial,helvetica"><img align=left src="http://discworld.imaginary.com/external//pics/dw4.gif"></font></td>
    <td><font face="arial,helvetica">
      <h2>Discworld Documentation:</h2>
      <h2>LPC for Dummies</h2>
      </font> 
      <p><font size="+1"><!-- #BeginEditable "Title" --><font size="+1"><b>Tutorial 
  Five - Putting It All Together- Advanced NPCs</b></font><!-- #EndEditable --></font></p>
      <p><i>N.B - This is a work in progress... a living document if you like. 
        If it appears to be dead when you view it, don't worry. It's most likely 
        just playing possum.</i></p>
      <p>Comments on these chapters and tutorials can be e-mailed to <a href="mailto:drakkos@cableinet.co.uk">Drakkos.</a></p>
    </td>
  </tr>
</table>
<br>
<!-- #BeginEditable "Body" --> 
<p>We'll finish off our set of basic tutorials with a look at some of the nifty 
  things we can do with NPCs and objects. As with part four of the tutorial set, 
  nothing in this document is vital to creating objects and NPCs. However, the 
  information contained within can be used to make your creations more interesting. 
  We'll start off with NPCs. We've already looked at how to create an NPC, give 
  it chats, and responses, and even give it some clothes and a weapon. But there's 
  a range of further functionality available that we can use to expand on what 
  we've already learned. 
<p><b>Unique NPCs</b>
<p>Again, we'll ease into this tutorial with an easy example: the unique property. 
  You can make NPCs 'unique' by adding the following line to their setup: 
<blockquote>
  <p><code>add_property("unique", 1); </code></p>
</blockquote>
<p>NPCs with this property do not give out death XP when they are killed. They 
  also trigger a nice leetle death inform when they are killed, so that all online 
  creators can see something like: 
<blockquote>
  <p><code>[grey blob killed by drakkos <drakkos>] </code></p>
</blockquote>
<p>The unique property, however, does not prevent two NPCs of the same type being 
  cloned. You must cater for this in the code that loads the NPC. Unique NPCs 
  should never be cloned with clone_object(). They should always be loaded with 
  load_object, and then moved into the appropriate room. Using load_object() will 
  ensure that two copies of the same unique NPC are never in the game at the same 
  time. We've already seen how to use load_object() in the after_reset() of our 
  simple room. The unique property also has a number of peripheral applications... 
  for example, unique NPCs will not be subjected to the flea infestation effect. 
  All NPCs that are named should have this property. If you want to create an 
  NPC that is not unique, but you want to take advantage of the fact that the 
  property removes death xp, you can instead mask query_death_xp() to return 0 
  in your NPC code:
<blockquote> 
  <p> <code>int query_death_xp() { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;return 0; <br>
    } </code></p>
</blockquote>
<p><b>NPCs, Guilds and Races</b>
<p>We've already seen how to set the race of an NPC through the function basic_setup. 
  In our previous example, however, we simply used the default, boring human race. 
  But there are a large number of other interesting races available for us to 
  choose from. You can 'call query_races() /std/race' to get a list of all valid 
  races. Races do lots of interesting things behind the scenes, like setting up 
  what body parts a creature has, and which body parts are part of which other 
  parts. It's the race object that allows for things like 'get teeth from corpse' 
  and 'get tooth from teeth'. Race objects also deal with the default settings 
  for a particular NPC... for example, armour classes, and basic attacks. We change 
  the race of a particular NPC by changing the first argument of our basic_setup. 
  Say we wanted to create a dwarf instead of a human, for example. We would use: 
<blockquote>
  <p><code>basic_setup("dwarf", "fighter", 50); </code></p>
</blockquote>
<p>Which would give our NPC all the characteristics of a dwarf. Note that changing 
  the race will also change the physical statistics of an NPC... strength, dexterity, 
  and so on. You can get this information easily by using 'stat <npc>' on a cloned 
  creature... this will give lots of information on your leetle NPC... including 
  its physical characteristics. 
<p>Many races will modify strength, constitution, etc, based on the values provided 
  in their race object. This allows for dwarfs, for example, to be much stronger 
  by default than humans. In the same way, we can change the guild of our NPC 
  simply by altering the second parameter of basic_setup to one of the various 
  guilds. You can get a list of these with 'call query_guilds() /std/race'. Say, 
  for example, we want to have a level 30 dwarf wizard. We would use: 
<blockquote>
  <p><code>basic_setup("dwarf", "wizard", 30); </code></p>
</blockquote>
<p>Simple! You can modify the physical characteristics of your NPCs using the 
  functions adjust_xxx() and set_xxx(), where xxx is any one of str (strength), 
  wis (wisdom), con (constitution), int (intelligence) or dex (dexterity). Adjust_xxx() 
  will modify the current statistic by the value passed in as a parameter... adjust_str(5), 
  for example, would add five to the NPC's strength. adjust_int(-3), would subtract 
  three from intelligence. The set_xxx() functions will set an NPC's statistic 
  to the value you pass in. set_str(20), for example, will set the NPC's strength 
  to 20. 
<p>Note however that when you setup your NPC as a one of the standard guilds, 
  unless it has the 'unique' property, you will not be able to set exact values 
  for their statistics. Standard guild NPCs have their statistics randomised to 
  a degree to increase variety. You can use the adjust_xxx() functions in your 
  setup to favour a particular range, but if you use set_xxx(), then the standard 
  guild object will over-ride these. Example: 
<p>NPC 1: 
<blockquote> 
  <p><code>void setup() { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_name("bing"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_short("Big Bing"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_long("This is a big bing!\n"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;basic_setup("human", "fighter", 30); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_str(18); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_int(18); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_dex(18); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_con(18); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_wis(18); <br>
    } </code></p>
</blockquote>
<p>And NPC 2: 
<blockquote> 
  <p><code>void setup() { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_name("bang"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_short("Big Bang"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_long("This is a big bang!\n"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;basic_setup("human", "fighter", 30); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;add_property("unique", 1); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_str(18); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_int(18); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_dex(18); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_con(18); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;set_wis(18); <br>
    } </code></p>
</blockquote>
<p>When cloning an example NPC 1, we get: 
<blockquote>
  <p><code>Con: 14, Dex: 19, Int: 17, Str: 22, Wis: 15 </code></p>
</blockquote>
<p>When cloning an example NPC 2, we get: 
<blockquote>
  <p><code>Con: 18, Dex: 18, Int: 18, Str: 18, Wis: 18 </code></p>
</blockquote>
<p>The presence of the unique property in the second example allows us to explicitly 
  set the statistics. If we want to adjust our first NPC, we must use adjust_xxx() 
  to modify the randomly chosen statistics by appropriate values. 
<p>Your choice of guild for your NPC will determine what skills they start off 
  with as default. Your NPC will get a few levels in fighting, other and other.health 
  as default. The rest of its skills will be determined by the guild object. You 
  can call query_skills() on the /std/race/<insert_guild> to find out what skills 
  a guild has as a primary. For example, 'call query_skills() /std/guilds/warrior' 
  gives: 
<blockquote>
  <p><code>fighting.points <br>
    fighting.combat.melee.sharp <br>
    fighting.combat.melee.pierce <br>
    fighting.combat.melee.blunt <br>
    fighting.combat.melee.unarmed <br>
    fighting.combat.range.thrown <br>
    fighting.combat.range.fired <br>
    fighting.combat.parry.melee <br>
    fighting.combat.parry.range <br>
    fighting.combat.dodging.melee <br>
    fighting.combat.dodging.range <br>
    fighting.combat.special.weapon <br>
    fighting.combat.special.unarmed <br>
    other.evaluating.weapon <br>
    other.evaluating.armour </code></p>
</blockquote>
<p>Once you've set your NPC up with the default skills, you can further modify 
  what levels and bonuses an NPC has in specific skills using the function add_skill_level(). 
  This takes two arguments, the first being a string containing the full name 
  of the skill, the second being an integer argument of the number of levels to 
  be advanced: 
<blockquote>
  <p><code>add_skill_level("other.health", 25); </code></p>
</blockquote>
<p>This adds twenty-five levels of other.health to your NPC on top of what it 
  already has from its guild object. Easy peasy! So let's start off with another 
  example NPC... this one a little more complex than the grey blob we coded in 
  tutorial one. We're going to be a little more adventurous and code a leetle 
  gnome with nasty teefs and a talent for casting spells. Sounds like fnu? Indeed 
  it does! So let's start with the setup: 
<blockquote> 
  <p><code>/* <br>
    &nbsp;&nbsp;&nbsp;&nbsp;The Laughing Gnome! <br>
    &nbsp;&nbsp;&nbsp;&nbsp;With teefs and spells! <br>
    &nbsp;&nbsp;&nbsp;&nbsp;Wrytten by Drakkos Thee Creator <br>
    &nbsp;&nbsp;&nbsp;&nbsp;18/10/2000 <br>
    */ </code></p>
  <p><code>void setup() { <br>
    </code></p>
  <blockquote> 
    <p><code>set_name("gnome"); <br>
      set_short("laughing gnome"); <br>
      set_long("This is a little, friendly looking gnome. Well... "<br>
      "friendly looking aside from the vicious sharp teefs and the "<br>
      "wicked razor-like claws. He has laughter lines all over " <br>
      "his face, tho', so he can't be all bad.\n"); <br>
      add_property("unique", 1);<br>
      basic_setup("gnome", "wizard", 50); <br>
      set_gender("male"); <br>
      set_int(23); <br>
      set_str(18); <br>
      set_wis(18); </code></p>
    <p><code>add_skill_level("magic", 100); <br>
      add_skill_level("fighting", 50);</code></p>
    <p><code>load_chat(20,({ 1, "' Ha ha ha!.", <br>
      1, "' He he he!.", <br>
      2 , "' I'm the laughing gnome, and you can't catch me!",<br>
      }) ); </code></p>
    <p><code>load_a_chat(20,({ 2, ": bares his teeth.", <br>
      1, "' I'll get my brother Fred onto you!.", <br>
      2 , "' I'll call out the Gnome Guard!", }) ); </code></p>
  </blockquote>
  <p><code>} </code></p>
</blockquote>
<p>Not much to go on just now... but we're going to cover the rest of what we 
  need to know next! 
<p><b>Spells And Your NPC </b>
<p>Spells are added to your NPC with the add_spell() function. This takes three 
  arguments... the first is the name the spell will be referenced by. The second 
  is the filename of the spell, and the third is the function the spell is called 
  through (in the majority of cases, this will be "cast_spell"). So, say we wanted 
  to add the Kamikaze Oryctalagus Flamullae spell to our NPC. Since we're not 
  too concerned about anything cosmetic here, we'll just call the spell 'bunnies'. 
  The path to the spell is /obj/spells/fire_bunny.c. Our function would then be: 
<blockquote>
  <p><code>add_spell("bunnies", "/obj/spells/fire_bunny", "cast_spell"); </code></p>
</blockquote>
<p>Simple! And now our NPC can attempt to cast the spell by simply using the command 
  'cast bunnies on <name of poor sod>'. Of course, our NPC is subject to the same 
  restrictions as players... he must have the correct number of magic GPs, he 
  must have the spell components to hand, etc. But assuming all of that is provided 
  for him, he'll be able to throw fire bunnies around with the best of them. That 
  was so easy, in fact, let's add a few more spells to him! All the wizard spells 
  are in the directory /obj/spells. Priest rituals are added in the same way, 
  but they reside in /obj/rituals. We're only going to be playing with wizard 
  spells at the moment, however, since all that god bothering nonsense is entirely 
  unnecessary for our wizard NPC. Let's give him a couple of other spells... namely 
  Eringyas Surprising Bouquet, and Sorklin's Field of Protection
<blockquote>
  <p><code>add_spell("flowers", "/obj/spells/flowers", "cast_spell"); <br>
    add_spell("shield", "/obj/spells/small_shield", "cast_spell"); </code></p>
</blockquote>
<p>Whee! Now our NPC has some nifty magic he can call upon when the going gets 
  tough. Neato! But... how do we get him to use them? 
<p><b>Function Pointers in Load Chats</b>
<p>So far, all we've done with load chats are simple commands for our NPC to perform: 
  say this, emote that, etc. But if we want to be a little more creative, we can 
  put a pointer to a function in our load_chat and load_a_chat by prefacing a 
  function name with a # symbol: 
<blockquote> 
  <p><code>load_chat(20,({ <br>
    &nbsp;&nbsp;&nbsp;&nbsp;1, "' Ha ha ha!.", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;1, "' He he he!.", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;2 , "' I'm the laughing gnome, and you can't catch 
    me!", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;1 , "#charm_women",<br>
    </code><code>}) ); </code></p>
  </blockquote>
<p>See the fourth chat we have there? Every time that chat option is called, the 
  function charm_women() will be executed. Nifty! But what will we do in this 
  function? Well, our gnome is a lecherous little devil... and he has Eringyas 
  Surprising Bouquet, allowing him to summon up a bouquet of flowers. So, let's 
  have it so that every time this function is called, he checks his current room 
  for any female players, and if one exists, he casts the spell and presents the 
  flowers to them. Cute? Well... it would be if he wasn't two foot tall and all 
  teeth. But the thought is there! 
<blockquote> 
  <p><code>void charm_women() {<br>
    &nbsp;&nbsp;&nbsp;&nbsp;object player; <br>
    &nbsp;&nbsp;&nbsp;&nbsp;foreach(player in all_inventory (environment(this_object()))) 
    { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (interactive(player) && 
    player->query_gender() == 2) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queue_command("cast 
    flowers"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queue_command("give 
    flowers to " + file_name (player)); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queue_command("bow 
    with a flourish"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>}<br>
    &nbsp;&nbsp;&nbsp;&nbsp; </code><code>} <br>
    } </code></p>
  </blockquote>
<p>Although this function is somewhat rough and ready (there are much better ways 
  to do the check for female players, for example), it serves to demonstrate what 
  we can do with a load_chat function pointer. I'll go through the function step 
  by step to make sure you understand exactly what it's doing: First, we declare 
  our object variable player. Then we use a foreach loop to cycle through all 
  objects in our gnomes room. All_inventory is an efun that takes a single argument 
  of an object, and returns the list of all other objects inside that object. 
  For example, if you pass in a room, it returns all the objects standing in that 
  room. If you pass in a backpack, it'll return the list of items inside the backpack. 
  In this case, we're passing in the environment of this_object() (our gnome). 
  The environment here is the room our NPC is standing in, so we get the list 
  of all objects currently in the room with our gnome. 
<p>For each object in the room, we perform an if conditional. If the object is 
  interactive() (In other words, if the object is a player), and if calling query_gender 
  on the object returns 2 (in other words, female), then we 
<blockquote>
  <p><code>1) Cast the spell flowers. This is the spell Eringyas Surprising Bouquet... 
    the flowers label we chose when we used add_spell. <br>
    2) Give the flowers to the player. <br>
    3) Bow with a flourish. <br>
    4) Return from the function since we've found a female player and presented 
    her with the flowers. </code></p>
</blockquote>
<p>If our if condition is never evaluated to true, the function eventually terminates 
  when all objects have been cycled over. So now we have a lecherous little gnome 
  with flowers and a glint in his eye. Neat! We can add other functions to our 
  load_chat to have our gnome do pretty much anything we want him to. The only 
  limit is your imagination! Oh, and the physical limits of the MUD. But your 
  imagination is likely to run out first. 
<p><b>Mixing It Up! Combat Actions!</b>
<p>Sooner, or later, any NPC you code is going to be attacked. No matter how sweet, 
  adorable, and thoroughly loveable your lickle creation is, someone is going 
  to come along and stick a big sword through it. It's a sad life, being an NPC. 
  You're standing around, minding your own business, and some psychopath with 
  a sledgehammer decides he doesn't like your face and attempts to practise retrophrenology 
  on a grand scale. What's a poor leetle NPC to do? 
<p>Well... fight back, of course! Most NPCs will do this automatically with their 
  hands, feet and whatever they may be holding in their hands. But with judicious 
  use of add_combat_action, you can make your NPCs fight a little better, and 
  maybe even provide a few surprises to unwitting players along the way. Take 
  our gnome, for example. He has a shielding spell. He has fire bunnies... wouldn't 
  it be neat if he used them both when attacked? Yes, it would! So let's add a 
  couple of combat actions to that effect! 
<p>Add_combat_action() takes three arguments. The first is an integer, and is 
  the chance an action will be called in any combat round. The second is the name 
  of the attack... we can refer to this later if we want to remove the action 
  at a later date. The third argument is either a function pointer (we'll go into 
  function pointers in more depth in a later document) to a function (it will 
  be called with two object arguments... the attacker and the target), or an array. 
  We'll just look at the function pointer for now... if you're interested in how 
  the array works, check the help file for add_combat_action. 
<blockquote>
  <p><code>add_combat_action(50, "bunny_them", (: do_bunny :)); <br>
    add_combat_action(50, "maintain_me", (: do_maintain :)); </code></p>
</blockquote>
<p>Now we need two functions to deal with the combat action calls... do_bunny 
  and do_maintain. Both of these will be called with two object arguments: 
<blockquote> 
  <p><code>void do_bunny(object attacker, object target) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;if (target != this_object() ) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_command("cast bunnies on 
    " + file_name (target)); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;} <br>
    } </code></p>
</blockquote>
<p>And for the do_maintain() function: 
<blockquote> 
  <p><code>void do_maintain(object attacker, object target) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;if (target == this_object() ) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_command("cast shield on 
    " + file_name (target)); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;} <br>
    } </code></p>
</blockquote>
<p>We'll also need to prototype these functions at the top of the file (read the 
  chapter on functions if you are unsure what this means), so we add at the top 
  of our file: 
<blockquote>
  <p><code>void do_bunny(object, object);<br>
    void do_maintain(object, object); </code></p>
</blockquote>
<p>Simple! Again, these are very rough and ready examples, and would require a 
  lot of work before they could actually be used in the game. They serve merely 
  to illustrate the principles. But! These will not work! Why not? Well, our poor 
  leetle gnome has no components to cast the spells with. 
<p>Sorklin's Field Of Protection requires a shield. Kamikaze Orytalagus Flammulae 
  requires a carrot and a torch. So... how do we get these components into our 
  NPC's grubby little hands? Well, there are two ways. One is to cheat and give 
  our NPC the components every time he wants to cast the spell. The other is to 
  give our NPC a number of components when he's cloned, and once he's used them 
  all up, he's on his own. Since we're never actually going to be unleashing our 
  leetle gnome on any players, we can afford to cheat and simply give him his 
  components when he needs them. So let's rewrite our functions slightly: 
<blockquote>
  <p><code>void do_bunny(object attacker, object target) { <br>
    object carrot, torch; </code></p>
  <p><code>if (target != this_object() ) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;if (!sizeof(match_objects_for_existence("carrot", 
    this_object()))) {<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;carrot = clone_object("/obj/food/carrot.food"); 
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;carrot->move(this_object()); 
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;} <br>
    &nbsp;&nbsp;&nbsp;&nbsp;if (!sizeof(match_objects_for_existence ("torch", 
    this_object()))) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;torch = clone_object("/obj/misc/torch"); 
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;torch->move(this_object()); 
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;} </code></p>
  <p><code>&nbsp;&nbsp;&nbsp;&nbsp;do_command("cast bunnies on " + file_name (target)); 
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;} <br>
    } </code></p>
</blockquote>
<p>And: 
<blockquote> 
  <p><code>void do_maintain(object attacker, object target) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;object temp; <br>
    &nbsp;&nbsp;&nbsp;&nbsp;if (!sizeof(match_objects_for_existence("shields", 
    this_object()))) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp = ARMOURY->request_item("wooden 
    djelian shield", 100); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp->move(this_object()); 
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;} </code></p>
  <p><code>&nbsp;&nbsp;&nbsp;&nbsp;do_command("cast shield on " + file_name (this_object())); 
    <br>
    } </code></p>
</blockquote>
<p>And tada! Whenever our gnome goes to use his spells, he'll magically have the 
  components he needs to hand, no matter what. How dastardly! Ooo, don't you feel 
  nice and evil? No? Well, you should... it's part of the job requirements. Ahem. 
  So now you know how to give your NPC neato combat actions. You even know how 
  to cheat and magically provide them with all the equipment they're ever likely 
  to need! Of course, if you're going to be coding something for the game, it 
  would probably be fairer to give them limited components at setup... but we're 
  not coding for the game at the moment, we're coding for fnu and we can cheat 
  if we want to! 
<p><b>Masking Critical Functions!</b>
<p>So, now we have our leetle gnome with all the magic he's ever going to need, 
  let's attack him and see if he uses it! So we clone him into our room, grin 
  wickedly, and type 'kill gnome'. And, whack: You kick the laughing gnome. You 
  killed the laughing gnome. Wow... that was easy! Why did he die so easily? Well, 
  being a gnome, he doesn't really have the physiology to withstand much punishment. 
  We can use add_skill_level() to increase his other.health, but that won't do 
  much since his maximum HPs is set deeper in the mudlib. So what can we do? Well, 
  there are a couple of things we can do! 
<p>One, we can stop people from attacking him at all by masking the function attack_by(). 
  This function is called on an object when another object attempts to attack 
  it. If we mask this to return 0, then an attack will not be permitted. We can 
  also use the stop_fight() function to make sure that the other object doesn't 
  keep fighting anyway, since returning 0 only stops that particular attack from 
  going through... it doesn't stop the fight itself. 
<p>Attack by takes one argument, the reference of the object making the attack: 
<blockquote> 
  <p><code>int attack_by(object ob) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;ob->stop_fight(this_object()); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;this_object()->stop_fight (ob); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;tell_object(ob, "You meanie! Leave the poor leetle 
    gnome alone!\n"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;return 0; <br>
    } </code></p>
</blockquote>
<p>So now we have an unattackable NPC. Neato. But... well... that's not exactly 
  what we want. Our NPC will only use his spells when he's in the middle of a 
  fight, so we'd need to make sure that he was able to fight back if attacked. 
  In the function above, we have two stop_fight() calls: 
<blockquote>
  <p><code>ob->stop_fight(this_object()); </code></p>
</blockquote>
<p>Which calls stop_fight() on the attacking object, and tells the object to stop 
  attacking this_object() (our gnome). We also have: 
<blockquote>
  <p><code>this_object()->stop_fight(ob); </code></p>
</blockquote>
<p>Which calls stop_fight on our gnome, and tells it to stop attacking the object 
  ob refers to. We could make the fight favour our gnome just a leetle by removing 
  the 'this_object()->stop_fight (ob)' line. This would allow the gnome to fight 
  us, but not allow us to fight back. So let's cheat some more and do that now: 
<blockquote> 
  <p><code>int attack_by(object ob) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;ob->stop_fight(this_object()); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;tell_object(ob, "You meanie! Leave the poor leetle 
    gnome alone!\n"); <br>
    &nbsp;&nbsp;&nbsp;&nbsp;return 0; <br>
    } </code></p>
</blockquote>
<p>But that's not enough. For example, if we cast fire bunnies on the NPC ourself, 
  we find that our gnome burns to a crisp within seconds. Since we're not actually 
  physically attacking the gnome with the bunnies, attack_by isn't stopping the 
  fight. What we also need to do is make sure our NPC doesn't actually get hurt 
  at all. We can do this by masking adjust_hp(). Adjust_hp() takes a single integer 
  argument, which is the number of HPs to adjust the NPCs HPs by. We can simply 
  mask this as: 
<blockquote> 
  <p><code>void adjust_hp(int number) { <br>
    &nbsp;&nbsp;&nbsp;&nbsp;return; <br>
    } </code></p>
</blockquote>
<p>Woohoo! Having both of these methods in our NPC is overkill, however, so we'll 
  just go with the adjust_hp() mask in our example. We discussed using attack_by 
  simply for completeness, and because it's very useful to know how to make NPCs 
  respond differently when attacked. 
<p><b>Adding Attacks!</b>
<p>Well, we've already seen our NPC has sharp teefs and claws... and now we know 
  our NPC will stand and take whatever damage we want to dish out to him. But, 
  when he's not casting his spells, he's not doing much with his teeth and claws... 
  he's just kicking and punching like a normal person! Our leetle gnome is more 
  dangerous than that, however, so we're going to give him a couple of extra attacks 
  to show his teeth and claws in action. We do this using the 'add_attack' function. 
  We've already seen this in action when we coded our dirty mop in the third tutorial, 
  so we don't need to spend too much time going over it again. But we're going 
  to expand on it a little and see how we can change the attack messages to something 
  more appropriate than the default messages for the attack. We can do this with 
  'add_attack_message'. So let's give our gnome some neat attacks: 
<blockquote>
  <p><code>add_attack("claws", 88, ({ 10, 8, 20 }), "sharp", "sharp", 0 );<br>
    add_attack("teeth", 88, ({ 5, 5, 25 }), "pierce", "pierce", 0 ); </code></p>
</blockquote>
<p>And now, we use add_attack_message to change the text we get when our leetle 
  gnome attacks. Add_attack_message takes three arguments. The first is the name 
  of the attack, the second is the type of attack, and the third is the attack 
  data. The attack data is of the form: 
<blockquote> 
  <p><code>({damage to switch on, <br>
    &nbsp;&nbsp;&nbsp;&nbsp;({Message attacker sees, <br>
    &nbsp;&nbsp;&nbsp;&nbsp; message target sees, <br>
    &nbsp;&nbsp;&nbsp;&nbsp;message room sees}),<br>
    }) </code></p>
</blockquote>
<p>If the damage is 0, then that is the default message set to display. So, let's 
  put some messages on these attacks: 
<blockquote> 
  <p><code>add_attack_message("claws", "sharp", ({ <br>
    &nbsp;&nbsp;&nbsp;&nbsp;100, <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;({ "You slice $hcname$ with 
    your claws.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ slices you with 
    $mposs$ claws.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ slices $hcname$ 
    with $mposs$ claws.\n"}), <br>
    &nbsp;&nbsp;&nbsp;&nbsp;200, <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;({ "You rip $hcname$ apart 
    with your claws.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ rips you apart with 
    $mcposs$ claws.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ rips $hcname$ apart 
    with $mposs$ claws.\n"}), <br>
    &nbsp;&nbsp;&nbsp;&nbsp;0, // The default message set. <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;({ "You scratch $hcname$ viciously 
    with your claws.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ scratches you viciously 
    with $mposs$ claws.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ scratches $hcname$ 
    viciously with $mposs$ claws.\n"}) <br>
    }));</code></p>
</blockquote>
<p> And for his teeth: 
<blockquote> 
  <p><code>add_attack_message("teeth", "pierce", ({ <br>
    &nbsp;&nbsp;&nbsp;&nbsp;100,<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;({ "You nibble $hcname$ with 
    your teeth.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ nibbles you with 
    $mposs$ teeth.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ nibbles $hcname$ 
    with $mposs$ teeth.\n"}), <br>
    &nbsp;&nbsp;&nbsp;&nbsp;200, <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;({ "You chew on $hcname$ with 
    your teeth.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ chews on you with 
    $mcposs$ teeth.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ chews on $hcname$ 
    with $mposs$ teeth.\n"}), <br>
    &nbsp;&nbsp;&nbsp;&nbsp;0, // The default message set. <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;({ "You sink your teeth into 
    $hcname$.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ sinks $mposs$ teeth 
    into you.\n", <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"$mcname$ sinks $mposs$ teeth 
    into $hcname$.\n"}) <br>
    &nbsp;&nbsp;&nbsp;&nbsp;})); </code></p>
</blockquote>
<p>And voila! Now we've given him a few neat attacks, let's give him a good kicking 
  to demonstrate. Jade scarabs at the ready though, boys and girls, 'cause he's 
  a vicious little bugger. Some pertinent extracts: 
<blockquote>
  <p><code>You prepare to attack a laughing gnome. <br>
    The laughing gnome rips you apart with his claws. <br>
    Ouch. That would have taken off 194 hit points. <br>
    The laughing gnome nibbles you with his teeth. <br>
    Ouch. That would have taken off 92 hit points. </code></p>
  <p><code>The laughing gnome looks pensive for a few moments. <br>
    The laughing gnome stares at nothing much in the air around himself. <br>
    The laughing gnome appears to tense momentarily. <br>
    With a noise that sounds like "Plink!", the air around the laughing gnome. 
    </code></p>
  <p><code>The laughing gnome wiggles his eyebrows around a bit. <br>
    The laughing gnome wrinkles his face in disgust. <br>
    The laughing gnome points at you. <br>
    The fiery carrot above your head flickers and goes out. <br>
    The laughing gnome sets fire to the carrot. <br>
    The carrot floats up and hovers above you. <br>
    Eight fire bunnies leap out of the ground and throw themselves at you. <br>
    Ouch. That would have taken off 197 hit points. </code></p>
</blockquote>
<p><b>Chapter Summary </b>
<p>Woo! Isn't our leetle gnome something? He sure is! And, as always, there's 
  more, much more to learn! But you'll have to discover all that for yourself 
  because this is where this tutorial ends! But you've come a long way in these 
  pages. You've learned about races, about combat actions and function pointers 
  in load chats, and unique attacks for NPCs. You're well on your way to becoming 
  the MASTAR OF NPC KNOWLIDGE!! 
<p>But our journey is nearly at an end... the next tutorial will be the last in 
  this suite of documents, and will mark the finale of the basic Discworld coding 
  tutorial. Sniff. Stay tuned for part six! 
<ul>
  <li><code>NPCs can be made 'unique' by adding the unique property to them. Unique 
    NPCs generate a death inform and give no XP when killed.</code></li>
  <li><code>All NPCs must have a race, guild, and level. NPCs will be given their 
    level in their primary skills, and an additional few levels in health and 
    fighting based on that level.</code></li>
  <li><code>Only unique NPCs can have their statistics set using the set_xxx() 
    function calls. </code></li>
  <li><code>Spells are added to an NPC using the add_spell() function. NPCs have 
    the same restriction on spells that players have. They must have the correct 
    component and have enough skills and GP to cast.</code></li>
  <li><code>It is possible to pass in a function as an argument to load_chat or 
    load_a_chat by prefacing the function name with #. </code></li>
  <li><code>The function add_combat_action may be used to add actions for an NPC 
    to perform during combat. </code></li>
  <li><code>If the function attack_by() is masked to return zero, no one can physically 
    attack our NPC. We can mask this function to change the behaviour of an NPC 
    when attacked.</code></li>
  <li><code>We can mask adjust_hp() to alter the way an NPC deals with being damaged. 
    </code></li>
  <li><code>We can use the add_attack() function to add physical attacks to an 
    NPC. - The function add_attack_message() can be used to provide unique messages 
    for an NPC's attacks. </code></li>
</ul>
<p><b>Support Files</b>
<blockquote>
  <p><code>/d/learning/newbie/introduction/advanced_npc.c</code></p>
</blockquote>
<!-- #EndEditable --> 
<p>
<hr>
<center><font size="-1"><a href="/login.html">Discworld MUD</a>'s world wide web pages.<br>brought to you by<br>
  <strong>Cut Me Own Throat Dibbler's <a href="/sausages.html">Sensational Sausages</a>;&nbsp;buy 
  one while they are hot.</strong> <br>
<hr>Lost?  Try Discworld's <a href="/">home page</a>.</font></center><font size="-1"><i><a href="mailto:drakkos@cableinet.co.uk"><font size="-2">Mail Drakkos!</font></a></i>
</font>
</body>
<!-- #EndTemplate --></html>