/**************************************************************************/
// magic_re.cpp - spells/skills written by Reave
/***************************************************************************
* 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 the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
/***************************************************************************
* FILE: magic_re.cpp - spells/skills written by Reave *
* (and one by Raphael) *
***************************************************************************/
#include "include.h"
#include "magic.h"
#include "o_lookup.h"
// Prototype definitions
DECLARE_DO_FUN( do_look );
void build_fire( char_data *ch, int chance );
void build_raft( char_data *ch, int chance );
void build_staff( char_data *ch, int chance );
/***************************************************************************
* Prayer - Adds +10 to a random stat modifier *
* By Reave, November 1998 *
***************************************************************************/
SPRESULT spell_prayer( int sn, int level, char_data *ch, void *vo, int )
{
AFFECT_DATA af;
char_data *victim = (char_data *) vo;
if ( is_affected( ch, sn ))
{
ch->println("You have already gained the favour of your god.");
return HALF_MANA;
}
int random;
random = dice(1,13);
ch->println("Your prayer has been granted.");
if (random >= 1 && random <= 12)
{
af.where = WHERE_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level/4;
af.modifier = 10;
af.bitvector = 0;
if (random == 1)
{
af.location = APPLY_ST;
affect_to_char( victim, &af );
victim->println("You feel stronger.");
}
if (random == 2)
{
af.location = APPLY_QU;
affect_to_char( victim, &af );
victim->println("You feel quicker.");
}
if (random == 3)
{
af.location = APPLY_PR;
affect_to_char( victim, &af );
victim->println("You feel more self-confident.");
}
if (random == 4)
{
af.location = APPLY_EM;
affect_to_char( victim, &af );
victim->println("You feel more one with the universe.");
}
if (random == 5)
{
af.location = APPLY_IN;
affect_to_char( victim, &af );
victim->println("You feel lucky.");
}
if (random == 6)
{
af.location = APPLY_CO;
affect_to_char( victim, &af );
victim->println("You feel more durable.");
}
if (random == 7)
{
af.location = APPLY_AG;
affect_to_char( victim, &af );
victim->println("You feel more agile.");
}
if (random == 8)
{
af.location = APPLY_SD;
affect_to_char( victim, &af );
victim->println("You feel more self-disciplined.");
}
if (random == 9)
{
af.location = APPLY_ME;
affect_to_char( victim, &af );
victim->println("You feel like your memory has expanded.");
}
if (random == 10)
{
af.location = APPLY_RE;
affect_to_char( victim, &af );
victim->println("You feel more intelligent.");
}
if (random == 11)
{
af.location = APPLY_HITROLL;
affect_to_char( victim, &af );
victim->println("You feel like you can use your weapon better.");
}
if (random == 12)
{
af.location = APPLY_DAMROLL;
affect_to_char( victim, &af );
victim->println("You feel like you can do more damage with your weapon.");
}
}
else
{
af.where = WHERE_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level/4;
af.modifier = -10;
af.bitvector = 0;
af.location = APPLY_SAVES;
affect_to_char( victim, &af );
victim->println("You feel a bit more protected from magic.");
}
act("$n glows very slightly for a moment.",victim,NULL,NULL,TO_ROOM);
return FULL_MANA;
}
/*********************************************************************************
* Wildstrike - Wild magic attack spell, pure energy + chance of random affect *
* By Reave, November 1998 *
*********************************************************************************/
SPRESULT spell_wildstrike( int sn, int level, char_data *ch, void *vo,int )
{
char_data *victim = (char_data *) vo;
AFFECT_DATA af;
int chance; /* 4% chance caster hits himself */
chance = dice(1,25);
if (chance == 1)
{
act("$n blasts $mself with a stream of pure energy!",ch,NULL,victim,TO_NOTVICT);
act("Your stream of pure energy goes wild and hits you!",ch,NULL,victim,TO_CHAR);
int dam;
dam = dice(level, 10);
if ( saves_spell( level, victim,DAMTYPE(sn) )) dam /= 2;
damage_spell( ch, ch, dam, sn, DAMTYPE(sn),true );
return FULL_MANA;
}
else /* 96% chance caster hits intended target */
{
act("$n blasts $N with a stream of pure energy!",ch,NULL,victim,TO_NOTVICT);
act("$n blasts you with a stream of pure energy!",ch,NULL,victim,TO_VICT);
act("You blast $N with a stream of pure energy!",ch,NULL,victim,TO_CHAR);
int dam;
dam = dice(level, 9);
if ( !saves_spell( level, victim,DAMTYPE(sn) )) {
int dtoss;
dtoss = dice(1,28); /* 25% chance of random short-duration
bad affect in addition to full damage */
switch (dtoss) {
case 1 :
if ( !is_affected( ch, gsn_blindness )) {
af.where = WHERE_AFFECTS;
af.type = gsn_blindness;
af.level = level;
af.location = APPLY_HITROLL;
af.modifier = -4;
af.duration = level / 10;
af.bitvector = AFF_BLIND;
affect_to_char( victim, &af );
victim->println("You are blinded!");
act("$n appears to be blinded.",victim,NULL,NULL,TO_ROOM);
}
break;
case 2 :
if ( !is_affected( ch, gsn_weaken )) {
af.where = WHERE_AFFECTS;
af.type = gsn_weaken;
af.level = level;
af.duration = level / 10;
af.location = APPLY_ST;
af.modifier = -1 * (level / 3);
af.bitvector = AFF_WEAKEN;
affect_to_char( victim, &af );
victim->println("You feel your strength slip away.");
act("$n looks tired and weak.",victim,NULL,NULL,TO_ROOM);
}
break;
case 3 :
if ( !is_affected( ch, gsn_giant_strength )) {
af.where = WHERE_AFFECTS;
af.type = gsn_giant_strength;
af.level = level;
af.duration = level / 10;
af.location = APPLY_ST;
af.modifier = 1 + level/5;
af.bitvector = 0;
affect_to_char( victim, &af );
victim->println("Your muscles surge with heightened power!");
act("$n's muscles surge with heightened power.",victim,NULL,NULL,TO_ROOM);
}
break;
case 4 :
if ( !is_affected( ch, gsn_slow )) {
af.where = WHERE_AFFECTS;
af.type = gsn_slow;
af.level = level;
af.duration = level/2;
af.location = APPLY_QU;
af.modifier = -1 - level/5;
af.bitvector = AFF_SLOW;
affect_to_char( victim, &af );
victim->println("You feel yourself slowing d o w n...");
act("$n starts to move in slow motion.",victim,NULL,NULL,TO_ROOM);
}
break;
case 5 :
ROOM_INDEX_DATA *pRoomIndex;
pRoomIndex = get_random_room(victim);
if (victim != ch)
victim->println("You have been teleported!");
act( "$n vanishes!", victim, NULL, NULL, TO_ROOM );
char_from_room( victim );
char_to_room( victim, pRoomIndex );
act( "$n slowly fades into existence.", victim, NULL, NULL, TO_ROOM );
do_look( victim, "auto" );
break;
case 6 :
if ( !is_affected( ch, gsn_haste )) {
af.where = WHERE_AFFECTS;
af.type = gsn_haste;
af.level = level;
af.duration = level / 10;
af.location = APPLY_QU;
af.modifier = 1 + level/5;
af.bitvector = AFF_HASTE;
affect_to_char( victim, &af );
victim->println("You feel yourself moving more quickly.");
act("$n is moving more quickly.",victim,NULL,NULL,TO_ROOM);
}
break;
case 7 :
if ( !is_affected( ch, gsn_faerie_fire )) {
af.where = WHERE_AFFECTS;
af.type = gsn_faerie_fire;
af.level = level;
af.duration = level / 10;
af.location = APPLY_AC;
af.modifier = 2 * level;
af.bitvector = AFF_FAERIE_FIRE;
affect_to_char( victim, &af );
victim->println("You are surrounded by a pink outline.");
act( "$n is surrounded by a pink outline.", victim, NULL, NULL, TO_ROOM );
}
break;
default:
break;
}
}
else dam /= 2;
damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true );
return FULL_MANA;
}
}
/***************************************************************************
* Smite - Clerical attack spell, alignment dependent damage *
* By Reave, November 1998 *
***************************************************************************/
SPRESULT spell_smite(int sn, int level, char_data *ch, void *vo,int )
{
char_data *victim = (char_data *) vo;
int dam;
act("$n calls down the wrath of the gods!",ch,NULL,NULL,TO_ROOM);
ch->println("You call down the wrath of the gods!");
dam = dice( level, 8 );
// Should do normal damage unless good vs. evil - if this
// is the case, will do 20% extra damage
if ( IS_EVIL(ch) && IS_GOOD(victim) )
{
dam = (dam*12)/10;
if ( saves_spell( level, victim, DAM_NEGATIVE ) )
dam /= 2;
damage_spell( ch, victim, dam, sn,DAM_NEGATIVE,true);
return FULL_MANA;
}
if ( IS_GOOD(ch) && IS_EVIL(victim) )
{
dam = (dam*12)/10;
if ( saves_spell( level, victim, DAM_HOLY ) )
dam /= 2;
damage_spell( ch, victim, dam, sn,DAM_HOLY,true);
return FULL_MANA;
}
if ( IS_GOOD(ch) && IS_GOOD(victim) )
{
dam /= 3;
if ( saves_spell( level, victim, DAM_HOLY ) )
dam /= 2;
damage_spell( ch, victim, dam, sn,DAM_HOLY,true);
return FULL_MANA;
}
if ( IS_EVIL(ch) && IS_EVIL(victim) )
{
dam /= 3;
if ( saves_spell( level, victim, DAM_HOLY ) )
dam /= 2;
damage_spell( ch, victim, dam, sn,DAM_HOLY,true);
return FULL_MANA;
}
else
{
if ( saves_spell( level, victim, DAM_HOLY ) )
dam /= 2;
damage_spell( ch, victim, dam, sn,DAM_HOLY,true);
return FULL_MANA;
}
return FULL_MANA;
}
/***************************************************************************
* Cantrip - Random minor magical affect *
* By Raphael, November 1998 *
***************************************************************************/
SPRESULT spell_cantrip( int , int level, char_data *ch, void *vo, int )
{
char_data *victim = (char_data *) vo;
OBJ_DATA *ouritem;
char_data *gch;
AFFECT_DATA af;
int ct=0;
int res;
if(level<20)
res=dice(1,5);
else
res=dice(1,9);
switch(res)
{
case 1:
if ( level < 15 )
{
act("$n causes a small gust of wind to blow.", ch, NULL, NULL, TO_ROOM );
ch->println("You cause a small gust of wind to blow.");
}
else
{
act("$n causes a small gust of wind to begin to blow.\nThe wind picks up speed, causing you to struggle to keep your footing!", ch, NULL, NULL, TO_ROOM );
ch->println("You cause a small gust of wind to blow that quickly\npicks up enough speed to make it difficult to keep your footing!");
}
break;
case 2:
if ( level < 15 )
{
act("You hear a faint tinkling of ethereal music.", ch, NULL, NULL, TO_ROOM );
ch->println("You cause a faint tinkling of ethereal music to be heard.");
}
else
{
act("A ghostly bard appears, playing some beautiful music.\nThe bard finishes, and fades from view.", ch, NULL, NULL, TO_ROOM );
ch->println("You summon a ghostly bard that begins playing some beautiful music.\nThe bard finishes, and fades from view.");
}
break;
case 3:
if ( level < 15 )
{
act("$n causes a small glowing ball to float over $s hand!\nThe ball dances back and forth for a while, and then vanishes.",ch, NULL, NULL, TO_ROOM );
ch->println("You cause a small glowing ball to float over your hand!\nThe ball dances back and forth for a while, and then vanishes.");
}
else
{
act("$n causes several glowing balls to float over $s hand!\nThe balls dance back and forth for a while, and then vanish.", ch, NULL, NULL, TO_ROOM );
ch->println("You cause several glowing balls to float over your hand!\nThe balls dance back and forth for a while, and then vanish.");
}
break;
case 4:
if ( level < 15 )
{
act("You hear what sounds like the faint sound of thunder.", ch, NULL, NULL, TO_ROOM );
ch->println("You cause the faint sound of thunder to be heard.");
}
else
{
act("$n claps $s hands together, causing a loud crash of thunder!", ch, NULL, NULL, TO_ROOM );
ch->println("You clap your hands together, causing a loud crash of thunder!");
}
break;
case 5:
if ( level < 15 )
{
act("A faint aura begins to glow around $N,\nbut it quickly fades.", ch, NULL, victim,TO_NOTVICT);
act("You begin to glow with a faint aura!\nThe aura quickly fades.",ch,NULL,victim,TO_VICT);
act("You cause a faint aura to begin to glow around $N,\nbut it quickly fades.",ch,NULL,victim,TO_CHAR);
}
else
{
act("A bright green aura begins to glow around $N!\nThe aura shimmers and waivers for several seconds, and then fades.",ch,NULL,victim,TO_NOTVICT);
act("A bright green aura begins to glow around you!\nThe aura shimmers and waivers for several seconds, and then fades.",ch,NULL,victim,TO_VICT);
if ( victim!=ch )
act("You cause a bright green aura to begin to glow around $N!\nThe aura shimmers and waivers for several seconds, and then fades.",ch,NULL,victim,TO_CHAR);
else
act("You cause a bright green aura to begin to glow around yourself!\nThe aura shimmers and waivers for several seconds, and then fades.",ch,NULL,victim,TO_CHAR);
}
break;
case 6: // make our papaya
ouritem = create_object( get_obj_index( OBJ_VNUM_MUSHROOM ));
free_string( ouritem->description );
free_string( ouritem->name );
free_string( ouritem->short_descr );
ouritem->value[0] = level / 2;
ouritem->value[1] = level;
ouritem->timer = level / 5;
ouritem->description = str_dup( "A nicely shaped papaya awaits to be munched on." );
ouritem->short_descr = str_dup( "a nice sized papaya" );
ouritem->name = str_dup( "papaya" );
obj_to_room( ouritem, ch->in_room );
act( "$p suddenly appears.", ch, ouritem, NULL, TO_ROOM );
act( "$p suddenly appears.", ch, ouritem, NULL, TO_CHAR );
break;
case 7:
for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) {
if (( gch != ch ) && ( !IS_AFFECTED( gch, AFF_INVISIBLE )) && ( dice( 1,10 ) == 1 ))
{
ct++;
act( "$n slowly fades out of existence.", gch, NULL, NULL, TO_ROOM );
gch->println("You slowly fade out of existence.");
af.where = WHERE_AFFECTS;
af.type = gsn_invisibility;
af.level = level/2;
af.duration = 24;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_INVISIBLE;
affect_to_char( gch, &af );
}
}
if ( ct )
{
if( ct > 1 )
ch->printlnf( "Your spell has caused %d people to disappear!", ct);
else
ch->println("Your spell has caused one person to disappear!");
}
else
{
act("$N appears to fade in and out of existance!",ch,NULL,victim,TO_NOTVICT);
act("$N appears to fade in and out of existance!",ch,NULL,victim,TO_VICT);
if( victim != ch )
act("You cause $N to appear to fade in and out of existance!",ch,NULL,victim,TO_CHAR);
else
act("You appear to fade in and out of existance!",ch,NULL,victim,TO_CHAR);
}
break;
case 8:
ouritem = create_object( get_obj_index( OBJ_VNUM_LIGHT_BALL ));
obj_to_room( ouritem, ch->in_room );
act( "$n causes $p to appear!", ch, ouritem, NULL, TO_ROOM );
act( "You cause $p to appear!", ch, ouritem, NULL, TO_CHAR );
break;
case 9:
for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room )
{
if (( gch != ch ) && ( !IS_AFFECTED(gch, AFF_FLYING)) && ( dice( 1,10 ) == 1 ))
{
ct++;
act( "$n's feet raise off the ground!", gch, NULL, NULL, TO_ROOM );
gch->println("You begin to float above the ground!");
af.where = WHERE_AFFECTS;
af.type = gsn_fly;
af.level = level;
af.duration = level+3;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_FLYING;
affect_to_char( gch, &af );
}
}
if ( ct )
{
if ( ct > 1 )
ch->printlnf( "Your spell has caused %d people to fly!", ct );
else
ch->println("Your spell has caused one person to fly!");
}
else
{
ch->println("Your spell doesn't seem to have had any effect.");
}
break;
default:
break;
}
return FULL_MANA;
}
/***************************************************************************
* Build - woodcraft ability, build fires and various objects *
* By Reave & Kerenos December 1998 *
***************************************************************************/
void do_build( char_data *ch, char *argument )
{
int chance;
char arg[MIL];
argument = one_argument(argument,arg);
chance = get_skill(ch,gsn_build) + 10;
if ( chance < 11 ) {
ch->println("You don't know how to build anything useful.");
return;
}
if ( arg[0] == '\0' ) {
ch->println("Build what?");
ch->println("Syntax is 'build <object>'");
ch->println("Only 'fire', 'raft' and 'staff' are available at this time.");
return;
}
if (!str_cmp(arg,"fire"))
{
build_fire( ch, chance );
}
else if ( !str_cmp(arg,"raft")) // Kerenos
{
build_raft( ch, chance );
}
else if ( !str_cmp(arg,"staff")) // Kerenos
{
build_staff( ch, chance );
}
else
{
ch->println("You can't build that.");
return;
}
}
/***************************************************************************/
SPRESULT spell_augment_hearing( int sn, int level, char_data *ch, void *vo, int )
{
char_data *victim = (char_data *) vo;
AFFECT_DATA af;
if( is_affected( victim, gsn_deafness ))
if( check_dispel( level, victim, gsn_deafness ))
{
act( "Your magic unravels a spell on $N.", ch, NULL, victim, TO_CHAR );
return FULL_MANA;
}
else
{
ch->println("You failed.");
return FULL_MANA;
}
if ( is_affected(victim, sn)) {
if (victim == ch)
ch->println("Your hearing is already augmented.");
else
act("$N already has augmented hearing.",ch,NULL,victim,TO_CHAR);
return HALF_MANA;
}
af.where = WHERE_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level/2;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char( victim, &af );
victim->println("Your hearing is greatly augmented.");
if ( ch != victim )
act("$N's hearing is greatly augmented.",ch,NULL,victim,TO_CHAR);
return FULL_MANA;
}
/***************************************************************************/
SPRESULT spell_aura_of_temperance( int sn, int level, char_data *ch, void *, int )
{
AFFECT_DATA af;
if ( !IS_IMMORTAL( ch )) {
if ( IS_EVIL( ch ) || IS_GOOD( ch ))
{
ch->println("You must walk within the path of balance to use this spell.");
return NO_MANA;
}
}
if ( is_affected( ch, sn )) {
ch->println("You are already affected by this spell.");
return HALF_MANA;
}
af.where = WHERE_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 1 + level/20;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char( ch, &af );
ch->println("You are protected from aggressive creatures.");
return FULL_MANA;
}
/***************************************************************************/
void build_fire( char_data *ch, int chance )
{
if ( !IS_OUTSIDE( ch )
|| IS_WATER_SECTOR( ch->in_room->sector_type )
|| ch->in_room->sector_type == SECT_AIR )
{
ch->println("You can't build a fire here.");
return;
}
if ( chance < number_range( 0, 105 ))
{
ch->println("You can't seem to remember Prometheus' lessons.");
WAIT_STATE( ch, skill_table[gsn_build].beats );
check_improve( ch, gsn_build, false, 1 );
return;
}
OBJ_DATA *fire;
if ( get_obj_index(OBJ_VNUM_FIRE) == NULL )
{
bugf("Vnum %d not found for do_build!", OBJ_VNUM_FIRE);
ch->printlnf( "Vnum %d not found for do_build!, please report to the admin.", OBJ_VNUM_FIRE );
return;
}
fire = create_object( get_obj_index( OBJ_VNUM_FIRE ));
fire->timer = number_fuzzy(4);
obj_to_room( fire, ch->in_room );
act("$n uses the skills taught to mortals by Prometheus to create a fire.",ch,NULL,NULL,TO_ROOM);
ch->println("Remembering the tricks Prometheus taught, you create a fire.");
check_improve( ch,gsn_build,true,2);
WAIT_STATE( ch, skill_table[gsn_build].beats );
return;
}
/***************************************************************************/
void build_raft( char_data *ch, int chance )
{
OBJ_DATA *axe = get_eq_char( ch, WEAR_WIELD );
OBJ_DATA *raft;
if ( ch->in_room->sector_type != SECT_FOREST )
{
ch->println("You must be in a forest to gather the necessary materials.");
return;
}
if ( !axe )
{
ch->println("You must wield an axe to build a raft.");
return;
}
if ( axe->value[0] != WEAPON_AXE )
{
ch->println("You must wield an axe to build a raft.");
return;
}
if ( chance < number_range( 0, 105 ))
{
ch->println("You work hard at building something that looks `rnothing`x like a raft.");
WAIT_STATE( ch, skill_table[gsn_build].beats );
check_improve( ch, gsn_build, false, 1 );
return;
}
if ( get_obj_index(OBJ_VNUM_RAFT) == NULL )
{
bugf("Vnum %d not found for do_build!", OBJ_VNUM_RAFT);
ch->printlnf( "Vnum %d not found for do_build!, please report to the admin.", OBJ_VNUM_RAFT );
return;
}
raft = create_object( get_obj_index( OBJ_VNUM_RAFT ));
raft->timer = 96;
obj_to_room( raft, ch->in_room );
act("$n chops some logs and busies $mself building a raft.",ch,NULL,NULL,TO_ROOM);
ch->println("You build a raft that you feel can keep you afloat.");
check_improve( ch,gsn_build,true,2);
WAIT_STATE( ch, skill_table[gsn_build].beats * 3/2 );
return;
}
/***************************************************************************/
void build_staff( char_data *ch, int chance )
{
OBJ_DATA *staff;
int vlevel, random, numdie, dietype;
if ( ch->in_room->sector_type != SECT_FOREST )
{
ch->println( "You must be in a forest to gather the necessary materials." );
return;
}
if ( chance < number_range( 0, 105 ))
{
ch->println( "You try to fashion a staff but it doesn't seem very sturdy." );
ch->println( "You toss out the useless piece of wood in frustration." );
WAIT_STATE( ch, skill_table[gsn_build].beats );
check_improve( ch, gsn_build, false, 1 );
return;
}
if ( get_obj_index(OBJ_VNUM_STAFF) == NULL )
{
bugf("Vnum %d not found for do_build!", OBJ_VNUM_STAFF);
ch->printlnf( "Vnum %d not found for do_build!, please report to the admin.", OBJ_VNUM_STAFF );
return;
}
staff = create_object( get_obj_index( OBJ_VNUM_STAFF ));
vlevel = UMIN( ch->level, 10 );
// first try to get a random damage based on level
random = number_range( 0, 7 );
numdie = weapon_balance_lookup( vlevel, random, 0 );
dietype = weapon_balance_lookup( vlevel, random, 1 );
// damage lookup failed, use polarmost damage class,
if ( numdie == 0 || dietype == 0 )
{
numdie = weapon_balance_lookup( vlevel, 0, 0 );
dietype = weapon_balance_lookup( vlevel, 0, 1 );
}
staff->value[1] = numdie;
staff->value[2] = dietype;
staff->level = vlevel;
obj_to_room( staff, ch->in_room );
act("$n fashions a usable staff.",ch,NULL,NULL,TO_ROOM);
ch->println( "You fashion a staff out of a nice sturdy branch." );
check_improve( ch,gsn_build,true,2);
WAIT_STATE( ch, skill_table[gsn_build].beats * 3/2 );
return;
}
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/