Vampires and Slayers [by BoxBoy]
Snippet Posted Saturday, August 19th @ 08:38:34 PM, by Brandon Brown in the Players dept.
BoxBoy writes, "I have been asked for my Vampire and Slayer code, so here it is... ...I am definately not the best coder in the world, BUT I know what I like and this snippet (rather large one at [that]) should help you add something that I really like to your mud, this is Vampires!"
I have been asked for my Vampire and Slayer code, so here it is.
Please do not show me shame for they way I have done some things
here, like bloodthirst using the same functions as normal thirst
but only being quenched by the biting of necks. I am definately 
not the best coder in the world, BUT I know what I like and 
this snippet (rather large one at the) should help you add something
that I really like to your mud, this is Vampires!

Among Some of the new features added by this are,
-Vampire and Slayer Classes
-Bloodthirst (mentioned above)
-Neckbite skill for Vampires
-Steaks skill for Slayers
-Vampires burning in sunlight
-Holy and Unholy Rooms
-Energy Steal Spell for Vampires
-New Load Rooms for Vampires
(this can be adapted for Hometowns)
and I believe there is a little more.
-make_dust replacement for vampires
(rather than make_corpse)

!!WARNING!! I have had some, er trouble with the make_dust as it
sends the equipment and gold to the room, rather than into the 
object and somewhere it sometimes loses equipment and I also believe
that all !RENT items get purged that the player had, but this is not
that much of a problem in my eyes, honest!

AND before you add this I am in no way reponsible for and damage or
lose of blood, sanity, world, object, zone or mobile files from use 
of this code. If you have any problems, they are not my fault! BUT 
I may be able to help you, so I don't mind you emailing me, buy use 
my E-Mail address that I use for help, which is boruki@as-if.com, 
rather than my normal baez@as-if.com.
B.Brown: There's a few parse errors in here..I fixed a couple,
but I'm not a human compilier and chances are I missed quite a few.
Just keep your eyes open for them when adding this.




NOW, onto the code *gulp*,
/************* START HERE ***************/

I will start by adding the classes, SO,

open structs.h,
find the line,
#define CLASS_WARRIOR  3
and below it add,
#define CLASS_VAMPIRE  4
#define CLASS_SLAYER  5

then further down find the line which looks similiar to,
#define ITEM_ANTI_WARRIOR  (1 << 13)

and below it add
#define ITEM_ANTI_VAMPIRE  (1 << 14)
#define ITEM_ANTI_SLAYER  (1 << 15)

then in utils.h,
find this statement,
#define IS_WARRIOR(ch) (!IS_NPC(ch) && \
(GET_CLASS(ch) == CLASS_WARRIOR))
then below it add,
#define IS_VAMPIRE(ch)  (!IS_NPC(ch) && \
(GET_CLASS(ch) == CLASS_VAMPIRE))

#define IS_SLAYER(ch)   (!IS_NPC(ch) && \
(GET_CLASS(ch) == CLASS_SLAYER))

now open shops.h
and find,
#define TRADE_NOWARRIOR   (1 << 6)
and below add,
#define TRADE_NOVAMPIRE    (1 << 7)
#define TRADE_NOSLAYER    (1 << 8)

then search for,
#define NOTRADE_WARRIOR(i)              (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NOWARRIOR))
and below it add,
#define NOTRADE_VAMPIRE(i)              (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NOVAMPIRE))
#define NOTRADE_SLAYER(i)              (IS_SET(SHOP_TRADE_WITH((i)), TRADE_NOSLAYER))

Now the .c files for class adding,
constants.c,
find,
  "!WARRIOR",
and below it add.
  "!VAMPIRE",
  "!SLAYER",

now open shops.c
search for this,

const char *trade_letters[] = {
        "Good",                 /* First, the alignment based ones */
        "Evil",
        "Neutral",
        "Magic User",           /* Then the class based ones */
        "Cleric",
        "Thief",
        "Warrior"

and change it to,

const char *trade_letters[] = {
        "Good",                 /* First, the alignment based ones */
        "Evil",
        "Neutral",
        "Magic User",           /* Then the class based ones */
        "Cleric",
        "Thief",
        "Warrior",
        "Vampire"
        "Slayer"

then further down find,
      (IS_WARRIOR(ch) && NOTRADE_WARRIOR(shop_nr))) {

and change it to,
      (IS_WARRIOR(ch) && NOTRADE_WARRIOR(shop_nr)) ||
      (IS_VAMPIRE(ch) && NOTRADE_VAMPIRE(shop_nr)) ||
      (IS_SLAYER(ch) && NOTRADE_VAMPIRE(shop_nr))) {

now into the heart of adding classes, class.c,

find,
   "Mu",
   "Cl",
   "Th",
   "Wa",
and below it add
   "Va",
   "Sl",

then below that find,
   "Magic User",
   "Cleric",
   "Thief",
   "Warrior",
   "Vampire",
   "Vampire Slayer", //you can change this to just "Slayer",

then a little further down you should find,
"\r\n"
"Select a class:\r\n",
"  [C]leric\r\n",
"  [T]hief\r\n",
"  [W]warrior\r\n",
"  [M]agic-user\r\n",
below this add,
"  [V]ampire\r\n",
"  [S]layer\r\n",

then a little lower down you should find,
 case 'w':
   return CLASS_WARRIOR;
   break;

below this add,
 case 'v':
   return CLASS_VAMPIRE;
   break;
 case 's':
   return CLASS_SLAYER;
   break;

further down find,
    case 'w': return (1 << CLASS_WARRIOR);
and below it add,
    case 'v': return (1 << CLASS_VAMPIRE);
    case 's': return (1 << CLASS_SLAYER);

then just a bit further down from there you should find a 'int' funtion that looks like,
int prac_params[4][NUM_CLASSES] = {

  /* MAG       CLE       THE       WAR*/
  {95,95,85,80},/* learned level */
  {100,100,12,12},/* max per prac */
  {25,25,0,0},/* min per pac */
  {SPELL,       SPELL,       SKILL,       SKILL}              /* prac name */
};
change it to,
int prac_params[4][NUM_CLASSES] = {

  /* MAG       CLE       THE       WAR       VAM       SLA*/
  {95,       95,       85,       80,       80,       95},              /* learned level */
  {100,       100,       12,       12,       50,       30},              /* max per prac */
  {25,       25,       0,       0,       25       20},              /* min per pac */
  {SPELL,       SPELL,       SKILL,       SKILL, SPELL, SKILL}              /* prac name */
};

Below is the infomation on guilds,
I will leave guilds out, just for now, So we will skip that
and move onto the next bit, find,

byte saving_throws(int class_num, int type, int level)
and just below that you should see
case CLASS_MAGIC_USER:
below this add
case CLASS_VAMPIRE:

the go down to the next
case CLASS_WARRIOR:
and below that add
case CLASS_SLAYER:

right next find the next,
case CLASS_MAGIC_USER:
and below it add,
case CLASS_VAMPIRE:
and again find the next,
case CLASS_WARRIOR:
and below it add,
case CLASS_SLAYER:

Notice that this is similiar to what I just added, cause it is the same kind of info.
Right, now find,

  case CLASS_WARRIOR:
    ch->real_abils.str = table[0];
    ch->real_abils.dex = table[1];
    ch->real_abils.con = table[2];
    ch->real_abils.wis = table[3];
    ch->real_abils.intel = table[4];
    ch->real_abils.cha = table[5];
    if (ch->real_abils.str == 18)
      ch->real_abils.str_add = number(0, 100);
    break;

and below it add,
  case CLASS_VAMPIRE:
    ch->real_abils.str = table[0];
    ch->real_abils.dex = table[1];
    ch->real_abils.con = table[2];
    ch->real_abils.wis = table[3];
    ch->real_abils.intel = table[4];
    ch->real_abils.cha = table[5];
    if (ch->real_abils.str == 18)
      ch->real_abils.str_add = number(0, 100);
    break;

  case CLASS_SLAYER:
    ch->real_abils.str = table[0];
    ch->real_abils.dex = table[1];
    ch->real_abils.con = table[2];
    ch->real_abils.wis = table[3];
    ch->real_abils.intel = table[4];
    ch->real_abils.cha = table[5];
    if (ch->real_abils.str == 18)
      ch->real_abils.str_add = number(0, 100);
    break;

now find something that looks similiar to,

  GET_COND(ch, THIRST) = 24;
  GET_COND(ch, FULL) = 24;
  GET_COND(ch, DRUNK) = 24;

and change it to, 

  if (GET_CLASS(ch) == CLASS_VAMPIRE)
  GET_ALIGNMENT(ch) = -1000;

  if (GET_CLASS(ch) == CLASS_VAMPIRE){
  GET_COND(ch, FULL) = -1;
  GET_COND(ch, DRUNK) = -1;
  } else {

  GET_COND(ch, THIRST) = 24;
  GET_COND(ch, FULL) = 24;
  GET_COND(ch, DRUNK) = 24;
  }

next find,

  case CLASS_WARRIOR:
    add_hp += number(10, 15);
    add_mana = 0;
    add_move = number(1, 3);
    break;

and below it add,
  case CLASS_VAMPIRE:
    add_hp += number(10, 20);
    add_mana = (5, 10);
    add_move = number(0, 1);
    break;

  case CLASS_SLAYER:
    add_hp += number(3, 15);
    add_mana = (1, 5);
    add_move = number(3, 5);
    break;

now find,
      (IS_OBJ_STAT(obj, ITEM_ANTI_THIEF) && IS_THIEF(ch)))
and change it to,
      (IS_OBJ_STAT(obj, ITEM_ANTI_VAMPIRE) && IS_VAMPIRE(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_SLAYER) && IS_SLAYER(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_THIEF) && IS_THIEF(ch)))

at the end of,
void init_spell_levels(void)
add,
       /*vampires*/
  spell_level(SPELL_ARMOR, CLASS_VAMPIRE, 2);
  spell_level(SPELL_BLINDNESS, CLASS_VAMPIRE, 5);
  spell_level(SKILL_KICK, CLASS_VAMPIRE, 7);
  spell_level(SPELL_CHILL_TOUCH, CLASS_VAMPIRE, 11);
  spell_level(SPELL_CURSE, CLASS_VAMPIRE, 14);
  spell_level(SPELL_ENERGY_DRAIN, CLASS_VAMPIRE, 23);
  spell_level(SPELL_HARM, CLASS_VAMPIRE, 26);
  spell_level(SPELL_INVISIBLE, CLASS_VAMPIRE, 29);
  spell_level(SPELL_WORD_OF_RECALL, CLASS_VAMPIRE, 36);
  spell_level(SPELL_REMOVE_CURSE, CLASS_VAMPIRE, 38);
  spell_level(SPELL_SHOCKING_GRASP, CLASS_VAMPIRE, 42);
  spell_level(SPELL_SLEEP, CLASS_VAMPIRE, 46);
  spell_level(SPELL_STRENGTH, CLASS_VAMPIRE, 50);
  spell_level(SPELL_POISON, CLASS_VAMPIRE, 53);
  spell_level(SPELL_ANIMATE_DEAD, CLASS_VAMPIRE, 60);
  spell_level(SPELL_DISPEL_GOOD, CLASS_VAMPIRE, 63);
  spell_level(SPELL_INFRAVISION, CLASS_VAMPIRE, 68);
  spell_level(SPELL_SUMMON, CLASS_VAMPIRE, 73);
  spell_level(SPELL_TELEPORT, CLASS_VAMPIRE, 103);
  spell_level(SPELL_ENCHANT_WEAPON, CLASS_VAMPIRE, 118);

       /*slayers*/
  spell_level(SKILL_KICK, CLASS_SLAYER, 4);
  spell_level(SKILL_RESCUE, CLASS_SLAYER, 7);
  spell_level(SKILL_TRACK, CLASS_SLAYER, 9);
  spell_level(SKILL_BASH, CLASS_SLAYER, 18);
  spell_level(SPELL_HEAL, CLASS_SLAYER, 52);
  spell_level(SPELL_FIREBALL, CLASS_SLAYER, 55);
  spell_level(SPELL_DISPEL_EVIL, CLASS_SLAYER, 67);
  spell_level(SPELL_SANCTUARY, CLASS_SLAYER, 74);

you will have to change the casting level to what you want them
to be, as I have no idea what levels you have win your MUD, but 
mine has 200 mortal levels, and 8 Immortal, so they you go.
Also note that the spells and skils That will be added later will
get included.

right, now again search for the next 
case CLASS_MAGIC_USER:
this should bring you to the experience tables,
now below this add,
case CLASS_VAMPIRE:
case CLASS_SLAYER:

okay, again doing this to save space.
now search for,
const char *title_male(int chclass, int level)

and at the end of this array add,
    case CLASS_VAMPIRE:
    switch(level) {
       case 1: return "the Newbie Vampire";
       case 2: return "the Newbie Vampire";
       case 3: return "the Newbie Vampire";
       case 4: return "the Newbie Vampire";
       case 5: return "the Newbie Vampire";
       case 6: return "the Newbie Vampire";
      case 7: return "the Newbie Vampire";
      case 8: return "the Newbie Vampire";
      case 9: return "the Newbie Vampire";
      case 10: return "the Newbie Vampire";
      case 11: return "the Blood Student";
       case 12: return "the Blood Student";
       case 13: return "the Blood Student";
       case 14: return "the Blood Student";
       case 15: return "the Blood Student";
       case 16: return "the Blood Student";
       case 17: return "the Blood Student";
       case 18: return "the Blood Student";
       case 19: return "the Blood Student";
       case 20: return "the Blood Student";
    default: return "the Vampire";
       }
       break;

    case CLASS_SLAYER:
    switch(level) {
       case 1: return "the Newbie Vampire Slayer";
       case 2: return "the Newbie Vampire Slayer";
       case 3: return "the Newbie Vampire Slayer";
       case 4: return "the Newbie Vampire Slayer";
       case 5: return "the Newbie Vampire Slayer";
       case 6: return "the Newbie Vampire Slayer";
    case 7: return "the Newbie Vampire Slayer";
    case 8: return "the Newbie Vampire Slayer";
    case 9: return "the Newbie Vampire Slayer";
    case 10: return "the Newbie Vampire Slayer";
    case 11: return "the Vampire Slayer";
       case 12: return "the Vampire Slayer";
       case 13: return "the Vampire Slayer";
       case 14: return "the Vampire Slayer";
       case 15: return "the Vampire Slayer";
       case 16: return "the Vampire Slayer";
       case 17: return "the Vampire Slayer";
       case 18: return "the Vampire Slayer";
       case 19: return "the Vampire Slayer";
       case 20: return "the Vampire Slayer";
    default: return "the Vampire Slayer";
       }
       break;

now search for the array,
const char *title_female(int chclass, int level)
and as above at the end add,

    case CLASS_VAMPIRE:
    switch(level) {
       case 1: return "the Newbie Vampire";
       case 2: return "the Newbie Vampire";
       case 3: return "the Newbie Vampire";
       case 4: return "the Newbie Vampire";
       case 5: return "the Newbie Vampire";
       case 6: return "the Newbie Vampire";
    case 7: return "the Newbie Vampire";
    case 8: return "the Newbie Vampire";
    case 9: return "the Newbie Vampire";
    case 10: return "the Newbie Vampire";
    case 11: return "the Blood Student";
       case 12: return "the Blood Student";
       case 13: return "the Blood Student";
       case 14: return "the Blood Student";
       case 15: return "the Blood Student";
       case 16: return "the Blood Student";
       case 17: return "the Blood Student";
       case 18: return "the Blood Student";
       case 19: return "the Blood Student";
       case 20: return "the Blood Student";
    default: return "the Vampire";
       }
       break;

    case CLASS_SLAYER:
    switch(level) {
       case 1: return "the Newbie Vampire Slayer";
       case 2: return "the Newbie Vampire Slayer";
       case 3: return "the Newbie Vampire Slayer";
       case 4: return "the Newbie Vampire Slayer";
       case 5: return "the Newbie Vampire Slayer";
       case 6: return "the Newbie Vampire Slayer";
    case 7: return "the Newbie Vampire Slayer";
    case 8: return "the Newbie Vampire Slayer";
    case 9: return "the Newbie Vampire Slayer";
    case 10: return "the Newbie Vampire Slayer";
    case 11: return "the Vampire Slayer";
       case 12: return "the Vampire Slayer";
       case 13: return "the Vampire Slayer";
       case 14: return "the Vampire Slayer";
       case 15: return "the Vampire Slayer";
       case 16: return "the Vampire Slayer";
       case 17: return "the Vampire Slayer";
       case 18: return "the Vampire Slayer";
       case 19: return "the Vampire Slayer";
       case 20: return "the Vampire Slayer";
    default: return "the Vampire Slayer";
       }
       break;

feel free to change the titles, i have removed these from my MUD,
for certain reasons.

/********** FINISH HERE ***********/

Well this the basic classes now added.
Now we shall move onto the adding the skills and spells.

/*********** START HERE ****************/

We will first add the 'energy steal' spell,

first we go to spells.h
find this line,
#define SPELL_WATERWALK                   51 /* Reserved Skill[] DO NOT CHANGE */
and below it add,
#define SPELL_ENERGY_STEAL         52 /* Added by Baez. Lord of Dimensia */

now we go to magic.c,

at the end of,
int mag_damage(int level, struct char_data * ch, struct char_data * victim,
                   int spellnum, int savetype)
add

  case SPELL_ENERGY_STEAL:
         if(IS_NPC(victim)){
      dam = dice(GET_LEVEL(ch)/GET_LEVEL(victim), (GET_LEVEL(ch)*2)/GET_LEVEL(victim));
         GET_HIT(ch) += dam;
         }
         else
      dam = dice(GET_LEVEL(ch)/GET_LEVEL(victim), (GET_LEVEL(ch)*2)/GET_LEVEL(victim));
         GET_HIT(ch) += dam;
         GET_MAX_HIT(ch) += dam;
    break;

then we go to spell_parser.c,
 find this line,
  /* NON-castable spells should appear below here. */

and just above it add,

  spello(SPELL_ENERGY_STEAL, "energy steal", 200, 175, 2, POS_STANDING,
       TAR_CHAR_ROOM, TRUE, MAG_DAMAGE);

now go back to class.c
in the 
void init_spell_levels(void)
find the line we added earlier which looked like,
spell_level(SPELL_ENCHANT_WEAPON, CLASS_VAMPIRE, 118);
and below it add,
spell_level(SPELL_ENERGY_STEAL, CLASS_VAMPIRE, 120);
and adjust the level to suit your mud.

I believe that is all. Now we will add the two skills, Steak, and Neckbite.
Back to spells.h
find the line,
#define SKILL_TRACK                                   140 /* Reserved Skill[] DO NOT CHANGE */
and below it add,
#define SKILL_NECKBITE                                   141 /*Added by Baez, lord of Dimensia */
#define SKILL_STEAKS                                   142 /*Added by Baez, lord of Dimensia */

now move to act.offensive.c,
at the top of the file add,
void make_corpse(struct char_data * ch);

note that this later be altered to make_dust

at the bottom of the file add,

ACMD(do_neckbite)
{
  struct char_data *vict;
  int percent, prob;

  if (!IS_VAMPIRE(ch)) {
    send_to_char("Huh?!?\r\n", ch);
    return;
  }
  one_argument(argument, arg);

  if (!(vict = get_char_vis(ch, arg, FIND_CHAR_ROOM))) {
    if (FIGHTING(ch) && IN_ROOM(ch) == IN_ROOM(FIGHTING(ch))) {
      vict = FIGHTING(ch);
    } else {
      send_to_char("Bite who?\r\n", ch);
      return;
    }
  }  if (vict == ch) {
    send_to_char("Aren't we funny today...\r\n", ch);
    return;
  }
  /* 101% is a complete failure */
  percent = ((10 - (compute_armor_class(vict) / 10)) * 2) + number(1, 101);
  prob = GET_LEVEL(ch);

  if(IMM_FLAGGED(vict, IMM_VAMP));
       percent = 101;

  if (percent > prob) {
    damage(ch, vict, 0, SKILL_NECKBITE);
       check_killer(ch, vict);
  } else {
    damage(ch, vict, GET_LEVEL(ch) *4, SKILL_NECKBITE);
       check_killer(ch, vict);

  gain_condition(ch, THIRST, 24);
  send_to_char("You drink the blood as bite into your victim!\r\nYour blood thirst is quenched.",ch);
  }

  WAIT_STATE(ch, PULSE_VIOLENCE * 3);
}

ACMD(do_steak)
{
  struct char_data *vict;
  int percent, prob;

  if (IS_NPC(ch) || !GET_SKILL(ch, SKILL_STEAKS)) {
    send_to_char("You have no idea how to do that.\r\n", ch);
    return;
  }

  one_argument(argument, buf);

  if (!(vict = get_char_vis(ch, buf, FIND_CHAR_ROOM))) {
    send_to_char("Steak which vampire?\r\n", ch);
    return;
  }
  if (vict == ch) {
    send_to_char("Hahaha, funny today aren't we?\r\n", ch);
    return;
  }
  if (!GET_EQ(ch, WEAR_WIELD)) {
    send_to_char("You need to wield a weapon to make it a success.\r\n", ch);
    return;
  }
  if (GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 3) != TYPE_PIERCE - TYPE_HIT) {
    send_to_char("Only piercing weapons can be used for steaking.\r\n", ch);
    return;
  }
  if (FIGHTING(vict)) {
    send_to_char("You can't steak a fighting person -- they're too alert!\r\n", ch);
    return;
  }
  if (!IS_VAMPIRE(vict)) {
       send_to_char("You can only steak vampire players!\r\n", ch);
       return;
  }
  if (GET_LEVEL(vict) >= LVL_IMMORT) {
       send_to_char("You should not try to steak an Immortal vampire, it be dangerous!\r\n", ch);
       return;
  }

  percent = number(1, 101);       /* 101% is a complete failure */
  prob = GET_SKILL(ch, SKILL_STEAKS);

  if (AWAKE(vict) && (percent > prob)){
    damage(ch, vict, 0, SKILL_STEAKS);
         check_killer(ch, vict);
  } else {
  check_killer(ch, vict);
  act("You place your piercing weapon through $N's black heart, who explodes into dust which scatters around the room.", FALSE, ch, 0, vict, TO_CHAR);
  act("$N places a steaking weapon through your black heart!\r\nYou explode into dust which scatters across the room.\r\nYou have given a chance to start over.", FALSE, vict, 0, ch, TO_CHAR);
  act("$n sticks $s piercing weapon through $N's black heart, who suddenly explodes into dust.", FALSE, ch, 0, vict, TO_NOTVICT);
  make_corpse(vict);//This will later become make_dust
  extract_char(vict);
  }
}

now back to spell_parser.c,

find the line
  skillo(SKILL_TRACK, "track");
and below it add,
  skillo(SKILL_NECKBITE, "neck bite");
  skillo(SKILL_STEAKS, "steaks");

now move back into class.c and onto the oh so familiar 'init spell_levels'
 now find the line,
  spell_level(SPELL_ARMOR, CLASS_VAMPIRE, 2);
and above it add,
  spell_level(SKILL_NECKBITE, CLASS_VAMPIRE, 1);
and then find the line,
  spell_level(SKILL_KICK, CLASS_SLAYER, 4);
and above that add,
  spell_level(SKILL_STEAKS, CLASS_SLAYER, 4);

then search for,
  case CLASS_THIEF:
    SET_SKILL(ch, SKILL_SNEAK, 10);
    SET_SKILL(ch, SKILL_HIDE, 5);
    SET_SKILL(ch, SKILL_STEAL, 15);
    SET_SKILL(ch, SKILL_BACKSTAB, 10);
    SET_SKILL(ch, SKILL_PICK_LOCK, 10);
    SET_SKILL(ch, SKILL_TRACK, 10);
    break;
and add below it,

  case CLASS_VAMPIRE:
       SET_SKILL(ch, SKILL_NECKBITE, 100);
       break;

  case CLASS_SLAYER:
       SET_SKILL(ch, SKILL_STEAKS, 100);

right that is the new spell, and the two new skills added.

I have just realised something,
I FORGET THE SKILL AND SPELL MESSAGES!!
So, instead of editing any file within the /src directory goto
the /lib/misc/ directory and open the 'messages' file.

 Find the following message set,
* Dispel Good
M
 46
$N is dissolved by your evil.
$n dissolves you -- the price paid for leading a good life -- you die...
$n completely dissolves $N!
$N is unaffected by your evil!!
$n thinks that $e is really evil, and tries to dispell you!!
$N laughs at $n as $e tries to dispell $M!!
$N shivers and suffers from $S goodness!!
$n makes your soul hurt and suffer!!
$n makes $N's good spirit shiver and suffer!!
Did you really expect $M to suffer?
$n unfruitfully tries to dispell you!!
$n is stupid...

and below it add,

* Energy Steal
M
 52
$N's lifeless body falls to the ground, devoid of energy $E is dead!
$n drains the energy from you body, you fall to the ground, DEAD....
$n drains $N's life away! $N's lifeless body flops to the floor, dead!
You cannot seem to steal and energy from $N.
$n fails $s attempt to steal energy from you.
$n tries to steal energy from $N, but fails.
You drain some of $N's life force!
$n drains some of your life force!
$n drains some of $N's life force!
$N's energy is to powerful for you to take!
$n realises what a mistake $e just made, trying to drain your energy.
$n attempts to drain to energy of $N who happens to be a greater being!

Now look for,

M
 134
Your kick at $N's face splits $S head open -- yummy!
$n aims a kick at your face which splits your head in two!
$n neatly kicks $N's head into pieces -- YUMMY!
You miss your kick at $N's groin, much to $S relief!!
$n misses a kick at your groin, you breathe lighter now!!
$n misses a kick at $N's groin, much to $N's relief!!
Your kick hits $N in the solar plexus!!
You're hit in solar plexus, wow, this is breathtaking!!
$n kicks $N in solar plexus, $N is rendered breathless!!
You attempt to kick $N but lose your balance and fall face down in some mud that has suddenly appeared.
When $n tries to kick you, you quickly make him fall in some mud you have created!!
$n falls face down in some mud created by $N.

and below it add,

*Neck bite
M
 141
You grab hold of $N and bite chucks out of $s neck! $N falls to the floor dead!
$n grabs hold of you and bites chucks out of you neck, you are dead!
You hear the sound of ripping flesh as $n bites $N's neck off!
You try to bite $N's neck, but you fly over thier shoulder!!
$n flies over your shoulder, after trying to bite your neck!!
$N dodges a bite to the neck from $n, who ends up flat on the floor!!
You bite into $N's neck, but they slip away before you can kill them!!
$n's bite to neck wounds you, but you escape!!
$n bites deep into $N's neck, but $E escapes before major damage was caused!!
You try to bite $N's neck but $s neck makes your teeth bounce off!
You grin as $n tries to bite your neck, but can't seem to pierce the skin!!
$n tries to bite $N'd neck, but $N doesn't seem to feel it.

*Steak
M
 142
$N disappears into dust as place $p through $S heart.
Suddenly $n steaks you through the heart, R.I.P...
$n places $p through the heart of $N, resulting in a pile of dust.
$N quickly avoids your attemp to steak $M!!
$n tries to steak you, but you avoid $m!!
$n tries to steak $N but nearly cuts $s own finger!!
$N makes a strange sound as you place $p through $S chest!!
Suddenly $n steaks you through the chest!!
$n places $p through the chest of $N, resulting in a lot of screaming!!
$N sends you a look that makes you forget all about steaking!
$n tries to steak you, but changes $s mind!!
$n tries to steak $N, but changes $s mind.

/***************** Finish Here, for now ****************/

From here onwards I will add the special effects of being a vampire
like burning in sunlight etc, etc.
But first you must also know that here I also will be telling the MUD
that vampires will be loading in room '208' and that this is also were
tthey recall to. So if you wish this to not be, look through this part
of the code first so you know which areas cover the new loadrooms. Also
this new loadroom can quiet easily be changed, or so I believe.

First I will add the burning of Vampire flesh in sunlight.

open limits.c
and search for,
      if (AFF_FLAGGED(i, AFF_POISON))
       if (damage(i, i, 2, SPELL_POISON) == -1)
         continue;       /* Oops, they died. -gg 6/24/98 */

and just above it add,

       if(IS_VAMPIRE(i)){
              if (GET_LEVEL(i) < LVL_IMMORT) {        /* if mortal */
       if (time_info.hours < 45 ||
           time_info.hours > 15 &&
          (SECT(i->in_room) != SECT_INSIDE ||
           SECT(i->in_room) != SECT_UNDERWATER)) {
                     if(damage(i, i, 2 * GET_LEVEL(i), TYPE_SUFFERING) == -1);
                     }
   }/* End if Mortal */
}
         continue;

Thats that bit done, right now for the bloodthirst
Still in limits.c,
search for
  case THIRST:
    send_to_char("You are thirsty.\r\n", ch);
    return;

and change it to,
  case THIRST:
         if(!IS_VAMPIRE(ch)){
    send_to_char("You are thirsty.\r\n", ch);
         }
         else{
       send_to_char("You need a drink of blood.\r\n", ch);
         }
    return;

now go to act.item.c,
and find this,

  gain_condition(ch, THIRST,
       (int) ((int) drink_aff[GET_OBJ_VAL(temp, 2)][THIRST] * amount) / 4);

and change it to,

  if (!IS_VAMPIRE(ch)) {
  gain_condition(ch, THIRST,
       (int) ((int) drink_aff[GET_OBJ_VAL(temp, 2)][THIRST] * amount) / 4);
  }

if in your score function you have something that says 'You are Thirsty'
like this,

  if (GET_COND(ch, THIRST) == 0){
    strcat(buf, "       You are thirsty.\r\n");
  }

or similar, change it to this,

  if (GET_COND(ch, THIRST) == 0){
         if(GET_CLASS(ch) == CLASS_VAMPIRE){
    strcat(buf, "       You are thirsty for blood.\r\n");
  }
  else {
    strcat(buf, "       You are thirsty.\r\n");
  }

I believe that is all in the way of Bloodthirst, as I said at the beginning, I
did this a very simple way!

Right, now for HOLY and UNHOLY rooms, by the way this was very simple!
open structs.h and find the lines,
#define ROOM_DARK              (1 << 0)   /* Dark                     */
#define ROOM_DEATH              (1 << 1)   /* Death trap              */
#define ROOM_NOMOB              (1 << 2)   /* MOBs not allowed              */
#define ROOM_INDOORS              (1 << 3)   /* Indoors                     */
#define ROOM_PEACEFUL              (1 << 4)   /* Violence not allowed       */
#define ROOM_SOUNDPROOF              (1 << 5)   /* Shouts, gossip blocked       */
#define ROOM_NOTRACK              (1 << 6)   /* Track won't go through       */
#define ROOM_NOMAGIC              (1 << 7)   /* Magic not allowed              */
#define ROOM_TUNNEL              (1 << 8)   /* room for only 1 pers       */
#define ROOM_PRIVATE              (1 << 9)   /* Can't teleport in              */
#define ROOM_GODROOM              (1 << 10)  /* LVL_GOD+ only allowed       */
#define ROOM_HOUSE              (1 << 11)  /* (R) Room is a house       */
#define ROOM_HOUSE_CRASH       (1 << 12)  /* (R) House needs saving       */
#define ROOM_ATRIUM              (1 << 13)  /* (R) The door to a house       */
#define ROOM_OLC              (1 << 14)  /* (R) Modifyable/!compress       */
#define ROOM_BFS_MARK              (1 << 15)  /* (R) breath-first srch mrk       */

i have included all of these, because I am not sure which are included within
stock circle, anyway at the bottom add,
#define ROOM_HOLY           (1 << 16)  /* Vampires may not pass into this room */
#define ROOM_UNHOLY         (1 << 17)  /* Only Vampires may enter this room */

and if the numbers are not the next after the ones above, then change them!

now goto constants.c
as above i am not sure how many of these are included in stock circle, so
/* ROOM_x */
const char *room_bits[] = {
  "DARK",
  "DEATH",
  "!MOB",
  "INDOORS",
  "PEACEFUL",
  "SOUNDPROOF",
  "!TRACK",
  "!MAGIC",
  "TUNNEL",
  "PRIVATE",
  "GODROOM",
  "HOUSE",
  "HCRSH",
  "ATRIUM",
  "OLC",
  "*",                            /* BFS MARK */
  "\n"
};

this is the list on mine before I add HOLY and UNHOLY,

and this is it afterwards,
/* ROOM_x */
const char *room_bits[] = {
  "DARK",
  "DEATH",
  "!MOB",
  "INDOORS",
  "PEACEFUL",
  "SOUNDPROOF",
  "!TRACK",
  "!MAGIC",
  "TUNNEL",
  "PRIVATE",
  "GODROOM",
  "HOUSE",
  "HCRSH",
  "ATRIUM",
  "OLC",
  "*",                            /* BFS MARK */
  "HOLY",
  "UNHOLY",
  "\n"
};

Eeekk, Im not sure bout explaining that, so I won't.
Right now on to act.movement.c, find,

  if ((ROOM_FLAGGED(ch->in_room, ROOM_GODROOM)) ||
      (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM))) {
  if (GET_LEVEL(ch) < LVL_GRGOD) {
      send_to_char("You are not Godly enough to enter there!\r\n", ch);
      return (0);
    }
  }

and below it add,

 if ((ROOM_FLAGGED(ch->in_room, ROOM_HOLY)) ||
      (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_HOLY))) {
  if (IS_VAMPIRE(ch)) {
      send_to_char("You are burned as you attempt to enter such a holy place!\r\n", ch);
        if (GET_LEVEL(ch) < LVL_IMMORT) {
         GET_HIT(ch) -= GET_LEVEL(ch);
//BoxBoy: I added the harming of vampires entering holy rooms
              }
      return (0);
    }
  }
  
  if ((ROOM_FLAGGED(ch->in_room, ROOM_UNHOLY)) ||
      (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_UNHOLY))) {
  if (!IS_VAMPIRE(ch)) {
      send_to_char("You cannot get through into such and Unholy place!\r\n", ch);
      return (0);
    }
  }

and that is all thats needed for that.

Ahh, right, yes the 'make_dust' function, open fight.c and near the top find the line
void make_corpse(struct char_data * ch);
and below it add,
void make_dust(struct char_data * ch);

now further down you will find the function,
void make_corpse(struct char_data * ch)

and above it add,

void make_dust(struct char_data * ch)
{
  struct obj_data *dust;
  struct obj_data *money;
  int i;

  dust = create_obj();

  dust->item_number = NOTHING;
  dust->in_room = NOWHERE;
  dust->name = str_dup("dust");

  sprintf(buf2, "Dust is scattered across the room, a result of %s's death.", GET_NAME(ch));
  dust->description = str_dup(buf2);

  sprintf(buf2, "a pile of charred dust");
  dust->short_description = str_dup(buf2);

  GET_OBJ_TYPE(dust) = ITEM_FOOD;
  GET_OBJ_EXTRA(dust) = ITEM_NODONATE;
  GET_OBJ_VAL(dust, 0) = 0;       /* You can't store stuff in a corpse */
  GET_OBJ_VAL(dust, 3) = 1;       /* corpse identifier */
  GET_OBJ_WEIGHT(dust) = GET_WEIGHT(ch) + IS_CARRYING_W(ch);
  GET_OBJ_RENT(dust) = 100000;
  if (IS_NPC(ch))
    GET_OBJ_TIMER(dust) = max_npc_corpse_time;
  else
    GET_OBJ_TIMER(dust) = max_pc_corpse_time;

  /*Boxboy: I am gonna change this so the objects are sent to the either the room, or the void */
  /* transfer character's inventory to the corpse */
  obj_to_room(ch->carrying, 3);

  /* transfer character's equipment to the corpse */
  for (i = 0; i < NUM_WEARS; i++)
    if (GET_EQ(ch, i))
      obj_to_room(unequip_char(ch, i), 3);

  /* transfer gold */
  if (GET_GOLD(ch) > 0) {
    /* following 'if' clause added to fix gold duplication loophole */
    if (IS_NPC(ch) || (!IS_NPC(ch) && ch->desc)) {
      money = create_money(GET_GOLD(ch));
      obj_to_room(money, 3);
    }
    GET_GOLD(ch) = 0;
  }
  ch->carrying = NULL;
  IS_CARRYING_N(ch) = 0;
  IS_CARRYING_W(ch) = 0;
  obj_to_room(dust, ch->in_room);
         }
}

right now we have to go back to the steak skill within act.offensive.c, find the line
  make_corpse(vict);//This will later become make_dust
and change it to,
  make_dust(vict);
also in fight.c when someone gets killed always turn vampires to dust so, find the lines,

  make_corpse(ch);
  extract_char(ch);

and change them to,

if (IS_VAMPIRE(ch)){
  make_dust(ch);
  extract_char(ch);
}
else {
  make_corpse(ch);
  extract_char(ch);
}

Within my MUD, that is all that needed, but your might need more alterations like that.

All that is left now is vampire load_rooms modifications.
Open config.c
find the lines,
/* virtual number of room that mortals should enter at */
room_vnum mortal_start_room = 1335;

and below add,
/* virtual number of room that vampires should enter at */
room_vnum vampire_start_room = 208;

now go into class.c and find the function,
void do_start(struct char_data * ch)

above the line,
 GET_LEVEL(ch) = 1;

add,
room_vnum load_room;

find these lines (which we added earlier)
  if (GET_CLASS(ch) == CLASS_VAMPIRE)
  GET_ALIGNMENT(ch) = -1000;

and above them add,

  if (GET_CLASS(ch) == CLASS_VAMPIRE)
  load_room = 208;

now open db.c and find these three lines,
room_rnum r_mortal_start_room;       /* rnum of mortal start room        */
room_rnum r_immort_start_room;       /* rnum of immort start room        */
room_rnum r_frozen_start_room;       /* rnum of frozen start room        */

and below them add,
room_rnum r_vampire_start_room; /* rnum of vampire start room    */

then find these three,
extern room_vnum mortal_start_room;
extern room_vnum immort_start_room;
extern room_vnum frozen_start_room;

and below them add,
extern room_vnum vampire_start_room;

now find the function,
void check_start_rooms(void) 
and above,
  if ((r_mortal_start_room = real_room(mortal_start_room)) < 0) {
    log("SYSERR:  Mortal start room does not exist.  Change in config.c.");
    exit(1);
  }

add,
  if ((r_vampire_start_room = real_room(vampire_start_room)) < 0) {
    log("SYSERR:  Vampire start room does not exist.  Change in config.c.");
    exit(1);
  }

now go into interpreter.c,
find these three lines,
extern room_rnum r_mortal_start_room;
extern room_rnum r_immort_start_room;
extern room_rnum r_frozen_start_room;

and below them add,
extern room_rnum r_vampire_start_room;

then search for,
       if (GET_LEVEL(d->character) >= LVL_IMMORT){
                load_room = r_immort_start_room;
                }
       else
         load_room = r_mortal_start_room;
      }

and change it to,
       if (GET_LEVEL(d->character) >= LVL_IMMORT){
                load_room = r_immort_start_room;
                }
       if (GET_CLASS(d->character) == CLASS_VAMPIRE){
                load_room = r_vampire_start_room;
                }
       else
         load_room = r_mortal_start_room;
      }

now goto spells.c
find these lines,
extern room_rnum r_mortal_start_room;
extern room_rnum r_immort_start_room;

and add this below them,
extern room_rnum r_vampire_start_room;

now look for,

  act("$n disappears.", TRUE, victim, 0, 0, TO_ROOM);
  char_from_room(victim);
  char_to_room(victim, r_mortal_start_room);
  act("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM);
  look_at_room(victim, 0);

and change it to,

  act("$n disappears.", TRUE, victim, 0, 0, TO_ROOM);
  if (GET_CLASS(victim) == CLASS_VAMPIRE){
  char_from_room(victim);
  char_to_room(victim, r_vampire_start_room);
  }
  else{
  char_from_room(victim);
  char_to_room(victim, r_mortal_start_room);
  }
  act("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM);
  look_at_room(victim, 0);

/***************** FINISHED ******************/
Well there you go, on my computer this registers as ninteen pages of code, so
if you have only looked through it so far, you now know how long this will
probably take you to put in.
I guess there is a fair bit that different people will leave out when they put
this into the their mud, or stuff people will change.

PLEASE give me credit for this code if you use it as I probably spent almost 20
hours doing this plus an additional 3 or 4 writing it up into this file for
people to use. So the more credit I get, they happier this lil vampire will be.
Also I wouldn't mind seeing some MUD's which use my code, so if you do use then 
I wouldn't mind getting the address.

And ONE more thing.........this is about me and how I came to code as I do.
As some people here know, I am just 14 years of age (how many people have just
done an amusing cough?) and I decided to make my MUD after the MUD I played
went down. Well so I started, got lots done, then got my hard drive formatted!
DOH! Then my sanity became, erm, lets say less so, then came my new MUD, and this
code. So Aswell as tahnking me for this code also thank my Dad, who accidentally
formated my hard drive (hehehehe), the owner of the MUD once known as 
'Insanity Minos II' (now known as AfflictionMUD) and also I would like to thank all
those people who like me have contributed code, no matter how big or tiny this
code/snippet was, they stil deserve thanx,

Well I hopefully will be able to post more of my code soon.

if you want to contact me, then use the following addresses:

boruki@as-if.com        - if you need help with some of my code
baez@as-if.com          - if you wish to congratulate me, 
                          or invite me to your MUD, etc, etc
boxboy22nd@trust-me.com - if you wish to send me hate mail or kinds

BoxBoy (aka Boruki Bunny and Baez Summers)

<< Second-Hand Shops [by Jake Turner] | Reply | Threaded | FTP Uploads 2000//0/9/ >>

 


Related Links
  Intel
BoxBoy
Related Articles
More by bbrown
 
 

Quick Links
 
The CircleMUD FAQ
The CircleMUD home page
Alex's Snippets
Wintermute Snippets
CircleMUD Bug Reporting or Help
CircleMUD List Archives
CircleMUD Resources
Death Gate's Scripts
(Author of C conversion)
Sammy's code site
Erwin S. Andreasen's page
(Author of mudFTP and other goodies)
Death's Gate Scripting site
Help for CircleMUD in Windows
The OasisOLC Maintenance Effort
George's Random Stuff
Imaginary Realities
MUD Dictionary
 
 


No Subject Given
by Lexiconical () on Monday, September 4th @ 12:28:59 PM
http://
I'm usually not nit-picky about spelling that only appears as part of the code, but when it's something that's integral to the game that appears within the game, it's best to spell things correctly, makes your MUD more credible and all... so I just thought I'd point out that the word you want is "stake," not "steak." Steaks are what you eat.
[ Reply to this comment ]

Accidents Happen!
by BoxBoy (boruki@as-if.com) on Saturday, September 9th @ 12:06:27 AM
http://
It took me a long time to complete the code, and it also took a long time to get the coded bugs out. By this time I had forgotten all about the spelling mistake (which I had noticed). Also I apoligise for any errors, I have fifteen classes on my Mud, and had to alter it slightly as i wrote it out, so there will be a couple of errors.
I thank Brandon Brown very much for fixing the errors he fixed.
[ Reply to this comment ]

Steaks/Stakes
by Rob (sibrwulf@hotmail.com) on Sunday, May 6th @ 10:59:08 PM
http://
Well if you're a woodchuck....nevermind..*slaps self*
[ Reply to this comment ]