/**************************************************************************/ // 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 try very hard, but can't start a fire."); 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 strikes flint and steel a few times and starts a small fire.",ch,NULL,NULL,TO_ROOM); ch->println("After trying for a bit, the fire catches and grows bright."); 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; } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /***************************************************************************/