/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Thanks to abaddon for proof-reading our comm.c and pointing out bugs. * * Any remaining bugs are, of course, our work, not his. :) * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1996 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Tartarus/doc/rom.license * ***************************************************************************/ /*************************************************************************** * Tartarus code is copyright (C) 1997-1998 by Daniel Graham * * In using this code you agree to comply with the Tartarus license * * found in the file /Tartarus/doc/tartarus.doc * ***************************************************************************/ #include "include.h" char *target_name; void spell_hex(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA hex; int severity = 0; if(is_affected(victim,sn)) return send_to_char("They are already hexed.\n\r",ch); act("$n grins maniacally and spits out an archaic word, unleashing a hex upon $N!",ch,0,victim,TO_NOTVICT); act("$n grins maniacally and spits out an archaic word, unleashing a hex upon you!",ch,0,victim,TO_VICT); act("You grin maniacally and spit out an archaic word, unleashing a hex upon $N!",ch,0,victim,TO_CHAR); if(saves_spell(level+4,victim,DAM_NEGATIVE) && number_percent()>35) { act("$n staggers for a moment, but resists the hex.",victim,0,0,TO_ROOM); act("You stagger as the power of the hex strikes you, but manage to resist it.",victim,0,0,TO_CHAR); return; } init_affect(&hex); hex.where = TO_AFFECTS; hex.type = sn; hex.level = level; hex.owner_name = str_dup(ch->original_name); hex.location = APPLY_SAVING_SPELL; hex.modifier = 10; hex.duration = level/4; hex.bitvector = AFF_CURSE; severity++; if(number_percent()>75) { hex.bitvector += AFF_BLIND; severity++; } affect_to_char(victim, &hex); if(number_percent()>70) { //plague hex.location = APPLY_STR; hex.modifier = -5; hex.bitvector = AFF_PLAGUE; affect_to_char(victim, &hex); severity++; } if(number_percent()>66) { //poison hex.location = APPLY_STR; hex.modifier = -6; hex.bitvector = AFF_POISON; affect_to_char(victim, &hex); severity++; } if(severity>1 && severity<4) { act("$n sags as the hex strikes him powerfully!",victim,0,0,TO_ROOM); act("You slump as the hex strikes you powerfully.",victim,0,0,TO_CHAR); } if(severity==4) { act("$n screams in utter agony as the full power of the hex strangles $s soul!",victim,0,0,TO_ROOM); act("You scream in utter agony as the full power of the hex strangles your soul!",victim,0,0,TO_CHAR); } act("You feel drained from the power of your hex.",ch,0,0,TO_CHAR); ch->hit *= (98 - (severity * 3.0)) / 100.1; } void spell_black_circle(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *pet; AFFECT_DATA af; bool found = FALSE; if(is_affected(ch,sn)) return send_to_char("You cannot summon your minions again yet.\n\r",ch); act("$n draws a black circle on the ground and falls into deep concentration.",ch,0,0,TO_ROOM); act("You draw a black circle on the ground and fall into deep concentration.",ch,0,0,TO_CHAR); for(pet = char_list; pet!= NULL; pet=pet->next) if(IS_NPC(pet) && IS_AFFECTED(pet,AFF_CHARM) && (IS_SET(pet->act, ACT_UNDEAD) || (pet->pIndexData->vnum == MOB_VNUM_L_GOLEM || pet->pIndexData->vnum==MOB_VNUM_G_GOLEM)) && pet->master == ch) { stop_fighting(pet,TRUE); act("$n disappears suddenly.",pet,0,0,TO_ROOM); char_from_room(pet); char_to_room(pet, ch->in_room); act("$n arrives suddenly, kneeling before $N outside the circle.",pet,0,ch,TO_ROOM); found = TRUE; } if(!found) return send_to_char("Your summonings went unanswered.\n\r",ch); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SPELL; af.type = sn; af.modifier = 0; af.location = 0; af.duration = 10; af.owner_name = str_dup(ch->original_name); af.affect_list_msg = str_dup("unable to perform the summoning ritual"); af.level = ch->level; af.bitvector = 0; af.end_fun = NULL; affect_to_char(ch,&af); } void spell_banshee_call(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *zombie; CHAR_DATA *check; AFFECT_DATA af; char buf1[MSL], buf2[MSL]; int count = 0; for (check = char_list; check != NULL; check = check->next) { if (IS_NPC(check) && IS_AFFECTED(check,AFF_CHARM) && IS_SET(check->act,ACT_UNDEAD) && check->master == ch) count++; } if (count >= 5) return send_to_char("You already control an army of banshees.\n\r",ch); if (is_affected(ch,skill_lookup("banshee call"))) return send_to_char("You cannot yet summon an army of banshees.\n\r",ch); while (count < 5) { zombie = create_mobile(get_mob_index(MOB_VNUM_ZOMBIE)); int z_level = number_range(47,49); zombie->level = z_level; zombie->max_hit = (dice(z_level, 15)); zombie->max_hit += (z_level * 20); zombie->hit = zombie->max_hit; zombie->damroll += (z_level*7/10); zombie->alignment = -1000; zombie->name = str_dup("banshee spirit"); sprintf( buf1, "a banshee spirit"); sprintf( buf2, "A banshee spirit is standing here.\n\r"); free_string(zombie->short_descr); free_string(zombie->long_descr); zombie->short_descr = str_dup(buf1); zombie->long_descr = str_dup(buf2); char_to_room(zombie,ch->in_room); SET_BIT(zombie->affected_by, AFF_CHARM); add_follower(zombie,ch); zombie->leader = ch; act("A banshee rises from the earth before $n.",ch,0,0,TO_ROOM); act("A banshee rises from the earth before you.",ch,0,0,TO_CHAR); count++; } init_affect(&af); af.type = skill_lookup("banshee call"); af.affect_list_msg = str_dup("unable to summon an army of banshees"); af.duration = 35; af.aftype = AFT_SPELL; affect_to_char(ch,&af); } void spell_minion_tactics( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *gch; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( !is_same_group(gch, ch) || !(IS_NPC(gch))) continue; if ((IS_AFFECTED(gch,AFF_CHARM)) && (gch->pIndexData->vnum==MOB_VNUM_ZOMBIE) && (gch->master == ch)) { act("$n's eyes widen with newly-acquired tactics.", gch, NULL, NULL, TO_ROOM ); send_to_char("Your eyes widen with newly-acquired tactics.\n\r", gch ); SET_BIT(gch->off_flags,OFF_BASH); SET_BIT(gch->off_flags,OFF_TRIP); SET_BIT(gch->off_flags,OFF_CRUSH); } } send_to_char( "Ok.\n\r", ch ); return; } void spell_minion_sanc( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *gch; sn = skill_lookup("sanctuary"); for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( !is_same_group(gch, ch) || !(IS_NPC(gch))) continue; if ((IS_AFFECTED(gch,AFF_CHARM)) && (gch->pIndexData->vnum==MOB_VNUM_ZOMBIE) && (gch->master == ch)) { spell_sanctuary(sn,ch->level,ch,gch,TARGET_CHAR); } } send_to_char( "Ok.\n\r", ch ); return; } void spell_minion_flight( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *gch; sn= skill_lookup("fly"); for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( !is_same_group(gch, ch) || !(IS_NPC(gch))) continue; if ((IS_AFFECTED(gch,AFF_CHARM)) && (gch->pIndexData->vnum==MOB_VNUM_ZOMBIE) && (gch->master == ch)) { spell_fly(sn,ch->level,ch,gch,TARGET_CHAR); } } send_to_char( "Ok.\n\r", ch ); return; } void spell_minion_sneak( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *gch; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( !is_same_group(gch, ch) || !(IS_NPC(gch))) continue; if ((IS_AFFECTED(gch,AFF_CHARM)) && (gch->pIndexData->vnum==MOB_VNUM_ZOMBIE) && (gch->master == ch)) { act("$n begins moving silently.", gch, NULL, NULL, TO_ROOM ); send_to_char("You begin moving silently.\n\r", gch ); SET_BIT(gch->affected_by,AFF_SNEAK); } } act("$n begins moving silently.", ch, NULL, NULL, TO_ROOM ); return; } void spell_minion_recall( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *gch, *gch_next; ROOM_INDEX_DATA *room; sn= skill_lookup("word of recall"); room = ch->in_room; spell_word_of_recall(sn,ch->level,ch,ch,TARGET_CHAR); for ( gch = room->people; gch != NULL; gch = gch_next) { gch_next = gch->next_in_room; if ( !is_same_group(gch, ch) || !(IS_NPC(gch))) continue; if ((IS_AFFECTED(gch,AFF_CHARM)) && (gch->pIndexData->vnum==MOB_VNUM_ZOMBIE || gch->pIndexData->vnum==MOB_VNUM_G_GOLEM || gch->pIndexData->vnum==MOB_VNUM_L_GOLEM) && (gch->master == ch)) { char_from_room(gch); char_to_room(gch,ch->in_room); act("$n appears in the room.", gch, NULL, NULL, TO_ROOM ); } } send_to_char( "Ok.\n\r", ch ); return; } void spell_minion_haste( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *gch; sn= skill_lookup("haste"); for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( !is_same_group(gch, ch) || !(IS_NPC(gch))) continue; if ((IS_AFFECTED(gch,AFF_CHARM)) && (gch->pIndexData->vnum==MOB_VNUM_ZOMBIE) && (gch->master == ch)) { spell_haste(sn,ch->level,ch,gch,TARGET_CHAR); } } send_to_char( "Ok.\n\r", ch ); return; } void spell_minion_trans( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *gch; sn= skill_lookup("pass door"); for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( !is_same_group(gch, ch) || !(IS_NPC(gch))) continue; if ((IS_AFFECTED(gch,AFF_CHARM)) && (gch->pIndexData->vnum==MOB_VNUM_ZOMBIE) && (gch->master == ch)) { spell_pass_door(sn,ch->level,gch,gch,TARGET_CHAR); } } send_to_char( "Ok.\n\r", ch ); return; } void do_lich( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim; if (IS_NPC(ch)) return; argument = one_argument( argument, arg1 ); if ((ch->level < 56 && ch->pcdata->induct != CABAL_LEADER) || IS_NPC(ch)) { send_to_char("Huh?\n\r", ch); return; } if ( arg1[0] == '\0' ) { buf[0] = '\0'; send_to_char( "Syntax: lich <char>\n\r",ch); return; } if ((victim = get_char_world(ch, arg1)) == NULL) { send_to_char("They aren't playing.\n\r", ch); return; } if (victim->race==race_lookup("lich")) { send_to_char("They are lich already.\n\r", ch); return; } sprintf(buf,"%s is now a Lich.\n\r", victim->name); send_to_char(buf,ch); sprintf(buf,"Your mortal body begins to decompose as you gain unholy power!\n\r"); send_to_char(buf,victim); victim->pcdata->learned[skill_lookup("minion tactics")] = 1; victim->pcdata->learned[skill_lookup("minion sanc")] =1; victim->pcdata->learned[skill_lookup("minion flight")] =1; victim->pcdata->learned[skill_lookup("minion sneak")] =1; victim->pcdata->learned[skill_lookup("minion recall")] =1; victim->pcdata->learned[skill_lookup("minion haste")] =1; victim->pcdata->learned[skill_lookup("minion trans")] =1; victim->pcdata->learned[skill_lookup("ritual of abominations")] = 1; victim->pcdata->learned[skill_lookup("vampiric touch")] = 1; victim->race = race_lookup("lich"); victim->perm_stat[STAT_STR]=pc_race_table[ch->race].max_stats[STAT_STR]; victim->perm_stat[STAT_INT]=pc_race_table[ch->race].max_stats[STAT_INT]; victim->perm_stat[STAT_WIS]=pc_race_table[ch->race].max_stats[STAT_WIS]; victim->perm_stat[STAT_DEX]=pc_race_table[ch->race].max_stats[STAT_DEX]; victim->perm_stat[STAT_CON]=pc_race_table[ch->race].max_stats[STAT_CON]; victim->mod_stat[STAT_STR]=0; victim->mod_stat[STAT_INT]=0; victim->mod_stat[STAT_WIS]=0; victim->mod_stat[STAT_DEX]=0; victim->mod_stat[STAT_CON]=0; sprintf(buf, "Your stats are Str: %2d Int: %2d Wis: %2d Dex: %2d Con: %2d\n\r", ch->perm_stat[STAT_STR], ch->perm_stat[STAT_INT], ch->perm_stat[STAT_WIS], ch->perm_stat[STAT_DEX], ch->perm_stat[STAT_CON]); send_to_char(buf,victim); } void do_ritual_of_abominations( CHAR_DATA *ch, char *argument ) { OBJ_DATA *corpse, *phylactery; AFFECT_DATA af; char buf[MSL]; int phylacRoll = number_percent(); OBJ_INDEX_DATA *phylac; if (ch->mana < 300) return send_to_char("You don't have the 300 mana required to perform the Ritual of Abominations.\n\r",ch); if (argument[0] == '\0') return send_to_char("Which corpse do you wish to perform it on?\n\r",ch); corpse = get_obj_here(ch,argument); if (corpse == NULL) return send_to_char("That corpse is not here.\n\r",ch); if (corpse->pIndexData->vnum != OBJ_VNUM_CORPSE_PC || corpse->noPhylactery) return send_to_char("You cannot perform the Ritual of Abominations on that.\n\r",ch); if (is_affected(ch,skill_lookup("ritual of abominations"))) return send_to_char("Your mind is still too weary from your previous Ritual.\n\r",ch); ch->mana -= 300; corpse->noPhylactery = TRUE; act("You kneel over $p and begin reciting unholy and forbidden incantations.",ch,corpse,0,TO_CHAR); act("Resting your bony hand on its already-rotting chest, you begin to drain its life energy.",ch,corpse,0,TO_CHAR); act("A phylactery formed from $p's own energy pulses into existence before you!",ch,corpse,0,TO_CHAR); act("$n kneels over $p and begins reciting unholy and forbidden incantations.",ch,corpse,0,TO_ROOM); act("Pulsing with energy, a phylactery appears before $n, surrounded in a hazy, dark aura.",ch,corpse,0,TO_ROOM); act("$p grows charred and black, devoid of anything beyond rotting flesh and bones.",ch,corpse,0,TO_CHAR); act("$p grows charred and black, devoid of anything beyond rotting flesh and bones.",ch,corpse,0,TO_ROOM); sprintf(buf,"A corpse is charred and blackened beyond recognition here."); corpse->description = str_dup(buf); if (corpse->owner_class == class_lookup("necromancer")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_DIAMOND); else if (phylacRoll >= 80) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE_AGATE); else if (phylacRoll >= 65) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ROUNDED_JADE); else if (phylacRoll >= 50) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BLACK_SAPPHIRE); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_FACETED_JASPER); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("healer")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BLACK_DIAMOND); else if (phylacRoll >= 80) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_AMETHYST); else if (phylacRoll >= 60) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_PALE_AQUAMARINE); else if (phylacRoll >= 40) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_STAR_DIOPSIDE); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("elementalist")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_RAINBOW_MOONSTONE); else if (phylacRoll >= 75) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BASALT); else if (phylacRoll >= 60) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_STRIPED_GLASS); else if (phylacRoll >= 45) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ZIRCON); else if (phylacRoll >= 35) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_MALACHITE_DISC); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_VIOLET_GARNET); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("channeler")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_SPHERICAL_MALACHITE); else if (phylacRoll >= 80) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE_AGATE); else if (phylacRoll >= 65) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_SOMETHING_OILY); else if (phylacRoll >= 50) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_PALE_AQUAMARINE); else if (phylacRoll >= 40) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_SOAPSTONE); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_TAUROIDAL_BERYL); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("ranger")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_FIRE_OPAL); else if (phylacRoll >= 75) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_JADE); else if (phylacRoll >= 60) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BASALT); else if (phylacRoll >= 45) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_STRIPED_GLASS); else if (phylacRoll >= 30) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ZIRCON); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("assassin")) { if (phylacRoll >= 95) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_FIRE_OPAL); else if (phylacRoll >= 85) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_MALACHITE_DISC); else if (phylacRoll >= 65) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ANGLED_JASPER); else if (phylacRoll >= 45) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_MILKY_QUARTZ); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BLACK_OPAL); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("thief")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE_AGATE); else if (phylacRoll >= 80) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ROUNDED_JADE); else if (phylacRoll >= 60) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ANGLED_JASPER); else if (phylacRoll >= 40) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_MILKY_QUARTZ); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_PALE_AQUAMARINE); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("warrior")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_FIRE_OPAL); else if (phylacRoll >= 80) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_GRANITE); else if (phylacRoll >= 60) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ROUNDED_JADE); else if (phylacRoll >= 40) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BASALT); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ZIRCON); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("zealot")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_SPHERICAL_MALACHITE); else if (phylacRoll >= 75) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_MALACHITE_DISC); else if (phylacRoll >= 60) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_PALE_JADE); else if (phylacRoll >= 45) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BLOODSTONE); else if (phylacRoll >= 35) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BLACK_OPAL); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BLACK_SAPPHIRE); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("anti-paladin")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BLACK_PEARL); else if (phylacRoll >= 70) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_PALE_JADE); else if (phylacRoll >= 55) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_SUNSTONE); else if (phylacRoll >= 35) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_STAR_DIOPSIDE); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_FIRE_OPAL); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("paladin")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BLACK_PEARL); else if (phylacRoll >= 70) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_PALE_JADE); else if (phylacRoll >= 55) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_SUNSTONE); else if (phylacRoll >= 45) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BASALT); else if (phylacRoll >= 35) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ZIRCON); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_PALE_AQUAMARINE); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else if (corpse->owner_class == class_lookup("druid")) { if (phylacRoll >= 90) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_GRANITE); else if (phylacRoll >= 70) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_JADE); else if (phylacRoll >= 60) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_TAUROIDAL_BERYL); else if (phylacRoll >= 50) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_BASALT); else if (phylacRoll >= 40) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_STRIPED_GLASS); else if (phylacRoll >= 30) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_ZIRCON); else if (phylacRoll >= 25) phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_AMETHYST); else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); } else phylac = get_obj_index(OBJ_VNUM_PHYLACTERY_CATS_EYE); phylactery = create_object(phylac,0); obj_to_char(phylactery,ch); act("A sickening aura surrounds you as you stand, your hand wrapped around $p.",ch,phylactery,0,TO_CHAR); act("A sickening aura surrounds $n as $e stands, $s hand wrapped around $p.",ch,phylactery,0,TO_ROOM); init_affect(&af); af.where = TO_AFFECTS; af.type = skill_lookup("ritual of abominations"); af.name = str_dup("ritual of abominatio"); af.level = 60; af.duration = 80; af.aftype = AFT_POWER; af.affect_list_msg = str_dup("inability to perform the Ritual of Abominations"); af.dispel_at_death = FALSE; affect_to_char(ch,&af); } void spell_maledict_corpse( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { OBJ_DATA *corpse; char *obj_name; if (target_name[0] == '\0') { send_to_char("Maledict which corpse?\n\r",ch); return; } obj_name = str_dup(target_name); corpse = get_obj_here(ch,obj_name); if (corpse == NULL) { send_to_char("You don't see that here.\n\r",ch); return; } if (corpse->pIndexData->vnum != OBJ_VNUM_CORPSE_PC) { send_to_char("You can only maledict player corpses.\n\r",ch); return; } act("You kneel down and pronounce a maledictive curse upon $p.", ch, corpse, 0, TO_CHAR); act("$n kneels down and pronounces a maledictive curse upon $p.", ch, corpse, 0, TO_ROOM); set_bit(&corpse->extra_flags, ITEM_MALEDICTED); return; } void spell_decay_corpse(int sn,int level,CHAR_DATA *ch,void *vo,int target) { char buf1[MSL], buf2[MSL]; OBJ_DATA *obj, *obj_next, *corpse, *skeleton; char *name, *last_name, *obj_name; int chance; if (target_name[0] == '\0') { send_to_char("Decay which corpse?\n\r",ch); return; } obj_name = str_dup(target_name); corpse = get_obj_here(ch,obj_name); if (corpse == NULL) { send_to_char("You can't find that object.\n\r",ch); return; } if ((corpse->item_type != ITEM_CORPSE_NPC) && (corpse->item_type != ITEM_CORPSE_PC) ) { send_to_char("You can't decay that.\n\r",ch); return; } name = corpse->short_descr; for (obj = corpse->contains; obj != NULL; obj = obj_next) { obj_next = obj->next_content; obj_from_obj(obj); obj_to_room(obj,ch->in_room); } chance = get_skill(ch,sn); if (number_percent() > chance) { act("Your decaying becomes uncontrolled and you destroy $p.", ch,corpse,NULL,TO_CHAR); act("$n tries to decay $p but reduces it to a puddle of slime.",ch,corpse,NULL,TO_ROOM); extract_obj(corpse); return; } act("$n decays the flesh off $p.",ch,corpse,NULL,TO_ROOM); act("You decay the flesh off $p and reduce it to a skeleton.",ch,corpse,NULL,TO_CHAR); skeleton = create_object(get_obj_index(OBJ_VNUM_SKELETON),1); obj_to_room(skeleton,ch->in_room); skeleton->level = corpse->level; last_name = name; last_name = one_argument(corpse->short_descr,name); last_name = one_argument(last_name,name); last_name = one_argument(last_name,name); name = last_name; extract_obj(corpse); sprintf(buf1,"the skeleton of %s",name); sprintf(buf2,"A skeleton of %s is lying here in a puddle of decayed flesh.",name); free_string(skeleton->short_descr); free_string(skeleton->description); skeleton->short_descr = str_dup(buf1); skeleton->description = str_dup(buf2); skeleton->item_type = ITEM_SKELETON; return; } void spell_preserve(int sn,int level,CHAR_DATA *ch,void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; long vnum, chance; vnum = obj->pIndexData->vnum; if (vnum != OBJ_VNUM_SEVERED_HEAD && vnum != OBJ_VNUM_TORN_HEART && vnum != OBJ_VNUM_SLICED_ARM && vnum != OBJ_VNUM_SLICED_LEG && vnum != OBJ_VNUM_GUTS && vnum != OBJ_VNUM_BRAINS) { send_to_char("You can't preserve that.\n\r",ch); return; } if (obj->timer > 10) { send_to_char("It's already in very well preserved condition.\n\r",ch); WAIT_STATE(ch,PULSE_VIOLENCE); return; } chance = get_skill(ch,sn); chance *= 90; if (number_percent() > chance) { act("$n destroys $p.",ch,obj,NULL,TO_ROOM); act("You fail and destroy $p.",ch,obj,NULL,TO_CHAR); extract_obj(obj); WAIT_STATE(ch,PULSE_VIOLENCE); return; } act("You surround $p with necromantic magic to slow it's decay.",ch,obj,NULL,TO_CHAR); WAIT_STATE(ch,PULSE_VIOLENCE); obj->timer += number_range(level/2,level); return; } void spell_lesser_golem(int sn,int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *golem; AFFECT_DATA af; CHAR_DATA *check; OBJ_DATA *part; OBJ_DATA *part_next; int parts, lvl; parts = 0; if (is_affected(ch,sn)) { send_to_char("You aren't up to fashioning another golem yet.\n\r",ch); return; } for (check = char_list; check != NULL; check = check->next) { if (IS_NPC(check)) if ( (check->master == ch) && (check->pIndexData->vnum == MOB_VNUM_L_GOLEM) ) { send_to_char("You already have a golem under your command.\n\r",ch); return; } } for (part = ch->carrying; part != NULL; part = part_next) { part_next = part->next_content; if (part->pIndexData->vnum != OBJ_VNUM_SEVERED_HEAD && part->pIndexData->vnum != OBJ_VNUM_TORN_HEART && part->pIndexData->vnum != OBJ_VNUM_SLICED_ARM && part->pIndexData->vnum != OBJ_VNUM_SLICED_LEG && part->pIndexData->vnum != OBJ_VNUM_GUTS && part->pIndexData->vnum != OBJ_VNUM_BRAINS) continue; parts++; } if (parts == 0) { send_to_char("You don't have any body parts to animate.\n\r",ch); return; } else if (parts <= 1) { send_to_char("You don't have enough parts to build a flesh golem.\n\r",ch); return; } for (part = ch->carrying; part != NULL; part = part_next) { part_next = part->next_content; if (part->pIndexData->vnum != OBJ_VNUM_SEVERED_HEAD && part->pIndexData->vnum != OBJ_VNUM_TORN_HEART && part->pIndexData->vnum != OBJ_VNUM_SLICED_ARM && part->pIndexData->vnum != OBJ_VNUM_SLICED_LEG && part->pIndexData->vnum != OBJ_VNUM_GUTS && part->pIndexData->vnum != OBJ_VNUM_BRAINS) continue; extract_obj(part); } if (parts >= ch->level/5) parts = ch->level/5; lvl = (level - 3 + parts); init_affect(&af); af.where = TO_AFFECTS; af.level = level; af.location = 0; af.modifier = 0; af.duration = 35; af.bitvector = 0; af.type = sn; af.affect_list_msg = str_dup("unable to summon a lesser golem"); af.aftype = AFT_SPELL; affect_to_char(ch,&af); act("$n fashions a flesh golem!",ch,0,0,TO_ROOM); send_to_char("You fashion a flesh golem to serve you!\n\r",ch); golem = create_mobile(get_mob_index(MOB_VNUM_L_GOLEM) ); golem->level = lvl; golem->damroll += level/2 + parts; if (parts <= 3) golem->max_hit = ((lvl*lvl/2) + dice(lvl,10)); else if (parts == 4) golem->max_hit = ((lvl*lvl/2) + dice(lvl,12)); else if (parts == 5) golem->max_hit = ((lvl*lvl/2) + dice(lvl,13)); else if (parts == 6) golem->max_hit = ((lvl*lvl/2) + dice(lvl,15)); else if (parts == 7) golem->max_hit = ((lvl*lvl/2) + dice(lvl,18)); else golem->max_hit = ((lvl*lvl/2) + dice(lvl,20)); golem->hit = golem->max_hit; golem->max_move = ch->max_move; golem->move = golem->max_move; char_to_room(golem,ch->in_room); SET_BIT(golem->affected_by, AFF_CHARM); add_follower(golem, ch); golem->leader = ch; return; } void spell_greater_golem(int sn,int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *golem, *check; AFFECT_DATA af; if (is_affected(ch,sn)) { send_to_char("You aren't up to fashioning another golem yet.\n\r",ch); return; } for (check = char_list; check != NULL; check = check->next) { if (IS_NPC(check)) if ( (check->master == ch) && (check->pIndexData->vnum == MOB_VNUM_G_GOLEM) ) { send_to_char("You already have a golem under your command.\n\r",ch); return; } } init_affect(&af); af.where = TO_AFFECTS; af.level = level; af.location = 0; af.modifier = 0; af.duration = 35; af.bitvector = 0; af.type = sn; af.aftype = AFT_SPELL; af.affect_list_msg = str_dup("unable to summon a greater golem"); affect_to_char(ch,&af); act("$n fashions an iron golem!",ch,0,0,TO_ROOM); send_to_char("You fashion an iron golem to serve you!\n\r",ch); golem = create_mobile(get_mob_index(MOB_VNUM_G_GOLEM) ); golem->level = ch->level; golem->damroll = (5 + 2*level/3); golem->max_hit = level*level; golem->hit = golem->max_hit; golem->max_move = ch->max_move; golem->move = golem->max_move; char_to_room(golem,ch->in_room); SET_BIT(golem->affected_by, AFF_CHARM); add_follower(golem, ch); golem->leader = ch; return; } void spell_animate_dead( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *zombie, *search; OBJ_DATA *corpse, *obj, *obj_next; AFFECT_DATA af; char *name, *last_name; char *obj_name; char buf1[MSL], buf2[MSL]; int chance, z_level, control; if (level == 72) target_name = "corpse"; if ((is_affected(ch,sn) || is_affected(ch,skill_lookup("mummify"))) && level < 70) { send_to_char("You have not yet regained your powers over the dead.\n\r",ch); return; } control = 0; for (search = char_list; search != NULL; search = search->next) { if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_ZOMBIE) control += 6; else if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_SKELETON) control += 4; else if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_MUMMY) control += 12; } control += 4; if ((ch->level < 30 && control > 12) || (ch->level < 35 && control > 18) || (ch->level < 40 && control > 24) || (ch->level < 52 && control > 30) || control >= 36) { send_to_char("You already control as many undead as you can.\n\r",ch); return; } if (target_name[0] == '\0') { send_to_char("Animate which corpse?\n\r",ch); return; } obj_name = str_dup(target_name); corpse = get_obj_here(ch, obj_name); if (corpse == NULL) { send_to_char("You can't animate that.\n\r",ch); return; } if ((corpse->item_type != ITEM_CORPSE_NPC) && (corpse->item_type != ITEM_CORPSE_PC) ) { send_to_char("You can't animate that.\n\r",ch); return; } if (is_set(&corpse->extra_flags,CORPSE_NO_ANIMATE)) { send_to_char("That corpse can not sustain further life beyond the grave.\n\r",ch); return; } name = corpse->short_descr; for (obj = corpse->contains; obj != NULL; obj = obj_next) { obj_next = obj->next_content; obj_from_obj(obj); obj_to_room(obj,ch->in_room); } init_affect(&af); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 12; af.modifier = 0; af.location = 0; af.bitvector = 0; af.affect_list_msg = str_dup("unable to attempt animating the dead"); af.aftype = AFT_SPELL; if (level < 70) affect_to_char(ch,&af); chance = get_skill(ch,sn); if (ch->level < corpse->level) { chance += (3*ch->level); chance -= (3*corpse->level); } chance = URANGE(20,chance,90); if (number_percent() > chance) { act("You fail and destroy $p",ch,corpse,NULL,TO_CHAR); act("$n tries to animate a corpse but destroys it.",ch,NULL,NULL,TO_ROOM); extract_obj(corpse); return; } act("$n utters an incantation and a burning red glow flares into the eyes of $p.",ch,corpse,NULL,TO_ROOM); act("$p shudders and comes to life!",ch,corpse,NULL,TO_ROOM); act("You call upon the powers of the dark to give life to $p.",ch,corpse,NULL,TO_CHAR); zombie = create_mobile(get_mob_index(MOB_VNUM_ZOMBIE)); z_level = UMAX(1,corpse->level - number_range(3,6)); zombie->level = z_level; zombie->max_hit = (dice(z_level, 15)); zombie->max_hit += (z_level * 20); zombie->hit = zombie->max_hit; zombie->damroll += (z_level*7/10); zombie->alignment = -1000; last_name = name; last_name = one_argument(corpse->short_descr, name); last_name = one_argument(last_name,name); last_name = one_argument(last_name,name); name = last_name; extract_obj(corpse); sprintf( buf1, "the zombie of %s", name); sprintf( buf2, "A zombie of %s is standing here.\n\r", name); free_string(zombie->short_descr); free_string(zombie->long_descr); zombie->short_descr = str_dup(buf1); zombie->long_descr = str_dup(buf2); char_to_room(zombie,ch->in_room); SET_BIT(zombie->affected_by, AFF_CHARM); add_follower(zombie,ch); zombie->leader = ch; return; } void spell_mummify( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *mummy, *search; OBJ_DATA *corpse, *obj, *obj_next; AFFECT_DATA af; char *name, *last_name, *obj_name; char buf1[MSL], buf2[MSL]; int chance, z_level, control; if ( (is_affected(ch,skill_lookup("animate dead")) || is_affected(ch,sn)) && level < 70) { send_to_char("You have not yet regained your powers to over the dead.\n\r",ch); return; } control = 0; for (search = char_list; search != NULL; search = search->next) { if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_ZOMBIE) control += 6; else if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_SKELETON) control += 4; else if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_MUMMY) control += 12; } control += 4; if ((ch->level < 30 && control > 12) || (ch->level < 35 && control > 18) || (ch->level < 40 && control > 24) || (ch->level < 52 && control > 30) || control >= 36) { send_to_char("You already control as many undead as you can.\n\r",ch); return; } if (level >= 70) target_name = "corpse"; if (target_name[0] == '\0') { send_to_char("Attempt to mummify which corpse?\n\r",ch); return; } obj_name = str_dup(target_name); corpse = get_obj_here(ch, obj_name); if (corpse == NULL) { send_to_char("You can't mummify that.\n\r",ch); return; } if ((corpse->item_type != ITEM_CORPSE_NPC) && (corpse->item_type != ITEM_CORPSE_PC) ) { send_to_char("You can't mummify and animate that.\n\r",ch); return; } if (is_set(&corpse->extra_flags,CORPSE_NO_ANIMATE)) { send_to_char("That corpse does not have the stability to be animated anymore.\n\r",ch); return; } name = corpse->short_descr; for (obj = corpse->contains; obj != NULL; obj = obj_next) { obj_next = obj->next_content; obj_from_obj(obj); obj_to_room(obj,ch->in_room); } init_affect(&af); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 20; af.modifier = 0; af.location = 0; af.bitvector = 0; af.aftype = AFT_SPELL; if (level < 70) affect_to_char(ch,&af); chance = get_skill(ch,sn); if (ch->level < corpse->level) { chance += (2*ch->level); chance -= (2*corpse->level); } chance = URANGE(10,chance,90); if (number_percent() > chance) { act("You fail and destroy $p",ch,corpse,NULL,TO_CHAR); act("$n tries to mummify $p but destroys it.",ch,corpse,NULL,TO_ROOM); extract_obj(corpse); return; } act("$n utters an incantation and $p slowly stumbles to it's feet.",ch,corpse,NULL,TO_ROOM); act("$p shudders and slowly stumbles to it's feet!",ch,corpse,NULL,TO_ROOM); act("You invoke the powers of death and $p slowly rises to it's feet.",ch,corpse,NULL,TO_CHAR); mummy = create_mobile(get_mob_index(MOB_VNUM_MUMMY)); z_level = UMAX(1,corpse->level - number_range(0,2)); mummy->level = z_level; mummy->max_hit = (dice(z_level, 25)); mummy->max_hit += (z_level * 25); mummy->hit = mummy->max_hit; mummy->damroll += (z_level*4/5); mummy->alignment = -1000; last_name = name; last_name = one_argument(corpse->short_descr, name); last_name = one_argument(last_name,name); last_name = one_argument(last_name,name); name = last_name; extract_obj(corpse); sprintf( buf1, "the mummy of %s", name); sprintf( buf2, "A torn and shredded mummy of %s is standing here.\n\r", name); free_string(mummy->short_descr); free_string(mummy->long_descr); mummy->short_descr = str_dup(buf1); mummy->long_descr = str_dup(buf2); char_to_room(mummy,ch->in_room); add_follower(mummy,ch); mummy->leader = ch; af.type = skill_lookup("animate dead"); af.duration = -1; af.bitvector = AFF_CHARM; affect_to_char(mummy,&af); return; } void spell_animate_skeleton( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *skeleton, *search; OBJ_DATA *corpse, *obj, *obj_next; AFFECT_DATA af; char *name, *last_name, *obj_name; char buf1[MSL], buf2[MSL]; int chance, z_level, control = 0, num_skeletons = 0; if (is_affected(ch,sn)) { send_to_char("You have not yet regained your powers to animate bones.\n\r",ch); return; } for (search = char_list; search != NULL; search = search->next) { if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_ZOMBIE) control += 6; else if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_SKELETON) { control += 4; num_skeletons++; } else if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_MUMMY) control += 12; } control += 4; if ((ch->level < 30 && control > 12) || (ch->level < 35 && control > 18) || (ch->level < 40 && control > 24) || (ch->level < 52 && control > 30) || control >= 36) { send_to_char("You already control as many undead as you can.\n\r",ch); return; } if (num_skeletons >= 3) { send_to_char("You cannot control any more skeletons.\n\r",ch); return; } if (target_name[0] == '\0') { send_to_char("Animate which skeleton?\n\r",ch); return; } obj_name = str_dup(target_name); corpse = get_obj_here(ch, obj_name); if (corpse == NULL) { send_to_char("You can't animate that.\n\r",ch); return; } if (corpse->item_type != ITEM_SKELETON) { send_to_char("You can't animate that.\n\r",ch); return; } if (is_set(&corpse->extra_flags,CORPSE_NO_ANIMATE)) { send_to_char("That skeleton does not have the stability to be animated anymore.\n\r",ch); return; } name = corpse->short_descr; for (obj = corpse->contains; obj != NULL; obj = obj_next) { obj_next = obj->next_content; obj_from_obj(obj); obj_to_room(obj,ch->in_room); } chance = get_skill(ch,sn); if (ch->level < corpse->level) { chance += (4*ch->level); chance -= (3*corpse->level); } chance = URANGE(10,chance,95); if (number_percent() > chance) { act("You fail and destroy $p",ch,corpse,NULL,TO_CHAR); act("$n tries to animate a skeleton but destroys it.",ch,NULL,NULL,TO_ROOM); extract_obj(corpse); return; } act("$n utters an incantation and $p slowly stumbles to it's feet.",ch,corpse,NULL,TO_ROOM); act("$p shudders and slowly stumbles to it's feet!",ch,corpse,NULL,TO_ROOM); act("You invoke the powers of death and $p slowly rises to it's feet.",ch,corpse,NULL,TO_CHAR); skeleton = create_mobile(get_mob_index(MOB_VNUM_SKELETON)); z_level = UMAX(1,corpse->level - number_range(6,11)); skeleton->level = z_level; skeleton->max_hit = (dice(z_level, 12)); skeleton->max_hit += (z_level * 15); skeleton->hit = skeleton->max_hit; skeleton->damroll += (z_level*2/3); skeleton->alignment = -1000; last_name = name; last_name = one_argument(corpse->short_descr, name); last_name = one_argument(last_name,name); last_name = one_argument(last_name,name); name = last_name; extract_obj(corpse); sprintf( buf1, "the skeleton of %s", name); sprintf( buf2, "A skeleton of %s is standing here.\n\r", name); free_string(skeleton->short_descr); free_string(skeleton->long_descr); skeleton->short_descr = str_dup(buf1); skeleton->long_descr = str_dup(buf2); char_to_room(skeleton,ch->in_room); add_follower(skeleton,ch); skeleton->leader = ch; init_affect(&af); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 8; af.modifier = 0; af.location = 0; af.bitvector = 0; affect_to_char(ch,&af); af.type = skill_lookup("animate dead"); af.duration = -1; af.bitvector = AFF_CHARM; affect_to_char(skeleton,&af); return; }