/*************************************************************************** * 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. * * * * 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" /* * The following special functions are available for mobiles. */ DECLARE_SPEC_FUN( spec_breath_any ); DECLARE_SPEC_FUN( spec_breath_acid ); DECLARE_SPEC_FUN( spec_breath_fire ); DECLARE_SPEC_FUN( spec_breath_frost ); DECLARE_SPEC_FUN( spec_breath_gas ); DECLARE_SPEC_FUN( spec_breath_lightning ); DECLARE_SPEC_FUN( spec_cast_adept ); DECLARE_SPEC_FUN( spec_bishop ); DECLARE_SPEC_FUN( spec_cast_cleric ); DECLARE_SPEC_FUN( spec_cast_judge ); DECLARE_SPEC_FUN( spec_cast_mage ); DECLARE_SPEC_FUN( spec_cast_undead ); DECLARE_SPEC_FUN( spec_executioner ); DECLARE_SPEC_FUN( spec_fido ); DECLARE_SPEC_FUN( spec_guard ); DECLARE_SPEC_FUN( spec_janitor ); DECLARE_SPEC_FUN( spec_mayor ); DECLARE_SPEC_FUN( spec_poison ); DECLARE_SPEC_FUN( spec_thief ); DECLARE_SPEC_FUN( spec_nasty ); DECLARE_SPEC_FUN( spec_troll_member ); DECLARE_SPEC_FUN( spec_ogre_member ); DECLARE_SPEC_FUN( spec_patrolman ); DECLARE_SPEC_FUN( spec_goodie ); DECLARE_SPEC_FUN( spec_enforcer ); DECLARE_SPEC_FUN( spec_preserver ); DECLARE_SPEC_FUN( spec_fallen_angel ); DECLARE_SPEC_FUN( spec_troll ); DECLARE_SPEC_FUN( spec_chimera ); DECLARE_SPEC_FUN( spec_bane ); DECLARE_SPEC_FUN( spec_monk ); DECLARE_SPEC_FUN( spec_darokin ); DECLARE_SPEC_FUN( spec_godfather ); DECLARE_SPEC_FUN( spec_rakshasa ); DECLARE_SPEC_FUN( spec_rakshasa_lich ); DECLARE_SPEC_FUN( spec_rakshasa_royal ); DECLARE_SPEC_FUN( spec_beholder ); DECLARE_SPEC_FUN( spec_deathknight ); DECLARE_SPEC_FUN( spec_room_thow ); DECLARE_SPEC_FUN( spec_room_throw ); DECLARE_SPEC_FUN( spec_spectre_king ); DECLARE_SPEC_FUN( spec_hydra ); DECLARE_SPEC_FUN( spec_bone_demon ); DECLARE_SPEC_FUN( spec_valere_knight ); DECLARE_SPEC_FUN( spec_drannor_wraith ); DECLARE_SPEC_FUN( spec_titan ); DECLARE_SPEC_FUN( spec_necromancer ); DECLARE_SPEC_FUN( spec_rager ); DECLARE_SPEC_FUN( spec_demonologist ); DECLARE_SPEC_FUN( spec_legionlord ); DECLARE_SPEC_FUN( spec_gold_dragon ); DECLARE_SPEC_FUN( spec_black_dragon ); DECLARE_SPEC_FUN( spec_red_dragon ); DECLARE_SPEC_FUN( spec_seneschal ); DECLARE_SPEC_FUN( spec_warder ); DECLARE_SPEC_FUN( spec_sage ); DECLARE_SPEC_FUN( spec_pincer ); DECLARE_SPEC_FUN( spec_outlaw ); DECLARE_SPEC_FUN( spec_flurry ); DECLARE_SPEC_FUN( spec_drum ); DECLARE_SPEC_FUN( spec_ishmael ); DECLARE_SPEC_FUN( spec_agamemnon ); DECLARE_SPEC_FUN( spec_meph ); DECLARE_SPEC_FUN( spec_baalzebub ); DECLARE_SPEC_FUN( spec_necruvian ); DECLARE_SPEC_FUN( spec_obsidian_prince ); DECLARE_SPEC_FUN( spec_golden_knight ); DECLARE_SPEC_FUN( spec_templar ); DECLARE_SPEC_FUN( spec_lothar ); DECLARE_SPEC_FUN( spec_cire ); DECLARE_SPEC_FUN( spec_familiar ); DECLARE_SPEC_FUN( spec_omegus ); DECLARE_SPEC_FUN( spec_stalker ); DECLARE_SPEC_FUN( spec_phantom ); DECLARE_SPEC_FUN( spec_grand_assassin ); DECLARE_SPEC_FUN( spec_cast_cold ); DECLARE_SPEC_FUN( spec_elthian ); DECLARE_SPEC_FUN( spec_tara ); DECLARE_SPEC_FUN( spec_blitz ); DECLARE_SPEC_FUN( spec_destructor ); DECLARE_SPEC_FUN( spec_destructorrage ); DECLARE_SPEC_FUN( spec_destructorcombo ); DECLARE_SPEC_FUN( spec_bounty_hunter ); DECLARE_SPEC_FUN( spec_healer_mercenary ); DECLARE_SPEC_FUN( spec_spitting_snake ); DECLARE_SPEC_FUN( spec_cockatrice ); DECLARE_SPEC_FUN( spec_practice_dummy ); DECLARE_SPEC_FUN( spec_elemental ); DECLARE_SPEC_FUN( spec_ranger ); DECLARE_SPEC_FUN( spec_master_warrior ); DECLARE_SPEC_FUN( spec_marshall ); const struct spec_type spec_table[] = { { "spec_breath_any", spec_breath_any }, { "spec_breath_acid", spec_breath_acid }, { "spec_breath_fire", spec_breath_fire }, { "spec_breath_frost", spec_breath_frost }, { "spec_breath_gas", spec_breath_gas }, { "spec_breath_lightning", spec_breath_lightning }, { "spec_cast_adept", spec_cast_adept }, { "spec_cast_cleric", spec_cast_cleric }, { "spec_bane", spec_bane }, { "spec_cast_judge", spec_cast_judge }, { "spec_cast_mage", spec_cast_mage }, { "spec_cast_undead", spec_cast_undead }, { "spec_executioner", spec_executioner }, { "spec_fido", spec_fido }, { "spec_guard", spec_guard }, { "spec_janitor", spec_janitor }, { "spec_mayor", spec_mayor }, { "spec_poison", spec_poison }, { "spec_thief", spec_thief }, { "spec_nasty", spec_nasty }, { "spec_troll", spec_troll }, { "spec_troll_member", spec_troll_member }, { "spec_ogre_member", spec_ogre_member }, { "spec_patrolman", spec_patrolman }, { "spec_bishop", spec_bishop }, { "spec_enforcer", spec_enforcer }, { "spec_preserver", spec_preserver }, { "spec_fallen_angel", spec_fallen_angel }, { "spec_monk", spec_monk }, { "spec_chimera", spec_chimera }, { "spec_darokin", spec_darokin }, { "spec_godfather", spec_godfather }, { "spec_rakshasa", spec_rakshasa }, { "spec_rakshasa_royal", spec_rakshasa_royal }, { "spec_rakshasa_lich", spec_rakshasa_lich }, { "spec_room_throw", spec_room_throw }, { "spec_beholder", spec_beholder }, { "spec_deathknight", spec_deathknight }, { "spec_red_dragon", spec_red_dragon }, { "spec_gold_dragon", spec_gold_dragon }, { "spec_black_dragon", spec_black_dragon }, { "spec_spectre_king", spec_spectre_king }, { "spec_hydra", spec_hydra }, { "spec_bone_demon", spec_bone_demon }, { "spec_valere_knight", spec_valere_knight }, { "spec_drannor_wraith", spec_drannor_wraith }, { "spec_necromancer", spec_necromancer }, { "spec_demonologist", spec_demonologist }, { "spec_rager", spec_rager }, { "spec_titan", spec_titan }, { "spec_legionlord", spec_legionlord }, { "spec_seneschal", spec_seneschal }, { "spec_warder", spec_warder }, { "spec_outlaw", spec_outlaw }, { "spec_sage", spec_sage }, { "spec_pincer", spec_pincer }, { "spec_flurry", spec_flurry }, { "spec_drum", spec_drum }, { "spec_ishmael", spec_ishmael }, { "spec_agamemnon", spec_agamemnon }, { "spec_meph", spec_meph }, { "spec_baalzebub", spec_baalzebub }, { "spec_necruvian", spec_necruvian }, { "spec_obsidian_prince", spec_obsidian_prince }, { "spec_golden_knight", spec_golden_knight }, { "spec_templar", spec_templar }, { "spec_goodie", spec_goodie }, { "spec_cire", spec_cire }, { "spec_lothar", spec_lothar }, { "spec_familiar", spec_familiar }, { "spec_omegus", spec_omegus }, { "spec_stalker", spec_stalker }, { "spec_phantom", spec_phantom }, { "spec_grand_assassin", spec_grand_assassin }, { "spec_cast_cold", spec_cast_cold }, { "spec_elthian", spec_elthian }, { "spec_tara", spec_tara }, { "spec_destructor", spec_destructor }, { "spec_destructorrage", spec_destructorrage }, { "spec_blitz", spec_blitz }, { "spec_destructorcombo", spec_destructorcombo }, { "spec_bounty_hunter", spec_bounty_hunter }, { "spec_healer_mercenary", spec_healer_mercenary }, { "spec_spitting_snake", spec_spitting_snake }, { "spec_cockatrice", spec_cockatrice }, { "spec_practice_dummy", spec_practice_dummy }, { "spec_elemental", spec_elemental }, { "spec_ranger", spec_ranger }, { "spec_master_warrior", spec_master_warrior }, { "spec_marshall", spec_marshall }, { NULL, NULL } }; /* * Given a name, return the appropriate spec fun. */ SPEC_FUN *spec_lookup( const char *name ) { int i; for ( i = 0; spec_table[i].name != NULL; i++) { if (LOWER(name[0]) == LOWER(spec_table[i].name[0]) && !str_prefix( name,spec_table[i].name)) return spec_table[i].function; } return 0; } char *spec_name( SPEC_FUN *function) { int i; for (i = 0; spec_table[i].function != NULL; i++) { if (function == spec_table[i].function) return spec_table[i].name; } return NULL; } bool spec_troll_member( CHAR_DATA *ch) { CHAR_DATA *vch, *victim = NULL; int count = 0; char *message; if (!IS_AWAKE(ch) || IS_AFFECTED(ch,AFF_CALM) || ch->in_room == NULL || IS_AFFECTED(ch,AFF_CHARM) || ch->fighting != NULL) return FALSE; /* find an ogre to beat up */ for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (!IS_NPC(vch) || ch == vch) continue; if (vch->pIndexData->vnum == MOB_VNUM_PATROLMAN) return FALSE; if (vch->pIndexData->group == GROUP_VNUM_OGRES && ch->level > vch->level - 2 && !is_safe(ch,vch)) { if (number_range(0,count) == 0) victim = vch; count++; } } if (victim == NULL) return FALSE; /* say something, then raise hell */ switch (number_range(0,6)) { default: message = NULL; break; case 0: message = "$n yells 'I've been looking for you, punk!'"; break; case 1: message = "With a scream of rage, $n attacks $N."; break; case 2: message = "$n says 'What's slimy Ogre trash like you doing around here?'"; break; case 3: message = "$n cracks his knuckles and says 'Do ya feel lucky?'"; break; case 4: message = "$n says 'There's no cops to save you this time!'"; break; case 5: message = "$n says 'Time to join your brother, spud.'"; break; case 6: message = "$n says 'Let's rock.'"; break; } if (message != NULL) act(message,ch,NULL,victim,TO_ALL); multi_hit( ch, victim, TYPE_UNDEFINED ); return TRUE; } bool spec_ogre_member( CHAR_DATA *ch) { CHAR_DATA *vch, *victim = NULL; int count = 0; char *message; if (!IS_AWAKE(ch) || IS_AFFECTED(ch,AFF_CALM) || ch->in_room == NULL || IS_AFFECTED(ch,AFF_CHARM) || ch->fighting != NULL) return FALSE; /* find an troll to beat up */ for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (!IS_NPC(vch) || ch == vch) continue; if (vch->pIndexData->vnum == MOB_VNUM_PATROLMAN) return FALSE; if (vch->pIndexData->group == GROUP_VNUM_TROLLS && ch->level > vch->level - 2 && !is_safe(ch,vch)) { if (number_range(0,count) == 0) victim = vch; count++; } } if (victim == NULL) return FALSE; /* say something, then raise hell */ switch (number_range(0,6)) { default: message = NULL; break; case 0: message = "$n yells 'I've been looking for you, punk!'"; break; case 1: message = "With a scream of rage, $n attacks $N.'"; break; case 2: message = "$n says 'What's Troll filth like you doing around here?'"; break; case 3: message = "$n cracks his knuckles and says 'Do ya feel lucky?'"; break; case 4: message = "$n says 'There's no cops to save you this time!'"; break; case 5: message = "$n says 'Time to join your brother, spud.'"; break; case 6: message = "$n says 'Let's rock.'"; break; } if (message != NULL) act(message,ch,NULL,victim,TO_ALL); multi_hit( ch, victim, TYPE_UNDEFINED ); return TRUE; } bool spec_patrolman(CHAR_DATA *ch) { CHAR_DATA *vch,*victim = NULL; OBJ_DATA *obj; char *message; int count = 0; if (!IS_AWAKE(ch) || IS_AFFECTED(ch,AFF_CALM) || ch->in_room == NULL || IS_AFFECTED(ch,AFF_CHARM) || ch->fighting != NULL) return FALSE; /* look for a fight in the room */ for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (vch == ch) continue; if (vch->fighting != NULL) /* break it up! */ { if (number_range(0,count) == 0) victim = (vch->level > vch->fighting->level) ? vch : vch->fighting; count++; } } if (victim == NULL || (IS_NPC(victim) && victim->spec_fun == ch->spec_fun)) return FALSE; if (((obj = get_eq_char(ch,WEAR_NECK_1)) != NULL && obj->pIndexData->vnum == OBJ_VNUM_WHISTLE) || ((obj = get_eq_char(ch,WEAR_NECK_2)) != NULL && obj->pIndexData->vnum == OBJ_VNUM_WHISTLE)) { act("You blow down hard on $p.",ch,obj,NULL,TO_CHAR); act("$n blows on $p, ***WHEEEEEEEEEEEET***",ch,obj,NULL,TO_ROOM); for ( vch = char_list; vch != NULL; vch = vch->next ) { if ( vch->in_room == NULL ) continue; if (vch->in_room != ch->in_room && vch->in_room->area == ch->in_room->area) send_to_char( "You hear a shrill whistling sound.\n\r", vch ); } } switch (number_range(0,6)) { default: message = NULL; break; case 0: message = "$n yells 'All roit! All roit! break it up!'"; break; case 1: message = "$n says 'Society's to blame, but what's a bloke to do?'"; break; case 2: message = "$n mumbles 'bloody kids will be the death of us all.'"; break; case 3: message = "$n shouts 'Stop that! Stop that!' and attacks."; break; case 4: message = "$n pulls out his billy and goes to work."; break; case 5: message = "$n sighs in resignation and proceeds to break up the fight."; break; case 6: message = "$n says 'Settle down, you hooligans!'"; break; } if (message != NULL) act(message,ch,NULL,NULL,TO_ALL); multi_hit(ch,victim,TYPE_UNDEFINED); return TRUE; } bool spec_nasty( CHAR_DATA *ch ) { CHAR_DATA *victim, *v_next; long gold; if (!IS_AWAKE(ch)) { return FALSE; } if (ch->position != POS_FIGHTING) { for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (!IS_NPC(victim) && (victim->level > ch->level) && (victim->level < ch->level + 10)) { do_backstab(ch,victim->name); if (ch->position != POS_FIGHTING) do_murder(ch,victim->name); /* should steal some coins right away? :) */ return TRUE; } } return FALSE; /* No one to attack */ } /* okay, we must be fighting.... steal some coins and flee */ if ( (victim = ch->fighting) == NULL) return FALSE; /* let's be paranoid.... */ switch ( number_bits(2) ) { case 0: act( "$n rips apart your coin purse, spilling your gold!", ch, NULL, victim, TO_VICT); act( "You slash apart $N's coin purse and gather his gold.", ch, NULL, victim, TO_CHAR); act( "$N's coin purse is ripped apart!", ch, NULL, victim, TO_NOTVICT); gold = victim->gold / 10; /* steal 10% of his gold */ victim->gold -= gold; ch->gold += gold; return TRUE; case 1: do_flee( ch, ""); return TRUE; default: return FALSE; } } /* * Core procedure for dragons. */ bool dragon( CHAR_DATA *ch, char *spell_name ) { CHAR_DATA *victim; CHAR_DATA *v_next; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 3 ) == 0 ) break; } if ( victim == NULL ) return FALSE; if ( ( sn = skill_lookup( spell_name ) ) < 0 ) return FALSE; if (check_absorb(ch,victim,sn)) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TARGET_CHAR); return TRUE; } /* * Special procedures for mobiles. */ bool spec_breath_any( CHAR_DATA *ch ) { if ( ch->position != POS_FIGHTING ) return FALSE; switch ( number_bits( 3 ) ) { case 0: return spec_breath_fire ( ch ); case 1: case 2: return spec_breath_lightning ( ch ); case 3: return spec_breath_gas ( ch ); case 4: return spec_breath_acid ( ch ); case 5: case 6: case 7: return spec_breath_frost ( ch ); } return FALSE; } bool spec_breath_acid( CHAR_DATA *ch ) { return dragon( ch, "acid breath" ); } bool spec_breath_fire( CHAR_DATA *ch ) { return dragon( ch, "fire breath" ); } bool spec_breath_frost( CHAR_DATA *ch ) { return dragon( ch, "frost breath" ); } bool spec_breath_gas( CHAR_DATA *ch ) { int sn; if ( ch->position != POS_FIGHTING ) return FALSE; if ( ( sn = skill_lookup( "gas breath" ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, NULL,TARGET_CHAR); return TRUE; } bool spec_breath_lightning( CHAR_DATA *ch ) { return dragon( ch, "lightning breath" ); } bool spec_cast_adept( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; if ( !IS_AWAKE(ch) ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim != ch && can_see( ch, victim ) && number_bits( 1 ) == 0 && !IS_NPC(victim) && victim->level < 11) break; } if ( victim == NULL ) return FALSE; act("$n closes his eyes for a moment and nods at $N",ch,NULL,victim,TO_ROOM); act("$n closes his eyes for a moment and nods at you",ch,NULL,victim,TO_VICT); switch ( number_bits( 4 ) ) { case 0: spell_armor( skill_lookup( "armor" ), ch->level,ch,victim,TARGET_CHAR); return TRUE; case 1: spell_bless( skill_lookup( "bless" ), ch->level,ch,victim,TARGET_CHAR); return TRUE; case 2: spell_cure_blindness( skill_lookup( "cure blindness" ), ch->level, ch, victim,TARGET_CHAR); return TRUE; case 3: spell_cure_light( skill_lookup( "cure light" ), ch->level, ch, victim,TARGET_CHAR); return TRUE; case 4: spell_cure_poison( skill_lookup( "cure poison" ), ch->level, ch, victim,TARGET_CHAR); return TRUE; case 5: spell_refresh( skill_lookup("refresh"), ch->level,ch,victim,TARGET_CHAR); return TRUE; case 6: spell_cure_disease(skill_lookup("cure disease"), ch->level,ch,victim,TARGET_CHAR); } return FALSE; } bool spec_cast_cleric( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; for ( ;; ) { int min_level; switch ( number_bits( 4 ) ) { case 0: min_level = 0; spell = "blindness"; break; case 1: min_level = 3; spell = "cause serious"; break; case 2: min_level = 7; spell = "earthquake"; break; case 3: min_level = 9; spell = "cause critical"; break; case 4: min_level = 10; spell = "dispel evil"; break; case 5: min_level = 12; spell = "blindness"; break; case 6: min_level = 12; spell = "change sex"; break; case 7: min_level = 13; spell = "flamestrike"; break; case 8: case 9: case 10: min_level = 15; spell = "harm"; break; case 11: min_level = 15; spell = "plague"; break; default: min_level = 16; spell = "dispel magic"; break; } if ( ch->level >= min_level ) break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; if (check_absorb(ch,victim,sn)) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim,TARGET_CHAR); return TRUE; } bool spec_cast_judge( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; spell = "high explosive"; if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim,TARGET_CHAR); return TRUE; } bool spec_cast_mage( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; for ( ;; ) { int min_level; switch ( number_bits( 4 ) ) { case 0: min_level = 0; spell = "blindness"; break; case 1: min_level = 3; spell = "chill touch"; break; case 2: min_level = 7; spell = "weaken"; break; case 3: min_level = 8; spell = "burning hands"; break; case 4: min_level = 11; spell = "colour spray"; break; case 5: min_level = 12; spell = "change sex"; break; case 6: min_level = 13; spell = "energy drain"; break; case 7: min_level = 13; spell = "earthmaw"; break; case 8: min_level = 15; spell = "fire and ice"; break; case 9: min_level = 18; spell = "teleport"; break; case 10: min_level = 20; spell = "plague"; break; default: min_level = 20; spell = "acid blast"; break; } if ( ch->level >= min_level ) break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; if (check_absorb(ch,victim,sn)) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim,TARGET_CHAR); return TRUE; } bool spec_cast_undead( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; for ( ;; ) { int min_level; switch ( number_bits( 4 ) ) { case 0: min_level = 0; spell = "weaken"; break; case 1: min_level = 3; spell = "weaken"; break; case 2: min_level = 6; spell = "chill touch"; break; case 3: min_level = 9; spell = "blindness"; break; case 4: min_level = 12; spell = "poison"; break; case 5: min_level = 15; spell = "energy drain"; break; case 6: min_level = 18; spell = "harm"; break; case 7: min_level = 21; spell = "teleport"; break; case 8: min_level = 20; spell = "plague"; break; default: min_level = 18; spell = "harm"; break; } if ( ch->level >= min_level ) break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; if (check_absorb(ch,victim,sn)) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim,TARGET_CHAR); return TRUE; } bool spec_executioner( CHAR_DATA *ch ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim; CHAR_DATA *v_next; char *crime; if ( !IS_AWAKE(ch) || ch->fighting != NULL ) return FALSE; crime = ""; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_CRIMINAL) && can_see(ch,victim)) { crime = "KILLER"; break; } if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_CRIMINAL) && can_see(ch,victim)) { crime = "THIEF"; break; } } if ( victim == NULL ) return FALSE; sprintf( buf, "%s is a criminal! PROTECT THE INNOCENT! MORE BLOOOOD!!!", victim->name); REMOVE_BIT(ch->comm,COMM_NOSHOUT); do_myell( ch, buf ); multi_hit( ch, victim, TYPE_UNDEFINED ); return TRUE; } bool spec_fido( CHAR_DATA *ch ) { OBJ_DATA *corpse; OBJ_DATA *c_next; OBJ_DATA *obj; OBJ_DATA *obj_next; if ( !IS_AWAKE(ch) ) return FALSE; for ( corpse = ch->in_room->contents; corpse != NULL; corpse = c_next ) { c_next = corpse->next_content; if ( corpse->item_type != ITEM_CORPSE_NPC ) continue; act( "$n savagely devours a corpse.", ch, NULL, NULL, TO_ROOM ); for ( obj = corpse->contains; obj; obj = obj_next ) { obj_next = obj->next_content; obj_from_obj( obj ); obj_to_room( obj, ch->in_room ); } extract_obj( corpse ); return TRUE; } return FALSE; } bool spec_guard( CHAR_DATA *ch ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim, *v_next; if ( !IS_AWAKE(ch) || ch->fighting != NULL ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_CRIMINAL) && can_see(ch,victim)) break; } if ( victim != NULL ) { sprintf( buf, "%s is a criminal! PROTECT THE INNOCENT!!", victim->name); REMOVE_BIT(ch->comm,COMM_NOSHOUT); do_myell( ch, buf ); sprintf( buf, "enforcer I just spotted %s at %s!", victim->name, victim->in_room->name); do_ccb(ch, buf); multi_hit( ch, victim, TYPE_UNDEFINED ); return TRUE; } return FALSE; } bool spec_janitor( CHAR_DATA *ch ) { OBJ_DATA *trash; OBJ_DATA *trash_next; if ( !IS_AWAKE(ch) ) return FALSE; for ( trash = ch->in_room->contents; trash != NULL; trash = trash_next ) { trash_next = trash->next_content; if ( !IS_SET( trash->wear_flags, ITEM_TAKE ) || !can_loot(ch,trash)) continue; if ( trash->item_type == ITEM_DRINK_CON || trash->item_type == ITEM_TRASH || trash->cost < 10 ) { act( "$n picks up some trash.", ch, NULL, NULL, TO_ROOM ); obj_from_room( trash ); obj_to_char( trash, ch ); return TRUE; } } return FALSE; } bool spec_mayor( CHAR_DATA *ch ) { static const char open_path[] = "W3a3003b33000c111d0d111Oe333333Oe22c222112212111a1S."; static const char close_path[] = "W3a3003b33000c111d0d111CE333333CE22c222112212111a1S."; static const char *path; static int pos; static bool move; if ( !move ) { if ( time_info.hour == 6 ) { path = open_path; move = TRUE; pos = 0; } if ( time_info.hour == 20 ) { path = close_path; move = TRUE; pos = 0; } } if ( ch->fighting != NULL ) return spec_cast_mage( ch ); if ( !move || ch->position < POS_SLEEPING ) return FALSE; switch ( path[pos] ) { case '0': case '1': case '2': case '3': move_char( ch, path[pos] - '0', FALSE ); break; case 'W': ch->position = POS_STANDING; act( "$n awakens and groans loudly.", ch, NULL, NULL, TO_ROOM ); break; case 'S': ch->position = POS_SLEEPING; act( "$n lies down and falls asleep.", ch, NULL, NULL, TO_ROOM ); break; case 'a': act( "$n says 'Hello Honey!'", ch, NULL, NULL, TO_ROOM ); break; case 'b': act( "$n says 'What a view! I must do something about that dump!'", ch, NULL, NULL, TO_ROOM ); break; case 'c': act( "$n says 'Vandals! Youngsters have no respect for anything!'", ch, NULL, NULL, TO_ROOM ); break; case 'd': act( "$n says 'Good day, citizens!'", ch, NULL, NULL, TO_ROOM ); break; case 'e': act( "$n says 'I hereby declare the city of Midgaard open!'", ch, NULL, NULL, TO_ROOM ); break; case 'E': act( "$n says 'I hereby declare the city of Midgaard closed!'", ch, NULL, NULL, TO_ROOM ); break; case 'O': /* do_unlock( ch, "gate" ); */ do_open( ch, "gate" ); break; case 'C': do_close( ch, "gate" ); /* do_lock( ch, "gate" ); */ break; case '.' : move = FALSE; break; } pos++; return FALSE; } bool spec_poison( CHAR_DATA *ch ) { CHAR_DATA *victim; if ( ch->position != POS_FIGHTING || ( victim = ch->fighting ) == NULL || number_percent( ) > number_range(60, 80) ) return FALSE; act( "You bite $N!", ch, NULL, victim, TO_CHAR ); act( "$n bites $N!", ch, NULL, victim, TO_NOTVICT ); act( "$n bites you!", ch, NULL, victim, TO_VICT ); spell_poison( gsn_poison, ch->level, ch, victim,TARGET_CHAR); return TRUE; } bool spec_thief( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; long gold; if ( ch->position != POS_STANDING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( IS_NPC(victim) || victim->level >= LEVEL_IMMORTAL || number_bits( 5 ) != 0 || !can_see(ch,victim)) continue; if ( IS_AWAKE(victim) && number_range( 0, ch->level ) == 0 ) { act( "You discover $n's hands in your wallet!", ch, NULL, victim, TO_VICT ); act( "$N discovers $n's hands in $S wallet!", ch, NULL, victim, TO_NOTVICT ); return TRUE; } else { gold = victim->gold * UMIN(number_range(1,20),ch->level / 2) / 100; gold = UMIN(gold, ch->level * ch->level * 10 ); ch->gold += gold; victim->gold -= gold; return TRUE; } } return FALSE; } bool spec_enforcer( CHAR_DATA *ch ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *victim, *v_next; if ( !IS_AWAKE(ch) || ch->fighting != NULL ) return FALSE; if (ch->leader != NULL && IS_SET(ch->leader->act,PLR_CRIMINAL)) { send_to_char("Guards will not follow a CRIMINAL!\n\r",ch->leader); REMOVE_BIT(ch->affected_by,AFF_CHARM); do_follow(ch,"self"); } for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( !IS_NPC(victim) && IS_SET(victim->act, PLR_CRIMINAL) && can_see(ch,victim)) break; } if ( victim != NULL ) { sprintf( buf, "%s is a criminal! PROTECT THE INNOCENT!!", victim->name); REMOVE_BIT(ch->comm,COMM_NOSHOUT); do_myell( ch, buf ); multi_hit( ch, victim, TYPE_UNDEFINED ); return TRUE; } return FALSE; } /* Spec fun for preserver */ bool spec_preserver(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn, level; level = 56; if (ch->position != POS_FIGHTING) return FALSE; for (victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (victim->fighting == ch && number_bits(2) == 0) break; } if (victim == NULL) return FALSE; spell = "acid blast"; switch(number_range(0,6)) { case (0): case (1): case (2): level = 60; spell = "acid blast"; break; case (3): level = 63; spell = "firestream"; break; case (4): level = 57; spell = "earthmaw"; break; case (5): level = 55; spell = "blindness"; break; case (6): level = 55; spell = "concatenate"; break; } if ( (sn = skill_lookup(spell)) < 0) return FALSE; if (check_absorb(ch,victim,sn)) return FALSE; (*skill_table[sn].spell_fun) ( sn, level, ch, victim,TARGET_CHAR); return TRUE; } bool spec_protector(CHAR_DATA *ch) { char buf[MAX_STRING_LENGTH]; int sn_hand, number; CHAR_DATA *vch; CHAR_DATA *vch_next; if (ch->fighting == NULL) return FALSE; for (; ;) { for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch->fighting == ch && number_bits(2) == 0) break; } if (vch != NULL) break; } number = number_percent(); if (number < 5) { do_say(ch,"You are breaking the Law! Leave now or be punished!"); return TRUE; } else if (number < 10 && number_bits(2) == 0) { sprintf(buf,"%s, you must pay for your crimes!",vch->name); do_say(ch,buf); } if (IS_SET(vch->act,PLR_CRIMINAL)) { sn_hand = skill_lookup("hand of vengeance"); act("$n points at $N and says, 'Defend the Protectorate!'",ch,0,vch,TO_NOTVICT); act("$n points at you and says, 'Defend the Protectorate!",ch,0,vch,TO_VICT); (*skill_table[sn_hand].spell_fun) (sn_hand,ch->level,ch,vch,TARGET_CHAR); return TRUE; } return spec_breath_lightning(ch); return FALSE; } bool spec_fallen_angel(CHAR_DATA *ch) { int num, sn_unholy_fire, sn_windwall; if (ch->fighting == NULL) return FALSE; num = number_percent(); if (num >= 50) return FALSE; sn_unholy_fire = skill_lookup("unholy fire"); sn_windwall = skill_lookup("windwall"); if (num < 10) { do_say(ch,"Burn in Hell!"); (*skill_table[sn_unholy_fire].spell_fun) ( sn_unholy_fire, 60, ch, NULL, TARGET_CHAR); return TRUE; } else if (num < 30) { act("$n rise up on $s blackened wings and beats them into the air!",ch,0,0,TO_ROOM); (*skill_table[sn_windwall].spell_fun) (sn_windwall, 60,ch,NULL,TARGET_CHAR); return TRUE; } else if (num < 50) { act("$n hisses and a steaming green gas explodes forth!",ch,0,0,TO_ROOM); return spec_breath_gas(ch); } return FALSE; } void spell_unholy_fire(int sn, int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam, tmp_dam; act("Black flames erupt from the ground to engulf the room!",ch,0,0,TO_ROOM); send_to_char("Black flames erupt from the ground to engulf the room!\n\r",ch); dam = dice(level,6); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch == ch || is_same_group(vch, ch) || vch->cabal==ch->cabal || (IS_IMMORTAL(vch) && ch->fighting!=vch)) continue; tmp_dam = dam; if (saves_spell(level,vch,DAM_NEGATIVE)) tmp_dam /= 2; damage_old(ch,vch,dam,sn,DAM_NEGATIVE,TRUE); } return; } /* Spec_fun for Dead Forest area */ bool spec_troll(CHAR_DATA *ch) { int action; CHAR_DATA *vch; CHAR_DATA *vch_next; return FALSE; if (!IS_AWAKE(ch)) return FALSE; action = number_range(0,3); if (ch->fighting != NULL) action += 4; if (action <= 3 && number_percent() > 10) return FALSE; vch = NULL; if (action >= 4) { for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch->fighting == ch && number_bits(2) == 0) break; } } if (action >= 4 && vch == NULL) return FALSE; switch(action) { case (0): act("$n picks up a piece of dead bark and licks the ichor off it.",ch,0,0,TO_ROOM); break; case (1): act("$n snarls and sniffs the air expecantly.",ch,0,0,TO_ROOM); break; case (2): act("$n licks at a pool of dark green blood.",ch,0,0,TO_ROOM); break; case (3): act("$n scratches at one of it's bloody scabs.",ch,0,0,TO_ROOM); break; case (4): /* Combat */ case (5): (*skill_table[gsn_acid_spit].spell_fun) (gsn_acid_spit,ch->level,ch,vch,TARGET_CHAR); break; case (6): /* Combat */ case (7): do_crush(ch,""); break; } return TRUE; } /* For spec_troll */ void spell_acid_spit(int sn,int level, CHAR_DATA *ch,void *vo, int target) { int dam; AFFECT_DATA af; CHAR_DATA *victim = (CHAR_DATA *) vo; init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_MALADY; af.type = sn; af.duration = 1; af.modifier = -2; af.location = APPLY_HITROLL; af.bitvector = AFF_BLIND; act("$n spits out a spray of burning acid!",ch,0,0,TO_ROOM); send_to_char("You spit forth a spray of acid!\n\r",ch); if (saves_spell(level,victim,DAM_ACID)) damage_old(ch,victim,0,sn,DAM_ACID,TRUE); else { dam = dice(4,5); damage_old(ch,victim,dam,sn,DAM_ACID,TRUE); if (!IS_AFFECTED(victim,AFF_BLIND)) { affect_to_char(victim,&af); send_to_char("You are blinded by the searing acid!\n\r",victim); act("$n appears blinded by the acid.",victim,0,0,TO_ROOM); } } return; } bool spec_monk(CHAR_DATA *ch) { CHAR_DATA *vch; int action; if ( (vch = ch->fighting) == NULL) return FALSE; action = number_range(0,2); if (is_affected(ch,gsn_palm)) action += 1; switch(action) { case (0): do_palm(ch,""); break; case (1): do_throw(ch,""); break; case (2): case (3): do_kick(ch,""); break; } return TRUE; } bool spec_chimera(CHAR_DATA *ch) { CHAR_DATA *vch; CHAR_DATA *vch_next; int action, sn; if (ch->fighting == NULL) return FALSE; action = number_range(0,3); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch->fighting == ch && number_bits(2) == 0) break; } if (vch == NULL) vch = ch->fighting; switch(action) { case (0): do_ram(ch,vch->name); break; case (1): act("$n's dragon head opens it's giant maw.",ch,0,0,TO_ROOM); sn = skill_lookup("fire breath"); (*skill_table[sn].spell_fun) (sn,ch->level,ch,vch,TARGET_CHAR); break; case (2): do_tail(ch,vch->name); break; } return TRUE; } bool evades(CHAR_DATA *ch, CHAR_DATA *victim) { int chance; chance = 50 + ((ch->level - victim->level) * 2); chance += get_curr_stat(ch,STAT_DEX)/3; chance -= get_curr_stat(victim,STAT_DEX)/2; if (number_percent() > chance) return TRUE; return FALSE; } void do_ram(CHAR_DATA *ch, char *argument) { CHAR_DATA *vch; char arg[MAX_INPUT_LENGTH]; int dam; one_argument(argument,arg); vch = get_char_room(ch,arg); if (arg[0] == '\0') vch = ch->fighting; if (IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM)) return; if (!IS_NPC(ch)) { if (get_skill(ch,gsn_chimera_goat) == 0) { send_to_char("Huh?\n\r",ch); return; } } if (vch == NULL) { send_to_char("You aren't fighting anyone.\n\r",ch); return; } if (!IS_NPC(ch) && is_safe(ch,vch)) return; if (evades(ch,vch)) { act("$n brings $s's goat head around in a violent swing but misses.",ch,0,0,TO_ROOM); send_to_char("You bring your goat's head around violently but miss.\n\r",ch); dam = 0; } else { act("$n slams $s's goat head into $N, sending $S sprawling!",ch,0,vch,TO_NOTVICT); act("$n slams $s's goat head into you, sending you sprawling!",ch,0,vch,TO_VICT); act("You slam your goat head into $N, sending $M sprawling!",ch,0,vch,TO_CHAR); dam = dice(ch->level,4); WAIT_STATE(vch,2*PULSE_VIOLENCE); } damage_old(ch,vch,dam,gsn_chimera_goat,DAM_BASH,TRUE); WAIT_STATE(ch,2*PULSE_VIOLENCE); return; } bool spec_darokin(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; int sn_elemental; int val; char buf[MAX_STRING_LENGTH]; sn_elemental = 0; val = number_range(0,8); if (val < 6) sn_elemental = skill_lookup("familiar"); /* sn_elemental = skill_lookup("summon earth elemental"); else if (val == 1) sn_elemental = skill_lookup("summon air elemental"); else if (val == 2) sn_elemental = skill_lookup("summon fire elemental"); else if (val == 3) sn_elemental = skill_lookup("familiar"); else sn_elemental = 0; */ if (ch->position != POS_FIGHTING) { if (ch->last_fought == NULL) return FALSE; if (number_percent() < 20) return FALSE; if (ch->last_fought->in_room->area != ch->in_room->area) return FALSE; victim = ch->last_fought; if (victim->fighting != NULL) return FALSE; if (victim->position == POS_FIGHTING) return FALSE; if (saves_spell(ch->level,victim,DAM_OTHER)) return FALSE; act("$n has summoned you!",ch,0,victim,TO_VICT); act("$n disappears!",victim,0,0,TO_ROOM); char_from_room(victim); char_to_room(victim,ch->in_room); do_look(victim,"auto"); sprintf(buf,"Help! I'm being summoned by %s!",ch->short_descr); do_myell(victim,buf); multi_hit(ch,victim,-1); return TRUE; } for (victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (victim->fighting == ch && number_bits(2) == 0) break; } if (victim == NULL && sn_elemental == 0) return FALSE; if (victim == NULL) { (*skill_table[sn_elemental].spell_fun) (sn_elemental,ch->level,ch,NULL,TARGET_CHAR); return TRUE; } switch (number_range(0,9)) { default: spell = "concatenate"; break; case 0: case 1: spell = "concatenate"; break; case 2: case 3: spell = "fireball"; break; case 4: spell = "windwall"; break; case 5: spell = "blindness"; break; case 6: spell = "cone of cold"; break; case 7: spell = "acid blast"; break; case 8: case 9: spell = "firestream"; break; } if ( (sn = skill_lookup(spell)) < 0) return FALSE; (*skill_table[sn].spell_fun) (sn,ch->level,ch,victim,TARGET_CHAR); return TRUE; } bool spec_godfather(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if (IS_NPC(victim)) continue; if ( victim->fighting == ch && number_bits(2) == 0) break; } if ( victim == NULL ) return FALSE; sn = -1; sn = gsn_revolt; if ( sn < 0 ) return FALSE; if (check_absorb(ch,victim,sn)) return FALSE; (*skill_table[sn].spell_fun) ( sn, 52, ch, victim,TARGET_CHAR); return TRUE; } bool spec_bishop(CHAR_DATA *ch) { OBJ_DATA *sceptre; int sn_frenzy; if (ch->fighting == NULL) return FALSE; sceptre = get_eq_char(ch,WEAR_HOLD); if (sceptre != NULL && sceptre->pIndexData->vnum == OBJ_VNUM_HEAVENLY_SCEPTRE && number_bits(2) == 0) { sn_frenzy = skill_lookup("heavenly wrath"); if (!is_affected(ch,sn_frenzy) && number_percent() < 50) do_say(ch,"I am the wrath of god"); else do_say(ch,"Feel the force of god"); return TRUE; } return (spec_cast_cleric(ch)); return FALSE; } bool spec_bane(CHAR_DATA *ch) { CHAR_DATA *vch; CHAR_DATA *vch_next; int num, sn; char buf[MAX_STRING_LENGTH]; CHAR_DATA *mob; num = 0; sn = -1; if (ch->fighting == NULL && ch->last_fought == NULL) { if (number_percent() > 2 && number_percent() > 10) return FALSE; for (vch = char_list;vch != NULL; vch = vch->next) { if (vch->in_room ==NULL) continue; if (vch->in_room->area != ch->in_room->area || IS_NPC(vch)) continue; num = number_range(0,40); if (num < 15) send_to_char("You feel a cold chill pass over your soul as something unspeakable stirs nearby.\n\r",vch); else if (num < 20) send_to_char("A demonic laugh echoes softly around you, only to fade as a blue light flares in the distance.\n\r",vch); else if (num <= 25) send_to_char("You feel something powerful and malevolent watching you from the darkness around you.\n\r",vch); else if (num < 30) send_to_char("An awesome force of pure darkness clutches your soul but then passes on...\n\r",vch); else if (num < 35) send_to_char("Something powerful demands your servitude, but it quickly fades as a green light flashes in a nearby tower.\n\r",vch); else if (num <= 40) send_to_char("You feel the prescence of a divine power seeking something in the ruins...\n\r",vch); return TRUE; } } if (ch->position == POS_SLEEPING) return FALSE; if (ch->fighting == NULL) { for (vch = char_list; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch->in_room != ch->in_room) continue; if (!is_same_group(ch,vch)) continue; if (number_bits(2) != 0) continue; sprintf(buf,"Help! %s is attacking me!",ch->short_descr); do_myell(vch,buf); multi_hit(ch,vch,TYPE_UNDEFINED); return TRUE; } } if (ch->fighting == NULL && ch->last_fought != NULL) { if (number_percent() > 5) return FALSE; for (vch = char_list; vch != NULL; vch = vch_next) { vch_next = vch->next; if (vch->in_room->area != ch->in_room->area) continue; if (is_same_group(vch,ch->last_fought) && !saves_spell(ch->level,vch,DAM_OTHER) ) { act("$n suddenly disappears!",vch,0,0,TO_ROOM); send_to_char("You have been summoned!\n\r",vch); char_from_room(vch); char_to_room(vch,ch->in_room); do_look(vch,"auto"); act("$n arrives suddenly!",vch,0,0,TO_ROOM); num = number_percent(); if (num < 30) sprintf(buf,"Help! I've been summoned by %s!",PERS(ch,vch)); else if (num < 70) sprintf(buf,"Help! I'm being attacked by %s!",PERS(ch,vch)); else sprintf(buf,"NO! I'm being slayed by %s!",PERS(ch,vch)); do_myell(vch,buf); multi_hit(ch,vch,TYPE_UNDEFINED); } } return TRUE; } num = number_percent(); if (num < 10) sn = skill_lookup("deathspell"); else if (num < 20) sn = skill_lookup("acid blast"); else if (num < 30) sn = skill_lookup("demonfire"); else if (num < 40) sn = skill_lookup("iceball"); else if (num < 50) sn = skill_lookup("fireball"); else if (num < 80) sn = -1; else if (num < 90) { do_say(ch,"Burn in the fires of hell!"); sn = skill_lookup("unholy fire"); } if (sn == -1) { for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (IS_NPC(vch) && vch->pIndexData->vnum == MOB_VNUM_SLAYER) break; } if (vch != NULL) return FALSE; if (number_percent() > 80) { act("$n's eye's glow bright red but nothing happens.",ch,0,0,TO_ROOM); return TRUE; } act("$n's eyes glow bright red and a dark figure materialises beside $s!",ch,0,0,TO_ROOM); mob = create_mobile(get_mob_index(MOB_VNUM_SLAYER)); char_to_room(mob,ch->in_room); mob->leader = ch; mob->master = ch; SET_BIT(mob->affected_by, AFF_CHARM); return TRUE; } for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch->fighting == ch && number_bits(2) == 0) break; } if (vch == NULL && sn != skill_lookup("deathspell") && sn != skill_lookup("iceball") && sn != skill_lookup("fireball")) return FALSE; (*skill_table[sn].spell_fun) (sn,ch->level,ch,vch,skill_table[sn].target); return TRUE; } bool spec_rakshasa(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; if (ch->position != POS_FIGHTING) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; return TRUE; } bool spec_rakshasa_royal(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int num; int sn, lvl; char buf[MAX_STRING_LENGTH]; if (ch->position != POS_FIGHTING) return FALSE; sn = -1; return (spec_rakshasa(ch)); for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; buf[0] = '\0'; for (; ;) { num = number_range(0,11); if (num == 12) return FALSE; if ((num == 0 || num == 1) && !IS_AFFECTED(victim,AFF_CURSE) ) break; if ((num == 2 || num == 3) && !IS_AFFECTED(victim,AFF_SLOW)) break; if (num >= 4) break; } lvl = ch->level; if (num == 0 || num == 1) { do_say(ch,"I curse thee mortal fool!"); sn = gsn_curse; } else if (num == 2 || num == 3) { sprintf(buf,"Stay still weakling mortal!"); do_say(ch,buf); sn = skill_lookup("slow"); lvl += 5; } else if (num == 4 || num == 5 ) { do_say(ch,"What a tasty meal you will make!"); sn = skill_lookup("acid blast"); lvl = 55; } else if (num == 6) { do_say(ch,"Begone from here intruder!"); sn = skill_lookup("teleport"); lvl = 50; } else if (num == 7 || num == 8 ) { act("$n opens $s mouth and a raging fireball explodes forth!",ch,0,0,TO_ROOM); sn = skill_lookup("fireball"); lvl = 55; } else if (num == 9 || num == 10) { sn = skill_lookup("blindness"); lvl = 55; } else if (num == 11) { sn = skill_lookup("energy drain"); } if (sn < 0) return FALSE; (*skill_table[sn].spell_fun) (sn,lvl,ch,victim,skill_table[sn].target); return TRUE; } bool spec_rakshasa_lich(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int num; int sn,lvl; char buf[MAX_STRING_LENGTH]; if (ch->position != POS_FIGHTING) return FALSE; sn = -1; return (spec_rakshasa(ch)); for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; for (; ;) { num = number_range(0,11); if (num == 12) return FALSE; if ((num == 0 || num == 1) && !IS_AFFECTED(victim,AFF_CURSE) ) break; if ((num == 2 || num == 3) && !IS_AFFECTED(victim,AFF_SLOW)) break; if (num >= 4) break; } buf[0] = '\0'; lvl = ch->level; if (num == 0 || num == 1) { do_say(ch,"I curse thee mortal fool!"); sn = gsn_blindness; } else if (num == 2 || num == 3) { do_say(ch,"Stay still impudent mortal!"); sn = skill_lookup("slow"); lvl += 5; } else if (num == 4 || num == 5 ) { if (!IS_NPC(victim)) return TRUE; if (number_percent() < 50) sprintf(buf,"Your corpse shall make a fine servant!"); else sprintf(buf,"It is time for you to be taught a lesson!"); do_say(ch,buf); sn = skill_lookup("acid blast"); lvl = 60; } else if (num == 6) { sn = skill_lookup("demonfire"); lvl = 50; } else if (num == 7 || num == 8 ) { act("$n opens $s mouth and a raging fireball explodes forth!",ch,0,0,TO_ROOM); sn = skill_lookup("fireball"); lvl = 55; } else if (num == 9 || num == 10) { sn = skill_lookup("blindness"); lvl = 55; } else if (num == 11) { sn = skill_lookup("energy drain"); } if (sn < 0) return FALSE; (*skill_table[sn].spell_fun) (sn,lvl,ch,victim,skill_table[sn].target); return TRUE; } /* * spec_fun for beholders, can use up to 3 eyes per round. Had to * mess with the spell selection to prevent same spell being used by mutliple * eyes though. Messy chunky code. */ bool spec_beholder(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *victim1; CHAR_DATA *victim2; CHAR_DATA *victim3; CHAR_DATA *v_next; char *spell1; char *spell2; char *spell3; int i; int sn1, sn2, sn3; if ( ch->position != POS_FIGHTING ) return FALSE; sn1 = -1; sn2 = -1; sn3 = -1; victim1 = NULL; victim2 = NULL; victim3 = NULL; for (i = 0; i < 3; i++) { if (victim3 != NULL) break; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_percent() < 30 ) { if (victim1 == NULL) victim1 = victim; else if (victim2 == NULL) victim2 = victim; else if (victim3 == NULL) victim3 = victim; else break; } } } if ( victim1 == NULL ) return FALSE; switch(number_bits(4)) { case 0: spell1 = "blindness"; break; case 1: spell1 = "energy drain"; break; case 2: spell1 = "harm"; break; case 3: spell1 = "weaken"; break; case 4: spell1 = "harm"; break; case 5: spell1 = "slow"; break; case 6: spell1 = "change sex"; break; case 7: spell1 = "fireball"; break; case 8: spell1 = "iceball"; break; default: spell1 = "dispel magic"; break; } sn1 = skill_lookup(spell1); if (victim2 != NULL) { for (; ;) { switch(number_bits(4)) { case 0: spell2 = "blindness"; break; case 1: spell2 = "energy drain"; break; case 2: spell2 = "harm"; break; case 3: spell2 = "weaken"; break; case 4: spell2 = "harm"; break; case 5: spell2 = "slow"; break; case 6: spell2 = "change sex"; break; case 7: spell2 = "fireball"; break; case 8: spell2 = "iceball"; break; default: spell2 = "dispel magic"; break; } sn2 = skill_lookup(spell2); if (sn2 != sn1) break; } } if (victim3 != NULL) { for (; ;) { switch(number_bits(4)) { case 0: spell3 = "blindness"; break; case 1: spell3 = "energy drain"; break; case 2: spell3 = "harm"; break; case 3: spell3 = "weaken"; break; case 4: spell3 = "harm"; break; case 5: spell3 = "slow"; break; case 6: spell3 = "change sex"; break; case 7: spell3 = "fireball"; break; case 8: spell3 = "iceball"; break; default: spell3 = "dispel magic"; break; } sn3 = skill_lookup(spell3); if (sn3 != sn2 && sn3 != sn1) break; } } act("$n turns one of it's eyestalks upon $N.",ch,0,victim1,TO_NOTVICT); act("$n turns one of it's eyestalks upon you.",ch,0,victim1,TO_VICT); if ( sn1 >= 0 ) (*skill_table[sn1].spell_fun) ( sn1, ch->level, ch, victim1,TARGET_CHAR ); if (victim2 != NULL) { if ( sn2 >= 0 ) { (*skill_table[sn2].spell_fun) ( sn1, ch->level, ch,victim2,skill_table[sn2].target ); } } if (victim3 != NULL) { if ( sn3 >= 0 ) { act("$n turns one of it's eyestalks upon $N.",ch,0,victim1,TO_NOTVICT); act("$n turns one of it's eyestalks upon you.",ch,0,victim1,TO_VICT); (*skill_table[sn3].spell_fun) ( sn3, ch->level, ch,victim3,skill_table[sn3].target ); } } return TRUE; } /* deathkngiht special */ bool spec_deathknight(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int sn, lvl; sn = -1; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return (spec_room_throw(ch)); lvl = ch->level; switch(number_range(0,16)) { case (0): do_say(ch,"Die!"); sn = skill_lookup("power word kill"); lvl = 50; break; case (1): case (2): case (3): case (4): case (5): do_say(ch,"Fire!"); sn = skill_lookup("fireball"); break; case (6): case (7): case (8): case (9): do_say(ch,"Ice!"); sn = skill_lookup("iceball"); break; case (10): case (11): case (12): sn = skill_lookup("plague"); break; case (13): case (14): sn = skill_lookup("energy drain"); break; case (15): case (16): sn = skill_lookup("wither"); lvl = 51; break; } if (sn < 0) return FALSE; (*skill_table[sn].spell_fun) (sn,lvl,ch,victim,skill_table[sn].target); return TRUE; } /* for spectre king in Myth Drannor */ bool spec_spectre_king(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; switch ( number_range(0,8) ) { case 0: spell = "blindness"; break; case 1: spell = "chill touch"; break; case 2: spell = "iceball"; break; case 3: spell = "energy drain"; break; case 4: spell = "cone of cold"; break; case 5: spell = "acid blast"; break; default: spell = "frost breath"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } /* throws a victim out of room..problems with this somewhere but I'm too lazy to fix 'em (Ceran) */ bool spec_room_throw(CHAR_DATA *ch) { ROOM_INDEX_DATA *was_in; CHAR_DATA *victim; int attempt, chance, dam, level; /* int rev_door; */ if (ch->position != POS_FIGHTING) return FALSE; if (number_bits(2) != 0) return FALSE; return FALSE; victim = ch->fighting; level = ch->level + 3; chance = (ch->level - victim->level)*3; chance += number_range(20,50); chance -= get_curr_stat(victim,STAT_DEX)/2; chance -= get_curr_stat(victim,STAT_STR)/3; chance += get_curr_stat(ch,STAT_STR); if (IS_AFFECTED(victim,AFF_HASTE)) chance -= 30; if (IS_AFFECTED(ch,AFF_HASTE)) chance += 15; if (IS_AFFECTED(victim,AFF_SLOW)) chance += 20; if (IS_AFFECTED(ch,AFF_SLOW)) chance -= 30; if (IS_AFFECTED(victim,AFF_FLYING)) chance += 5; chance += (ch->size - victim->size)*10; if (number_percent() > chance) { act("$n grabs at $N but looses hold.",ch,0,victim,TO_NOTVICT); act("$n grabs at you but looses hold.",ch,0,victim,TO_VICT); return FALSE; } was_in = victim->in_room; dam = dice(level,5); for ( attempt = 0; attempt < 6; attempt++ ) { EXIT_DATA *pexit; int door; door = number_door( ); if ( ( pexit = was_in->exit[door] ) == 0 || pexit->u1.to_room == NULL || ( IS_SET(pexit->exit_info, EX_CLOSED) ) || ( IS_NPC(victim) && IS_SET(pexit->u1.to_room->room_flags, ROOM_NO_MOB) ) ) continue; if ( ( was_in->sector_type == SECT_AIR) || ( (pexit->u1.to_room->sector_type == SECT_AIR ) && ( !IS_AFFECTED(victim, AFF_FLYING) ) ) ) continue; if (IS_SET(pexit->exit_info,EX_CLOSED)) { act( "$n grabs $N and sends $M crashing through the door with incredible force!",ch,0,victim,TO_NOTVICT); act("$n grabs you and sends you crashing through the door with incredible force!",ch,0,victim,TO_VICT); } else { act( "$n grabs $N and hurls $M from the room with incredible force!", ch, NULL, victim, TO_NOTVICT); act("$n grabs you and hurls you from the room with incredible force!",ch,0,victim,TO_VICT); dam = dice(level,7); } char_from_room(victim); char_to_room(victim, pexit->u1.to_room); do_look(victim,"auto"); if (IS_SET(pexit->exit_info,EX_CLOSED)) { /* if (door == 0) rev_door = 2; else if (door == 1) rev_door = 3; else if (door == 2) rev_door = 0; else if (door == 3) rev_door = 1; else if (door == 4) rev_door = 5; else rev_door = 4; */ REMOVE_BIT(pexit->exit_info,EX_CLOSED); /* if (victim->in_room->exit[rev_door] != NULL) REMOVE_BIT(victim->in_room->exit[rev_door]->exit_info,EX_CLOSED); */ act("With a deafening crash the door explodes open and $n comes flying into the room!",ch,0,0,TO_ROOM); } else { act("$n comes flying into the room with incredible force!",ch,0,0,TO_ROOM); } if (saves_spell(ch->level - 3,victim,DAM_BASH)) dam /= 2; damage_old(ch,victim,dam,gsn_throw,DAM_BASH,TRUE); stop_fighting( ch, TRUE ); return TRUE; } act("$n grabs $N and hurls $M brutally into a wall!",ch,0,victim,TO_NOTVICT); act("$n grabs you and hurtls you brutally into a wall!",ch,0,victim,TO_VICT); if (saves_spell(ch->level - 3,victim,DAM_BASH)) dam /= 2; damage_old(ch,victim,dam,gsn_throw,DAM_BASH,TRUE); return TRUE; } /* hydra spec fun for myth drannor */ bool spec_hydra(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *victim1; CHAR_DATA *victim2; CHAR_DATA *victim3; CHAR_DATA *v_next; char *spell1; char *spell2; char *spell3; int level, i; int sn1, sn2, sn3; if ( ch->position != POS_FIGHTING && ch->last_fought != NULL) return FALSE; if (ch->position != POS_FIGHTING) { if (number_percent() < 30) return FALSE; act("$n swings it's heads about in anger then turns and slips back to where it came.",ch,0,0,TO_ROOM); extract_char(ch,TRUE); return TRUE; } sn1 = 0; sn2 = 0; sn3 = 0; victim1 = NULL; victim2 = NULL; victim3 = NULL; level = ch->level; for (i = 0; i < 3; i++) { if (victim3 != NULL) break; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_percent() < 30 ) { if (victim1 == NULL) victim1 = victim; else if (victim2 == NULL) victim2 = victim; else if (victim3 == NULL) victim3 = victim; else break; } } } if ( victim1 == NULL ) return FALSE; switch(number_range(0,3)) { case 0: spell1 = "acid blast"; break; case 1: spell1 = "fireball"; level = 50; break; case 3: spell1 = "flame scorch"; break; default: spell1 = "flame scorch"; break; } sn1 = skill_lookup(spell1); spell2 = "weaken"; if (victim2 != NULL && (sn1 != gsn_flame_scorch)) { switch(number_range(0,3)) { case 1: spell2 = "poison"; level = 53; break; case 2: spell2 = "slow"; level = 55; break; case 3: spell2 = "weaken"; level = 55; break; } sn2 = skill_lookup(spell2); } if (victim3 != NULL && (sn1 != gsn_flame_scorch)) { switch(number_range(0,4)) { case 1: spell3 = "harm"; level = 58; break; case 2: spell3 = "iceball"; level = 55; break; default: spell3 = "dispel magic"; level = 54; break; } sn3 = skill_lookup(spell3); } if (sn1 == gsn_flame_scorch) { act("The hydra's heads swing around and rise up above you.",ch,0,0,TO_ROOM); (*skill_table[sn1].spell_fun) ( sn1, ch->level, ch, victim1,skill_table[sn1].target ); return TRUE; } else if ( sn1 >= 0 ) { act("$n brings it's massive red head down to bear upon $N!",ch,0,victim1,TO_NOTVICT); act("$n brings it's massive red head around to bear upon you!",ch,0,victim1,TO_VICT); (*skill_table[sn1].spell_fun) ( sn1, level, ch, victim1,skill_table[sn1].target ); } if (victim2 != NULL) { if ( ( sn2 >= 0 ) && victim2->in_room == ch->in_room) { act("$n brings it's massive green head down to bear upon $N!",ch,0,victim2,TO_NOTVICT); act("$n brings it's massive green head around to bear upon you!",ch,0,victim2,TO_VICT); (*skill_table[sn2].spell_fun) ( sn1, level, ch, victim2,skill_table[sn2].target); } } if (victim3 != NULL && victim3->in_room == ch->in_room) { if ( sn3 >= 0 ) { act("$n brings it's massive blue head down to bear upon $N!",ch,0,victim3,TO_NOTVICT); act("$n brings it's massive blue head around to bear upon you!",ch,0,victim3,TO_VICT); (*skill_table[sn3].spell_fun) ( sn3, level, ch, victim3, skill_table[sn3].target); } } return TRUE; } void spell_flame_scorch(int sn, int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam, tmp_dam; act("$n strafes the room in a crossfire of searing blue-green fire!",ch,0,0,TO_ROOM); dam = dice(ch->level, 12); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe(vch,ch)) continue; if (vch == ch) continue; if (IS_NPC(vch) && vch->pIndexData->vnum == MOB_VNUM_BONES) { act("$n explodes into bits of shattered bone!",vch,0,0,TO_ROOM); extract_char(vch,TRUE); } else { if (saves_spell(level,vch,DAM_ENERGY)) tmp_dam = dam/2; else tmp_dam = dam; if (saves_spell(level +5, vch,DAM_ENERGY)) tmp_dam -= 50; damage_old(ch,vch,tmp_dam,sn,DAM_ENERGY,TRUE); } } return; } /* horn valere knight spec */ bool spec_valere_knight(CHAR_DATA *ch) { CHAR_DATA *bane; int sn; if (ch->position != POS_FIGHTING) { if (number_percent() < 90) return FALSE; act("$n sighs softly and $s body slowly fades away once again.",ch,0,0,TO_ROOM); extract_char(ch,TRUE); return TRUE; } if (number_percent() > 5) return FALSE; bane = ch->fighting; if (!IS_NPC(bane)) return FALSE; if (bane->pIndexData->vnum == 13718) { switch(number_range(0,3)) { case 0: case 1: do_say(ch,"Pay for your evil against my people Lord of Darkness!"); multi_hit(ch,bane,TYPE_UNDEFINED); multi_hit(ch,bane,TYPE_UNDEFINED); break; case 2: act("$n is surrounded in a bright halo of burning white light!",ch,0,0,TO_ROOM); sn = skill_lookup("concatenate"); if (sn <= 0) return FALSE; (*skill_table[sn].spell_fun) (sn,ch->level,ch,bane,skill_table[sn].target); break; case 3: sn = skill_lookup("wrath"); if (sn <= 0) return FALSE; (*skill_table[sn].spell_fun) (sn,ch->level,ch,bane,skill_table[sn].target); break; } } return TRUE; } /* Bone demon in drannor */ bool spec_bone_demon(CHAR_DATA *ch) { OBJ_DATA *obj; CHAR_DATA *vch; CHAR_DATA *vch_next; int dam, sn; int chance; if (ch->position != POS_FIGHTING) return FALSE; for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch->fighting == ch && number_bits(2) == 0) break; } if (vch == NULL) return FALSE; chance = (ch->level - vch->level)* 5; chance += 50; switch(number_range(1,7)) { case 1: case 2: if (number_percent() > chance) { act("$n's arms reach out and flail at $N but miss.",ch,0,vch,TO_NOTVICT); act("$n's arms reach out and flail at you but miss.",ch,0,vch,TO_VICT); return FALSE; } act("$n's arms reach out and flail across $N's body!",ch,0,vch,TO_NOTVICT); act("$n's arms reach out and flail across your body!",ch,0,vch,TO_VICT); dam = dice(ch->level,6); damage_old(ch,vch,(saves_spell(ch->level,vch,DAM_SLASH) ? dam/2 : dam),gsn_flail_arms,DAM_SLASH,TRUE); if (ch->in_room == vch->in_room) { dam = dice(ch->level, 4); damage_old(ch,vch,(saves_spell(ch->level,vch,DAM_SLASH) ? dam/2 : dam),gsn_flail_arms,DAM_SLASH,TRUE); } if (ch->in_room == vch->in_room) { dam = dice(ch->level, 2); damage_old(ch,vch,(saves_spell(ch->level,vch,DAM_SLASH) ? dam/2 : dam),gsn_flail_arms,DAM_SLASH,TRUE); } return TRUE; break; case 3: case 4: do_kick(ch,""); break; case 5: case 6: act("$n raises it's bone arms and calls forth the demons of hell!",ch,0,0,TO_ROOM); sn = skill_lookup("demonfire"); if (sn <= 0) return FALSE; dam = dice(ch->level,7); if (saves_spell(ch->level,vch,DAM_NEGATIVE)) dam /= 2; /* if (spellbaned(ch,vch,sn) || (absorbed(ch,vch,sn)) break; else */ damage_old(ch,vch,dam,sn,DAM_NEGATIVE,TRUE); break; case 7: if (ch->hit > 250) { do_say(ch,"Come share your bones mortal!"); act("$n raises it's bone arms and the bloody waters surge up around you!",ch,0,0,TO_ROOM); sn = skill_lookup("blood tide"); dam = dice(ch->level,7); for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (vch == ch) continue; if (is_safe(vch,ch)) continue; damage_old(ch,vch,(saves_spell(ch->level,vch,DAM_OTHER) ? dam/2 : dam), sn,DAM_COLD,TRUE); } break; } act("$n's body suddenly shudders and explodes into shards of shattered bone!",ch,0,0,TO_ROOM); dam = dice(ch->level,12); sn = gsn_shattered_bone; for (vch = char_list; vch != NULL; vch = vch_next) { vch_next = vch->next; if (vch->in_room->area != ch->in_room->area) continue; if (vch == ch) continue; if (vch->in_room == ch->in_room) damage_old(ch,vch,(saves_spell(ch->level,vch,DAM_PIERCE) ? dam/2 : dam),sn,DAM_PIERCE,TRUE); else send_to_char("You hear an explosive detonation and shattered bits of bone fall around you.\n\r",vch); } for (obj = ch->carrying; obj != NULL; obj = obj->next_content) obj_to_room(obj,ch->in_room); extract_char(ch,TRUE); break; } return TRUE; } bool spec_drannor_wraith(CHAR_DATA *ch) { if (ch->position == POS_FIGHTING) return FALSE; if (ch->position != POS_FIGHTING && ch->last_fought == NULL && number_percent() > 20) { act("$n slowly sinks into the ground with a long sad sigh.",ch,0,0,TO_ROOM); extract_char(ch,TRUE); return TRUE; } return FALSE; } /* For arkham legion...Ceran */ bool spec_necromancer( CHAR_DATA *ch ) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; CHAR_DATA *zombie; OBJ_DATA *corpse; OBJ_DATA *obj_next; OBJ_DATA *obj; CHAR_DATA *search; AFFECT_DATA af; char *name; char *last_name; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; int z_level, count; if ( ch->position != POS_FIGHTING ) { if (ch->level < 45) return FALSE; if (ch->pIndexData->vnum != 29723 && ch->pIndexData->vnum != 29731) return FALSE; for (victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (victim != ch && victim->leader != ch && victim->master != ch && can_see(victim,ch) && number_bits( 2) == 0) break; } if (victim == NULL) return FALSE; sn = skill_lookup("power word kill"); if (sn <= 0) return FALSE; act("$n raises $s cowled face and burning red eyes turn upon you in hatred!",ch,0,0,TO_ROOM); if (!IS_NPC(victim)) { sprintf(buf1,"Help! %s is casting on me!",ch->short_descr); do_myell(victim,buf1); } (*skill_table[sn].spell_fun) ( sn,IS_NPC(victim) ? 60 : ch->level - 2, ch, victim , TAR_CHAR_OFFENSIVE); return TRUE; } for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; for ( ;; ) { int min_level; switch ( number_range(0,8) ) { case 1: min_level = 0; spell = "blindness"; break; case 2: min_level = 5; spell = "blindness"; break; case 3: min_level = 15; spell = "energy drain"; break; case 4: min_level = 24; spell = "fireball"; break; case 5: min_level = 28; spell = "acid blast"; break; case 6: min_level = 35; spell = "frostbolt"; break; default: min_level = 28; spell = "acid blast"; break; } if ( ch->level >= min_level ) break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; if (sn == skill_lookup("animate dead")) { if (is_affected(ch,sn)) { return FALSE; } count = 0; for (search = char_list; search != NULL; search = search->next) { if (IS_NPC(search) && (search->master == ch) && search->pIndexData->vnum == MOB_VNUM_ZOMBIE) count++; } if ((ch->level < 30 && count > 1) || (ch->level < 35 && count > 2) || (ch->level < 40 && count > 3) || (ch->level < 51 && count > 4) || count > 4) { return FALSE; } corpse = get_obj_here(ch,"corpse"); if (corpse == NULL) { return FALSE; } if ((corpse->item_type != ITEM_CORPSE_NPC) && (corpse->item_type != ITEM_CORPSE_PC) ) { return FALSE; } if (is_set(&corpse->extra_flags,CORPSE_NO_ANIMATE)) { return FALSE; } 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.aftype = AFT_SPELL; af.type = sn; af.level = ch->level; af.duration = 4; af.modifier = 0; af.location = 0; af.bitvector = 0; affect_to_char(ch,&af); if (number_percent() > 95) { act("$n tries to animate a corpse but destroys it.",ch,NULL,NULL,TO_ROOM); extract_obj(corpse); return TRUE; } 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)); char_to_room(zombie,ch->in_room); z_level = UMAX(1,corpse->level - 5); zombie->level = z_level; zombie->max_hit = (dice(z_level, 15)); zombie->max_hit += (z_level * 18); zombie->hit = zombie->max_hit; zombie->damroll += z_level*2/3; 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); add_follower(zombie,ch); zombie->leader = ch; af.duration = -1; af.bitvector = AFF_CHARM; affect_to_char(zombie,&af); return TRUE; } else { (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim , TARGET_CHAR); } return TRUE; } /* For arkham legion...Ceran */ bool spec_rager(CHAR_DATA *ch) { if (ch->position != POS_FIGHTING) return FALSE; switch(number_range(1,2)) { case 1: spec_flurry(ch); return TRUE; break; case 2: spec_pincer(ch); return TRUE; break; default: spec_flurry(ch); return TRUE; break; } return FALSE; } /* For arkham legion...Ceran */ bool spec_demonologist(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; CHAR_DATA *mob; char buf1[MAX_STRING_LENGTH]; char *spell; int sn; int lvl; spell = "bash"; if ( ch->position != POS_FIGHTING ) { if (ch->level < 51) return FALSE; if ( ch->pIndexData->vnum != 29732) return FALSE; for (victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (victim != ch && victim->leader != ch && victim->master != ch && can_see(victim,ch) && !IS_NPC(victim) ) break; } if (victim == NULL) return FALSE; sn = skill_lookup("fireball"); if (sn <= 0) return FALSE; act("$n intones a word of death and the pentegram flares up!",ch,0,0,TO_ROOM); for (victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (victim != ch && victim->leader != ch && victim->master != ch) { sprintf(buf1,"Help! %s is casting on me!",ch->short_descr); do_myell(victim,buf1); } } (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim + 4 , TAR_CHAR_OFFENSIVE); return TRUE; } for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } sn = 0; if ( victim == NULL ) return FALSE; for ( ;; ) { int min_level; switch ( number_range(0,10) ) { case 1: min_level = 0; spell = "blindness"; break; case 2: min_level = 5; spell = "disease"; break; case 3: min_level = 25; spell = "demonfire"; break; case 4: min_level = 20; spell = "fireball"; break; case 5: min_level = 35; spell = "deathspell"; break; case 6: min_level = 10; spell = "power word fear"; break; case 7: case 8: min_level = 45; sn = -1; break; case 9 : min_level = 20; spell = "cone of cold"; break; default: min_level = 20; spell = "acid blast"; break; } if ( ch->level >= min_level ) break; } if (sn == -1) { for (victim = ch->in_room->people; victim != NULL; victim = victim->next_in_room) { if (IS_NPC(victim) && victim->pIndexData->vnum == MOB_VNUM_SLAYER) break; } if (victim != NULL) return FALSE; mob = create_mobile(get_mob_index(MOB_VNUM_SLAYER)); if (mob == NULL) return FALSE; act("$n raises $s arms and calls forth a demonic servant!",ch,0,0,TO_ROOM); char_to_room(mob,ch->in_room); mob->leader = ch; mob->master = ch; mob->level = ch->level; SET_BIT(mob->affected_by, AFF_CHARM); act("A gate opens up and $n steps forth.",mob,0,0,TO_ROOM); return TRUE; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; lvl = ch->level; if (sn == skill_lookup("deathspell")) { act("$n gestures and a flaming hexagram burns into the air!",ch,0,0,TO_ROOM); send_to_char("You gesture and a flaming hexagram burns into the air!\n\r",ch); lvl += 3; } else if (sn == skill_lookup("fireball") && number_percent() > 65) { act("$n gestures and red runes etched into the floor explode!",ch,0,0,TO_ROOM); lvl += 4; } else if (sn == skill_lookup("cone of cold") && number_percent() > 75) { act("$n gestures and blue runes etched into the floor explode!",ch,0,0,TO_ROOM); lvl += 3; } (*skill_table[sn].spell_fun) ( sn,lvl, ch, victim , TAR_CHAR_OFFENSIVE); return TRUE; } /* For titan in Arkham legion..Ceran */ bool spec_titan(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int num, dam; AFFECT_DATA af; int chance; int sn; if (ch->fighting == NULL) { if (ch->last_fought != NULL) { if (number_percent() > 5 || is_affected(ch,gsn_trophy)) return FALSE; if (number_percent() > 50) do_myell(ch,"Come back puny mortals and feed my hungry stomach!"); else do_myell(ch,"You fight like mortals and flee like children!"); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SPELL; af.type = gsn_trophy; /* Just using as trigger */ af.modifier = 0; af.bitvector = 0; af.level = 0; af.duration = 2; af.location = 0; affect_to_char(ch,&af); return TRUE; } if (number_percent() > 5 || is_affected(ch,gsn_trophy)) return FALSE; num = number_range(0,5); if (num == 0 || num == 1) do_yell(ch,"Release me mortals or suffer my wrath!"); else if (num == 3) do_yell(ch,"I shall crush you like twigs and feast on your corpses mortal fools!"); else do_yell(ch,"Ni Sothoth Den Cael Yog Nar Sethan!"); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SPELL; af.type = gsn_trophy; /* Just using as trigger */ af.modifier = 0; af.bitvector = 0; af.level = 0; af.duration = 2; af.location = 0; affect_to_char(ch,&af); return TRUE; return TRUE; } for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim->fighting == ch && number_bits( 2 ) == 0 ) break; } if ( victim == NULL ) return FALSE; num = number_range(0,4); switch( num ) { case 1: sn = gsn_crush; break; case 2: sn = skill_lookup("windwall"); break; case 3: sn = skill_lookup("acid blast"); break; case 4: sn = -1; break; default: sn = -1; break; } if (sn == -1) return FALSE; if (sn == skill_lookup("acid blast")) { act("$n hurls a bolt of seething acid at $N!",ch,0,victim,TO_NOTVICT); act("$n hurls a bolt of seething acid at you!",ch,0,victim,TO_VICT); act("You hurl a bolt of seething acid at $N!",ch,0,victim,TO_CHAR); } else if (sn == skill_lookup("windwall")) { act("$n breathes out and releases a blast of gale force wind!",ch,0,0,TO_ROOM); act("You breath out and release a blast of gale force wind!",ch,0,0,TO_CHAR); } else { chance = 50 + (ch->level - victim->level) * 3; if (number_percent() > chance) return FALSE; dam = dice(ch->level,8); if (saves_spell(ch->level,victim,DAM_BASH)) dam /= 2; act("$n grabs hold of $N and slams $M to the ground!",ch,0,victim,TO_NOTVICT); act("You grab hold of $N and slam $M to the ground!",ch,0,victim,TO_CHAR); act("$n grabs hold of you and slams you to the ground!",ch,0,victim,TO_VICT); damage_old(ch,victim,dam,gsn_crush,DAM_BASH,TRUE); WAIT_STATE(ch,24); WAIT_STATE(victim,12); return TRUE; } (*skill_table[sn].spell_fun) ( sn,ch->level, ch, victim , TAR_CHAR_OFFENSIVE); return TRUE; } /* Real nasty spec..Ceran */ bool spec_legionlord(CHAR_DATA *ch) { CHAR_DATA *victim; char *msg; CHAR_DATA *v_next; int sn, dam, level, num; num = number_range(0,5); level = ch->level; msg = "none"; if (ch->position == POS_SLEEPING) /* stops blackjack/strangle */ { act("$n shudders and slowly rises to $s feet.",ch,0,0,TO_ROOM); ch->position = POS_STANDING; } if (ch->position != POS_FIGHTING) { for (victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (victim == ch || ( IS_NPC(victim) && victim->pIndexData->vnum == 29782) ) continue; if (number_percent() < 80) break; } if (victim == NULL) return FALSE; sn = skill_lookup("demonfire"); if (sn < 0) return FALSE; do_say(ch,"Time to die puny mortal!"); dam = 400 + dice(ch->level,5); if (saves_spell(ch->level,victim,DAM_NEGATIVE)) dam /= 2; damage_old(ch,victim,dam,sn,DAM_NEGATIVE,TRUE); return TRUE; } switch(number_range(0,4)) { case 0: return (spec_necromancer(ch)); break; case 1: return (spec_demonologist(ch)); break; case 2: return (spec_breath_frost(ch)); break; case 3: return (spec_breath_acid(ch)); break; default: return (spec_breath_frost(ch)); break; } return FALSE; } /* For special functions that use area messaging .. Ceran */ bool area_act(CHAR_DATA *ch,char *msg, int min_sect, int max_sect) { CHAR_DATA *ach; CHAR_DATA *ach_next; CHAR_DATA *mob; int count; bool found = FALSE; return FALSE; count = 0; if (!str_cmp(msg,"zombie call")) { for (ach = char_list; ach != NULL; ach = ach_next) { ach_next = ach->next; if (ach->in_room == NULL) continue; if (ach->in_room->area != ch->in_room->area) continue; if (ach == ch || IS_NPC(ach)) continue; if (ach->in_room->sector_type >= min_sect && ach->in_room->sector_type < max_sect) found = TRUE; } if (!found) return FALSE; for (; ;) { count++; for (ach = char_list; ach != NULL; ach = ach_next) { ach_next = ach->next; if (ach->in_room == NULL) continue; if (ach->in_room->area != ch->in_room->area) continue; if (ach == ch || IS_NPC(ach)) continue; if (ach->in_room->sector_type >= min_sect && ach->in_room->sector_type < max_sect && number_bits(2) == 0) break; } if ((ach != NULL) || count >= 20) break; } if (ach == NULL) return FALSE; mob = create_mobile(get_mob_index(29708)); if (mob == NULL) return FALSE; char_to_room(mob,ach->in_room); act("The ground heaves and $n claws it's way out!",mob,0,0,TO_ROOM); multi_hit(mob,ach,TYPE_UNDEFINED); return TRUE; } for (ach = char_list; ach != NULL; ach = ach_next) { ach_next = ach->next; if (ach->in_room == NULL) continue; if (ach->in_room->area != ch->in_room->area) continue; if (ach == ch || IS_NPC(ach)) continue; if (ach->in_room->sector_type >= min_sect && ach->in_room->sector_type < max_sect && IS_AWAKE(ach)) act(msg,ch,0,ach,TO_VICT); } return TRUE; } /* new specials for dragons .. Ceran */ bool spec_wings(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int dam; int sn; sn = skill_lookup("windwall"); if (sn <= 0) return FALSE; act("$n spreads $s wings and beats violently at the air!",ch,0,0,TO_ROOM); dam = dice(ch->level,6); for (victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (is_safe(victim,ch) || (victim == ch) || is_same_group(victim,ch)) continue; damage_old(ch,victim,(saves_spell(ch->level,victim,DAM_OTHER) ? dam/2 : dam),sn, DAM_BASH,TRUE); } return TRUE; } bool spec_red_dragon(CHAR_DATA *ch) { int num; CHAR_DATA *victim; CHAR_DATA *v_next; CHAR_DATA *tmp_vict,*last_vict,*next_vict; bool found; int dam, sn; int level; if (ch->position != POS_FIGHTING) return FALSE; level = ch->level; num = number_range(0,5); sn = skill_lookup("chain lightning"); if (sn <= 0) sn = skill_lookup("lightning bolt"); if (num == 0) { for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim != ch && can_see( ch, victim ) && number_bits( 1 ) == 0 ) break; } if ( victim == NULL ) return FALSE; if (sn <= 0) return FALSE; act("$n raises $s talon and blue lightning streaks forth!", ch,NULL,victim,TO_ROOM); act("A lightning bolt leaps from $n's claw and arcs to $N.", ch,NULL,victim,TO_ROOM); act("A lightning bolt leaps from your claw and arcs to $N.", ch,NULL,victim,TO_CHAR); act("A lightning bolt leaps from $n's claw and hits you!", ch,NULL,victim,TO_VICT); dam = dice(level,6); if (saves_spell(level,victim,DAM_LIGHTNING)) dam /= 2; damage_old(ch,victim,dam,sn,DAM_LIGHTNING,TRUE); last_vict = victim; level -= 3; /* decrement damage */ /* new targets */ while (level > 0) { found = FALSE; for (tmp_vict = ch->in_room->people; tmp_vict != NULL; tmp_vict = next_vict) { next_vict = tmp_vict->next_in_room; if (!is_safe_spell(ch,tmp_vict,TRUE) && tmp_vict != last_vict) { found = TRUE; last_vict = tmp_vict; if (last_vict == ch) { if (number_percent()>=ch->level) { act("The bolt arcs back to $n, and it stabilizes!",tmp_vict,NULL,NULL,TO_ROOM); act("The bolt arcs back to you and you stabilize its energy!",tmp_vict,NULL,NULL,TO_ROOM); level+=7; } else { act("The bolt arcs back to $n!",tmp_vict,NULL,NULL,TO_ROOM); act("The bolt arcs back to you!",tmp_vict,NULL,NULL,TO_ROOM); } } else { act("The bolt arcs to $n!",tmp_vict,NULL,NULL,TO_ROOM); act("The bolt hits you!",tmp_vict,NULL,NULL,TO_CHAR); dam = dice(level,6); if (saves_spell(level,tmp_vict,DAM_LIGHTNING)) dam /= 2; damage_old(ch,tmp_vict,dam,sn,DAM_LIGHTNING,TRUE); level -= 3; /* decrement damage */ } } } /* end target searching loop */ if (!found) /* no target found, hit the caster */ { if (ch == NULL) return TRUE; if (last_vict == ch) /* no double hits */ { act("The bolt fades away in a flickering spark.",ch,NULL,NULL,TO_ROOM); act("The bolt grounds out harmlessly through your body.", ch,NULL,NULL,TO_CHAR); return TRUE; } last_vict = ch; act("The bolt arcs back to $n!",ch,NULL,NULL,TO_ROOM); send_to_char("The bolt arcs harmlessly back to you.\n\r",ch); level -= 4; /* decrement damage */ if (ch == NULL) return TRUE; } } } else if (num == 1 || num == 2 || num == 3) return spec_breath_fire(ch); else if (num == 4) return spec_wings(ch); else return spec_cast_mage(ch); return TRUE; } bool spec_black_dragon(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int sn, dam, num; int sn_p, sn_b, level; if (ch->position != POS_FIGHTING) return FALSE; num = number_range(0,5); level = ch->level; if (num == 0) { sn = skill_lookup("acid breath"); sn_p = skill_lookup("poison"); sn_b = skill_lookup("blindness"); if ((sn <= 0) || (sn_p <= 0) || (sn_b <= 0)) return FALSE; act("$n hisses out a word of draconic power!",ch,NULL,NULL,TO_ROOM); dam = dice(level,5); for (victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (is_safe(victim,ch) || victim == ch) continue; damage_old(ch,victim,saves_spell(level,victim,DAM_ACID) ? dam/2 : dam, sn, DAM_ACID,TRUE); (*skill_table[sn_p].spell_fun) (sn_p,level,ch,victim,TAR_CHAR_OFFENSIVE); (*skill_table[sn_b].spell_fun) (sn_b,level,ch,victim,TAR_CHAR_OFFENSIVE); } return TRUE; } else if (num == 1 || num == 2 || num== 3) return spec_breath_acid(ch); else if (num == 4) return spec_wings(ch); else return spec_cast_mage(ch); return TRUE; } bool spec_gold_dragon(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int sn, dam; int num; if (ch->position != POS_FIGHTING) return FALSE; num = number_range(0,5); if (num == 0) { sn = skill_lookup("concatenate"); if (sn <= 0) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next ) { v_next = victim->next_in_room; if ( victim != ch && can_see( ch, victim ) && number_bits( 1 ) == 0 ) break; } if ( victim == NULL ) return FALSE; act("$n points a talon at $N and unleashes a blast of light!",ch,0,victim,TO_NOTVICT); act("You point a talon at $N and unleash a blast of light!",ch,0,victim,TO_CHAR); act("$n points a talon at you and unleashes a blast of light!",ch,0,victim,TO_VICT); dam = dice(ch->level,13); damage_old(ch,victim,saves_spell(ch->level,victim,DAM_LIGHT) ? dam/2 : dam, sn, DAM_LIGHT,TRUE); return TRUE; } else if (num == 1 || num == 2 || num == 3) return spec_breath_fire(ch); else if (num == 4) return spec_wings(ch); else return spec_cast_cleric(ch); return TRUE; } bool spec_warder(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 65) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; spell = "earthmaw"; switch ( number_range(0,8) ) { case 0: spell = "beast call"; break; case 1: spell = "insectswarm"; break; case 2: spell = "earthmaw"; break; case 3: spell = "icelance"; break; case 4: spell = "breath fire"; break; if (is_affected(victim,gsn_sanctuary) || is_affected(victim,gsn_wraithform) || is_affected(victim,gsn_fireshield)) { case 5: spell = "flamestrike"; break; case 6: spell = "flamestrike"; break; } default: spell = "windwall"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_seneschal(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 65) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; spell = "crushing hand"; switch ( number_range(0,3) ) { case 0: spell = "ball lightning"; break; case 1: spell = "concatenate"; break; case 2: spell = "crushing hand"; break; case 3: spell = "hellfire"; break; case 4: spell = "nova"; break; default: spell = "crushing hand"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_outlaw(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 50) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; switch ( number_range(0,3) ) { case 0: spell = "flamestrike"; break; case 1: spell = "ball lightning"; break; case 2: spell = "crushing hand"; break; case 3: spell = "flamestrike"; break; case 4: spell = "faerie fire"; break; case 5: spell = "faerie fire"; break; default: spell = "weaken"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_blitz(CHAR_DATA *ch) { CHAR_DATA *victim; int chance = 80, imod; bool isDS; if (ch-> position != POS_FIGHTING) return FALSE; if ((victim=ch->in_room->people) != NULL) { if(victim->fighting == ch && victim->cabal != ch->cabal) { chance += ch->carry_weight / 200; chance -= victim->carry_weight / 200; if (ch->size < victim->size) { chance += (ch->size - victim->size) * 5; } else { chance += (ch->size - victim->size) * 5; } if (is_affected(victim,gsn_protective_shield)) { chance -= 5; } if (is_affected(victim,gsn_fireshield)) { chance -= 5; } chance += get_curr_stat(ch,STAT_STR) + 5; chance -= (get_curr_stat(victim,STAT_DEX)); chance -= GET_AC(victim,AC_BASH) /20; if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE)) { chance += 10; } if (is_affected(ch,skill_lookup("bloodthirst"))) { chance += 10; } if (is_affected(ch,skill_lookup("berserk"))) { chance += 10; } if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE)) { chance -= 5; } chance += (ch->level - victim->level); if (!IS_NPC(victim) && chance < get_skill(victim,gsn_dodge) ) { chance -= 3 * (get_skill(victim,gsn_dodge) - chance); } imod = 25; isDS = FALSE; chance += 15; act("$n pummels you to the ground with excruciating force!", ch,NULL,victim,TO_VICT); act("You slam into $N, pummeling $M into the ground!",ch,NULL,victim,TO_CHAR); act("$n pummels $N into the ground with a powerful blitz.",ch,NULL,victim,TO_NOTVICT); damage_old(ch,victim,((3 * ch->size + chance) / 2),gsn_blitz,DAM_BASH,TRUE); WAIT_STATE(victim,PULSE_VIOLENCE*1); WAIT_STATE(ch,2*PULSE_VIOLENCE); if (number_percent() < 40) { if (is_affected(victim,gsn_sanctuary) && (number_percent() < 20)) { if (check_dispel(ch->level-3,victim,skill_lookup("sanctuary"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The white aura about $n vanishes!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } if ((isDS == FALSE) && is_affected(victim,gsn_fireshield) && (number_percent() < 20)) { if (check_dispel(ch->level,victim,skill_lookup("fireshield"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The fire around $n vanishes!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } if ((isDS == FALSE) && is_affected(victim,gsn_stoneskin) && (number_percent() < 20)) { if (check_dispel(ch->level-2,victim,skill_lookup("stone skin"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The skin of $n softens into flesh!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } if ((isDS == FALSE) && is_affected(victim,gsn_wraithform) && (number_percent() < 20)) { if (check_dispel(ch->level-2,victim,skill_lookup("wraithform"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The body of $n fades back into the Prime Material Plane!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } if ((isDS == FALSE) && is_affected(victim,gsn_shroud) && (number_percent() < 20)) { if (check_dispel(ch->level,victim,skill_lookup("shroud"))) { act("$n looks stunned as $s mind wanders from $s spells.",victim,0,0,TO_ROOM); act("Your head throbs with pain as you lose control over your spells.",victim,0,0,TO_CHAR); act("The black aura about $n vanishes!",victim,NULL,NULL,TO_ROOM); isDS = TRUE; } } } } return TRUE; } else return FALSE; } bool spec_destructorcombo(CHAR_DATA *ch) { CHAR_DATA *v_next; CHAR_DATA *victim; int chance; if (ch-> position != POS_FIGHTING) return FALSE; for (victim=ch->in_room->people;victim !=NULL;victim=v_next) { if (victim->fighting==ch && victim->cabal != ch->cabal && victim->in_room==ch->in_room) { act("$n yells and charges towards you, barreling into you with his body!",ch,0,victim,TO_VICT); act("$n yells and charges towards $N, barreling into him with his body!",ch,0,victim,TO_NOTVICT); damage_new(ch,victim,number_range(40,60),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"charge"); chance = number_percent(); if (chance < 20) { act("You manage to hold your ground despite $n's powerful bash.",ch,0,victim,TO_VICT); act("$N manages to hold his ground despite $n's powerful bash.",ch,0,victim,TO_NOTVICT); WAIT_STATE(victim,1); } else if (chance >= 20 && victim->in_room==ch->in_room) { act("Momentarily stunned from the blow, you hunch over only to meet $n's kick with your head!",ch,0,victim,TO_VICT); act("Momentarily stunned from the blow, $N hunches over only to meet $n's kick with his head!",ch,0,victim,TO_NOTVICT); damage_new(ch,victim,number_range(45,65),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"kick"); if (chance < 45) { act("You fall to the ground in agony, but manage to pick yourself up again before sustaining further damage.",ch,0,victim,TO_VICT); act("$N falls to the ground in agony, but manage to pick himself up again before sustaining further damage.",ch,0,victim,TO_NOTVICT); WAIT_STATE(victim,2); } else if (chance >= 45 && victim->in_room==ch->in_room) { act("Dazed, you faintly feel your body being picked up off the ground and hurled across the room!",ch,0,victim,TO_VICT); act("$n hurls $N across the room mercilessly!",ch,0,victim,TO_NOTVICT); damage_new(ch,victim,number_range(50,75),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"throw"); if (chance < 65) { act("Recovering, you land solidly on your feet, regaining your equilibrium.",ch,0,victim,TO_VICT); act("$N lands solidly on his feet, regaining his equilibrium.",ch,0,victim,TO_NOTVICT); WAIT_STATE(victim,3); } else if (chance >= 65 && victim->in_room==ch->in_room) { act("As you lie on the ground in pain, $n leaps on top of you, crushing you with his weight!",ch,0,victim,TO_VICT); act("As $N lies on the ground in pain, $n leaps on top of him, crushing him with his weight!",ch,0,victim,TO_NOTVICT); damage_new(ch,victim,number_range(60,85),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"crush"); if (chance < 85) { act("You manage to shove $n off of you and regain your balance.",ch,0,victim,TO_VICT); act("$N manages to shove $n off of him and regain his balance.",ch,0,victim,TO_NOTVICT); WAIT_STATE(victim,4); } else if (chance >= 85 && victim->in_room==ch->in_room) { act("Seizing the opportunity, $n kicks you while you are down!",ch,0,victim, TO_VICT); act("Seizing the opportunity, $n kicks $N while he is down!",ch,0,victim, TO_NOTVICT); damage_new(ch,victim,number_range(65,90),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"cheap shot"); if (chance < 95) { act("Wincing in pain, you manage to roll away from $n and pick yourself up.",ch,0,victim,TO_VICT); act("$N manages to roll away from $n and pick himself up.",ch,0,victim,TO_NOTVICT); WAIT_STATE(victim,5); } else if (chance >= 95 && victim->in_room==ch->in_room) { act("$n pummels you into the ground with a series of deadly attacks!",ch,0,victim,TO_VICT); act("$n pummels $N into the ground with a series of deadly attacks!",ch,0,victim,TO_VICT); damage_new(ch,victim,number_range(70,95),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"pummeling blow"); damage_new(ch,victim,number_range(70,95),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"pummeling blow"); damage_new(ch,victim,number_range(70,95),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"pummeling blow"); WAIT_STATE(victim,6); } } } } } } break; } return TRUE; } bool spec_destructorrage(CHAR_DATA *ch) { CHAR_DATA *v_next; CHAR_DATA *victim; if (ch-> position != POS_FIGHTING) return FALSE; for (victim=ch->in_room->people;victim !=NULL; victim=v_next) { if(ch->cabal==victim->cabal || IS_IMMORTAL(victim)) { v_next = victim->next_in_room; } else { act("$n lets out a wild warcry and begins attacking you in a berserker rage!",ch,0,victim,TO_VICT); act("$n lets out a wild warcry and begins attacking $N in a berserker rage!",ch,0,victim,TO_NOTVICT); damage_new(ch,victim,number_range(60,70),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"berserker fury"); if(victim->in_room==ch->in_room) damage_new(ch,victim,number_range(60,70),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"berserker fury"); if (number_percent() < 60) { act("You find a moment of weakness in $n's furious assault!",ch,0,victim,TO_VICT); act("$N finds a moment of weakness in $n's furious assault!",ch,0,victim,TO_NOTVICT); damage_new(victim,ch,number_range(100,120),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"reprisal"); } v_next = victim->next_in_room; } continue; } return TRUE; } bool spec_flurry(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int numhits; int i; numhits=number_range(4,9); for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if (ch->position != POS_FIGHTING || victim == NULL) return FALSE; if (number_percent() > 30) return TRUE; act("$n begins a wild flurry of attacks!",ch,0,0,TO_ROOM); for ( i=0; i< numhits; i++ ) { if (number_percent() > 80) { damage( ch, victim, 0, gsn_flurry, DAM_NONE,TRUE); continue; } one_hit_new(ch,victim,gsn_flurry,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,NULL); } WAIT_STATE(ch,PULSE_VIOLENCE*3); return TRUE; } bool spec_pincer(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int numhits; int i; numhits=number_range(2,2); for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if (ch->position != POS_FIGHTING || victim == NULL) return FALSE; if (number_percent() > 30) return TRUE; act("$n pincers $s between his axes!",ch,0,0,TO_ROOM); for ( i=0; i< numhits; i++ ) { if (number_percent() > 80) { damage( ch, victim, 0, gsn_pincer, DAM_NONE,TRUE); continue; } one_hit_new(ch,victim,gsn_pincer,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,NULL); } WAIT_STATE(ch,PULSE_VIOLENCE*1); return TRUE; } bool spec_drum(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; int numhits; int i; numhits=number_range(3,6); for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if (ch->position != POS_FIGHTING || victim == NULL) return FALSE; if (number_percent() > 30) return TRUE; act("$n drums at $N with $s maces.",ch,0,victim,TO_NOTVICT); act("$n drums at you with $s maces.",ch,0,victim,TO_VICT); for ( i=0; i < numhits; i++ ) { if (number_percent() > 95) { damage( ch, victim, 0, gsn_drum,DAM_NONE,TRUE); continue; } one_hit_new(ch,victim,gsn_drum,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,NULL); } one_hit_new(ch,victim,gsn_pincer,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,150,NULL); WAIT_STATE(ch,3*PULSE_VIOLENCE); return TRUE; } bool spec_ishmael(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; CHAR_DATA *phantasmal; bool phantasmals_in_room; phantasmals_in_room=FALSE; if(ch->fighting==NULL) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { if(victim!=NULL && IS_NPC(victim) && victim->pIndexData->vnum==2926) { phantasmals_in_room=TRUE; break; } v_next = victim->next_in_room; } if(!phantasmals_in_room) { act("$n grins evilly before raising his hands and speaking a word of unholy power.",ch,0,0,TO_ROOM); for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { if(victim!=NULL && !IS_NPC(victim)) { phantasmal = create_mobile(get_mob_index(2926)); char_to_room(phantasmal,victim->in_room); phantasmal->max_hit=number_range(3500,(50-get_curr_stat(victim,STAT_INT))*100); phantasmal->hit=phantasmal->max_hit; act("$n's worst nightmare steps from the shadows to confront $m.",victim,0,0,TO_ROOM); send_to_char("Your worst nightmare steps from the shadows to confront you.\n\r",victim); multi_hit(phantasmal,victim,TYPE_UNDEFINED); } v_next = victim->next_in_room; } } return TRUE; } bool spec_agamemnon(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; AFFECT_DATA af; if(number_percent()==1) do_zecho(ch,"You hear a horrible scuttling sound of something crawling."); for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if (ch->position != POS_FIGHTING || victim == NULL) return FALSE; if (number_percent() > 65) return TRUE; if (number_percent() < 60) { act("$n brings its appendages around in a deadly assault, pincering $N between its claws!",ch,0,victim,TO_NOTVICT); act("$n brings its appendages around in a deadly assault, pincering you between its claws!",ch,0,victim,TO_VICT); damage_new(ch,victim,number_range(120,170),TYPE_UNDEFINED,DAM_TRUESTRIKE,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"left pincer"); damage_new(ch,victim,number_range(190,210),TYPE_UNDEFINED,DAM_TRUESTRIKE,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"right pincer"); WAIT_STATE(victim,PULSE_VIOLENCE*2); return TRUE; } if(number_percent()>85) { act("$n attempts to disembowel $N with a slashing pincer, but $E evades it!",ch,0,victim,TO_NOTVICT); act("$n attempts to disembowel you with a slashing pincer, but you evade it!",ch,0,victim,TO_VICT); damage_new(ch,victim,0,TYPE_UNDEFINED,DAM_SLASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"disembowelment"); return TRUE; } act("$n disembowels $N with a sharp pincer, as blood begins to gush from $S wound!",ch,0,victim,TO_NOTVICT); act("$n disembowels you with a sharp pincer, as blood begins to gush from your wound!",ch,0,victim,TO_VICT); damage_new(ch,victim,number_range(150,240),TYPE_UNDEFINED,DAM_TRUESTRIKE,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"disembowelment"); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = gsn_impale; af.level = ch->level; af.duration = 7; af.bitvector = 0; af.location = APPLY_DEX; af.modifier = -4; affect_to_char(victim,&af); af.location = APPLY_STR; af.bitvector = 0; affect_to_char(victim,&af); return TRUE; } bool spec_meph(CHAR_DATA *ch) { CHAR_DATA *victim=ch->fighting; CHAR_DATA *rmfire; char *spell; int sn; AFFECT_DATA af; if(!victim) return FALSE; for(rmfire=ch->in_room->people; rmfire!=NULL; rmfire=rmfire->next_in_room) { if(is_affected(rmfire,gsn_fireshield)) affect_strip(rmfire,gsn_fireshield); if(is_affected(rmfire,gsn_shield_of_flames)) affect_strip(rmfire,gsn_shield_of_flames); } switch(number_range(0,6)) { case 0: spell = "nova"; break; case 1: act("$n raises $s hands and fire envelops the room!",ch,0,0,TO_ALL); spell = "fireball"; break; case 2: act("$n draws upon the heat of the room and a towering vortex of flame forms!",ch,0,0,TO_ROOM); do_say(ch,"Burn!"); spell = "spire of flames"; break; case 3: case 4: case 5: act("$N throws back his head and cackles as a pillar of flame consumes $n!",victim,0,ch,TO_ROOM); act("$n throws back his head and cackles as a pillar of flame consumes you!",ch,0,victim,TO_VICT); damage_new(ch, victim, number_range(200,300), TYPE_UNDEFINED, DAM_FIRE, TRUE, HIT_UNBLOCKABLE, HIT_NOADD, HIT_NOMULT, "flames of the apocalypse"); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_MALADY; af.type = gsn_incinerate; af.location = APPLY_STR; af.modifier = -5; af.duration = 3; af.level = ch->level; af.bitvector = 0; affect_to_char(victim,&af); return FALSE; default: spell = "nova"; break; } if ((sn=skill_lookup(spell))<0) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, (int)NULL); return TRUE; } bool spec_baalzebub(CHAR_DATA *ch) { CHAR_DATA *victim, *v_next; AFFECT_DATA af; int skill=0; if (number_percent() > 85) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if (IS_AFFECTED(victim, AFF_BLIND)) continue; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; skill = number_range(0,1); if (skill == 0) { act("$n attempts to gouge at your eye.",ch,NULL,victim,TO_VICT); act("$n attempts to gouge at $N's eye.",ch,NULL,victim,TO_NOTVICT); act("You are blinded.",ch,NULL,victim,TO_VICT); act("$N appears to be blinded.",ch,NULL,victim,TO_NOTVICT); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_MALADY; af.duration = ch->level/25; af.bitvector = AFF_BLIND; af.type = gsn_gouge; af.level = ch->level; af.location = APPLY_HITROLL; af.modifier = -5; affect_to_char(victim,&af); check_improve(ch,gsn_gouge,TRUE,1); one_hit_new(ch,victim,gsn_gouge,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,120,"eye gouge"); } else { act("$n unleashes with a viscious stab.",ch,NULL,victim,TO_VICT); act("$n unleashes with a viscious stab on $N.",ch,NULL,victim,TO_NOTVICT); one_hit_new(ch,victim,gsn_stab,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,200,"vicious stabbing"); } return TRUE; } bool spec_necruvian(CHAR_DATA *ch) { CHAR_DATA *victim, *v_next; char *spell; int sn; if(number_percent()==1) { if(number_percent()>50) do_yell(ch,"Make sure their corpses are properly embalmed before bringing them to me this time, hmm?"); else do_yell(ch,"Ah, more corpses to serve me! Splendid."); } if (number_percent() > 65) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; switch ( number_range(0,5) ) { case 0: spell = "nova"; break; case 1: spell = "windwall"; break; case 2: spell = "concatenate"; break; case 3: spell = "hellfire"; break; case 4: spell = "slow"; break; case 5: spell = "haunting"; break; default: spell = "haunting"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level+1, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_obsidian_prince(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; if(ch->fighting==NULL) return FALSE; obsidian_prince_timer--; if(obsidian_prince_timer==45) { act("{RThe Obsidian Prince raises his eyes to the skies, as the crimson clouds loom ominously.{x",ch,0,0,TO_ROOM); do_say(ch,"The time of my ascension approaches!"); return TRUE; } if(obsidian_prince_timer==25) { act("{RThe Obsidian Prince raises his hand in the air, and a ball of black light forms, growing ever larger.{x",ch,0,0,TO_ROOM); do_say(ch,"I will consume your soul!"); return TRUE; } if(obsidian_prince_timer==10) { act("{RThe ball of black light seems to fold in upon itself, forming some sort of portal.{x",ch,0,0,TO_ALL); return TRUE; } if(obsidian_prince_timer==1) { do_say(ch,"I reign victorious!"); act("The portal opens and a hulking greater ice devil steps out, chittering viciously to itself.",ch,0,0,TO_ALL); act("Regarding you disdainfully, the devil kneels before the Obsidian Prince.",ch,0,0,TO_ALL); act("The Obsidian Prince smirks and says '{YKill them all.{x'",ch,0,0,TO_ALL); for(victim = ch->in_room->people; victim!=NULL; victim=v_next) { v_next=victim->next_in_room; if(IS_NPC(victim) && victim->pIndexData->vnum==ch->pIndexData->vnum) continue; if(IS_IMMORTAL(victim) && !can_see(ch,victim)) act("The devil gestures at $n, uttering a word of power.",victim,0,0,TO_NOTVICT); send_to_char("The devil gestures at you, uttering a word of power.\n\r",victim); act("$n gets a horrible expression on his face and falls over, dead.",victim,0,0,TO_NOTVICT); send_to_char("You feel your mind begin to disintegrate under the torments of Hell.\n\r",victim); raw_kill(ch,victim); } obsidian_prince_timer=50; return TRUE; } if(number_percent()>92) { do_say(ch,"My vengeance is inexorable!"); return TRUE; } else if(number_percent()>94) { do_say(ch,"Suffer!"); return TRUE; } return FALSE; } bool spec_golden_knight(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; AFFECT_DATA af; char *spell; int sn; int numhits; int i; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; if(number_percent()>50) { /*Do a skill*/ switch(number_range(0,2)) { case 0: if(is_affected(ch,gsn_trophy)) return FALSE; numhits=number_range(3,7); act("$n begins a wild flurry of attacks!",ch,0,0,TO_ROOM); for ( i=0; i< numhits; i++ ) { if (number_percent() > 80) { damage( ch, victim, 0, gsn_flurry, DAM_NONE,TRUE); continue; } one_hit(ch,victim,gsn_flurry); } init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SPELL; af.type = gsn_trophy; /* Nobody likes mobs that flurry every round! */ af.modifier = 0; af.bitvector = 0; af.level = 0; af.duration = 0; af.location = 0; affect_to_char(ch,&af); return TRUE; break; case 1: act("$n jabs viciously at you with his sword!",ch,0,victim,TO_VICT); act("$n jabs viciously at $N with his sword!",ch,0,victim,TO_NOTVICT); if(number_percent()>90) { damage(ch,victim,0,gsn_dragonsword,DAM_LIGHT,TRUE); } /* We're using gsn_dragonsword as a placeholder for the 'jab' dam message. */ else { damage(ch,victim,80+(number_percent()*2),gsn_dragonsword,DAM_LIGHT,TRUE); } return TRUE; break; default: act("$n brings both his swords together into your body in an attempt to doublethrust you!",ch,0,victim,TO_VICT); act("$n brings both his swords together into $N's body in an attempt to doublethrust $M!",ch,0,victim,TO_NOTVICT); if(number_percent()>90) { damage(ch,victim,0,gsn_honorable_combat,DAM_LIGHT,TRUE); } /* We're using gsn_honorable as a placeholder for the 'doublethrust' dam message. */ else { damage(ch,victim,50+(number_percent()*2),gsn_honorable_combat,DAM_LIGHT,TRUE); damage(ch,victim,50+(number_percent()*2),gsn_honorable_combat,DAM_LIGHT,TRUE); } return TRUE; break; } } else { switch(number_range(0,4)) { case 0: spell = "crushing hand"; break; case 1: spell = "crushing hand"; break; case 2: spell = "ray of truth"; break; case 3: spell = "wrath"; break; default: return TRUE; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } } bool spec_templar(CHAR_DATA *ch) { CHAR_DATA *victim, *v_next; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; switch(number_range(0,8)) { case 0: do_trip(ch,""); return TRUE; case 1: do_bash(ch,""); return TRUE; case 2: return TRUE; case 3: return TRUE; case 4: return TRUE; case 5: return TRUE; case 6: return TRUE; case 7: return TRUE; case 8: return TRUE; } return FALSE; } bool spec_goodie(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if (ch->position != POS_FIGHTING || victim == NULL) return FALSE; if (victim->alignment == 1000) { act("$n sighs softly and calls the wrath of an Immortal onto $N.",ch,0,victim,TO_NOTVICT); act("$n sighs softly and calls the wrath of an Immortal onto you.",ch,0,victim,TO_VICT); raw_kill(ch,victim); } return TRUE; } bool spec_lothar(CHAR_DATA *ch) { spec_goodie(ch); spec_flurry(ch); return TRUE; } bool spec_cire(CHAR_DATA *ch) { spec_goodie(ch); spec_drum(ch); return TRUE; } bool spec_sage(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 65) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; spell = "divine aid"; switch ( number_range(0,8) ) { case 0: spell = "divine aid"; break; case 1: spell = "incinerate"; break; case 2: spell = "ray of truth"; break; case 3: spell = "rot"; break; case 4: spell = "mental knife"; break; case 5: spell = "mental knife"; break; if (is_affected(victim,gsn_sanctuary) || is_affected(victim,gsn_wraithform) || is_affected(victim,gsn_fireshield)) { case 6: spell = "dispel magic"; break; case 7: spell = "dispel magic"; break; } default: spell = "divine aid"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_familiar(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 65) return FALSE; if (is_affected(ch, AFF_CHARM)) return TRUE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; spell = "mental knife"; switch ( number_range(0,8) ) { case 0: spell = "mental knife"; break; case 1: spell = "acid blast"; break; case 2: spell = "concatenate"; break; case 3: spell = "firestream"; break; if (is_affected(victim,gsn_sanctuary) || is_affected(victim,gsn_wraithform) || is_affected(victim,gsn_fireshield)) { case 4: spell = "dispel magic"; break; case 5: spell = "dispel magic"; break; } default: spell = "mental knife"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_omegus(CHAR_DATA *ch) { CHAR_DATA *victim, *v_next; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; switch(number_range(0,4)) { case 0: do_trip(ch,""); return TRUE; case 1: do_shove(ch,victim->name); return TRUE; case 2: do_dirt(ch,""); return TRUE; case 3: spec_flurry(ch); return TRUE; case 4: spec_drum(ch); return TRUE; } return FALSE; } bool spec_stalker(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 65) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; spell = "crushing hand"; switch ( number_range(0,3) ) { case 0: spell = "crushing hand"; break; case 1: spell = "windwall"; break; case 2: spell = "flamestrike"; break; default: spell = "crushing hand"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_phantom(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 65) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; spell = "plague"; switch ( number_range(0,2) ) { case 0: spell = "slow"; break; case 1: spell = "weaken"; break; default: spell = "slow"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_grand_assassin(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 65) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; spell = "energy drain"; switch ( number_range(0,2) ) { case 0: spell = "hellfire"; break; case 1: spell = "energy drain"; break; case 2: spell = "haunting"; break; default: spell = "energy drain"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_cast_cold(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 50) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; switch ( number_range(0,4) ) { case 0: spell = "icelance"; break; case 1: spell = "iceball"; break; case 2: spell = "icy shards"; break; case 3: spell = "cone of cold"; break; case 4: spell = "chill touch"; break; default: spell = "icelance"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_elthian(CHAR_DATA *ch) { CHAR_DATA *victim; CHAR_DATA *v_next; char *spell; int sn; if (number_percent() > 50) return FALSE; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; switch ( number_range(0,8) ) { case 0: spell = "scourge"; break; case 1: spell = "nova"; break; case 2: spell = "nova"; break; case 3: spell = "crushing hand"; break; case 4: spell = "scourge"; break; case 5: spell = "concatenate"; break; case 6: spell = "nova"; break; case 7: spell = "colour spray"; break; case 8: spell = "earthmaw"; break; default: spell = "nova"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; if(number_percent()==1) do_myell(ch,"It'll all end in tragedy!"); (*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim, TAR_CHAR_OFFENSIVE ); return TRUE; } bool spec_tara(CHAR_DATA *ch) { if(number_percent()==1) do_yell(ch,"With the power of Infinity I will destroy you, Obsidian Prince!"); return spec_flurry(ch); } bool spec_destructor(CHAR_DATA *ch) { CHAR_DATA *victim, *v_next; if ( ch->position != POS_FIGHTING ) return FALSE; for ( victim = ch->in_room->people; victim != NULL; victim = v_next) { v_next = victim->next_in_room; if(victim->fighting==ch) { break; } } if ( victim == NULL ) return FALSE; switch(number_range(0,2)) { case 0: { if (number_percent() < 60) spec_blitz(ch); return TRUE; } case 1: { if (number_percent() < 60) spec_destructorcombo(ch); return TRUE; } case 2: { if (number_percent() < 85) spec_destructorrage(ch); return TRUE; } } return FALSE; } bool spec_bounty_hunter(CHAR_DATA *ch) { CHAR_DATA *vch; if(!ch->fighting) return FALSE; if(number_percent()<7) for(vch=ch->in_room->people;vch!=NULL;vch=vch->next_in_room) { if(IS_NPC(vch) || vch->pcdata->bounty>=500 || !vch->fighting || vch->fighting!=ch) continue; act("$n places a bounty of 500 gold on the head of $N!",ch,0,vch,TO_NOTVICT); act("$n places a bounty of 500 gold on your head!",ch,0,vch,TO_VICT); vch->pcdata->bounty=500; break; } if(number_percent()<30) return spec_drum(ch); if(number_percent()<30) return spec_flurry(ch); return TRUE; } bool spec_spitting_snake(CHAR_DATA *ch) { CHAR_DATA *victim = ch->fighting; if (victim != NULL && number_percent() > 60) { act("$n hisses loudly towards $N!",ch,0,victim,TO_ROOM); (*skill_table[skill_lookup("acid spit")].spell_fun) (skill_lookup("acid spit"), 55, ch, victim, TAR_CHAR_OFFENSIVE); return TRUE; } else return FALSE; } bool spec_cockatrice(CHAR_DATA *ch) { CHAR_DATA *victim = ch->fighting; AFFECT_DATA af; if (victim != NULL && number_percent() < 25) { act("$n petrifies you with its piercing gaze!",ch,0,victim,TO_VICT); act("$n petrifies $N with its piercing gaze!",ch,0,victim,TO_NOTVICT); act("You petrify $N with your piercing gaze!",ch,0,victim,TO_CHAR); init_affect(&af); af.duration = 0; af.aftype = AFT_MALADY; af.level = ch->level; af.type = gsn_hold_person; af.name = str_dup("petrification"); af.location = 0; af.bitvector = 0; affect_to_char(victim,&af); return TRUE; } else return FALSE; } bool spec_healer_mercenary(CHAR_DATA *ch) { CHAR_DATA *master = ch->master, *mob; int sn; char *spell; mob=ch; if(!master || master->in_room!=mob->in_room) return FALSE; if(number_percent()>38) { switch(number_range(0,4)) { case 0: if(!IS_AFFECTED(master,AFF_FLYING)) { spell = "fly"; break; } case 1: spell = "heal"; break; case 2: if(IS_AFFECTED(master,AFF_BLIND)) { spell = "cure blindness"; break; } case 3: if(!is_affected(master,skill_lookup("bless"))) { spell = "bless"; break; } default: spell = "cure critical"; break; } if ( ( sn = skill_lookup( spell ) ) < 0 ) return FALSE; if((!str_cmp(spell,"heal") || !str_cmp(spell,"cure critical")) && master->hit>(master->max_hit*.60)) return FALSE; if(IS_IMMORTAL(master)) { send_to_char("(",master); send_to_char(capitalize(spell),master); send_to_char(") ",master); } act("$n closes $s eyes for a moment and nods at $N.",mob,0,master,TO_NOTVICT); act("$n closes $s eyes for a moment and nods at you.",mob,0,master,TO_VICT); (*skill_table[sn].spell_fun) ( sn, mob->level, mob, master, TAR_CHAR_DEFENSIVE); return TRUE; } return FALSE; } bool spec_practice_dummy (CHAR_DATA *ch) { if (ch->hit < ch->max_hit) { ch->hit = ch->max_hit; return TRUE; } else return FALSE; } bool spec_elemental(CHAR_DATA *ch) { int spell_num=0; CHAR_DATA *victim = ch->fighting; if (victim == NULL) return FALSE; if (number_percent() > 65) return FALSE; switch(ch->pIndexData->vnum) { // Fire case 2902: spell_num = skill_lookup("fireball"); break; // Water case 2903: spell_num = skill_lookup("hydrolic ram"); break; // Air case 2904: spell_num = skill_lookup("windwall"); break; // Earth case 2905: spell_num = skill_lookup("earthmaw"); break; default: return FALSE; break; } if (spell_num == 0) return FALSE; (*skill_table[spell_num].spell_fun) (spell_num, ch->level, ch, victim, TAR_CHAR_OFFENSIVE); return FALSE; } bool spec_ranger(CHAR_DATA *ch) { CHAR_DATA *victim = ch->fighting; OBJ_DATA *wield; int action=0; if (!victim) return FALSE; if (number_percent() > 20) return FALSE; action = number_range(0, 2); switch(action) { case 0: wield = get_eq_char(ch,WEAR_WIELD); if (wield == NULL) return FALSE; if (wield->value[0] == WEAPON_STAFF) one_hit_new(ch,victim,gsn_pugil,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,120,"pugil"); else { damage_new(ch,victim,number_range(40,80),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"bearcharge"); ADD_WAIT_STATE(victim,PULSE_VIOLENCE*2); } break; case 1: damage_new(ch,victim,number_range(80,100),TYPE_UNDEFINED,DAM_BASH,TRUE,HIT_UNBLOCKABLE,HIT_NOADD,HIT_NOMULT,"serpent strike"); break; case 2: ch->hit = UMIN( ch->hit + 300, ch->max_hit ); act("$n applies herbs to $mself.",ch,0,0,TO_ROOM); break; default: return FALSE; } return TRUE; } bool spec_master_warrior(CHAR_DATA *ch) { CHAR_DATA *victim=ch->fighting, *group; int action=0, s=0; AFFECT_DATA af; if (!victim) return FALSE; action = number_range(0,5); switch(action) { case 0: init_affect(&af); af.where = TO_AFFECTS; af.type = gsn_feint; af.aftype = AFT_SKILL; af.location = 0; af.duration = 1; af.bitvector = 0; af.level = ch->level; af.strippable = FALSE; affect_to_char(ch, &af); break; case 1: one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,125,"crushing assault"); WAIT_STATE(victim, PULSE_VIOLENCE*2); break; case 2: one_hit_new(ch,victim,TYPE_UNDEFINED,HIT_NOSPECIALS,HIT_UNBLOCKABLE,HIT_NOADD,250,"jaw smash"); break; case 3: for (group=char_list; group!=NULL; group=group->next) { if (is_same_group(group,victim) && !IS_NPC(group)) { stop_fighting(ch, FALSE); stop_fighting(group, FALSE); set_fighting(group, victim); break; } } if (!group) return FALSE; act("$n starts aiming at you!", ch, 0, group, TO_VICT); act("$n starts aiming at $N.", ch, 0, group, TO_NOTVICT); break; case 4: if (is_affected(ch, gsn_berserk)) return spec_master_warrior(ch); act("$n lets out a savage battle cry!", ch, 0, 0, TO_ALL); init_affect(&af); af.where = TO_AFFECTS; af.aftype = AFT_SKILL; af.type = gsn_berserk; af.duration = 12; af.modifier = 20; af.level = ch->level; af.bitvector = 0; af.location = APPLY_HITROLL; affect_to_char(ch, &af); af.location = APPLY_DAMROLL; affect_to_char(ch, &af); break; case 5: s = number_range(0,5); switch(s) { case 0: do_say(ch, "You don't have the skill to defeat me."); break; case 1: do_say(ch, "Your form is pathetic."); break; case 2: do_say(ch, "I outmatch you by tenfold."); break; case 3: do_say(ch, "I'm going to enjoy full looting you, weakling."); break; case 4: do_say(ch, "I'm overpowered."); break; default: return FALSE; } break; default: return FALSE; } return TRUE; } bool spec_marshall(CHAR_DATA *ch) { char buf[MSL]; int sn_hand, number; CHAR_DATA *vch, *vch_next; if (ch->fighting == NULL) return FALSE; for (; ;) { for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (vch->fighting == ch && number_bits(2) == 0) break; } if (vch != NULL) break; } number = number_percent(); if (number < 5) { do_say(ch,"You are breaking the Law! Leave now or be punished!"); return TRUE; } else if (number < 10 && number_bits(2) == 0) { sprintf(buf,"%s, you must pay for your crimes!",vch->original_name); do_say(ch,buf); do_wanted(ch,vch->name); } if (IS_SET(vch->act,PLR_CRIMINAL)) { sn_hand = skill_lookup("hand of vengeance"); act("$n points at $N and says, 'Defend the Protectorate!'",ch,0,vch,TO_NOTVICT); act("$n points at you and says, 'Defend the Protectorate!",ch,0,vch,TO_VICT); (*skill_table[sn_hand].spell_fun) (sn_hand,ch->level,ch,vch,TARGET_CHAR); return TRUE; } return spec_drum(ch); }