#include "define.h" #include "struct.h" /* * DAMAGE */ bool spell_meteor_swarm( char_data* ch, char_data*, void*, int level, int ) { char_data* rch; if( null_caster( ch, SPELL_METEOR_SWARM ) ) return TRUE; for( int i = *ch->array-1; i >= 0; i-- ) if( ( rch = character( ch->array->list[i] ) ) != NULL && rch != ch && can_kill( ch, rch, FALSE ) ) damage_physical( rch, ch, spell_damage( SPELL_METEOR_SWARM, level ), "*The swarm of meteors" ); return TRUE; } bool spell_maelstrom( char_data* ch, char_data*, void*, int level, int ) { char_data* rch; if( null_caster( ch, SPELL_MAELSTROM ) ) return TRUE; for( int i = ch->array->size; i >= 0; i-- ) if( ( rch = character( ch->array->list[i] ) ) != NULL && rch != ch && can_kill( ch, rch, FALSE ) ) damage_magic( rch, ch, spell_damage( SPELL_MAELSTROM, level ), "*The maelstrom" ); return TRUE; } /* * MISSILE SPELLS */ bool spell_magic_missile( char_data* ch, char_data* victim, void*, int level, int ) { if( null_caster( ch, SPELL_MAGIC_MISSILE ) ) return TRUE; damage_magic( victim, ch, spell_damage( SPELL_MAGIC_MISSILE, level ), "*The magic missile" ); return TRUE; } bool spell_prismic_missile( char_data* ch, char_data* victim, void*, int level, int ) { if( null_caster( ch, SPELL_PRISMIC_MISSILE ) ) return TRUE; damage_magic( victim, ch, spell_damage( SPELL_PRISMIC_MISSILE, level ), "*A multi-hued burst of light" ); return TRUE; } /* * SLEEP SPELLS */ void sleep_affect( char_data* ch, char_data* victim, int level, int duration ) { if( !can_kill( ch, victim, FALSE ) ) return; if( is_set( victim->affected_by, AFF_SLEEP_RESIST ) ) return; if( ch != NULL && makes_save( victim, ch, RES_MAGIC, SPELL_SLEEP, level ) ) { if( victim->position > POS_SLEEPING ) send( victim, "You feel drowsy but quickly shrug it off.\r\n" ); return; } spell_affect( ch, victim, level, duration, SPELL_SLEEP, AFF_SLEEP ); record_damage( victim, ch, 10 ); stop_fight( victim ); if( victim->position <= POS_SLEEPING ) return; send( victim, "You feel sleepy and suddenly fall asleep!\r\n" ); if( victim->mount != NULL ) { fsend( *victim->array, "%s tumbles off %s %s is riding and drops to the ground.", victim, victim->mount, victim->He_She( ) ); victim->mount->rider = NULL; victim->mount = NULL; } else { send_seen( victim, "%s drops to the ground dead asleep.\r\n", victim ); } victim->position = POS_SLEEPING; return; } bool spell_sleep( char_data* ch, char_data* victim, void*, int level, int duration ) { sleep_affect( ch, victim, level, duration ); return TRUE; } bool spell_mists_sleep( char_data* ch, char_data*, void*, int level, int duration ) { char_data* rch; if( null_caster( ch, SPELL_MISTS_SLEEP ) ) return TRUE; if( ch->in_room->sector_type == SECT_UNDERWATER ) { send( ch, "You are unable to summon the mists underwater.\r\n" ); return TRUE; } for( int i = 0; i < *ch->array; i++ ) if( ( rch = character( ch->array->list[i] ) ) != NULL && rch != ch ) sleep_affect( ch, rch, level, duration ); return TRUE; } /* * STRENGTH SPELL */ bool spell_ogre_strength( char_data* ch, char_data* victim, void*, int level, int duration ) { spell_affect( ch, victim, level, duration, SPELL_OGRE_STRENGTH, AFF_OGRE_STRENGTH, min( 17, victim->shdata->strength+3 ) ); return TRUE; } /* * ENCHANTMENT SPELLS */ bool spell_detect_magic( char_data* ch, char_data* victim, void*, int level, int duration ) { spell_affect( ch, victim, level, duration, SPELL_DETECT_MAGIC, AFF_DETECT_MAGIC ); return TRUE; } bool spell_minor_enchantment( char_data* ch, char_data*, void* vo, int level, int ) { obj_data* obj = (obj_data*) vo; int roll = number_range( 0, 100 ); if( null_caster( ch, SPELL_MINOR_ENCHANTMENT ) ) return TRUE; obj->selected = 1; if( is_set( obj->extra_flags, OFLAG_NO_ENCHANT ) ) { send( ch, "This object cannot be enchanted.\r\n", obj ); return TRUE; } if( obj->value[0] < 0 ) { send( *ch->array, "%s starts to glow, but the light turns black and then fades.\r\n", obj ); return TRUE; } if( roll < 30-level+10*obj->value[0] ) { fsend( *ch->array, "%s glows briefly, but then suddenly explodes in a burst\ of energy!\r\n", obj ); obj->Extract( 1 ); return TRUE; } if( roll <= 60-2*level+20*obj->value[0] ) { fsend( *ch->array, "%s glows briefly but the enchantment fails.\r\n", obj ); return TRUE; } send( *ch->array, "%s glows for a while.\r\n", obj ); if( obj->number > 1 ) { obj->number--; obj = duplicate( obj ); } obj->value[0]++; set_bit( obj->extra_flags, OFLAG_MAGIC ); if( obj->array == NULL ) ch->contents += obj; return TRUE; } bool spell_major_enchantment( char_data* ch, char_data*, void* vo, int level, int ) { obj_data* obj = (obj_data*) vo; int roll = number_range( 0, 100 ); if( null_caster( ch, SPELL_MAJOR_ENCHANTMENT ) ) return TRUE; if( is_set( obj->extra_flags, OFLAG_NO_MAJOR ) ) { send( ch, "%s cannot be enchanted.\r\n", obj ); return TRUE; } obj->selected = 1; if( obj->value[0] < 0 || obj->value[0] >= 3 ) { fsend( *ch->array, "%s starts to glow, but the light turns black and then fades.", obj ); return TRUE; } if( roll <= 30-level+20*obj->value[0] ) { fsend( *ch->array, "%s glows briefly but the enchantment fails.\r\n", obj ); return TRUE; } send( *ch->array, "%s glows for a while.\r\n", obj ); if( obj->number > 1 ) { obj->number--; obj = duplicate( obj ); } obj->value[0]++; set_bit( obj->extra_flags, OFLAG_MAGIC ); if( obj->array == NULL ) obj->To( ch ); return TRUE; } /* * REPLICATE */ bool spell_replicate( char_data* ch, char_data*, void* vo, int, int ) { obj_data* obj = (obj_data*) vo; if( is_set( obj->extra_flags, OFLAG_COPIED ) ) { fsend( ch, "You feel %s has already been copied and lacks the essence\ required for you to replicate it.", obj ); return TRUE; } fsend( ch, "In a swirl of colors %s materializes in your hand.", obj ); fsend_seen( ch, "In a swirl of colors %s materializes in %s's hand.", obj, ch ); obj->pIndexData->count++; if( obj->number > 1 ) { obj->number--; obj = duplicate( obj ); } obj->number = 2; set_bit( obj->extra_flags, OFLAG_COPIED ); if( obj->array == NULL ) obj->To( ch ); return TRUE; } /* * IDENTIFY SPELL */ bool spell_identify( char_data* ch, char_data*, void* vo, int, int ) { char buf [ MAX_INPUT_LENGTH ]; affect_data* paf; obj_data* obj = (obj_data*) vo; obj_clss_data* obj_clss = obj->pIndexData; bool found = FALSE; int i; if( null_caster( ch, SPELL_IDENTIFY ) ) return TRUE; if( obj == NULL ) { bug( "Identify: NULL object." ); return TRUE; } if( obj->number > 1 ) { obj->number--; obj = duplicate( obj ); } set_bit( obj->extra_flags, OFLAG_IDENTIFIED ); set_bit( obj->extra_flags, OFLAG_KNOWN_LIQUID ); send( ch, scroll_line[0] ); sprintf( buf, "%s%s", obj->Seen_Name( ch, 1 ), is_set( obj->extra_flags, OFLAG_NOREMOVE ) ? " [CURSED]" : "" ); send_title( ch, buf ); send( ch, " Base Cost: %-12d Level: %-11d Weight: %.2f lbs\r\n", obj->Cost( ), obj_clss->level, obj->Empty_Weight( 1 )/100. ); sprintf( buf, " " ); switch( obj_clss->item_type ) { case ITEM_WEAPON : sprintf( buf+5, " Damage: %dd%d ", obj_clss->value[1], obj_clss->value[2] ); sprintf( buf+25, " Class: %s ", ( obj_clss->value[3] >= 0 && obj_clss->value[3] < MAX_WEAPON ) ? skill_table[ WEAPON_UNARMED+obj_clss->value[3] ].name : "none" ); sprintf( buf+45, " Attack: %s\r\n", ( obj_clss->value[3] >= 0 && obj_clss->value[3] < MAX_WEAPON ) ? weapon_attack[ obj_clss->value[3] ] : "none" ); break; case ITEM_WAND : sprintf( buf+5, " Spell: %s ", ( obj_clss->value[0] >= 0 && obj_clss->value[0] < MAX_SPELL ) ? spell_table[ obj_clss->value[0] ].name : "none" ); sprintf( buf+25, " Charges: %d\r\n", obj->value[3] ); break; case ITEM_WHISTLE: if( obj_clss->value[0] > 0 ) sprintf( buf+5, " Range: %d\r\n", obj_clss->value[0] ); break; case ITEM_SCROLL : case ITEM_POTION : sprintf( buf+5, " Spell: %s ", ( obj_clss->value[0] >= 0 && obj_clss->value[0] < MAX_SPELL ) ? spell_table[ obj_clss->value[0] ].name : "none" ); sprintf( buf+25, " Level: %d\r\n", obj_clss->value[1] ); break; case ITEM_TRAP : sprintf( buf, "Damage: %dd%d\r\n", obj_clss->value[1], obj_clss->value[2] ); break; case ITEM_ARMOR : sprintf( buf, " Armor Class: %-3d", armor_class( obj ) ); if( obj->value[2] != 0 && can_wear( obj, ITEM_WEAR_WRIST ) ) sprintf( buf+strlen( buf ), "Protection Aura: %d", obj->value[2] ); strcat( buf, "\r\n" ); break; default : buf[0] = '\0'; break; } if( *buf != '\0' ) { send( ch, buf ); } sprintf( buf, "%d%%", obj->vs_acid( ) ); sprintf( buf+20, "%d%%", obj->vs_fire( ) ); sprintf( buf+40, "%d%%", obj->vs_cold( ) ); send( ch, " Acid: %-13s Fire: %-13s Cold: %s\r\n\r\n", buf, buf+20, buf+40 ); /* CONDITION */ if( obj_clss->item_type == ITEM_ARMOR || obj_clss->item_type == ITEM_WEAPON ) send( ch, " Condition: %s\r\n", obj->condition_name( ch, TRUE ) ); /* MATERIALS */ strcpy( buf, " Materials: " ); material_flags.sprint( &buf[16], &obj->materials ); send( ch, buf ); send( ch, "\r\n" ); /* WEAR LOC */ buf[0] = '\0'; for( i = 1; i < MAX_ITEM_WEAR; i++ ) if( is_set( &obj_clss->wear_flags, i ) ) { if( buf[0] == '\0' ) sprintf( buf, " Wear Loc.: %s", wear_name[i] ); else sprintf( buf+strlen( buf ), ", %s", wear_name[i] ); } if( *buf != '\0' ) { send( ch, buf ); send( ch, "\r\n" ); } /* ANTI-FLAGS */ buf[0] = '\0'; for( i = 0; i < MAX_ANTI; i++ ) if( is_set( &obj_clss->anti_flags, i ) ) { if( buf[0] == '\0' ) sprintf( buf, "\r\n Anti-Flags: %s", anti_flags[i] ); else sprintf( buf+strlen( buf ), ", %s", anti_flags[i] ); } if( *buf != '\0' ) { strcat( buf, "\r\n" ); send( ch, buf ); } /* AFFECTS */ for( i = 0; i < obj_clss->affected; i++ ) { paf = obj_clss->affected[i]; if( paf->type == AFF_NONE ) { if( !found ) { send( ch, "\r\n Affects:\r\n" ); found = TRUE; } send( ch, "%12s%s by %d.\r\n", "", affect_location[ paf->location ], paf->modifier ); } } for( i = 0; i < MAX_ENTRY_AFF_CHAR; i++ ) { if( is_set( obj_clss->affect_flags, i ) ) { if( !found ) { send( ch, "\r\n Affects:\r\n" ); found = TRUE; } send( ch, "%12s%s\r\n", "", aff_char_table[i].id_line ); } } for( i = 0; i < MAX_OFLAG; i++ ) { if( is_set( obj->extra_flags, i ) && oflag_ident[i][0] != '\0' ) { if( !found ) { send( ch, "\r\n Affects:\r\n" ); found = TRUE; } send( ch, "%12s%s\r\n", "", oflag_ident[i] ); } } send( ch, "\r\n" ); send( ch, scroll_line[0] ); if( obj->array == NULL ) obj->To( ch ); return TRUE; }; bool spell_obscure( char_data* ch, char_data*, void* vo, int, int ) { obj_data* obj = (obj_data*) vo; if( null_caster( ch, SPELL_OBSCURE ) ) return TRUE; remove_bit( obj->extra_flags, OFLAG_IDENTIFIED ); remove_bit( obj->extra_flags, OFLAG_KNOWN_LIQUID ); return TRUE; } /* * FLASH OF LIGHT */ bool spell_blind( char_data* ch, char_data* victim, void*, int level, int duration ) { if( victim->species != NULL && !is_set( &victim->species->act_flags, ACT_HAS_EYES ) ) { send( ch, "%s does not see with %s eyes so blind has no affect.\r\n", victim, victim->His_Her( ) ); return TRUE; } if( !can_kill( ch, victim ) ) return TRUE; if( makes_save( victim, ch, RES_MAGIC, SPELL_BLIND, level ) ) return TRUE; spell_affect( ch, victim, level, duration, SPELL_BLIND, AFF_BLIND ); return TRUE; } bool spell_blinding_light( char_data* ch, char_data*, void*, int level, int duration ) { // char_data* rch; /* for( rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room ) { if( rch == ch || !rch->Can_See( ) || ( rch->species != NULL && !is_set( &rch->species->act_flags, ACT_HAS_EYES ) ) ) continue; send( rch, "### The room explodes in a flash of light. ###\r\n" ); if( makes_save( rch, ch, RES_MAGIC, SPELL_BLINDING_LIGHT, level ) ) { send( rch, "Fortunately you were not looking at the blast and\ are unaffected.\r\n" ); } else if( !can_kill( ch, rch ) ) { send( rch, "Oddly the flash has no affect on you.\r\n" ); } else { spell_affect( ch, rch, level, duration, SPELL_BLINDING_LIGHT, AFF_BLIND ); } } */ return TRUE; } /* * ENTROPY SPELLS */ bool spell_wither( char_data* ch, char_data* victim, void*, int level, int ) { affect_data affect; if( !can_kill( ch, victim ) ) return TRUE; if( makes_save( victim, ch, RES_MAGIC, SPELL_WITHER, level ) ) { send( ch, "The spell fails.\r\n" ); return TRUE; } send( victim, "You feel your skin shrivel.\r\n" ); send_seen( victim, "%s seems to shrivel before you.\r\n", victim ); affect.type = AFF_NONE; affect.location = APPLY_CON; affect.modifier = -1; affect.duration = level*3; affect.level = level; affect.leech = NULL; add_affect( victim, &affect ); damage_magic( victim, ch, spell_damage( SPELL_WITHER, level ), "*A withering stare" ); return TRUE; } bool spell_drain_life( char_data* ch, char_data* victim, void*, int level, int ) { affect_data affect; if( victim->shdata->race == RACE_UNDEAD ) { send( ch, "You cannot drain life from the undead.\r\n" ); return TRUE; } if( !can_kill( ch, victim ) ) return TRUE; if( makes_save( victim, ch, RES_MAGIC, SPELL_DRAIN_LIFE, level ) ) { send( ch, "The spell fails.\r\n" ); return TRUE; } send( victim, "The chill of death momentarily touchs your soul.\r\n" ); send_seen( victim, "%s shivers for a brief instant.\r\n", victim ); affect.type = AFF_NONE; affect.location = APPLY_CON; affect.modifier = -1; affect.duration = level*3; affect.level = level; affect.leech = NULL; add_affect( victim, &affect ); return TRUE; } /* * WEB SPELLS */ bool spell_web( char_data* ch, char_data* victim, void*, int level, int duration ) { affect_data* paf; if( null_caster( ch, SPELL_WEB ) ) return TRUE; if( !can_kill( ch, victim ) ) return TRUE; if( is_set( victim->affected_by, AFF_ENTANGLED ) ) { for( int i = 0; i < ch->affected; i++ ) { paf = ch->affected[i]; if( paf->type == AFF_ENTANGLED ) { paf->level += 1+number_range( 0, level/3 ); paf->duration = max( level/2, paf->duration+1 ); break; } } send( "The web around you thickens.\r\n", victim ); send( *victim->array, "The web trapping %s thickens.\r\n", victim ); return TRUE; } else { send( victim, "A web begins to form around you.\r\n" ); send( *victim->array, "A web begins to form around %s.\r\n", victim ); if( makes_save( victim, ch, RES_DEXTERITY, SPELL_WEB, level ) && makes_save( victim, ch, RES_MAGIC, SPELL_WEB, level ) ) { send( victim, "Luckily you avoid becoming entangled.\r\n" ); send( *victim->array, "%s skillfully avoids the web.\r\n", victim ); return TRUE; } } spell_affect( ch, victim, level, duration, SPELL_WEB, AFF_ENTANGLED ); set_delay( victim, 32 ); return TRUE; } /* * MIND SPELLS */ bool spell_confuse( char_data* ch, char_data* victim, void*, int level, int duration ) { if( makes_save( victim, ch, RES_MIND, SPELL_CONFUSE, level/2 ) ) return TRUE; spell_affect( ch, victim, level, duration, SPELL_CONFUSE, AFF_CONFUSED ); return TRUE; } bool spell_hallucinate( char_data* ch, char_data* victim, void*, int level, int duration ) { if( makes_save( victim, ch, RES_MIND, SPELL_HALLUCINATE, level ) ) return TRUE; spell_affect( ch, victim, level, duration, SPELL_HALLUCINATE, AFF_HALLUCINATE ); return TRUE; } /* * VISION SPELLS */ bool spell_sense_danger( char_data* ch, char_data* victim, void*, int level, int duration ) { spell_affect( ch, victim, level, duration, SPELL_SENSE_DANGER, AFF_SENSE_DANGER ); return TRUE; } bool spell_eagle_eye( char_data* ch, char_data* victim, void*, int level, int ) { room_data* room; if( null_caster( ch, SPELL_EAGLE_EYE ) ) return FALSE; room = ch->in_room; if( victim->in_room == NULL ) { send( ch, "They are somewhere unusual.\r\n" ); return TRUE; } if( victim->in_room->area->status != AREA_OPEN || is_set( &victim->in_room->room_flags, RFLAG_NO_MAGIC ) || ( victim->shdata->level >= LEVEL_BUILDER && get_trust( ch ) < get_trust( victim ) ) ) { send( ch, "The spell is mysteriously blocked.\r\n" ); return TRUE; } if( level < 4 && is_set( &victim->in_room->room_flags, RFLAG_INDOORS ) ) { send( ch, "Your victim is not visible from the sky.\r\n" ); return TRUE; } if( level < 8 && is_set( &victim->in_room->room_flags, RFLAG_UNDERGROUND ) ) { send( ch, "Your victim is nowhere above ground.\r\n" ); return TRUE; } ch->in_room = victim->in_room; send( ch, "\r\n" ); do_look( ch, "" ); ch->in_room = room; return TRUE; } bool spell_scry( char_data* ch, char_data* victim, void*, int level, int ) { room_data* room; if( null_caster( ch, SPELL_SCRY ) ) return FALSE; room = ch->in_room; if( victim->in_room == NULL ) { send( ch, "They are somewhere unusual.\r\n" ); return TRUE; } if( victim->in_room->area->status != AREA_OPEN || is_set( &victim->in_room->room_flags, RFLAG_NO_MAGIC ) || ( victim->shdata->level >= LEVEL_BUILDER && get_trust( ch ) < get_trust( victim ) ) ) { send( ch, "The spell is mysteriously blocked.\r\n" ); return TRUE; } if( level < 4 && is_set( &victim->in_room->room_flags, RFLAG_INDOORS ) ) { send( ch, "Your victim is not visible from the sky.\r\n" ); return TRUE; } if( level < 8 && is_set( &victim->in_room->room_flags, RFLAG_UNDERGROUND ) ) { send( ch, "Your victim is nowhere above ground.\r\n" ); return TRUE; } ch->in_room = victim->in_room; send( ch, "\r\n" ); do_look( ch, "" ); ch->in_room = room; return TRUE; } bool spell_hawks_view( char_data* ch, char_data* victim, void*, int level, int ) { room_data* room; if( null_caster( ch, SPELL_HAWKS_VIEW ) ) return FALSE; room = ch->in_room; if( victim->in_room == NULL ) { send( ch, "They are somewhere unusual.\r\n" ); return TRUE; } if( victim->in_room->area->status != AREA_OPEN || is_set( &victim->in_room->room_flags, RFLAG_NO_MAGIC ) || ( victim->shdata->level >= LEVEL_BUILDER && get_trust( ch ) < get_trust( victim ) ) ) { send( ch, "The spell is mysteriously blocked.\r\n" ); return TRUE; } if( level < 4 && is_set( &victim->in_room->room_flags, RFLAG_INDOORS ) ) { send( ch, "Your victim is not visible from the sky.\r\n" ); return TRUE; } if( level < 8 && is_set( &victim->in_room->room_flags, RFLAG_UNDERGROUND ) ) { send( ch, "Your victim is nowhere above ground.\r\n" ); return TRUE; } ch->in_room = victim->in_room; send( ch, "\r\n" ); do_look( ch, "" ); ch->in_room = room; return TRUE; } /* * INVULNERABILITY */ bool spell_invulnerability( char_data* ch, char_data* victim, void*, int level, int duration ) { spell_affect( ch, victim, level, duration, SPELL_INVULNERABILITY, AFF_INVULNERABILITY ); return TRUE; } /* * LEVITATION/FLY */ bool spell_float( char_data* ch, char_data* victim, void*, int level, int duration ) { spell_affect( ch, victim, level, duration, SPELL_FLOAT, AFF_FLOAT ); return TRUE; } bool spell_fly( char_data* ch, char_data* victim, void*, int level, int duration ) { spell_affect( ch, victim, level, duration, SPELL_FLY, AFF_FLY ); return TRUE; } /* * SLOW/HASTE */ bool spell_haste( char_data* ch, char_data* victim, void*, int level, int duration ) { spell_affect( ch, victim, level, duration, SPELL_HASTE, AFF_HASTE ); return TRUE; } bool spell_slow( char_data* ch, char_data* victim, void*, int level, int duration ) { if( makes_save( victim, ch, RES_MAGIC, SPELL_SLOW, level ) ) return TRUE; spell_affect( ch, victim, level, duration, SPELL_SLOW, AFF_SLOW ); return TRUE; }