/**************************************************************************/ // magic_ke.cpp - spells/skills written by Kerenos /*************************************************************************** * 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. * **************************************************************************/ #include "include.h" #include "areas.h" #include "magic.h" #include "o_lookup.h" #include "ictime.h" /********************************/ /* START OF FUNCTION PROTOTYPES */ bool check_social( char_data *ch, char *arg, char *arg1, bool global ); /* END OF FUNCTION PROTOTYPES */ /********************************/ /**************************************************************************/ // Kerenos - Sept 98 SPRESULT spell_otterlungs( int sn, int level, char_data *ch, void *, int ) { AFFECT_DATA af; // You may want to omit this check // Would allow character to update his otterlungs if ( is_affected( ch, sn )) { ch->println( "You already are affected by otterlungs." ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = ch->level; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_OTTERLUNGS; affect_to_char( ch, &af ); ch->println("You can now travel underwater without fear of drowning."); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_benedict( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim; AFFECT_DATA af; int chance, stat; victim = ( char_data * ) vo; if ( victim == ch ) { ch->println( "You may only benedict others, it is a selfless supplication." ); return NO_MANA; } if ( !IS_IMMORTAL( ch )) { if ( victim->alliance!= URANGE(ch->alliance -1, victim->alliance, ch->alliance+1)) { act( "You cannot grant a benediction upon $N.", ch, NULL, victim, TO_CHAR ); return HALF_MANA; } // Only works on PC's with simular alignment, (good neutral evil) } // lawful and chaotic makes no difference if ( is_affected( victim, sn )) { act( "The grace of the gods already touch $N.", ch, NULL, victim, TO_CHAR ); return HALF_MANA; } if (( chance = number_range( 0, 1 ))){ stat = number_range( 1, 5 ); // ST QU PR EM IN }else{ stat = number_range( 26, 30); // CO AG SD ME RE } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.location = translate_old_apply_number(stat); // determined above af.modifier = 10; // level dependant or always +10? Balance issue af.bitvector = 0; // will be a fairly low level spell so I think // leaving it at 10 will be ok. affect_to_char( victim, &af ); victim->println( "The gods smile kindly upon you." ); act( "The gods smile kindly upon $N.", ch, NULL, victim, TO_CHAR ); return FULL_MANA; } /***********************************************************************/ SPRESULT spell_maledict( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim; AFFECT_DATA af; int chance, stat; victim = ( char_data * ) vo; if ( victim == ch ) { ch->println( "Your god will not forsake you." ); return NO_MANA; } if ( !IS_IMMORTAL( ch )) { if ( victim->alliance== URANGE(ch->alliance -1, victim->alliance, ch->alliance+1)) { act( "You cannot maledict $N.", ch, NULL, victim, TO_CHAR ); return HALF_MANA; } // Only works on PC's of unequal alignment, (good neutral evil) } // lawful and chaotic makes no difference if ( is_affected( victim, sn )) { act( "The cannot maledict $N any further.", ch, NULL, victim, TO_CHAR ); return HALF_MANA; } if (( chance = number_range( 0, 1 ))){ stat = number_range( 1, 5 ); // ST QU PR EM IN }else{ stat = number_range( 26, 30); // CO AG SD ME RE } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.location = translate_old_apply_number(stat); // determined above af.modifier = -10; // level dependant or always -10? Balance issue af.bitvector = 0; // will be a fairly low level spell so I think // leaving it at -10 will be ok. affect_to_char( victim, &af ); victim->println( "The gods look upon you with distate." ); act( "The gods look upon $N with distate.", ch, NULL, victim, TO_CHAR ); return FULL_MANA; } /****************************************************************************/ SPRESULT spell_earthwalk( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = ( char_data * ) vo; char *buf; if (( victim = get_char_icworld( ch, target_name )) == NULL || victim == ch || victim->in_room == NULL || !can_see_room(ch,victim->in_room ) || IS_SET( victim->in_room->room_flags, ROOM_SAFE ) || IS_SET( victim->in_room->room_flags, ROOM_INDOORS ) || IS_SET( victim->in_room->room_flags, ROOM_ANTIMAGIC ) || IS_SET( victim->in_room->room_flags, ROOM_PET_SHOP ) || IS_SET( victim->in_room->room_flags, ROOM_PRIVATE ) || IS_SET( victim->in_room->room_flags, ROOM_SOLITARY ) || IS_SET( victim->in_room->room_flags, ROOM_NO_RECALL ) || IS_SET( victim->in_room->room_flags, ROOM_NOSCRY ) || IS_SET( victim->in_room->area->area_flags, AREA_NOSCRY ) || IS_SET( victim->in_room->area->area_flags, AREA_NOGATEINTO) || IS_SET( ch->in_room->room_flags, ROOM_NO_RECALL ) || victim->level >= level + 3 || victim->in_room->sector_type == SECT_INSIDE || victim->in_room->sector_type == SECT_CITY || victim->in_room->sector_type == SECT_WATER_SWIM || victim->in_room->sector_type == SECT_WATER_NOSWIM || victim->in_room->sector_type == SECT_AIR || victim->in_room->sector_type == SECT_UNDERWATER || ( !IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL ) // NOT trust || ( IS_NPC(victim) && IS_SET(victim->imm_flags,IMM_SUMMON )) || ( IS_NPC(victim) && saves_spell( level, victim,DAMTYPE(sn))) || ( !IS_NPC(victim) && saves_spell( level, victim, DAMTYPE(sn)))) { ch->println( "You failed." ); return FULL_MANA; } switch ( ch->in_room->sector_type ) { case SECT_FIELD: act("The grass below $n opens up and swallows $m up.",ch,NULL,NULL,TO_ROOM); ch->println( "The grass below you opens wide and swallows you." ); break; case SECT_FOREST: act("$n melts into a tree and vanishes.",ch,NULL,NULL,TO_ROOM); ch->println( "You step into a tree and vanish." ); break; case SECT_HILLS: case SECT_MOUNTAIN: act("$n suddenly sinks into the rocky soil and is gone.",ch,NULL,NULL,TO_ROOM); ch->println( "Suddenly the rocky soil splits open and you sink down." ); break; case SECT_SWAMP: act("The swampy ground under $n bubbles, and $e sinks and is gone.",ch,NULL,NULL,TO_ROOM); ch->println( "The ground under your feet swallows you up." ); break; case SECT_DESERT: act("A sandy whirlpool is created under $n and suddenly $e disappears.",ch,NULL,NULL,TO_ROOM); ch->println( "You flush yourself into the sand and vanish." ); break; case SECT_CAVE: act("$n is sucked into the ground and is longer before you.",ch,NULL,NULL,TO_ROOM); ch->println( "The ground sucks you deep into the bowels of the earth." ); break; default: ch->println( "You could not attune yourself enough to travel." ); return HALF_MANA; break; } char_from_room(ch); char_to_room(ch,victim->in_room); switch ( ch->in_room->sector_type ) { case SECT_FIELD: buf = str_dup("rises from the grass"); break; case SECT_FOREST: buf = str_dup("steps out of a tree"); break; case SECT_HILLS: case SECT_MOUNTAIN: buf = str_dup("rises up from the rocky soil"); break; case SECT_SWAMP: buf = str_dup("rises up from the swampy ground"); break; case SECT_DESERT: buf = str_dup("materializes from the sand"); break; case SECT_CAVE: buf = str_dup("appears from the ground"); break; default: buf = str_dup("appears from nowhere"); // This should never occur break; } act("$n $t.",ch,buf,NULL,TO_ROOM); do_look(ch,"auto"); if ( IS_NPC( ch ) && HAS_TRIGGER( ch, TRIG_ENTRY )) mp_percent_trigger( ch, NULL, NULL, NULL, TRIG_ENTRY ); if ( !IS_NPC( ch )) mp_greet_trigger( ch ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_detect_scry( int sn, int level, char_data *ch, void *, int ) { AFFECT_DATA af; if ( is_affected( ch, sn )) { ch->println( "You can already detect scrying attempts." ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = 0; affect_to_char( ch, &af ); ch->printf( "You are now able to detect scrying attempts." ); return FULL_MANA; } /*****************************************************************************/ SPRESULT spell_sunfire( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim = (char_data *) vo; int dam, dam2; dam2 = number_range( 6, 12); dam = dice( level, dam2 ); if ( !IS_OUTSIDE( ch ) || ( time_info.hour < 6 || time_info.hour > 18 )) { ch->println( "This spell requires the light of the sun to work." ); return NO_MANA; } if ( ch->in_room->sector_type == SECT_CAVE ) { ch->println( "The sun does not shine here." ); return NO_MANA; } if ( saves_spell( level, victim, DAMTYPE(sn))) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn), true ); return FULL_MANA; } /********************************************************************************/ SPRESULT spell_cure_chaotic_poison(int ,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; if ( !is_affected( victim, gsn_chaotic_poison )) { if (victim == ch) ch->println( "You aren't poisoned." ); else act("$N doesn't appear to be poisoned.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if (check_dispel(level,victim,gsn_chaotic_poison )) { victim->println( "The poison no longer courses through your veins!" ); act("$n is no longer poisoned.",victim,NULL,NULL,TO_ROOM); } else ch->println( "Spell failed." ); return FULL_MANA; } /****************************************************************************/ SPRESULT spell_shadowflight( int , int level, char_data *ch, void *vo,int ) { char_data *victim = ( char_data * ) vo; if ( time_info.hour >= 6 && time_info.hour <= 18 ) { ch->println( "You may only use shadowflight under the cloak of night." ); return HALF_MANA; } if (( victim = get_char_icworld( ch, target_name )) == NULL || victim == ch || victim->in_room == NULL || !can_see_room(ch,victim->in_room ) || IS_SET( victim->in_room->room_flags, ROOM_SAFE ) || IS_SET( victim->in_room->room_flags, ROOM_INDOORS ) || IS_SET( victim->in_room->room_flags, ROOM_ANTIMAGIC ) || IS_SET( victim->in_room->room_flags, ROOM_PET_SHOP ) || IS_SET( victim->in_room->room_flags, ROOM_PRIVATE ) || IS_SET( victim->in_room->room_flags, ROOM_SOLITARY ) || IS_SET( victim->in_room->room_flags, ROOM_NO_RECALL ) || IS_SET( victim->in_room->room_flags, ROOM_NOSCRY ) || IS_SET( victim->in_room->area->area_flags, AREA_NOSCRY ) || IS_SET( victim->in_room->area->area_flags, AREA_NOGATEINTO ) || IS_SET( ch->in_room->room_flags, ROOM_NO_RECALL ) || victim->level >= level + 5 || ( !IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL ) // NOT trust || ( IS_NPC(victim) && IS_SET(victim->imm_flags,IMM_SUMMON ))) { ch->println( "You failed." ); return FULL_MANA; } if ( ch->in_room->area->continent != victim->in_room->area->continent ) { ch->println( "The spell cannot span such a great distance." ); return FULL_MANA; } act("$n steps into the night and vanishes.",ch,NULL,NULL,TO_ROOM); ch->println( "You step into the night and vanish." ); char_from_room(ch); char_to_room(ch,victim->in_room); act("The shadows suddenly deepen.",ch,NULL,NULL,TO_ROOM); do_look(ch,"auto"); if ( IS_NPC( ch ) && HAS_TRIGGER( ch, TRIG_ENTRY )) mp_percent_trigger( ch, NULL, NULL, NULL, TRIG_ENTRY ); if ( !IS_NPC( ch )) mp_greet_trigger( ch ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_mirage(int,int,char_data *ch,void *,int ) { ch->mirage = ch->in_room->vnum; ch->mirage_hours = UMAX( 1, number_range( ch->level/4, ch->level/2)); ch->println( "You have attuned your image to this location." ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_commune_with_dead(int, int, char_data *ch,void *vo,int target) { OBJ_DATA *corpse; if (target == TARGET_OBJ) { corpse = (OBJ_DATA *) vo; if (corpse->item_type != ITEM_CORPSE_NPC && corpse->item_type != ITEM_CORPSE_PC) { ch->println( "You can only commune through corpses." ); return HALF_MANA; } act( "A ghostly form rises from $p.", ch, corpse, NULL, TO_CHAR ); if(corpse->killer){ ch->wraplnf("A mental image forms in your mind, you see the outline of %s.", corpse->killer ); }else{ ch->wrapln( "A mental image starts to form in your mind, " "then vanishes before you can focus on it."); } return FULL_MANA; } ch->println( "You can only commune through corpses." ); return HALF_MANA; } /*******************************************************************************/ SPRESULT spell_utterdark( int sn, int level, char_data *ch, void *, int ) { AFFECT_DATA af; if ( IS_SET( ch->in_room->room_flags, ROOM_LAW )) { ch->println( "Spell failed." ); return NO_MANA; } if ( IS_SET( ch->in_room->affected_by, ROOMAFF_UTTERDARK )) { ch->println( "This room is already as dark as it will get." ); return HALF_MANA; } if (IS_SET(ch->in_room->room_flags,ROOM_LAW)) { ch->println( "For a moment the room appears dark, then the darkness dissipates as quickly as it came." ); act( "For a moment the room appears dark, then the darkness dissipates as quickly as it came.", ch, NULL, NULL, TO_ROOM ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = ch->level; af.duration = level/20; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = ROOMAFF_UTTERDARK; affect_to_room( ch->in_room, &af ); ch->println( "Suddenly, everything around you becomes very dark." ); act( "Suddenly, everything around you becomes very dark.", ch, NULL, NULL, TO_ROOM ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_alarm( int sn, int, char_data *ch, void *, int ) { AFFECT_DATA af; if(!ch->in_room){ bug("spell_alarm(): ch->in_room==NULL."); return NO_MANA; } // This should never happen, since entering a room with alarm // should trip the alarm off if ( IS_SET( ch->in_room->affected_by, ROOMAFF_ALARM )) { ch->println( "This room is already alarmed." ); return NO_MANA; } if ( is_affected( ch, sn )) { ch->println( "You cannot place another alarm quite yet." ); return NO_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = ch->level; af.duration = -1; // Permanent af.location = APPLY_NONE; af.modifier = 0; af.bitvector = ROOMAFF_ALARM; affect_to_room( ch->in_room, &af ); ch->in_room->alarm = ch; ch->println( "The alarm has been set." ); af.where = WHERE_AFFECTS; af.type = sn; af.level = ch->level; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = 0; affect_to_char( ch, &af ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_divine_light( int sn, int level, char_data *ch, void *, int ) { OBJ_DATA *dlight; AFFECT_DATA af; if ( is_affected( ch, sn )) { ch->println( "You cannot summon the mists quite yet." ); return NO_MANA; } if ( get_obj_index( OBJ_VNUM_DIVINE_LIGHT ) == NULL ) { bugf("Vnum %d not found for Divine Light!", OBJ_VNUM_DIVINE_LIGHT ); ch->printlnf( "Vnum %d not found for Divine Light, please report to the admin.", OBJ_VNUM_DIVINE_LIGHT ); return NO_MANA; } dlight = create_object( get_obj_index( OBJ_VNUM_DIVINE_LIGHT )); dlight->timer = 25; dlight->value[3] = (100 + ((level / 10) * 5)); // Heal bonus of 5% per 10 levels dlight->value[4] = (100 + ((level / 20) * 5)); // Mana bonus of 5% per 20 levels obj_to_room( dlight, ch->in_room ); act( "$n calls up to the heavens and a shimmering globe of light descends,", ch, NULL, NULL, TO_ROOM ); act( "diffusing into an ethereal, glowing mist that hovers on the floor.", ch, NULL, NULL, TO_ROOM ); act( "You call up to the heavens and a shimmering globe of light descends,", ch, NULL, NULL, TO_CHAR ); act( "diffusing into an ethereal, glowing mist that hovers on the floor.", ch, NULL, NULL, TO_CHAR ); af.where = WHERE_AFFECTS; af.type = sn; af.level = ch->level; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = 0; affect_to_char( ch, &af ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_immolation( int sn, int level, char_data *ch, void *, int ) { char_data *vch; AFFECT_DATA af; if ( is_affected( ch, gsn_immolation )) { ch->println( "You failed." ); return NO_MANA; } ch->println( "You are engulfed within the flames of wizardry." ); act( "$n is engulfed in fire.", ch, NULL, NULL, TO_ROOM ); af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 2; af.location = APPLY_HITROLL; af.modifier = get_skill(ch, gsn_sorcery ) / 5; af.bitvector = 0; affect_to_char( ch, &af ); af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 2; af.location = APPLY_DAMROLL; af.modifier = get_skill(ch, gsn_sorcery ) / 5; af.bitvector = 0; affect_to_char( ch, &af ); af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 2; af.location = APPLY_AC; af.modifier = 0 - get_skill(ch, gsn_sorcery ) / 2; af.bitvector = 0; affect_to_char( ch, &af ); ch->println( "Tongues of flame from your body fly forth." ); act( "Fire from $n reach out threatening to consume you.", ch, NULL, NULL, TO_ROOM ); for ( vch = ch->in_room->people; vch; vch = vch->next_in_room ) { if ( vch->in_room == NULL ) continue; if ( vch->in_room == ch->in_room ) { if ( vch != ch && !is_safe_spell(ch,vch,true)) if (IS_AFFECTED(vch,AFF_FLYING)) damage_spell(ch,vch,0,sn,DAMTYPE(sn),true); else damage_spell( ch,vch, dice(level, 10 ) + 10, sn, DAMTYPE(sn),true); continue; } } return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_treeform( int sn, int level, char_data *ch, void *, int ) { AFFECT_DATA af; if ( ch->in_room->sector_type != SECT_FOREST ) { ch->println( "You can only cast this spell in a forest." ); return NO_MANA; } if ( IS_SET( ch->affected_by2, AFF2_TREEFORM )) { ch->println( "You have already assumed the shape of a tree." ); return NO_MANA; } if ( !is_affected( ch, gsn_barkskin )) { ch->println( "You must make your skin as that of a tree first." ); return NO_MANA; } af.where = WHERE_AFFECTS2; af.type = sn; af.level = level; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF2_TREEFORM; affect_to_char( ch, &af ); ch->println( "Your body transforms into the shape of a tree." ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_pass_without_trace( int sn, int level, char_data *ch, void *, int ) { AFFECT_DATA af; if (IS_AFFECTED2(ch, AFF2_PASSWOTRACE)) { ch->println("You are not leaving any footprints already."); return NO_MANA; } af.where = WHERE_AFFECTS2; af.type = sn; af.level = level; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bitvector= AFF2_PASSWOTRACE; affect_to_char( ch, &af ); ch->println( "You will not leave footprints outdoors." ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_pine_needles( int sn, int level, char_data *ch, void *, int ) { AFFECT_DATA af; if ( ch->in_room->sector_type != SECT_FOREST ) { ch->println( "You can only cast this spell in a forest." ); return NO_MANA; } if ( is_affected( ch, sn )) { ch->println( "Pine needles already swirl about you." ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.modifier = -(level / 5 + 1); // -2 to -20 af.location = APPLY_AC; af.bitvector = 0; affect_to_char( ch, &af ); ch->println( "A swirl of pine needles surrounds you." ); act( "A swirl of pine needles surrounds $n.", ch, NULL, NULL, TO_ROOM ); return FULL_MANA; } /*******************************************************************************/ void do_needlepoint( char_data *ch, char *argument ) { int ac; // to store the -ac value to be ++ed AFFECT_DATA paf; char_data *victim = NULL; char arg1[MIL]; char arg2[MIL]; if ( !is_affected( ch, gsn_pine_needles )){ ch->println("You have to be affected by pine needles to use this spell."); return; } argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if ( IS_NULLSTR( arg1 )) { victim = ch->fighting; if (victim == NULL) { ch->println( "But you aren't fighting anyone!" ); return; } } else if (( victim = get_char_room( ch, arg1 )) == NULL ) { ch->println( "They aren't here." ); return; } if ( !can_initiate_combat( ch, victim, CIT_GENERAL )) return; // point to the right affect in ch->affected paf = *affect_find( ch->affected, gsn_pine_needles ); // store the ac from the pine needles into int ac ac = paf.modifier; if ( ch->desc && ch->desc->repeat>4 ) { ac += 5; // spamming point will weaken the needles by 5 :) ch->wrapln( "The constant stream of needles issuing forth causes some of the other needles to drop harmlessly to the ground." ); } if ( ac >= 0 ) { ch->println( "You have depleted all your pine needles." ); affect_strip( ch, gsn_pine_needles ); return; } // increment ac, lessening their reserve by one (or all if 10 or more and all is used) if ( !str_cmp( arg2, "all" )) { if ( ac > -10 ) { ch->println( "You don't have enough needles swirling about you to do this." ); return; } else { // all of them shoot (acid blast damage) act( "You shoot a barrage of pine needles at $N.", ch, NULL, victim, TO_CHAR ); act( "$n let's loose a barrage of needles at $N.", ch, NULL, victim, TO_ROOM ); if ( ac <= -20 ) { damage_spell( ch, victim, ( dice( ch->level, 10 )) * 2, gsn_pine_needles, DAM_PIERCE, true ); ch->mana -= 75; } else { damage_spell( ch, victim, ( dice( ch->level, 10 )) , gsn_pine_needles, DAM_PIERCE, true ); ch->mana -= 30; } ch->println( "You have depleted all your pine needles." ); affect_strip( ch, gsn_pine_needles ); WAIT_STATE(ch, skill_table[gsn_pine_needles].beats * 3 / 2); return; } } act( "One of your pine needles flies towards $N.", ch, NULL, victim, TO_CHAR ); act( "A needle from $n flies straight towards you.", ch, NULL, victim, TO_VICT ); act( "A needle from $n flies towards $N.", ch, NULL, victim, TO_NOTVICT ); damage_spell( ch, victim, ch->level / 4 + 2, gsn_pine_needles, DAM_PIERCE, true ); ch->mana -= 5; WAIT_STATE(ch, skill_table[gsn_pine_needles].beats ); // increment and update AC in character's thingie :) ac++; affect_strip( ch, gsn_pine_needles ); paf.where = WHERE_AFFECTS; paf.type = gsn_pine_needles; paf.level = ch->level; paf.duration = 24; paf.modifier = ac; paf.location = APPLY_AC; paf.bitvector = 0; affect_to_char( ch, &paf ); return; } /*******************************************************************************/ SPRESULT spell_spirit_hammer(int sn, int, char_data *ch, void *, int ) { AFFECT_DATA af; OBJ_INDEX_DATA *pObj; OBJ_DATA *obj; OBJ_DATA *cObj; int numdie, dietype, random, vlevel; if ( is_affected( ch, gsn_spirit_hammer )) { ch->println("You cannot summon another hammer quite yet."); return NO_MANA; } if (( pObj = get_obj_index( OBJ_VNUM_SPIRIT_HAMMER )) == NULL ) { ch->printf( "Vnum %d not found for Spirit Hammer, please report to the admin.", OBJ_VNUM_SPIRIT_HAMMER ); return NO_MANA; } obj = create_object( pObj); obj->level = ch->level; vlevel = obj->level + number_range( 0, (( 100 - 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 ); } obj->attune_flags = ATTUNE_NEED_TO_USE|ATTUNE_HARD|ATTUNE_INFURIATING|ATTUNE_PREVIOUS; obj->attune_id = ch->id; obj->timer = 48; obj->value[1] = numdie; obj->value[2] = dietype; obj->wear_loc = WEAR_WIELD; if ( IS_EVIL( ch )){ SET_BIT( obj->extra_flags, OBJEXTRA_ANTI_GOOD ); } if ( IS_GOOD( ch )){ SET_BIT( obj->extra_flags, OBJEXTRA_ANTI_EVIL ); } af.where = WHERE_AFFECTS; af.type = sn; af.level = ch->level; af.duration = 48; af.location = APPLY_NONE; af.modifier = 0; af.bitvector= 0; affect_to_char( ch, &af ); ch->println( "You call to the heavens and your cry is heard." ); ch->println( "A mighty hammer appears in your hands." ); act( "A fervent look passes across the face of $n.", ch, NULL, NULL, TO_ROOM ); act( "A hammer suddenly appears in $s hands.", ch, NULL, NULL, TO_ROOM ); // see if the have a weapon, this will allow removal of cursed items too cObj = get_eq_char( ch, WEAR_WIELD ); if ( cObj ){ unequip_char( ch, cObj ); } obj_to_char( obj, ch ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_druidstaff( int, int level, char_data *ch, void *, int ) { AFFECT_DATA *af; OBJ_INDEX_DATA *pObj; OBJ_DATA *obj; OBJ_DATA *cObj; int numdie, dietype, random, vlevel; if (( pObj = get_obj_index( OBJ_VNUM_DRUIDSTAFF )) == NULL ) { ch->printlnf( "Vnum %d not found for Druidstaff, please report to the admin.", OBJ_VNUM_DRUIDSTAFF ); return NO_MANA; } // see if the have a built staff in their wield slot cObj = get_eq_char( ch, WEAR_WIELD ); if ( cObj ) { if ( cObj->pIndexData->vnum != OBJ_VNUM_STAFF ) { ch->println( "You must cast this spell on a built staff that you are holding." ); return NO_MANA; } } else { ch->println( "You must cast this spell on a built staff that you are holding." ); return NO_MANA; } obj = create_object( pObj); vlevel = UMIN( level, 20 ); obj->level = vlevel; // 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 ); } obj->attune_flags = ATTUNE_NEED_TO_USE|ATTUNE_PREVIOUS|ATTUNE_ONCE_ONLY; obj->attune_id = ch->id; obj->attune_next = current_time + ICTIME_IRLSECS_PER_DAY; // 8640 seconds or 144 Minutes :) obj->value[1] = numdie; obj->value[2] = dietype; obj->wear_loc = WEAR_WIELD; // Set wear loc to the character's inventory af = new_affect(); af->location = APPLY_MANA; af->modifier = UMIN( ch->level / 3, 10 ); af->where = WHERE_OBJEXTRA; af->type = -1; af->duration = -1; af->bitvector = 0; af->level = vlevel; af->next = obj->affected; obj->affected = af; act( "A faint green glow passes over $p.", ch, cObj, NULL, TO_CHAR ); act( "A faint green glow passes over $p held by $n.", ch, cObj, NULL, TO_ROOM ); extract_obj( cObj ); // Nuke the built staff obj_to_char( obj, ch ); // give them the new one return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_totemstaff( int, int level, char_data *ch, void *, int ) { OBJ_INDEX_DATA *pObj; OBJ_DATA *obj; OBJ_DATA *cObj; int numdie, dietype, random, vlevel; if (( pObj = get_obj_index( OBJ_VNUM_TOTEMSTAFF )) == NULL ) { ch->printlnf( "Vnum %d not found for Druidstaff, please report to the admin.", OBJ_VNUM_TOTEMSTAFF ); return NO_MANA; } // see if the have a druidstaff in their wield slot cObj = get_eq_char( ch, WEAR_WIELD ); if ( cObj ) { if ( cObj->pIndexData->vnum != OBJ_VNUM_DRUIDSTAFF ) { ch->println( "You must cast this spell on a druidstaff that you are holding." ); return NO_MANA; } } else { ch->println( "You must cast this spell on a druidstaff that you are holding." ); return NO_MANA; } if ( cObj->attune_id != ch->id ) { ch->println( "That is not your staff." ); return NO_MANA; } if ( current_time < cObj->attune_next && !IS_IMMORTAL(ch)) { ch->println( "You cannot convert the druidstaff yet." ); return NO_MANA; } obj = create_object( pObj); vlevel = UMIN( level, 30 ); obj->level = vlevel; // 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 ); } obj->attune_flags = ATTUNE_NEED_TO_USE|ATTUNE_PREVIOUS|ATTUNE_ONCE_ONLY; obj->attune_id = ch->id; obj->attune_next = current_time + ICTIME_IRLSECS_PER_DAY * 2; obj->value[1] = numdie; obj->value[2] = dietype; obj->wear_loc = WEAR_WIELD; // Set wear loc to the character's inventory act( "A mild green glow passes over $p.", ch, cObj, NULL, TO_CHAR ); act( "A mild green glow passes over $p held by $n.", ch, cObj, NULL, TO_ROOM ); extract_obj( cObj ); // Nuke the druid staff obj_to_char( obj, ch ); // give them the new one return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_mnemonics(int sn,int level,char_data *ch,void *,int ) { AFFECT_DATA af; if ( is_affected( ch, sn )) { ch->println( "You cannot cram any more information into your head." ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_ME; af.modifier = +5; af.bitvector = 0; affect_to_char( ch, &af ); ch->println( "You seem to be able to recall events more clearly." ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_logic(int sn,int level,char_data *ch,void *,int ) { AFFECT_DATA af; if ( is_affected( ch, sn )) { ch->println( "You are not able to process information any quicker." ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_RE; af.modifier = +5; af.bitvector = 0; affect_to_char( ch, &af ); ch->println( "You seem to be able to reason more effectively." ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_clarity(int sn,int level,char_data *ch,void *,int ) { AFFECT_DATA af; if ( is_affected( ch, sn )) { ch->println( "You see things as clearly as you are able." ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_IN; af.modifier = +5; af.bitvector = 0; affect_to_char( ch, &af ); ch->println( "You gain insight into the unknown." ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_persuasion(int sn,int level,char_data *ch,void *,int ) { AFFECT_DATA af; if ( is_affected( ch, sn )) { ch->println( "You are as persuasive as can be." ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_PR; af.modifier = +5; af.bitvector = 0; affect_to_char( ch, &af ); ch->println( "You feel more persuasive." ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_lucidity(int sn,int level,char_data *ch,void *,int ) { AFFECT_DATA af; if ( is_affected( ch, sn )) { ch->println( "You are already thinking clearly." ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_IN; af.modifier = +5; af.bitvector = 0; affect_to_char( ch, &af ); ch->println( "You feel more lucid." ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_night_eyes( int sn, int level, char_data *, void *vo, int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if(!is_affected(victim,sn)) { af.where = WHERE_RESIST; af.type = sn; af.level = level; af.duration = level/4+10; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = RES_LIGHT; affect_to_char(victim, &af); if ( !IS_AFFECTED(victim, AFF_INFRARED )) { af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level/4+10; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INFRARED; affect_to_char( victim, &af ); } victim->println( "Your pupils contract." ); } else { victim->println( "Your pupils are as small as they will get." ); return HALF_MANA; } return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_shrink(int sn,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( victim->size <= SIZE_SMALL ) // small or tiny { if ( victim == ch ) { ch->println( "You cannot shrink yourself any smaller." ); return NO_MANA; } else { ch->println( "They cannot be shrunk down any more than they already are." ); return NO_MANA; } } if ( is_affected( victim, sn )) { if ( victim == ch ) { ch->println( "You are already in a shrunken state." ); return HALF_MANA; } else { ch->println( "They are already in a shrunken state." ); return HALF_MANA; } } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level/4; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = 0; affect_to_char( ch, &af ); victim->println( "You feel yourself shrinking." ); if ( ch != victim ) act("$N shrinks to a fraction of $s former size.", ch, NULL, victim, TO_CHAR ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_night_of_the_leonids( int sn, int level, char_data *ch, void *, int ) { AFFECT_DATA af; char_data *rch; int dam; if ( ch->in_room->sector_type == SECT_INSIDE || IS_SET( ch->in_room->room_flags, ROOM_INDOORS )) { ch->println( "You can only call upon the Leonids in the out of doors." ); return NO_MANA; } if ( time_info.hour >= HOUR_SUNRISE && time_info.hour <= HOUR_SUNSET ) { ch->println( "This song is only effective at night." ); return NO_MANA; } ch->println( "Meteors rain from the sky." ); act( "Meteors rain from the sky.", ch, NULL, NULL, TO_ROOM ); for ( rch = ch->in_room->people; rch; rch = rch->next_in_room ) { if ( rch->in_room == NULL ) continue; if ( is_affected( rch, gsn_canticle_of_warding )) continue; if ( is_safe_spell(ch, rch, true)) continue; // damage is level/30 * 20 with half dam done if victim saves vs spell dam = ( level / 30 * 20 ) / ( saves_spell( level, rch, DAMTYPE(sn)) ? 2 : 1 ); damage_spell( ch, rch, dam, sn, DAMTYPE(sn), true ); } if ( IS_SET( ch->in_room->affected_by, ROOMAFF_UTTERDARK )) REMOVE_BIT( ch->in_room->affected_by, ROOMAFF_UTTERDARK ); // check to see if the room is already lit up, no stacked effect if ( IS_SET( ch->in_room->affected_by, ROOMAFF_LEONIDS )) { return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 1; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = ROOMAFF_LEONIDS; affect_to_room( ch->in_room, &af ); ch->println( "The room is washed in an ethereal glow." ); act( "The room is washed in an ethereal glow.", ch, NULL, NULL, TO_ROOM ); return FULL_MANA; } /*******************************************************************************/ SPRESULT spell_canticle_of_warding( int, int, char_data *, void *, int ) { return NO_MANA; } /*******************************************************************************/ /*******************************************************************************/