voiceamulet.c and voicefuncs.c - examples for course 09

[previous example] [course09] [Table of contents] [next example]
/* Filename      : voiceamulet.c
 * Description   : a special eq - amulet
 *
 * written       : 04-10-1996 - Gunner
 * last modified : 28-05-1998 - Gunner
 * HTML-Version  : 06-02-2000 - Ghorwin
 */

#include <mudlib.h>
inherit I_ARMOUR;

#define FUNC "/doc/crashcourse/course09/voicefuncs"

create()
{
    ::create();
    set_name("glass amulet");
    add_id(({"amulet","amulet of glass","glass","voice_amulet"}));
    set_short("A glass amulet");
    set_long("The amulet is made out of glass. You can see right through "
        "it. It must be very fragile.\n");
    add_item("glass",(:call_other,FUNC,"amulet_glass",this_object():));
    set_weight(1);
    set_value(300+random(200));
    set_type("amulet");
    set_info("The amulet feeds upon souls and will use it to help its "
        "owner.\n");
  
    add_hook("__wear",(:call_other,FUNC,"wear_amulet",this_object():));
    add_hook("__remove",(:call_other,FUNC,"remove_amulet",this_object():));
    add_property(({"hidden","magic","fragile"}));    // Drop = break ;-)
    replace_program(I_ARMOUR);
}

voicefuncs.c


/* Filename      : voicefuncs.c
 * Description   : the functionfile for voiceamulet.c
 *
 * written       : 04-10-1996 - Gunner
 * last modified : 28-05-1998 - Gunner
 * HTML-Version  : 06-02-2000 - Ghorwin
 */

#include <mudlib.h>
#include <colours.h>
#include "/doc/crashcourse/defs.h"
inherit I_DAEMON;

#define TIMER 60*5+random(60*5)

string* voices = ({"You think you hear a scream coming from the amulet.\n",
                   "The amulet shivers slightly.\n",
                   "You hear a voice inside your head crying: 'KILL! KILL!'\n",
                   "A voice comes out from nowhere: 'KILL...KILL...'\n",
                   "The amulet seems to fade away for a moment.\n",
                   "The glass seems to cry out some strange words at you.\n",
                   "A whisper is heard: 'Help me.. Help me..'\n"});

/* 
 * wear_amulet : Called by the __wear hook in voiceamulet.c
 */
void
wear_amulet(object amulet)
{
    object wearer, room;

    wearer = ENV(amulet);
    if (!wearer) return;
    room = ENV(wearer);
    if (!room) return;

    tell_object(wearer,"The amulet fills you with a strange cold.\n");
    wearer->add_tmp_prop("vuln_fire",10);
    wearer->add_hook("__kill",(:call_other,TO,"player_kills",wearer:));
    amulet->add_property("player_kills",0);
    remove_call_out("amulet_tick");   // Just to be sure
    call_out("amulet_tick",TIMER,amulet);
}

/* 
 * amulet_tick : Time to do something...
 */
void
amulet_tick(object amulet)
{
    object wearer;
    int kills, spend;

    if (!amulet) return;                    // Where did the amulet go? *sob*
    wearer = amulet->query_worn_by();
    if (!wearer) return;                    // Where did the wearer go? *sob*

    call_out("amulet_tick",TIMER,amulet);   // A new call_out

    kills = amulet->_query_property("player_kills");
    if (kills < 1) return;               // No fun this one.. KILL SOMETHING!

    if (query_idle(wearer) > 60*2)       // DON'T IDLE, YOU.. YOU...
    {
        tell_object(wearer,voices[random(sizeof(voices))]);
        return;
    }

    spend = random(kills);
    kills -= spend;                         // Update the kills property
    amulet->add_property("player_kills",kills);

    switch (random(5))
    {
        case 0..1   : wearer->reduce_hit_point(-spend*2);    break;
        case 2..3   : wearer->reduce_spell_point(-spend*2);  break;
        case 4      : wearer->heal_self(spend*2);            break;
    }

    tell_object(wearer,C_BOLD + "The amulet shines brightly for a short "
        "while.\n" + C_END);
}

/* 
 * remove_amulet : Called by the __remove hook in voiceamulet.c
 */
void
remove_amulet(object amulet)
{
    object wearer, room;

    wearer = ENV(amulet);
    if (!wearer) return;
    room = ENV(wearer);
    if (!room) return;

    tell_object(wearer,"As you remove the amulet, the strange cold leaves "
        "your body.\n");
    wearer->add_tmp_prop("vuln_fire",-10);
    wearer->remove_hook("__kill");
    amulet->remove_property("player_kills");
    amulet->remove_item(({"soul","souls"}));
    remove_call_out("amulet_tick");
}

/* 
 * amulet_glass : Displays a message when the player looks at the glass
 */
string
amulet_glass(object amulet)
{
    string message;

    switch (amulet->_query_property("player_kills"))
    {
        case 0      : message = "right through the glass";              break;
        case 1..5   : message = "a couple of souls captured inside it"; break;
        case 6..10  : message = "a few souls captured inside it";       break;
        case 11..30 : message = "quite a few souls inside it";          break;
        case 31..60 : message = "a whole bunch of souls inside it";     break;
        case 61..100: message = "a lot of souls inside it";             break;
        default     : message = "what appears to be hundreds of souls "
                                "captured inside the glass";            break;
    }

    message = "You can see " + message + ".\n";

    return message;
}

/* 
 * player_kills : Called whenever the player kills something
 */
void
player_kills(object wearer)
{
    int kills;
    object amulet = present("voice_amulet",wearer);

    if (!amulet) return;    // Paranoia check.

    tell_object(wearer,"The amulet shines briefly.\n");

    kills = amulet->_query_property("player_kills") + 1;

    if (kills == 1)
        amulet->add_item("soul","It's a soul captured inside the amulet.\n");
    if (kills > 1)
        amulet->add_item(({"soul","souls"}),
            "They're souls captured inside the glass.\n");

    amulet->add_property("player_kills",kills);
}