This is a snippet to implement Ghosts on your mud, this was tested on CircleMUD30bpl17. I used this as "holograms" on my mud as it's a star trek mud. This will implement a "summon spirit", "sense spirits" and "banish spirits" spell, also there will be a SPIRIT mobflag which can be set to mob. Spirits die instantly with no exp gain, spirits will also protect a player from aggressive/helper mobs. Mobs will attack a player's spirit before it attacks them, giving precious few seconds to escape an aggressive mob. DISCLAIMER: I am in no way reponsible for this code...etc. Please backup your world files before installing ANY snippet. (better safe than sorry) open act.informative.c ~~~~~~~~~~~~~~~~~~~~~~ In "list_all_char()" or possibly "list_one_char()" (i got Stacking installed) " is sitting here.", "!FIGHTING!", " is standing here." }; if (IS_NPC(i) && i->player.long_descr && GET_POS(i) == GET_DEFAULT_POS(i)) { if (AFF_FLAGGED(i, AFF_INVISIBLE)) strcpy(buf, "(cloaked)"); + if (MOB_FLAGGED(i, MOB_SPIRIT) && AFF_FLAGGED(ch, AFF_SENSESPIRIT)) + strcpy(buf, "(Spirit)"); Further down in same function: send_to_char(buf, ch); if (AFF_FLAGGED(i, AFF_SANCTUARY)) act("...$e glows with a bright light!", FALSE, i, 0, ch, TO_VICT); if (AFF_FLAGGED(i, AFF_BLIND)) act("...$e is groping around blindly!", FALSE, i, 0, ch, TO_VICT); + /*** (MG) Spirit Stuff */ + if (AFF_FLAGGED(i, AFF_SPIRIT) && AFF_FLAGGED(ch, AFF_SENSESPIRIT)) { + sprintf(buf, "A Spirit is floating here protecting %s.\r\n", GET_NAME(i)); + send_to_char(buf, ch); + } Further down again: strcat(buf, "\r\n"); send_to_char(buf, ch); if (AFF_FLAGGED(i, AFF_SANCTUARY)) act("...$e glows with a bright light!", FALSE, i, 0, ch, TO_VICT); + /*** (MG) Spirit Stuff */ + if (AFF_FLAGGED(i, AFF_SPIRIT) && AFF_FLAGGED(ch, AFF_SENSESPIRIT)) { + sprintf(buf, "A Spirit is floating here protecting %s.\r\n", GET_NAME(i)); + send_to_char(buf, ch); + } } In "look_at_room()" /* now list characters & objects */ send_to_char(CCGRN(ch, C_NRM), ch); list_obj_to_char(world[ch->in_room].contents, ch, 0, FALSE); send_to_char(CCYEL(ch, C_NRM), ch); list_char_to_char(world[ch->in_room].people, ch); + /*** (MG) Player should see his/her spirit in their room */ + if (AFF_FLAGGED(ch, AFF_SPIRIT)) + send_to_char("A Spirit is floating here protecting you.\r\n", ch); send_to_char(CCNRM(ch, C_NRM), ch); open class.c ~~~~~~~~~~~~ beside other spell levels put: + spell_level(SPELL_SPIRIT , CLASS_XXX, XX); + spell_level(SPELL_SENSESPIRIT, CLASS_XXX, XX); + spell_level(SPELL_BANISH , CLASS_XXX, XX); open constants.c ~~~~~~~~~~~~~~~~ in MOB_x array "SENTINEL", "SCAVENGER", "ISNPC", "AWARE", "AGGR", "STAY-ZONE", "WIMPY", "AGGR_EVIL", "AGGR_GOOD", "AGGR_NEUTRAL", "MEMORY", "HELPER", "!CHARM", "!TRANS", "!SLEEP", "!BASH", "!BLIND", + "SPIRIT", Further down in AFF_x array "DET-CLOAK", "DET-MAGIC", "DET-PHASE", "WATWALK", "SHIPSHIELDS", "GROUP", "CURSE", "INFRA", "POISON", "PROT-EVIL", "PROT-GOOD", "SLEEP", "!TRACK", "UNUSED", "UNUSED", "SNEAK", "PHASE", "UNUSED", "CHARM", + "SPIRIT", + "SENSESPIRIT", In the spell_wear_off_messages array add at the bottom + "Your spirit guardian is summoned back to the underworld.", + "Your senses seem to dull and the world seems to take on a different hue.", + "!Banish Spirits!", "!UNUSED!" }; open fight.c ~~~~~~~~~~~~ /* External procedures */ char *fread_action(FILE * fl, int nr); ACMD(do_flee); int backstab_mult(int level); int thaco(int ch_class, int level); int ok_damage_shopkeeper(struct char_data * ch, struct char_data * victim); void Crash_rentsave(struct char_data * ch, int cost); +int destroy_spirit(struct char_data *ch, struct char_data *killer); In "damage()" + /*** (MG) Spirits are destroyed, just like it says */ + if (destroy_spirit(victim, ch)) + return (0); + /* peaceful rooms */ if (ch != victim && (ROOM_FLAGGED(ch->in_room, ROOM_PEACEFUL))) { send_to_char("This room just has such a peaceful, easy feeling...\r\n", ch); return (0); } In "hit()" + /*** (MG) Spirits are destroyed, just like it says */ + if (destroy_spirit(victim, ch)) + return; + /* Find the weapon type (for display purposes only) */ if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) w_type = GET_OBJ_VAL(wielded, 3) + TYPE_HIT; else { if (IS_NPC(ch) && (ch->mob_specials.attack_type != 0)) w_type = ch->mob_specials.attack_type + TYPE_HIT; else w_type = TYPE_HIT; } open magic.c ~~~~~~~~~~~~ byte saving_throws(int class_num, int type, int level); /* class.c */ void clearMemory(struct char_data * ch); void weight_change_object(struct obj_data * obj, int weight); void add_follower(struct char_data * ch, struct char_data * leader); extern struct spell_info_type spell_info[]; +int destroy_spirit(struct char_data *ch, struct char_data *killer); In "mag_affects()" + case SPELL_SPIRIT: + af[0].bitvector = AFF_SPIRIT; + af[0].duration = level; + accum_duration = FALSE; + + to_vict = "You summon a spirit from the underworld to protect you."; + to_room = "$n summons a spirit from the underworld to protect $m."; + break; + + + case SPELL_SENSESPIRIT: + af[0].bitvector = AFF_SENSESPIRIT; + af[0].duration = level; + accum_duration = FALSE; + + to_vict = "Your see a whole new plain of existance."; + to_room = "$n's eyes briefly glow white."; + break; + + case SPELL_ARMOR: af[0].location = APPLY_AC; af[0].modifier = -20; af[0].duration = 24; accum_duration = TRUE; to_vict = "You feel something protecting you."; break; In "mag_masses()" for (tch = world[ch->in_room].people; tch; tch = tch_next) { tch_next = tch->next_in_room; if (tch == ch) continue; switch (spellnum) { + case SPELL_BANISH: + destroy_spirit(tch, ch); + break; } } open mobact.c ~~~~~~~~~~~~~ /* local functions */ +int destroy_spirit(struct char_data *ch, struct char_data *killer); void mobile_activity(void); Further down /* ****************************************************************** Please create an object with vnum #6 that is "a Broken Holy Medallion". or not :) your choice, i think an object dropping to the ground is something of interest to the player. IDEA: You could make it that if a player follows a SPIRIT mob that when the mob returns to the underworld (when player attacks it) the player will be pulled into the vortex too and brought to the underworld (most muds have an underworld zone) ****************************************************************** */ +int destroy_spirit(struct char_data *ch, struct char_data *killer) +{ + struct obj_data *obj; + + if (MOB_FLAGGED(ch, MOB_SPIRIT)) { + obj = read_object(real_object(6), REAL); + if (killer == NULL) + act("A Vortex opens and $n is pulled back to the underworld, $s expression is of pure horror!", TRUE, ch, 0, 0, TO_ROOM); + else + act("$N swings for $n and as $S blade slices through the air a vortex quickly sucks $n back to the underworld!", TRUE, ch, 0, killer, TO_ROOM); + obj_to_room(obj, ch->in_room); + extract_char(ch); + return(TRUE); + } + else if (AFF_FLAGGED(ch, AFF_SPIRIT)) { + if (killer != NULL) { + if (AFF_FLAGGED(killer, AFF_SENSESPIRIT)) + return(FALSE); + } + if (affected_by_spell(ch, SPELL_SPIRIT)) + affect_from_char(ch, SPELL_SPIRIT); + obj = read_object(real_object(6), REAL); + if (killer == NULL) { + act("A Vortex opens and $n's Guardian Spirit is pulled back to the underworld, his expression is of pure horror!", TRUE, ch, 0, 0, TO_ROOM); + act("A Vortex opens and your Guardian Spirit is pulled back to the underworld, his expression is of pure horror!", TRUE, ch, 0, 0, TO_CHAR); + } else { + act("$N swings for $n's Guardian Spirit and as $S blade slices through the air a vortex quickly sucks the Spirit back to the underworld!", TRUE, ch, 0, killer, TO_ROOM); + act("$N swings for your Guardian Spirit and as $S blade slices through the air a vortex quickly sucks the Spirit back to the underworld!", TRUE, ch, 0, killer, TO_CHAR); + } + obj_to_room(obj, ch->in_room); + REMOVE_BIT(AFF_FLAGS(ch), AFF_SPIRIT); + return(TRUE); + } + return(FALSE); +} + void mobile_activity(void) { Somewhere in "mobile_activity()" + if (MOB_FLAGGED(ch, MOB_SPIRIT) && (GET_HIT(ch) != GET_MAX_HIT(ch))) + if (destroy_spirit(ch, NULL)) + continue; + open spell_parser.c ~~~~~~~~~~~~~~~~~~~ Somewhere near the end of spello definitions + spello(SPELL_SPIRIT, "summon spirit", 100, 50, 5, POS_STANDING, + TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS); + + spello(SPELL_SENSESPIRIT, "sense spirit", 100, 50, 5, POS_STANDING, + TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS); + + spello(SPELL_BANISH, "banish spirit", 200, 50, 3, POS_STANDING, + TAR_IGNORE, FALSE, MAG_MASSES); + open spells.h ~~~~~~~~~~~~~ Under other SPELL_XXX definitions +#define SPELL_SPIRIT 63 +#define SPELL_SENSESPIRIT 64 +#define SPELL_BANISH 65 open structs.h ~~~~~~~~~~~~~~ #define MOB_AWARE (1 << 4) /* Mob can't be backstabbed */ #define MOB_AGGRESSIVE (1 << 5) /* Mob hits players in the room */ #define MOB_STAY_ZONE (1 << 6) /* Mob shouldn't wander out of zone */ #define MOB_WIMPY (1 << 7) /* Mob flees if severely injured */ #define MOB_AGGR_EVIL (1 << 8) /* auto attack evil PC's */ #define MOB_AGGR_GOOD (1 << 9) /* auto attack good PC's */ #define MOB_AGGR_NEUTRAL (1 << 10) /* auto attack neutral PC's */ #define MOB_MEMORY (1 << 11) /* remember attackers if attacked */ #define MOB_HELPER (1 << 12) /* attack PCs fighting other NPCs */ #define MOB_NOCHARM (1 << 13) /* Mob can't be charmed */ #define MOB_NOSUMMON (1 << 14) /* Mob can't be summoned */ #define MOB_NOSLEEP (1 << 15) /* Mob can't be slept */ #define MOB_NOBASH (1 << 16) /* Mob can't be bashed (e.g. trees) */ #define MOB_NOBLIND (1 << 17) /* Mob can't be blinded */ +#define MOB_SPIRIT (1 << 18) Further down #define AFF_WATERWALK (1 << 6) /* Char can walk on water */ #define AFF_SANCTUARY (1 << 7) /* Char protected by sanct. */ #define AFF_GROUP (1 << 8) /* (R) Char is grouped */ #define AFF_CURSE (1 << 9) /* Char is cursed */ #define AFF_INFRAVISION (1 << 10) /* Char can see in dark */ #define AFF_POISON (1 << 11) /* (R) Char is poisoned */ #define AFF_PROTECT_EVIL (1 << 12) /* Char protected from evil */ #define AFF_PROTECT_GOOD (1 << 13) /* Char protected from good */ #define AFF_SLEEP (1 << 14) /* (R) Char magically asleep */ #define AFF_NOTRACK (1 << 15) /* Char can't be tracked */ #define AFF_UNUSED16 (1 << 16) /* Room for future expansion */ #define AFF_UNUSED17 (1 << 17) /* Room for future expansion */ #define AFF_SNEAK (1 << 18) /* Char can move quietly */ #define AFF_HIDE (1 << 19) /* Char is hidden */ #define AFF_UNUSED20 (1 << 20) /* Room for future expansion */ #define AFF_CHARM (1 << 21) /* Char is charmed */ +#define AFF_SPIRIT (1 << 22) +#define AFF_SENSESPIRIT (1 << 23) Ok, thats should be it, have fun with it. ************************************************************************* If you use this code please email me and let me know. I'd appreciated it. Subliminal m_gally@hotmail.com Head Coder/Implementor of "Star Trek: First Contact MUD" (formerly known as "STFMUD: The Second Coming"). http://www.stfmud.com/ (you can find my other snippets there) *************************************************************************