/**************************************************************************/
// special.cpp - mob special functions
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with all the licenses *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
***************************************************************************
* >> Original Diku Mud copyright (c)1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, & Katja Nyboe. *
* >> Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* >> ROM 2.4 is copyright 1993-1995 Russ Taylor and 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) *
* >> Oblivion 1.2 is copyright 1996 Wes Wagner *
**************************************************************************/
#include "include.h" // dawn standard includes
#include "magic.h"
void do_unlock( char_data *ch, char *argument );
void do_lock( char_data *ch, char *argument );
void do_order( char_data *ch, char *argument );
void do_pkill( char_data *ch, char *argument );
void say_spell( char_data *ch, int sn, CLASS_CAST_TYPE type );
// these really only relate to rom based area files
#define MOB_VNUM_PATROLMAN 2106
#define GROUP_VNUM_TROLLS 2100
#define GROUP_VNUM_OGRES 2101
/* direction command procedures needed */
DECLARE_DO_FUN(do_north );
DECLARE_DO_FUN(do_south );
DECLARE_DO_FUN(do_west );
DECLARE_DO_FUN(do_east );
/* other command procedures needed */
DECLARE_DO_FUN(do_pbackstab );
DECLARE_DO_FUN(do_close );
DECLARE_DO_FUN(do_flee );
DECLARE_DO_FUN(do_kill );
DECLARE_DO_FUN(do_open );
DECLARE_DO_FUN(do_say );
DECLARE_DO_FUN(do_sleep );
DECLARE_DO_FUN(do_wake );
DECLARE_DO_FUN(do_yell );
// The following special functions are available for MOBS
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_breath_steam );
DECLARE_SPEC_FUN( spec_cast_adept );
DECLARE_SPEC_FUN( spec_cast_cleric );
DECLARE_SPEC_FUN( spec_cast_druid );
DECLARE_SPEC_FUN( spec_cast_mage );
DECLARE_SPEC_FUN( spec_cast_undead );
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_gold_dragon );
DECLARE_SPEC_FUN( spec_red_drac );
DECLARE_SPEC_FUN( spec_fearful );
DECLARE_SPEC_FUN( spec_lava_monster );
DECLARE_SPEC_FUN( spec_assassin );
DECLARE_SPEC_FUN( spec_beggar );
DECLARE_SPEC_FUN( spec_summoned_guardian );
DECLARE_SPEC_FUN( spec_elf_muncher );
DECLARE_SPEC_FUN( spec_shadow_dragon );
DECLARE_SPEC_FUN( spec_steel_dragon );
DECLARE_SPEC_FUN( spec_cast_mean );
DECLARE_SPEC_FUN( spec_cast_meaner );
//DECLARE_SPEC_FUN( spec_charmer );
DECLARE_SPEC_FUN( spec_master_thief );
DECLARE_SPEC_FUN( spec_questmaster );
DECLARE_SPEC_FUN( spec_troll_member );
DECLARE_SPEC_FUN( spec_ogre_member );
DECLARE_SPEC_FUN( spec_clan_transport );
DECLARE_SPEC_FUN( spec_oracle );
DECLARE_SPEC_FUN( spec_chicken );
//DECLARE_SPEC_FUN( spec_hound );
// The following special functions are available for OBJS
DECLARE_OSPEC_FUN( spec_obj_test );
// Special Functions Table -- MOBS
const struct spec_type spec_table [ ] =
{
// Special function commands.
{ "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_breath_steam", spec_breath_steam },
{ "spec_cast_adept", spec_cast_adept },
{ "spec_cast_cleric", spec_cast_cleric },
{ "spec_cast_druid", spec_cast_druid },
{ "spec_cast_mage", spec_cast_mage },
{ "spec_cast_undead", spec_cast_undead },
{ "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_gold_dragon", spec_gold_dragon },
{ "spec_red_drac", spec_red_drac },
{ "spec_fearful", spec_fearful },
{ "spec_lava_monster", spec_lava_monster },
{ "spec_assassin", spec_assassin },
{ "spec_beggar", spec_beggar },
{ "spec_summoned_guardian", spec_summoned_guardian },
{ "spec_elf_muncher", spec_elf_muncher },
{ "spec_shadow_dragon", spec_shadow_dragon },
{ "spec_steel_dragon", spec_steel_dragon },
// { "spec_charmer", spec_charmer },
{ "spec_master_thief", spec_master_thief },
{ "spec_cast_mean", spec_cast_mean },
{ "spec_cast_meaner", spec_cast_meaner },
{ "spec_questmaster", spec_questmaster },
{ "spec_troll_member", spec_troll_member },
{ "spec_ogre_member", spec_ogre_member },
{ "spec_clan_transport", spec_clan_transport },
{ "spec_oracle", spec_oracle },
{ "spec_chicken", spec_chicken },
// { "spec_hound", spec_hound },
{ "", 0 }
};
// Special Functions Table -- OBJS
const struct ospec_type ospec_table[] =
{
{ "spec_obj_test", spec_obj_test },
{ NULL, NULL }
};
/*****************************************************************************
Name: ospec_lookup
Purpose: Given a name, return the appropriate object spec fun.
****************************************************************************/
OSPEC_FUN *ospec_lookup( const char *name )
{
int i;
for ( i = 0; ospec_table[i].ospec_name != NULL; i++)
{
if (LOWER(name[0]) == LOWER(ospec_table[i].ospec_name[0])
&& !str_prefix( name,ospec_table[i].ospec_name))
return ospec_table[i].ospec_fun;
}
return 0;
}
/*****************************************************************************
Name: spec_lookup
Purpose: Given a name, return the appropriate mobile spec fun.
Called by: do_mset(act_wiz.c) load_specials,reset_area(db.c)
****************************************************************************/
SPEC_FUN *spec_lookup( const char *name ) // OLC
{
int cmd;
char buf[MSL], bufmatch[MSL];
sprintf(buf, name);
buf[5]='\0';
if (!str_cmp( buf, "spec_"))
{
sprintf(bufmatch, name);
}
else
{
sprintf(bufmatch,"spec_%s", name);
}
for ( cmd = 0; !IS_NULLSTR(spec_table[cmd].spec_name); cmd++ )
if ( !str_prefix( bufmatch, spec_table[cmd].spec_name ) )
return spec_table[cmd].spec_fun;
return NULL;
}
/*****************************************************************************
Name: spec_string
Purpose: Given a function, return the appropriate name.
Called by: <???>
****************************************************************************/
char *spec_string( SPEC_FUN *fun ) /* OLC */
{
int cmd;
for ( cmd = 0; spec_table[cmd].spec_fun; cmd++ )
if ( fun == spec_table[cmd].spec_fun )
return spec_table[cmd].spec_name;
return 0;
}
/***************************************************************************/
/*modified for OLC */
char *spec_name( SPEC_FUN *function)
{
char *i;
i=spec_string( function );
return i;
}
/***************************************************************************/
// returns the name of the object special function
char *ospec_name( OSPEC_FUN *function)
{
int i;
for (i = 0; ospec_table[i].ospec_fun != NULL; i++)
{
if (function == ospec_table[i].ospec_fun )
return ospec_table[i].ospec_name;
}
return NULL;
}
/***************************************************************************
!!!!!!!!!!!!!!!!!!!!!!!MOB SPECIAL FUNCTIONS BELOW HERE!!!!!!!!!!!!!!!!!!!!
***************************************************************************/
bool spec_fearful( char_data *ch )
{
if(ch->position==POS_FIGHTING)
{
do_yell(ch,"HELP! I am being attacked!!! HELP!!!");
do_flee(ch,"");
return true;
}
return false ;
}
/***************************************************************************/
bool spec_red_drac( char_data *ch )
{
char_data *victim;
char_data *v_next;
char *spell;
int sn;
if(ch->position!=POS_FIGHTING)
{
if(ch->hit<ch->max_hit)
{
sn = gsn_heal;
(*skill_table[sn].spell_fun) (sn, ch->level, ch, ch, TARGET_CHAR);
}
if(number_range(1,100)>99)
{
switch(number_range(0,3))
{
case 0: spell = "haste"; break;
case 1: spell = "fire shield"; break;
case 2: spell = "protection good"; break;
case 3: spell = "sanctuary"; break;
default: spell = "protection good"; break;
}
if( ( sn = skill_lookup(spell) ) < 0 ) return false;
(*skill_table[sn].spell_fun) ( sn, ch->level, ch, ch,TARGET_CHAR);
return true;
}
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;
for ( ; ; )
{
switch ( number_bits( 4 ) )
{
case 0: spell = "blindness"; break;
case 1: spell = "chain lightning"; break;
case 2: spell = "acid blast"; break;
case 3: spell = "chain lightning"; break;
case 4: spell = "frostball"; break;
case 5: spell = "curse"; break;
case 6: spell = "poison"; break;
case 7: spell = "heat metal"; break;
case 8: spell = "teleport"; break;
case 9:
case 10: spell = "wrath"; break;
case 11: spell = "prismatic spray"; break;
default: spell = "dispel magic"; break;
}
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_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_pbackstab(ch,victim->name);
if (ch->position != POS_FIGHTING){
do_pkill(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;
(*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_steam( char_data* ch )
{
if ( ch->wait > 0 )
return false;
if ( is_affected(ch, gsn_neck_thrust))
return false;
return dragon( ch, "steam breath" );
}
/***************************************************************************/
bool spec_breath_gas( char_data *ch )
{
int sn;
if ( ch->position != POS_FIGHTING )
return false;
if (( sn = gsn_gas_breath) < 0 )
return false;
(*skill_table[sn].spell_fun) ( sn, ch->level, ch, NULL,TARGET_CHAR);
return true;
}
/***************************************************************************/
bool spec_gold_dragon( char_data *ch )
{
if(ch->in_room==NULL)
return false;
if( (ch->in_room->vnum==15024) && (ch->in_room->exit[3]!=NULL)
&& (!IS_SET(ch->in_room->exit[3]->exit_info,EX_CLOSED)))
{
if(!IS_AWAKE(ch))
{ do_wake(ch,""); }
else
{ do_west(ch,""); }
return true;
}
if( (ch->in_room->vnum==15025) && (ch->position!=POS_FIGHTING) )
{
do_east(ch, "");
do_sleep(ch, "");
return true;
}
if(ch->position==POS_FIGHTING)
{
switch ( number_bits( 2 ) )
{
case 0: return dragon(ch, "prismatic spray");
case 1: return dragon(ch, "fire breath");
case 2: return dragon(ch, "gas breath");
case 3: return dragon(ch, "acid breath");
}
}
return false;
}
/***************************************************************************/
bool spec_breath_lightning( char_data *ch )
{
return dragon( ch, "lightning breath" );
}
/***************************************************************************/
// This is the 'healer' system
bool spec_cast_adept( char_data *ch )
{
char_data *victim;
char_data *v_next;
int sn;
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) )
break;
}
if ( victim == NULL )
return false;
switch ( number_range(0,12) )
{
case 0:
sn=gsn_armor;
if ( !is_affected( victim, sn ))
{
act( "$n feeds you a sour vitamin.", ch, NULL, NULL, TO_ROOM );
spell_armor( sn, ch->level,ch,victim,TARGET_CHAR);
}
return true;
case 1:
sn=gsn_bless;
if ( !is_affected( victim, sn ))
{
act( "$n feeds you a special herb.", ch, NULL, NULL, TO_ROOM );
spell_bless( sn, ch->level,ch,victim,TARGET_CHAR);
}
return true;
case 2:
sn=gsn_cure_blindness;
if ( IS_AFFECTED(victim, AFF_BLIND))
{
act("$n has you eat a paste from a bowl.",ch,NULL,NULL,TO_ROOM);
spell_cure_blindness( sn, ch->level, ch, victim,TARGET_CHAR);
}
return true;
case 3:
sn=gsn_cure_light;
if ( victim->hit != victim->max_hit )
{
act("$n makes you take a pill.", ch,NULL, NULL, TO_ROOM );
spell_cure_light( sn, ch->level, ch, victim,TARGET_CHAR);
}
return true;
case 4:
sn=gsn_cure_poison;
if ( is_affected( victim, gsn_poison ))
{
act( "$n has you drink an anti-venom.",ch,NULL,NULL,TO_ROOM);
spell_cure_poison( sn, ch->level, ch, victim,TARGET_CHAR);
}
return true;
case 5:
sn=gsn_refresh;
if ((victim->max_move != victim->move))
{
act("$n gives you a special tea.", ch, NULL, NULL, TO_ROOM );
spell_refresh( sn,ch->level,ch,victim,TARGET_CHAR);
}
return true;
case 6:
sn=gsn_cure_disease;
if ( is_affected( victim, gsn_plague ))
{
act("$n has you down a bitter potion.",ch,NULL,NULL,TO_ROOM);
spell_cure_disease( sn, ch->level,ch,victim,TARGET_CHAR);
}
return true;
}
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
|| ch->wait>0
|| IS_AFFECTED(ch,AFF2_MUTE)
|| IS_AFFECTED( ch, AFF_BLIND ) // because they can't see the target, most are target spells
|| IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) ){
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 = "curse"; break;
case 6: min_level = 12; spell = "change sex"; break;
case 7: min_level = 13; spell = "flamestrike"; break;
case 8: min_level = 14; spell = "cause headache"; break; //Y: mobs cause headache too!!
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;
say_spell(ch, sn, CCT_CLERIC);
(*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim,TARGET_CHAR);
return true;
}
/***************************************************************************/
bool spec_cast_druid( char_data *ch )
{
char_data *victim;
char_data *v_next;
char *spell;
int sn;
if ( ch->position != POS_FIGHTING
|| ch->wait>0
|| IS_AFFECTED(ch,AFF2_MUTE)
|| IS_AFFECTED( ch, AFF_BLIND ) // because they can't see the target, most are target spells
|| IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) ){
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 = "faerie fire"; break;
case 1: min_level = 3; spell = "withering"; break;
case 2: min_level = 6; spell = "vitality drain"; break;
case 3: min_level = 9; spell = "closed eyes"; break;
case 4: min_level = 12; spell = "snake bite"; break;
case 5: min_level = 15; spell = "remove spells"; break;
case 6: min_level = 18; spell = "merciless hunger"; break;
case 7: min_level = 21; spell = "merciless thirst"; break;
case 8: min_level = 20; spell = "black death"; break;
case 9: min_level = 50; spell = "flamestorm"; break;
default: min_level = 18; spell = "destroy living"; break;
}
if ( ch->level >= min_level )
break;
}
if ( ( sn = skill_lookup( spell ) ) < 0 )
return false;
say_spell(ch, sn, CCT_DRUID);
(*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
|| ch->wait>0
|| IS_AFFECTED(ch,AFF2_MUTE)
|| IS_AFFECTED( ch, AFF_BLIND ) // because they can't see the target, most are target spells
|| IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) ){
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
|| ch->wait>0
|| IS_AFFECTED(ch,AFF2_MUTE)
|| IS_AFFECTED( ch, AFF_BLIND ) // because they can't see the target, most are target spells
|| IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) ){
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 = "burning hands"; break;
case 1: min_level = 3; spell = "chill touch"; break;
case 2: min_level = 7; spell = "weaken"; break;
case 3: min_level = 8; spell = "teleport"; 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:
case 8:
case 9: min_level = 15; spell = "fireball"; break;
case 10: min_level = 20; spell = "decay"; break;
case 11: min_level = 30; spell = "cause fear"; break;
case 12: min_level = 50; spell = "chaotic poison"; break;
default: min_level = 20; spell = "acid blast"; break;
}
if ( ch->level >= min_level )
break;
}
if ( ( sn = skill_lookup( spell ) ) < 0 ){
return false;
}
say_spell(ch, sn, CCT_MAGE);
(*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
|| ch->wait>0
|| IS_AFFECTED(ch,AFF2_MUTE)
|| IS_AFFECTED( ch, AFF_BLIND ) // because they can't see the target, most are target spells
|| IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) ){
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 = "curse"; 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;
(*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim,TARGET_CHAR);
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 *)
{
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, OBJWEAR_TAKE )
|| (trash->item_type == ITEM_CORPSE_PC)
|| !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 Whore!'", ch, NULL, NULL, TO_ROOM );
break;
case 'b':
act( "$n says 'These Humans can not clean up after themselves.'",
ch, NULL, NULL, TO_ROOM );
break;
case 'c':
act( "$n says 'Vandals! I shall see them Hung!'",
ch, NULL, NULL, TO_ROOM );
break;
case 'd':
act( "$n says 'Out of my way!'", ch, NULL, NULL, TO_ROOM );
break;
case 'e':
act( "$n says 'I hereby declare this wretched city open!'",
ch, NULL, NULL, TO_ROOM );
break;
case 'E':
act( "$n says 'I hereby declare this wretched city 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;
victim = ch->fighting;
if ( ch->position != POS_FIGHTING
|| !victim
|| number_percent( ) > 2 * ch->level )
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,silver;
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;
silver = victim->silver * UMIN(number_range(1,20),ch->level/2)/100;
silver = UMIN(silver,ch->level*ch->level * 25);
ch->silver += silver;
victim->silver -= silver;
return true;
}
}
return false;
}
/*************************************************************************
* *
* Lava monster comes out of his lair after few ticks of someone *
* being on his bridge - Kalahn & Raine - Apr 97 *
* *
************************************************************************/
bool spec_lava_monster( char_data *ch )
{
static ROOM_INDEX_DATA *bridge[5];
static long last_tick = 0;
static int wake_countdown = 3 , /* countdown before mob awakens */
mob_state = 0; /* state mob is in - 0 = sleeping in lair */
int room_index;
bool player_found;
if(ch->in_room==NULL)
return false;
if (!bridge[0] ) /* load pointers to all the rooms required */
{
bridge[0] = get_room_index(29646); /* lava monsters lair */
bridge[1] = get_room_index(29627); /* just outside his lair */
bridge[2] = get_room_index(29626); /* on northern end of bridge */
bridge[3] = get_room_index(29625); /* on southern end of bridge */
bridge[4] = get_room_index(29624); /* just south of bridge */
}
for(int checkrooms=0; checkrooms<5; checkrooms++){
if(!bridge[checkrooms]){
return false;
}
}
/* Every tick check for people around or on the lava bridge
- this is used to delay the lava monster from coming out straight away
*/
if (tick_counter > last_tick)
{ /* a tick has past */
last_tick = tick_counter;
/* check all along bridge for a players */
player_found = false;
for (room_index=1; room_index<=4; room_index++)
{
if (bridge[room_index]->people != NULL)
{
wake_countdown--;
player_found = true;
}
}
/* check to reset counter if no one on bridge*/
if (player_found == false) wake_countdown=3;
if ((wake_countdown<=0) && (mob_state==0)) mob_state = 1; /* awaken mob if it isn't already */
}
switch (mob_state)
{
case 0: /* mob is asleep - check for ppl in mobs lair - instant wakeup */
if ((bridge[0]->people != ch) || (ch->next_in_room != NULL))
{
wake_countdown = 0;
do_wake(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
do_yell(ch,"Who is this that disturbs my slumber?");
mob_state = 2;
}
break;
case 1: /* awaken mob */
do_wake(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
do_yell(ch,"Fool's are they that disturb my slumber");
mob_state = 2;
break;
case 2: /* mob awake in lair */
if (ch->position!=POS_FIGHTING)
{
do_west(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
mob_state = 3;
}
break;
case 3: /* mob just outside of lair */
if (ch->position!=POS_FIGHTING)
{
do_south(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
mob_state = 4;
}
break;
case 4: /* mob on northern end of bridge */
if (ch->position!=POS_FIGHTING)
{
do_south(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
mob_state = 5;
}
break;
case 5: /* mob on southern end of bridge */
if (ch->position!=POS_FIGHTING)
{
do_south(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
mob_state = 6;
}
break;
case 6: /* mob just south of bridge - turn around and go back up */
if (ch->position!=POS_FIGHTING)
{
do_north(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
mob_state = 7;
}
break;
case 7: /* mob on southern end of bridge - returning */
if (ch->position!=POS_FIGHTING)
{
do_north(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
mob_state = 8;
}
break;
case 8: /* mob on northern end of bridge - returning */
if (ch->position!=POS_FIGHTING)
{
do_north(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
mob_state = 9;
}
break;
case 9: /* mob just north of bridge, west of lair - returning */
if (ch->position!=POS_FIGHTING)
{
do_east(ch,"");
act("$n rises up menacingly above YOU!, flame ripples along its form.", ch, NULL, NULL, TO_ROOM );
mob_state = 10;
}
break;
case 10: /* in lair - going to sleep */
if (ch->position!=POS_FIGHTING)
{
do_sleep(ch,"");
mob_state = 0;
wake_countdown=3; /* reset mob */
act("$n reclines slowly back into the lava.", ch, NULL, NULL, TO_ROOM );
}
break;
default:
if (ch->position!=POS_FIGHTING)
return dragon(ch, "fire breath");
}
return false;
}
/***************************************************************************/
bool spec_assassin( char_data *ch )
{
char buf[MSL];
char_data *victim;
char_data *v_next;
int rnd_say;
if ( ch->fighting != NULL )
return false;
for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
{
v_next= victim->next_in_room;
if (victim->clss != class_lookup("thief"))
break;
}
if ( victim == NULL || victim == ch || IS_IMMORTAL(victim) )
return false;
if ( victim->level > ch->level + 7 || IS_NPC(victim))
return false;
rnd_say = number_range (1, 10);
switch (rnd_say)
{
case 6:
sprintf( buf, "Time to die...");
break;
case 7:
sprintf( buf, "Death is the true end...");
break;
case 8:
sprintf( buf, "Welcome to your fate...");
break;
case 9:
sprintf( buf, "Its a good day to die...");
break;
case 10:
sprintf( buf, "Ever dance the dance...");
break;
default:
sprintf( buf, "Die!!!");
break;
}
do_say( ch, buf );
multi_hit( ch, victim, gsn_backstab );
multi_hit( ch, victim, gsn_backstab );
return true;
}
/*************************************************************************
* spec_beggar - Created by Raine & edited by Kalahn - Apr 97 *
************************************************************************/
bool spec_beggar( char_data *ch )
{
char buf[MSL];
int rnd_say;
static long last_tick = 0;
if ( ch->fighting != NULL )
return false;
if (tick_counter > last_tick)
{
last_tick = tick_counter;
rnd_say = number_range (1, 10);
switch (rnd_say)
{
case 6:
act("$n points at the sky.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Blue red green pink, I can never remember which one.");
break;
case 7:
act("$n chuckles insanely.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Dance the dance they said, and oh how I danced.");
break;
case 8:
act("$n mulls over some idea.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Tis funny i could never tell ripe olives from unripe ones.");
break;
case 9:
act("$n rants and raves.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Aye, south's the one, take the south road.");
break;
case 10:
act("$n smiles coyly.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Beware your next step. It may be your last, so go prepared.");
break;
default:
act("$n shudders as he rants and raves.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Tis the she-beast. It's the one. Walk quick or she will have some fun!");
break;
}
do_say( ch, buf );
}
return true;
}
/************************************************************************
* spec_summoned_guardian - Created by Raine & Kalahn - Sept97 *
************************************************************************/
bool spec_summoned_guardian( char_data *ch )
{
char_data *victim;
/* timer for guardian, timer is approx
number of ticks guardian exists for */
if (number_range(1,(int)PULSE_TICK/PULSE_MOBILE) == 1)
ch->timer--;
if ( ch->timer<1 )
{
act("$n shimmers and fades out of existance.", ch, NULL, NULL, TO_ROOM );
extract_char( ch, true );
return false;
}
if ( ch->fighting != NULL )
return false;
for ( victim = ch->in_room->people; victim != NULL; victim = victim->next_in_room)
{
// dont activate on a mage, itself or an immortal
if (victim->clss == class_lookup("mage") || victim == ch || IS_IMMORTAL(victim))
continue;
break; // someone is in the room to attack
}
if (victim == NULL)
return false;
/* dont attack newbies */
if ( victim->level < 11 )
{
do_yell(ch,"Master, someone disturbs you!");
return false;
}
/* dont attack those under 15 levels of the mob */
if ( victim->level+15 < ch->level)
{
do_yell(ch,"Master, someone disturbs you!");
return false;
}
do_say(ch, "The master commands it");
do_yell(ch,"Master, someone disturbs you!");
act("$n charges toward you on wings of stone.", ch, NULL, NULL, TO_ROOM );
do_kill(ch, victim->name);
return true;
}
/************************************************************************
* spec_elf_muncher - Created by Raine - Sept97 *
************************************************************************/
bool spec_elf_muncher( char_data *ch )
{
char_data *victim;
if ( ch->fighting != NULL )
return false;
for ( victim = ch->in_room->people; victim != NULL; victim = victim->next_in_room)
{
/* dont activate on imm or self or NPC*/
if (victim == ch || IS_IMMORTAL(victim) || IS_NPC(victim))
continue;
break; /* someone is in the room to attack */
}
if (victim == NULL)
return false;
// only activate on elves
if (victim->race != race_lookup("elf"))
return false;
/* dont attack to low a level */
if ( victim->level < 29 )
{
do_yell(ch,"Filthy Elf! Id kill you if you were not so pathetic");
return false;
}
/* yell and smash an elf */
do_say(ch, "Time to die Elf!");
do_yell(ch,"Call out the guard, elf kiblits all around!");
act("$n charges toward you, blood red eyes a flame.", ch, NULL, NULL, TO_ROOM );
do_kill(ch, victim->name);
return true;
}
/***************************************************************************/
bool spec_shadow_dragon( 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 = "shadow breath"; break;
case 1: min_level = 3; spell = "vampiric touch"; break;
case 2: min_level = 7; spell = "energy drain"; break;
case 3: min_level = 8; spell = "curse"; break;
case 4: min_level = 0; spell = "shadow breath"; break;
case 5: min_level = 0; spell = "shadow breath"; break;
case 6: min_level = 0; spell = "shadow breath"; break;
case 7: min_level = 0; spell = "shadow breath"; break;
case 8: min_level = 0; spell = "shadow breath"; break;
case 9: min_level = 0; spell = "shadow breath"; break;
case 10: min_level = 20; spell = "wrath"; break;
default: min_level = 20; spell = "shadow breath"; break;
}
if ( ch->level >= min_level )
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_steel_dragon( 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 = "steel breath"; break;
case 1: min_level = 3; spell = "steel breath"; break;
case 2: min_level = 7; spell = "steel breath"; break;
case 3: min_level = 8; spell = "heat metal"; break;
case 4: min_level = 3; spell = "steel breath"; break;
case 5: min_level = 3; spell = "steel breath"; break;
case 6: min_level = 3; spell = "steel breath"; break;
case 7: min_level = 3; spell = "steel breath"; break;
case 8: min_level = 3; spell = "steel breath"; break;
case 9: min_level = 3; spell = "steel breath"; break;
case 10: min_level = 20; spell = "heat metal"; break;
default: min_level = 20; spell = "steel breath"; break;
}
if ( ch->level >= min_level )
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_cast_mean( char_data* ch )
{
char_data* victim;
char_data* v_next;
char *spell;
int sn;
if ( ( ch->position != POS_FIGHTING ) ||
( ch->wait > 0 ) ||
( IS_AFFECTED( ch, AFF_BLIND ) ) ||
( IS_AFFECTED( ch, AFF2_MUTE ) ) ||
( IS_AFFECTED2( ch, AFF2_TAUNT ) ) ||
( IS_AFFECTED2( ch, AFF2_ROAR ) ) ||
( IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) ) )
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;
if ( IS_AFFECTED( ch, AFF_BLIND ) )
{
victim = ch;
min_level = 0;
spell = "cure blindness";
break;
}
else if ( IS_AFFECTED( ch, AFF2_MUTE ) ||
IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) )
{
victim = ch;
min_level = 0;
spell = "dispel silence";
break;
}
else switch ( number_bits( 4 ) )
{
case 0: min_level = 0; spell = "blindness"; break;
case 1: min_level = 3; spell = "mental implosion"; break;
case 2: min_level = 7; spell = "natures fury"; break;
case 3: min_level = 8; spell = "dispel magic"; break;
case 4: min_level = 11; spell = "ice storm"; break;
case 5: min_level = 12; spell = "faerie fire"; break;
case 6: min_level = 13; spell = "heat metal"; break;
case 7:
case 8: min_level = 14; spell = "mute"; break;
case 9: min_level = 15; spell = "frostball"; break;
case 10: min_level = 20; spell = "spirit lance"; break;
default: min_level = 20; spell = "improved phantasm"; break;
}
if ( ch->level >= min_level )
break;
}
if ( ( sn = skill_lookup( spell ) ) < 0 )
return false;
say_spell(ch, sn, CCT_MAGE);
(*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim,TARGET_CHAR);
return true;
}
/***************************************************************************/
bool spec_cast_meaner( char_data* ch )
{
char_data* victim;
char_data* v_next;
char *spell;
int sn;
if ( ( ch->position != POS_FIGHTING ) ||
( ch->wait > 0 ) ||
( IS_AFFECTED( ch, AFF_BLIND ) ) ||
( IS_AFFECTED( ch, AFF2_MUTE ) ) ||
( IS_AFFECTED2( ch, AFF2_TAUNT ) ) ||
( IS_AFFECTED2( ch, AFF2_ROAR ) ) ||
( IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) ) )
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;
if ( IS_AFFECTED( ch, AFF_BLIND ) )
{
victim = ch;
min_level = 0;
spell = "cure blindness";
break;
}
else if ( IS_AFFECTED( ch, AFF2_MUTE ) ||
IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ) )
{
victim = ch;
min_level = 0;
spell = "dispel silence";
break;
}
else switch ( number_bits( 4 ) )
{
case 0: min_level = 0; spell = "meteor swarm"; break;
case 1: min_level = 3; spell = "mental implosion"; break;
case 2: min_level = 7; spell = "gas breath"; break;
case 3: min_level = 8; spell = "dispel magic"; break;
case 4: min_level = 11; spell = "elemental storm"; break;
case 5: min_level = 12; spell = "holy fire"; break;
case 6: min_level = 13; spell = "heat metal"; break;
case 7: min_level = 13; spell = "fire breath"; break;
case 8: min_level = 14; spell = "lightning breath"; break;
case 9: min_level = 15; spell = "steam breath"; break;
case 10: min_level = 20; spell = "spirit lance"; break;
default: min_level = 20; spell = "mind thrust"; break;
}
if ( ch->level >= min_level )
break;
}
if ( ( sn = skill_lookup( spell ) ) < 0 )
return false;
say_spell(ch, sn, CCT_MAGE);
(*skill_table[sn].spell_fun) ( sn, ch->level, ch, victim,TARGET_CHAR);
return true;
}
/***************************************************************************/
bool spec_master_thief( char_data* ch )
{
char_data* victim;
char_data* v_next;
OBJ_DATA *obj;
int percent, skill;
if ( ( ch->position < POS_STANDING ) ||
( ch->wait > 0 ) ||
( IS_AFFECTED( ch, AFF_BLIND ) ) ||
( IS_AFFECTED2( ch, AFF2_TAUNT ) ) ||
( IS_AFFECTED2( ch, AFF2_ROAR ) ) )
return false;
for ( victim = ch->in_room->people; victim != NULL; victim = v_next )
{
v_next = victim->next_in_room;
if ( IS_NPC(victim) ) /* Only PC's are targets */
return false;
if ( is_safe( ch, victim ) ) /* Only viable targets */
return false;
if ( victim->level >= LEVEL_IMMORTAL /* Don't mess with IMMs */
|| number_bits( 5 ) != 0
|| !can_see(ch,victim) )
continue;
skill = 40 + 2 * ch->level;
percent = number_percent();
/* Some sanity checking below, NPC's should NOT be targets */
if ( !IS_NPC( victim ) && get_skill(victim, gsn_awareness) >= 1 )
{
percent += victim->pcdata->learned[gsn_awareness]/2;
if ( !IS_AWAKE( victim ) )
do_wake(victim, "");
check_improve(victim, gsn_awareness, true, 14);
}
percent += (!IS_AWAKE(victim) ? -50 : !can_see(victim, ch) ? -25 : 10);
if ( percent+victim->level-ch->level > skill )
{
/*
* Failure.
*/
act( "$n tried to steal from you!\r\n", ch, NULL, victim, TO_VICT );
act( "$n tried to steal from $N!\r\n", ch, NULL, victim, TO_NOTVICT );
return false;
}
else
{
switch ( number_range(1, 2) )
{
int gold, silver;
case 1:
gold = victim->gold * number_range(1, ch->level) / 160;
silver = victim->silver * number_range(1, ch->level) / 160;
if ( gold <= 0 && silver <= 0 )
return false;
ch->gold += gold;
ch->silver += silver;
victim->silver -= silver;
victim->gold -= gold;
return true;
case 2:
if ( ( obj = get_random_obj( victim ) ) == NULL
|| !can_see_obj( ch, obj ) )
return false;
obj_from_char( obj );
obj_to_char( obj, ch );
return true;
}
}
}
return false;
}
/***************************************************************************/
/*
bool spec_charmer( char_data* ch )
{
char_data* victim;
char_data* v_next;
char buf[MSL];
if ( ch->position != POS_FIGHTING )
{
switch ( number_bits( 3 ) )
{
case 0:
sprintf( buf, "all sing %s", ch->name );
do_order( ch, buf ); // a chance to get free here
break;
case 1:
break;
case 2:
break;
case 3:
do_order( ch, "all remove dagger" );
sprintf( buf, "all give dagger %s", ch->name );
do_order( ch, buf );
break;
case 4:
do_order( ch, "all remove sword" );
sprintf( buf, "all give sword %s", ch->name );
do_order( ch, buf );
break;
case 5:
do_order( ch, "all remove mace" );
sprintf( buf, "all give mace %s", ch->name );
do_order( ch, buf );
break;
case 6:
do_order( ch, "all drop all" );
break;
case 7:
sprintf( buf, "all cast 'cure light' %s", ch->name );
do_order( ch, buf );
break;
};
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;
if (IS_AFFECTED2(ch, AFF2_MUTE) || IS_SET( ch->in_room->affected_by, ROOMAFF_CONE_OF_SILENCE ))
return false;
act( "$n begins playing a new, beautiful song.", ch, NULL, NULL,TO_ROOM );
spell_charm_person(gsn_charm_person, ch->level, ch, victim, TARGET_CHAR );
if (IS_AFFECTED(victim, AFF_CHARM))
stop_fighting( victim, true );
return true;
}
*/
/***************************************************************************/
bool spec_troll_member( char_data* ch)
{
char_data* vch;
char_data* victim = 0;
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;
char_data* victim = 0;
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_questmaster (char_data* ch)
{
if (ch->fighting != NULL) return spec_cast_mage( ch );
return false;
}
/***************************************************************************/
bool spec_clan_transport( char_data* ch )
{
char_data* victim;
char_data* 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 ( victim == NULL )
return false;
if ( IS_NPC(victim) )
return false;
act("$n eyes glow brightly for a moment.",ch,NULL,victim,TO_ALL);
ROOM_INDEX_DATA *location;
int recall_vnum=get_recallvnum(ch);
if ( ( location = get_room_index( recall_vnum ) ) == NULL )
{
ch->println("You are completely lost.");
if ( ( location = get_room_index( ROOM_VNUM_OOC ) ) == NULL)
{
ch->printf("BUG: Cant find the main ooc room (vnum = %d)\r\n"
"Please report this to an admin.\r\n", ROOM_VNUM_OOC);
return false;
}
else
{
if (IS_SET(location->room_flags, ROOM_OOC))
{
ch->println("Taking you to the main OOC room since your normal recall doesnt exist.");
}
else
{
ch->printf("BUG: Taking you to the main ooc room (vnum = %d)\r\n"
"This room SHOULD be an OOC room - please report this bug to an admin.\r\n", ROOM_VNUM_OOC);
}
}
}
char_from_room(victim);
char_to_room(victim, location);
do_look( victim, "auto" );
return true;
}
return false;
}
/***************************************************************************
!!!!!!!!!!!!!!!!!!!!!!!OBJ SPECIAL FUNCTIONS BELOW HERE!!!!!!!!!!!!!!!!!!!!
***************************************************************************/
bool spec_obj_test( OBJ_DATA *, char_data *)
{
act("SAYS HELLO!!!!",NULL,NULL,NULL,TO_ROOM);
act("SAYS HELLO!!!!",NULL,NULL,NULL,TO_CHAR);
return true;
}
/*************************************************************************
* spec_oracle - Created by Hera for Athens - the mud *
************************************************************************/
bool spec_oracle( char_data *ch )
{
char buf[MSL];
int rnd_say;
static long last_tick = 0;
if ( ch->fighting != NULL )
return false;
if (tick_counter > last_tick)
{
last_tick = tick_counter;
rnd_say = number_range (1, 10);
switch (rnd_say)
{
case 5:
act("$n mumbles an ambiguous prediction.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "You will soon discover how truly fortunate you really are.");
break;
case 6:
act("$n mumbles an ambiguous prediction.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Asking about the future has brought about change.");
break;
case 7:
act("$n mumbles an ambiguous prediction.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "As soon as you admit your own ignorance, you will be wise.");
break;
case 8:
act("$n mumbles an ambiguous prediction.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "The gods are smiling down upon someone.");
break;
case 9:
act("$n mumbles an ambiguous prediction.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Your attribues will be recognized and suitably rewarded.");
break;
case 10:
act("$n mumbles an ambiguous prediction.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "The god of fortune becons you to gamble.");
break;
default:
act("$n mumbles an ambiguous prediction.", ch, NULL, NULL, TO_ROOM );
sprintf( buf, "Your present plans are going to succeed.");
break;
}
do_say( ch, buf );
}
return true;
}
/*************************************************************************
* spec_chicken - Created by Hera for Athens - the mud *
************************************************************************/
bool spec_chicken( char_data *ch )
{
int eggevent;
static long last_tick = 0;
OBJ_DATA *egg;
if (tick_counter > last_tick)
{
last_tick = tick_counter;
eggevent = number_range (1, 7);
switch (eggevent)
{
case 1:
act("$n clucks.", ch, NULL, NULL, TO_ROOM );
break;
case 2:
act("$n clucks loudly as an egg rolls down from her basket.", ch, NULL, NULL, TO_ROOM );
if (get_obj_index(OBJ_VNUM_EGG)) {
egg = create_object(get_obj_index(OBJ_VNUM_EGG));
obj_to_room( egg, ch->in_room );
}else{
ch->println( "BUG: No available egg object for chickens - please report!" );
break;
}
case 3:
act("$n flaps her wings.", ch, NULL, NULL, TO_ROOM );
break;
case 4:
act("$n clucks and flaps her wings wildly.", ch, NULL, NULL, TO_ROOM );
break;
case 5:
act("$n shifts in her basket.", ch, NULL, NULL, TO_ROOM );
break;
case 6:
act("$n prunes her wings.", ch, NULL, NULL, TO_ROOM );
break;
case 7:
act("$n pecks at her food bowl.", ch, NULL, NULL, TO_ROOM );
break;
default:
act("$n clucks.", ch, NULL, NULL, TO_ROOM );
break;
}
}
return true;
}
/*************************************************************************
* spec_hound - Created by Hera for Athens - the mud *
************************************************************************/
/*
bool spec_hound( char_data* ch)
{
char_data* victim = 0;
int houndevent;
char *message;
houndevent = number_range (1,4);
switch (houndevent)
{
default: message = "$n barks!";
break;
case 1: message = "$n barks viciously!";
break;
case 2: message = "$n snarls.";
break;
case 3: message = "$n growls";
break;
case 4: message = "$n licks his chops.";
break;
}
if (message != NULL)
act(message,ch,NULL,victim,TO_ALL);
multi_hit( ch, victim, TYPE_UNDEFINED );
return true;
}
*/
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/