/***************************************************************************
* 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. *
* *
* Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David *
* Love, Guilherme 'Willie' Arnold, and Mitchell Tse. *
* *
* In order to use any part of this Envy Diku Msud, you must comply with *
* the original Diku license in 'license.doc', the Merc license in *
* 'license.txt', as well as the Envy license in 'license.nvy'. *
* 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. *
***************************************************************************/
/*$Id: cls_rng.c,v 1.50 2005/03/23 14:47:01 ahsile Exp $*/
#if defined( macintosh )
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include "merc.h"
char* target_name;
int spell_force_of_nature( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( IS_AFFECTED4( victim, AFF_FORCE_OF_NATURE ) )
{
affect_strip(victim, sn);
if(skill_table[sn].msg_off)
{
send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim );
send_to_char(C_DEFAULT, "\n\r", victim );
}
act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT);
victim->shields -= 1;
return SKPELL_NO_DAMAGE;
}
if ( !IS_SHIELDABLE( victim ) )
return SKPELL_MISSED;
af.type = sn;
af.level = level;
af.duration = -1;
af.location = APPLY_HITROLL;
if( !IS_NPC( ch ) )
{
af.modifier = ( ( ch->level + ch->pcdata->learned[sn] / 10 ) ) * 2 / 3;
}
else
{
af.modifier = ( ch->level + 100 ) * 2 / 3;
}
af.bitvector = AFF_FORCE_OF_NATURE;
affect_to_char4( victim, &af );
af.location = APPLY_DAMROLL;
if( !IS_NPC( ch ) )
{
af.modifier = ( ch->level + ( ch->pcdata->learned[sn] / 10 ) ) * 2 / 3;
}
else
{
af.modifier = ( ch->level + 100 ) * 2 / 3;
}
affect_to_char4( victim, &af );
af.location = APPLY_STR;
af.modifier = ch->level / 10;
affect_to_char4( victim, &af );
af.location = APPLY_DEX;
af.modifier = ch->level / 10;
affect_to_char4( victim, &af );
af.location = APPLY_SAVING_SPELL;
if( !IS_NPC( ch ) )
{
af.modifier = ( ch->level + ( ch->pcdata->learned[sn] / 10 ) ) / 3 * -1;
}
else
{
af.modifier = ( ch->level + 100 ) * 2 / 3 * -1;
}
affect_to_char4( victim, &af );
victim->shields += 1;
send_to_char(AT_GREEN, "Your soul is fused with a force of nature.\n\r", victim );
act(AT_GREEN, "$n's soul is fused with a force of nature.", victim, NULL, NULL, TO_ROOM );
return SKPELL_NO_DAMAGE;
}
int spell_forestwalk( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( victim->position == POS_FIGHTING )
return SKPELL_BOTCHED;
if ( is_affected( victim, sn ) )
{
affect_strip(victim, sn);
if(skill_table[sn].msg_off)
{
send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim );
send_to_char(C_DEFAULT, "\n\r", victim );
}
act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT);
return SKPELL_NO_DAMAGE;
}
af.type = sn;
af.level = level;
af.duration = -1;
af.location = APPLY_NONE;
af.modifier = level;
af.bitvector = 0;
affect_to_char( victim, &af );
if ( ch != victim )
send_to_char(AT_DGREEN, "You call forth the power of the forests.\n\r", ch );
send_to_char(AT_DGREEN, "The power of the forests rests upon you.\n\r", victim );
return SKPELL_NO_DAMAGE;
}
int spell_mountainwalk( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( victim->position == POS_FIGHTING )
return SKPELL_BOTCHED;
if ( is_affected( victim, sn ) )
{
affect_strip(victim, sn);
if(skill_table[sn].msg_off)
{
send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim );
send_to_char(C_DEFAULT, "\n\r", victim );
}
act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT);
return SKPELL_NO_DAMAGE;
}
af.type = sn;
af.level = level;
af.duration = -1;
af.location = APPLY_NONE;
af.modifier = level;
af.bitvector = 0;
affect_to_char( victim, &af );
if ( ch != victim )
send_to_char(AT_ORANGE, "You call forth the power of the mountains and hills.\n\r", ch );
send_to_char(AT_ORANGE, "The power of the mountains and hills rests upon you.\n\r", victim );
return SKPELL_NO_DAMAGE;
}
int spell_plainswalk( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( victim->position == POS_FIGHTING )
return SKPELL_BOTCHED;
if ( is_affected( victim, sn ) )
{
affect_strip(victim, sn);
if(skill_table[sn].msg_off)
{
send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim );
send_to_char(C_DEFAULT, "\n\r", victim );
}
act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT);
return SKPELL_NO_DAMAGE;
}
af.type = sn;
af.level = level;
af.duration = -1;
af.location = APPLY_NONE;
af.modifier = level;
af.bitvector = 0;
affect_to_char( victim, &af );
if ( ch != victim )
send_to_char(AT_YELLOW, "You call forth the power of the plains and deserts.\n\r", ch );
send_to_char(AT_YELLOW, "The power of the plains and deserts rests upon you.\n\r", victim );
return SKPELL_NO_DAMAGE;
}
int spell_swampwalk( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( victim->position == POS_FIGHTING )
return SKPELL_BOTCHED;
if ( is_affected( victim, sn ) )
{
affect_strip(victim, sn);
if(skill_table[sn].msg_off)
{
send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim );
send_to_char(C_DEFAULT, "\n\r", victim );
}
act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT);
return SKPELL_NO_DAMAGE;
}
af.type = sn;
af.level = level;
af.duration = -1;
af.location = APPLY_NONE;
af.modifier = level;
af.bitvector = 0;
affect_to_char( victim, &af );
if ( ch != victim )
send_to_char(AT_PINK, "You call forth the power of the swamps.\n\r", ch );
send_to_char(AT_PINK, "The power of the swamps rests upon you.\n\r", victim );
return SKPELL_NO_DAMAGE;
}
int spell_thunder_strike( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
static const int dam_each [ ] =
{
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 30, 35, 40, 45, 50, 55,
60, 65, 70, 75, 80, 82, 85, 90, 95, 100,
105, 110, 115, 120, 125, 130, 135, 140, 145, 150,
155, 160, 165, 170, 175, 180, 185, 190, 195, 200,
205, 210, 215, 220, 225, 230, 235, 240, 245, 250,
252, 254, 256, 258, 260, 262, 264, 266, 268, 270,
272, 274, 276, 278, 280, 282, 284, 286, 288, 290,
292, 394, 396, 398, 300, 302, 304, 306, 308, 310,
315, 320, 325, 330, 335, 340, 345, 350, 355, 360
};
int dam;
level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 );
level = UMAX( 0, level );
dam = number_range( dam_each[level] / 2, dam_each[level] * 5 );
if ( IS_OUTSIDE( ch ) )
{
dam = (int) (dam * 1.5);
if ( weather_info.sky < SKY_RAINING )
{
dam /= 2;
}
if ( weather_info.sky > SKY_RAINING )
{
send_to_char(AT_WHITE, "The bad weather increases the spells power!\n\r", ch );
dam *= 2;
}
}
if ( saves_spell( level, victim ) )
dam /= 2;
//damage( ch, victim, dam, sn );
return dam;
}
int spell_lightning_storm( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *vch;
int dam;
send_to_char(AT_BLUE, "You call forth a thunderous storm!\n\r", ch );
act(AT_BLUE, "$n calls forth a thunderous storm.", ch, NULL, NULL, TO_ROOM );
if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE))
{
send_to_char(AT_WHITE, "You are in a safe room!", ch);
return SKPELL_MISSED;
}
for ( vch = char_list; vch; vch = vch->next )
{
if ( vch->deleted || !vch->in_room || vch == ch )
continue;
dam = number_range( ch->level*2, ch->level * 7 );
if ( vch->in_room == ch->in_room )
{
if ( IS_OUTSIDE( ch ) )
{
dam = (int) (dam * 1.5);
if ( weather_info.sky < SKY_RAINING )
{
dam /= 2;
}
if ( weather_info.sky > SKY_RAINING )
{
send_to_char(AT_WHITE, "The bad weather increases the spells power!\n\r", ch );
dam *= 2;
}
}
if ( saves_spell( level, vch ) )
dam /= 2;
damage( ch, vch, dam, sn );
continue;
}
if ( vch->in_room->area == ch->in_room->area )
send_to_char(AT_ORANGE, "The earth trembles and shivers.\n\r", vch );
}
return SKPELL_NO_DAMAGE;
}
int spell_friend_of_nature( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( IS_AFFECTED( victim, AFF_PEACE) )
return SKPELL_MISSED;
af.type = sn;
af.level = level;
af.duration = number_fuzzy( level / 5 );
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_PEACE;
affect_to_char( victim, &af );
send_to_char(AT_BLUE, "You the protective forces of nature come over you.\n\r", victim );
act(AT_BLUE, "$n looks like he is one with nature.", victim, NULL, NULL, TO_ROOM );
return SKPELL_NO_DAMAGE;
}
int spell_refreshing_rain( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *vch;
send_to_char(AT_BLUE, "You enchant the heavens to rain a healing water.\n\r", ch );
act(AT_ORANGE, "$n causes the heavens to rain a healing rain.", ch, NULL, NULL, TO_ROOM );
for ( vch = char_list; vch; vch = vch->next )
{
if ( vch->deleted || !vch->in_room )
continue;
if ( vch->in_room == ch->in_room )
{
if( IS_OUTSIDE( ch ) )
{
spell_heal( skill_lookup("heal"), ch->level + 50, ch, vch );
}
else
{
spell_heal( skill_lookup("heal"), ch->level / 2, ch, vch );
}
continue;
}
}
return SKPELL_NO_DAMAGE;
}
int spell_storm_seeker(int sn, int level, CHAR_DATA *ch, void *vo)
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
int loss;
if ( is_affected( victim, sn ))
{
send_to_char(AT_RED, "A curse has already been inflicted.\n\r", ch );
return SKPELL_MISSED;
}
if( IS_OUTSIDE( ch ) )
{
loss = number_fuzzy( ch->level * 2 / 3 );
}
else
{
loss = number_fuzzy( ch->level * 2 / 4 );
}
af.type = sn;
af.level = level;
af.duration = level / 6;
af.location = APPLY_SAVING_SPELL;
af.modifier = loss;
af.bitvector = AFF_CURSE;
affect_to_char( victim, &af );
af.location = APPLY_DAM_WIND;
af.modifier = 0 - loss;
af.bitvector = AFF_CURSE;
affect_to_char( victim, &af );
if(ch != victim)
send_to_char(AT_GREEN, "Ok.\n\r", ch );
send_to_char(AT_GREEN, "A lightning bolt strikes you square in the chest.\n\r", victim);
spell_lightning_bolt( skill_lookup("lightning bolt"), ch->level, ch, victim );
return SKPELL_NO_DAMAGE;
}
int spell_essence_of_gaia( int sn, int level, CHAR_DATA *ch, void *vo )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( IS_AFFECTED4( victim, AFF_ESSENCE_OF_GAIA ) )
{
affect_strip(victim, sn);
if(skill_table[sn].msg_off)
{
send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim );
send_to_char(C_DEFAULT, "\n\r", victim );
}
act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT);
victim->shields -= 1;
return SKPELL_NO_DAMAGE;
}
if ( IS_AFFECTED2( victim, AFF_GOLDEN_ARMOR ) || IS_AFFECTED4( victim, AFF_GOLDEN_SANCTUARY ) || IS_AFFECTED4( victim, AFF_BIOFEEDBACK ) || IS_AFFECTED( victim, AFF_SANCTUARY ) )
return SKPELL_MISSED;
if ( !IS_SHIELDABLE( victim ) )
return SKPELL_MISSED;
af.type = sn;
af.level = level;
af.duration = -1;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_ESSENCE_OF_GAIA;
affect_to_char4( victim, &af );
victim->shields += 1;
send_to_char(AT_WHITE, "You are surrounded by Gaia's essence.\n\r", victim );
act(AT_WHITE, "$n is surrounded by Gaia's essence.", victim, NULL, NULL, TO_ROOM );
return SKPELL_NO_DAMAGE;
}
int skill_lightning_arrow( int sn, int level, CHAR_DATA *ch, void *vo )
{
ROOM_INDEX_DATA* in_room = NULL;
ROOM_INDEX_DATA* to_room = NULL;
OBJ_DATA* bow;
OBJ_DATA* ammo;
CHAR_DATA* victim = NULL;
int distance = 0;
int target = 0;
int dam = 0;
char buf[MAX_STRING_LENGTH];
/* check conditions */
if (!IS_NPC(ch) && number_percent() > ( ch->pcdata->learned[sn] / 10 ) )
{
send_to_char(C_DEFAULT, "You failed.\n\r", ch);
return SKPELL_MISSED;
}
if ( ! (bow = get_eq_char(ch, WEAR_WIELD) )
|| (bow->value[3] != flag_value (weapon_flags, "shot") )
|| (bow->value[0] != flag_value (ammo_flags, "arrow") ) )
{
send_to_char(AT_WHITE, "You need a BOW and arrows to shoot!\n\r", ch);
return SKPELL_MISSED;
} else if (!(ammo = find_arrows( ch ) ) )
{
send_to_char(AT_WHITE, "You need a bow and ARROWS to shoot!\n\r", ch);
return SKPELL_MISSED;
}
/* calculate damage */
dam = 100;
if ( (target = find_missle_target(sn, ch, (char*) target_name, &victim, &to_room, &distance) ) )
{
ammo->value[0]--;
act( AT_BLUE, "$n draws $s weapon and fires a lightning arrow!", ch, NULL, NULL, TO_ROOM );
if (!ammo->value[0])
ammo->deleted = TRUE;
if (target == SHOOT_HERE)
{
if (ch->fighting == victim)
return dam;
else
{
damage( ch, victim, dam, sn);
multi_hit( victim, ch, TYPE_UNDEFINED ); /* start a fight */
}
}
in_room = ch->in_room;
if (in_room != to_room)
{
char_from_room( ch );
char_to_room( ch, to_room );
}
if ( target == SHOOT_DOOR )
{
sprintf(buf, "Your lightning arrow flies %d rooms away and strikes something solid.", distance);
act( AT_BLUE, buf, ch, NULL, NULL, TO_CHAR );
act( AT_BLUE, "A lightning arrow flies into the area and strikes something solid.", ch, NULL, NULL, TO_ROOM );
}
else if (target == SHOOT_DIST )
{
sprintf(buf, "Your lightning arrow flies %d rooms away and falls harmlessly to the ground.\n\r", distance);
send_to_char(AT_BLUE, buf, ch);
}
else if (target == SHOOT_FOUND )
{
act( AT_BLUE, "A lightning arrow flies into the area and hits $N!", ch, NULL, victim, TO_NOTVICT );
sprintf(buf, "Your lightning arrow flies %d rooms away and hits $N!", distance);
act( AT_BLUE, buf, ch, NULL, victim, TO_CHAR);
act( AT_BLUE, "$n's lightning arrow flies into the area and hits YOU!" , ch, NULL, victim, TO_VICT );
damage( ch, victim, (int) ( dam / (distance + 1) ), sn );
}
char_from_room( ch );
char_to_room( ch, in_room );
}
return SKPELL_NO_DAMAGE;
}