/*****************************************************************************
* All the racial skills *
* -- Hannibal *
*****************************************************************************/
#define unix 1
#if defined( macintosh )
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "merc.h"
/*
* External functions.
*/
extern void set_fighting args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
extern void forge_obj args( ( CHAR_DATA *ch, OBJ_DATA *to_forge ) );
void do_headbutt( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char arg [ MAX_INPUT_LENGTH ];
int timer = 24;
int mod;
int dmg;
if ( ch->race != RACE_MINOTAUR )
{
send_to_char( AT_GREY, "Wham! Ouch! You sure are no minotaur\n\r", ch );
return;
}
if ( ch->race_wait > 0 )
return;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return;
}
one_argument( argument, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return;
}
switch ( prime_class(ch) )
{
case CLASS_MAGE:
case CLASS_CLERIC: timer = 240; break;
case CLASS_THIEF: timer = 180; break;
case CLASS_WARRIOR: timer = 120; break;
case CLASS_PSIONICIST:
case CLASS_DRUID: timer = 240; break;
case CLASS_RANGER:
case CLASS_PALADIN:
case CLASS_BARD:
case CLASS_VAMPIRE: timer = 180; break;
case CLASS_NECROMANCER: timer = 240; break;
case CLASS_WEREWOLF: timer = 180; break;
}
mod = ch->level / 5;
mod = UMAX( 1, mod );
timer = timer / mod;
timer = ( timer < 24 ) ? 24 : timer;
ch->race_wait = timer;
act( AT_YELLOW, "You slam your head into $N's!", ch, NULL, victim, TO_CHAR );
act( AT_YELLOW, "$n slams his head into yours!", ch, NULL, victim, TO_VICT );
act( AT_YELLOW, "$n slams his head into $N's!", ch, NULL, victim, TO_NOTVICT );
dmg = number_range( ch->level, ch->level * 5 );
damage( ch, victim, dmg, gsn_headbutt );
STUN_CHAR( ch, 2, STUN_MAGIC );
if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
return;
if ( number_percent() < 15 && victim->position != POS_STUNNED )
{
act( AT_WHITE, "$N reels from the blow...", ch, NULL, victim, TO_CHAR );
act( AT_WHITE, "$N reels from the blow...", ch, NULL, victim, TO_NOTVICT );
act( AT_WHITE, "You real from the blow and feel disoriented.",
ch, NULL, victim, TO_VICT );
STUN_CHAR( victim, 2, STUN_TOTAL );
victim->position = POS_STUNNED;
}
return;
}
void do_drowfire( CHAR_DATA *ch, char *argument )
{
AFFECT_DATA af;
CHAR_DATA *victim;
if ( ch->race != RACE_DROW )
{
send_to_char( AT_GREY, "Drowfire by a non-drow?\n\r", ch );
return;
}
if(argument[0] != '\0')
{
if(!(victim = get_char_room(ch, argument)))
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch);
return;
}
}
else
{
if(!(victim = ch->fighting))
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch);
return;
}
}
if ( is_affected( victim, gsn_drowfire ) )
return;
WAIT_STATE( ch, skill_table[gsn_drowfire].beats );
af.type = gsn_drowfire;
af.level = ch->level;
af.duration = ch->level / 10;
af.location = APPLY_AC;
af.modifier = 5 * ch->level;
af.bitvector = 0;
affect_to_char( victim, &af );
af.location = APPLY_HITROLL;
af.modifier = 0 - ch->level / 5;
af.bitvector = 0;
affect_to_char( victim, &af );
send_to_char(AT_PINK, "You are surrounded by a purple outline.\n\r", victim );
act(AT_PINK, "$n is surrounded by a purple outline.", victim, NULL, NULL, TO_ROOM );
if ( !victim->fighting )
set_fighting( victim, ch );
return;
}
void do_globedarkness( CHAR_DATA *ch, char *argument )
{
ROOM_AFFECT_DATA raf;
POWERED_DATA *pd;
OBJ_DATA *globe;
char buf[MAX_STRING_LENGTH];
bool found = FALSE;
if ( ch->race != RACE_DROW )
{
send_to_char(AT_GREY, "Huh?\n\r", ch );
return;
}
if ( argument[0] == '\0' )
{
send_to_char( AT_DGREY, "Syntax: globe <create|dissipate|locate>\n\r", ch );
return;
}
if ( !str_cmp( argument, "locate" ) )
{
for ( pd = ch->powered; pd; pd = pd->next )
{
if ( pd->type == gsn_globedark )
{
sprintf( buf, "Globe of Darkness&w, &W%s&w; &cCost&w: &R%d&w.\n\r",
pd->room->name, pd->cost );
send_to_char( AT_DGREY, buf, ch );
found = TRUE;
}
}
if ( !found )
send_to_char( AT_CYAN, "You are not sustaining any &zGlobes&w.\n\r", ch );
return;
}
if ( !str_cmp( argument, "dissipate" ) )
{
if ( !is_raffected( ch->in_room, gsn_globedark ) )
{
send_to_char( AT_CYAN, "There is no &zGlobe &cin this room&w.\n\r", ch );
return;
}
for ( pd = ch->powered; pd; pd = pd->next )
{
if ( !pd )
break;
if ( pd->type == gsn_globedark )
{
found = TRUE;
if ( pd->room == ch->in_room )
{
send_to_char( AT_DGREY, "You wave your hand and the globe dissipates.\n\r", ch );
act( AT_DGREY, "The globe of darkness dissipates.",
ch, NULL, NULL, TO_ROOM );
raffect_remove( ch->in_room, ch, pd->raf );
return;
}
}
}
if ( !found )
{
send_to_char( AT_CYAN, "You are not sustaining any &zGlobes&w.\n\r", ch );
return;
}
send_to_char( AT_CYAN, "You are not powering the &zGlobe&c in this room.\n\r", ch );
return;
}
if ( !str_cmp( argument, "create" ) )
{
if ( is_raffected( ch->in_room, gsn_globedark ) )
{
send_to_char(AT_GREY, "A globe of darkness already sits in this room.\n\r", ch );
return;
}
globe = create_object( get_obj_index( OBJ_VNUM_WARD_PHYS ), 1 );
free_string( globe->name );
free_string( globe->short_descr );
free_string( globe->description );
globe->name = str_dup( "globe darkness" );
globe->short_descr = str_dup( "&za Globe of Darkness" );
globe->description = str_dup( "A &zGlobe of Darkness &Xsits upon the room." );
raf.type = gsn_globedark;
raf.location = ROOM_NONE;
raf.room = ch->in_room;
raf.material = globe;
raf.powered_by = ch;
raffect_to_room( ch->in_room, ch, &raf );
send_to_char( AT_DGREY, "You raise your hand and place of globe of darkness upon the area!\n\r", ch );
act( AT_DGREY, "$n raises his hand and everything goes pitch black!",
ch, NULL, NULL, TO_ROOM );
return;
}
do_globedarkness( ch, "" );
}
void do_forge( CHAR_DATA *ch, char *argument )
{
char arg[ MAX_INPUT_LENGTH ];
char arg2[ MAX_INPUT_LENGTH ];
char buf[ MAX_INPUT_LENGTH ];
OBJ_DATA *obj, *hammer;
int wear, lvl;
long group1 = ITEM_ANTI_HUMAN + ITEM_ANTI_DROW + ITEM_ANTI_ELF + ITEM_ANTI_ELDER;
long group2 = ITEM_ANTI_OGRE + ITEM_ANTI_TROLL + ITEM_ANTI_DEMON + ITEM_ANTI_MINOTAUR;
long group3 = ITEM_ANTI_DWARF + ITEM_ANTI_HALFLING + ITEM_ANTI_SHADOW;
long group4 = ITEM_ANTI_ILLITHID + ITEM_ANTI_GHOUL;
long group5 = ITEM_ANTI_PIXIE;
long group6 = ITEM_ANTI_LIZARDMAN;
long antirace = 0;
wear = 0;
if ( ch->race != RACE_DWARF )
{
send_to_char( AT_GREY, "You aren't a dwarf!\n\r", ch );
return;
}
if ( argument[0] == '\0' )
{
send_to_char( AT_WHITE, "Syntax: Forge <obj> <race> <lvl>\n\r", ch );
send_to_char( AT_WHITE, " obj = ring necklace armor helm\n\r", ch );
send_to_char( AT_WHITE, " mask leggings boots gauntlets\n\r", ch );
send_to_char( AT_WHITE, " gauntlets armplates shield\n\r", ch );
send_to_char( AT_WHITE, " belt bracer anklet weapon\n\r", ch );
send_to_char( AT_WHITE, " race= any valid race. HELP FORGE RACES\n\r", ch );
send_to_char( AT_WHITE, " to see race groupings.\n\r", ch );
sprintf( buf, " lvl = minimum 30, maximum %d.\n\r", ch->level );
send_to_char( AT_WHITE, buf, ch );
send_to_char( AT_WHITE, " BASE cost to make item is: 100 gold * lvl\n\r", ch );
return;
}
if ( ch->in_room->vnum != ROOM_VNUM_SMITHY )
{
send_to_char( AT_GREY, "You cannot forge equipment here.\n\r", ch );
return;
}
for ( hammer = ch->carrying; hammer; hammer = hammer->next )
{
if ( hammer->pIndexData->vnum == OBJ_VNUM_SMITHY_HAMMER
&& hammer->wear_loc == WEAR_HOLD )
break;
}
if ( !hammer )
{
send_to_char( AT_GREY, "You must hold a smithy hammer to forge something.\n\r", ch );
return;
}
argument = one_argument( argument, arg );
argument = one_argument( argument, arg2 );
if ( !str_prefix( arg, "ring" ) )
wear = ITEM_WEAR_FINGER;
if ( !str_prefix( arg, "necklace" ) )
wear = ITEM_WEAR_NECK;
if ( !str_prefix( arg, "armor" ) )
wear = ITEM_WEAR_BODY;
if ( !str_prefix( arg, "helm" ) )
wear = ITEM_WEAR_HEAD;
if ( !str_prefix( arg, "mask" ) )
wear = ITEM_WEAR_FACE;
if ( !str_prefix( arg, "leggings" ) )
wear = ITEM_WEAR_LEGS;
if ( !str_prefix( arg, "boots" ) )
wear = ITEM_WEAR_FEET;
if ( !str_prefix( arg, "gauntlets" ) )
wear = ITEM_WEAR_HANDS;
if ( !str_prefix( arg, "armplates" ) )
wear = ITEM_WEAR_ARMS;
if ( !str_prefix( arg, "shield" ) )
wear = ITEM_WEAR_SHIELD;
if ( !str_prefix( arg, "belt" ) )
wear = ITEM_WEAR_WAIST;
if ( !str_prefix( arg, "bracer" ) )
wear = ITEM_WEAR_WRIST;
if ( !str_prefix( arg, "anklet" ) )
wear = ITEM_WEAR_ANKLE;
if ( !str_prefix( arg, "weapon" ) )
wear = ITEM_WIELD;
if ( !str_prefix( arg2, "elf" )
|| !str_prefix( arg2, "drow" )
|| !str_prefix( arg2, "elder" )
|| !str_prefix( arg2, "human" ) )
antirace = group2 + group3 + group4 + group5 + group6;
if ( !str_prefix( arg2, "ogre" )
|| !str_prefix( arg2, "demon" )
|| !str_prefix( arg2, "troll" )
|| !str_prefix( arg2, "minotaur" ) )
antirace = group1 + group3 + group4 + group5 + group6;
if ( !str_prefix( arg2, "dwarf" )
|| !str_prefix( arg2, "halfling" )
|| !str_prefix( arg2, "shadow" ) )
antirace = group1 + group2 + group4 + group5 + group6;
if ( !str_prefix( arg2, "illithid" )
|| !str_prefix( arg2, "ghoul" ) )
antirace = group1 + group2 + group3 + group5 + group6;
if ( !str_prefix( arg2, "pixie" ) )
antirace = group1 + group2 + group3 + group4 + group6;
if ( !str_prefix( arg2, "lizardman" ) )
antirace = group1 + group2 + group3 + group4 + group5;
if ( is_number( argument ) )
lvl = atoi( argument );
else
lvl = 0;
if ( wear && antirace && ( lvl < 30 || lvl > ch->level ) )
{
sprintf( buf, "Illegal level. Valid levels are 30 to %d.\n\r", ch->level );
send_to_char( AT_GREY, buf, ch );
return;
}
if ( wear && antirace == 0 )
{
send_to_char( AT_GREY, "Illegal race. Help RACE for valid race list.\n\r", ch );
return;
}
if ( wear )
{
#ifdef NEW_MONEY
if ( (ch->money.gold + (ch->money.silver/SILVER_PER_GOLD) +
(ch->money.copper/COPPER_PER_GOLD) ) < (lvl * 100) )
{
#else
if ( ch->gold < lvl * 10000 )
{
#endif
send_to_char( AT_GREY, "You do not have enough money to create the base item of this level.\n\r", ch );
return;
}
else
if ( wear == ITEM_WIELD )
obj = create_object( get_obj_index( OBJ_VNUM_TO_FORGE_W ), lvl );
else
obj = create_object( get_obj_index( OBJ_VNUM_TO_FORGE_A ), lvl );
#ifdef NEW_MONEY
obj->cost.silver = obj->cost.copper = 0;
obj->cost.gold = lvl * 100;
#else
obj->cost = lvl * 10000;
#endif
obj->weight = lvl * 0.15;
obj->level = lvl;
obj->anti_race_flags = antirace;
if ( obj->level >= 101 )
obj->extra_flags += ITEM_NO_DAMAGE;
obj->wear_flags += wear;
forge_obj( ch, obj );
}
else
do_forge( ch, "" );
return;
}
void do_spit( CHAR_DATA *ch, char *argument )
{
AFFECT_DATA af;
CHAR_DATA *victim;
char arg[ MAX_INPUT_LENGTH ];
int dam;
if ( ch->race != RACE_LIZARDMAN )
{
send_to_char( AT_GREY, "Huh?\n\r", ch );
return;
}
if ( ch->race_wait > 0 )
return;
if ( !ch->fighting )
{
send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
return;
}
one_argument( argument, arg );
victim = ch->fighting;
if ( arg[0] != '\0' )
if ( !( victim = get_char_room( ch, arg ) ) )
{
send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
return;
}
dam = ch->level + number_range( ch->level, ch->level * 4 );
damage( ch, victim, dam, gsn_spit );
ch->race_wait = 36;
if ( !victim || victim->position == POS_DEAD || !victim->in_room
|| victim->in_room != ch->in_room )
return;
if ( number_percent( ) < 25 )
{
int location = number_range( 0, 1 );
switch( location )
{
case 0:
if ( victim->race != RACE_ILLITHID )
{
act( AT_DGREEN, "You spit right in $S eyes!", ch, NULL, victim, TO_CHAR );
act( AT_DGREEN, "$n spit into $N's eyes!", ch, NULL, victim, TO_NOTVICT );
act( AT_DGREEN, "$n spit into your eyes!", ch, NULL, victim, TO_VICT );
if ( !IS_AFFECTED( victim, AFF_BLIND ) )
{
send_to_char( AT_WHITE, "You are blinded!", victim );
act( AT_WHITE, "$n is blinded!", victim, NULL, NULL, TO_ROOM );
af.type = gsn_spit;
af.level = ch->level;
af.duration = 0;
af.location = APPLY_HITROLL;
af.modifier = -10;
af.bitvector = AFF_BLIND;
affect_to_char( victim, &af );
af.location = APPLY_AC;
af.modifier = 50;
affect_to_char( victim, &af );
}
}
break;
case 1:
act( AT_DGREEN, "You spit right in $S mouth!", ch, NULL, victim, TO_CHAR );
act( AT_DGREEN, "$n spit into $N's mouth! Gross!", ch, NULL, victim, TO_NOTVICT );
act( AT_DGREEN, "$n spit into your mouth!", ch, NULL, victim, TO_VICT );
send_to_char( AT_WHITE, "The acidic spit burns your mouth and throat.\n\r", victim );
STUN_CHAR( victim, 2, STUN_MAGIC );
break;
}
}
if ( !saves_spell( ch->level, victim ) && victim->race != RACE_GHOUL )
{
af.type = gsn_poison;
af.level = ch->level;
af.duration = 2;
af.location = APPLY_STR;
af.modifier = -3;
af.bitvector = 0;
affect_join( victim, &af );
}
return;
}