/***************************************************************************
* 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);
}