/**************************************************************************** Using the configurable object /inherit/monster. Coding Style: Have a neat style - It does make coding, and debugging easier. Use strict types - It catches errors in compile time, rather then in run-time. People looking at your code know what the functions are supposed to return. Indent - Then you don't lose the blocks (ie. '{' '}'). Some people use the indentor in the editor. I do it by hand, usually indenting 2 spaces. Its up to you. Note: This is an example file. The cloned object filenames do not actually exist. ****************************************************************************/ /* orc shaman */ inherit "inherit/monster"; /* notes: 1 */ void reset(status arg) { /* notes: 2 */ ::reset(arg); /* notes: 3 */ if(!present("staff")) { /* notes: 4 */ object staff; /* notes: 5 */ staff = clone_object("players/zilanthius/weapons/staff"); /* notes: 6 */ move_object(staff, this_object()); /* notes: 7 */ init_command("wield staff"); /* notes: 8 */ } if(!present("robes")) { object robes; robes = clone_object("players/zilanthius/armour/robes"); move_object(robes, this_object()); init_command("wear robes"); } if(arg) return; /* notes: 9 */ set_name("shaman"); /* notes: 10 */ set_alt_name("orc"); /* notes: 11 */ set_alias_name("orc shaman"); set_short("Orc Shaman"); /* notes: 12, 13, 14 */ set_long("The orc is dressed all in black. Wisps of smoke waft\n"+ "slowly from his shoulders.\n"); set_extra_info("Examining the shaman closely, you notice that the\n"= "air is smoking from a recently cast fire spell.\n"); set_gender(1); /* notes: 15 */ set_race("orc"); /* notes: 16 */ set_level(8); /* notes: 17 */ add_class("mage"); /* notes: 18 */ add_class("cleric"); load_spells(10, ({ "minor malison", "comet", "sbf", "cure minor wounds", "cause minor wounds", })); /* notes: 19 */ load_chat(8, ({ "The shaman stares at you intently.\n", "Shaman exclaims: Leave now!\n", "The Orc Shaman gives you the Evil Eye!\n", })); /* notes: 20 */ load_l_chat(8,"orc", ({ "Fools, they are all fools!", "You will never find the secret ways.", })); /* notes: 21 */ load_a_chat(15, ({ "The orc shaman screams!\n", "Shaman says: Now you will never know!\n", "Shaman hits you with a mighty blow!\n", })); /* notes: 22 */ set_smell("The orc shaman hasn't had a bath for a while.\n"); } /************************************************************************** -=[ Notes ]=- 1. Inherit is an effeicient way to use memory. Inherit means, use the functions of the inherited object, but make a copy of all the global variables used in that object for my use. So in effect this object only requires memory for its 'object header' and global variables. 2. The reset function is called the first time when a file is loaded into memory (then we call it an object), or when an object is cloned with an arguement 'arg' of 0. Thereafter reset is called 1 to 2 hours later with an 'arg' of 1. 3. As soon as any function is written into this file, it will override any functions of the same name which it has inherited. Note the if any functions in that inherited file call this function name, it will call this function. If you wish to use an overridden function in the parent object then you must use the scoping operator. :: is known as the scoping operator. "inherit/monster" has the reset() function to initialise some variables, but to most importantly enable_commands(). enable_commands() is an efun which flags this object to allow it to use actions(). Without actions the monster cannot wear, wield, or move. So it is important to call ::reset(arg) first. 4. There are a number of ways to determine if a monster, or any object in fact has the equipment on them. The method in the example is recommended as it will replace equipment stolen by thieves. There are alternative methods. Alternative 1: Object is unique throughout mud. inherit "inherit/monster"; object staff; void reset(status arg) { ::reset(arg); if(!staff) { Alternative 2: Less efficient method of example. But useful when the monster is carrying two or more pieces of the same equipment. inherit "inherit/monster"; object staff; void reset(status arg) { ::reset(arg); if(!present(staff)) { 5. declare the variable 'staff' as an object (object is really an LPC data structure, but you don't need to know that). 6. An alternative to cloning an already pre-configured object, is to clone the configurable object and configure it direclty. If you are going to use the weapon more then once it is recommended that you use a pre-configured file. Cloning is very similar to inherit. It will make a new object that has a copy of global variables, but using the functions of the cloned object. This saves memory, when used in conjunction with the configurable objects (most objects in /inherit are configurable). Alternative 1: staff = clone_object("inherit/weapon"); staff->set_name("staff"); staff->set_alt_name("shaman staff"); staff->set_short("Shaman Staff"); staff->set_long("The staff is a gnarled piece of wood.\n"); staff->set_info("There is nothing magical about the staff.\n"); staff->set_smell("The wood smells quite smoky.\n"); staff->set_value(50); staff->set_wc(10); move_object(staff, this_object()); Alternative 2: This is a shorthand of that shown in example, though long filenames tend to cramp it. if(!present("staff")) { move_object(clone_object("players/zilanthius/staff"),this_object()); } 7. When an object is first loaded, or cloned it has no environment. Or in otherwords an efun environment() call will return 0. Rooms usually have no environment, and are not moved. But equipment of monsters are moved to the monster, which is this_object(). 8. This will command the monster to wield the staff. For appearances it looks better when a monster is wielding or wearing their equipment. (See also Notes: 3) Alternative 1: init_command() is a left over from the original mudlib. But is still widely used. command("wield staff", this_object()); 9. The reset function is called every hour or so with an arg of 1 after it is originally coded. It is really a waste of cpu time to reconfigure stuff in the monster at each reset. So we return after checking to see if equipment (or other statuses) is still on the monster. 10. Set name will set the living name of the monster with the efun set_living_name(name). The monster will be able to be located with find_living(name). However, if there is more then one monster with the same living name, then only the last one which used set_living_name will be found. Flagging the monster as living will allow it to catch write(), tell_object(), say(), and tell_room() communication messages with the function catch_tell(). This allows greater player - npc interaction. 11. These set alternative ids that the orc shaman can be identified. So the Orc Shaman can be call "orc", "shaman", or "orc shaman". 12. short - This is what a player will see when they first walk into the room. If this is not set, then the monster is invisible to the player. 13. long - This is the message the player sees when they 'look at orc'. 14. extra_info - This is the message the player sees when they 'examine orc' 15. gender - there are 3 genders, 0. neuter, 1. male, and 2. female. A lot of messages use gender pronoun, possessive, and objectives. 16. race - setting race is important. A lot of spells use the race for spell effects. For example charm person works only on humanoid type creatures. 17. level - The level determines the fighting difficulty of a monster. Setting the level will set the appropriate hit points, weapon class, armour class and experience for that monster. 18. add_class() - There are 4 standard classes. Fighter, thief, mage, cleric. You should make the monster one or more of the above classes. At the moment, thief does not do anything for a monster (but I will work on that). The skill level of a class is equal to its level. "fighter" - The class of fighter will make the monster gain better fighting skills. These include multiple attacks, and multi-opponent attacks; "cleric" - The class of cleric will give the monster access to spells from the cleric bin. Using the function load_spells(). "mage" - The class of mage will give the monster access to the spells from the mage bin. Using the function load_spells(). Note that the monster must be of the appropriate casting level, and have on them the necessary spell components. Some spells may be inappropriate for this because of the default targeting system. Passive spells ("cure light wounds) will default to monster. Whereas offensive spells default to primary attack. 19. load_spells - It is a chance out of 100 per heart beat to caste one of the spells. The monster has to be in an appropriate class, have the right level, and spell components. Spell selection is random, and does use spell points. This is the simplest way to add multiple spell spell casting to the monster. There is an alternative to add a single default spell. This can be accessed in two ways. The old way is limited in its approach, but is still usuable. Note that load_spells() will override the default spell if they both chance to happen in the same heart beat. Old Method: This dates back to at least 2.4.5lib, is kept only for compatibility. set_chance(10); /* 10% chance per heart beat */ set_spell_dam(30); /* maximum damage */ set_spell_mess1("Fire explodes around you!\n"); /* msg target */ set_spell_mess2("Fire engulfs the room.\n"); /* msg room */ set_spell_type("fire"); /* immune to this, take no damage */ set_spell_skill_type("evocation"); /*school of spell - for new system */ New Method: The new method is the same as writing spells for the spell bins. Read the spell docs for a more detailed analysis (it is recommended). Spell Example 1: set_spell(({ "chance", 10, "damage", 30, "msg caster", "You see flames engulf @@query_name:$this_object()$@@.\n", "msg room", "You see flames engulf @@query_name:$this_object()$@@.\n", "msg target", "Fire explodes around you!\n", "immune", "fire", "sphere", "evocation", })); Example 2: Bypassing spell level, component limitations. A little understanding of spell system is needed to understand how this works. But the effort is worth it, if you want quick and easy special spells. set_spell(({ "target", this_object(), "name", "Heal", "sphere", "healing_sphere", "cost", 5, "spell object", "skills/cleric/heal", "passive", "chance", 2, })); 20. load_chat - This will say() a statement to the whole room. The chance to do so should be between 5 and 10 for good results. In this case 8%. note it has full punctuation, and newlines. 21. load_l_chat - This is a language chat. It actually runs through the player 'say' command. And because of this it adds the newline for you. The chance should be between 5 - 10 for good results. 22. load_a_chat - when attacking the load_l_chat, and load_chat switch off and the load_a_chat is used. The chance should be between 15 and 30 for good results. 23. A nice message for 'smell orc'. */