/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1995 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ /*************************************************************************** * ROT 1.4 is copyright 1996-1997 by Russ Walsh * * By using this code, you have agreed to follow the terms of the * * ROT license, in the file doc/rot.license * ***************************************************************************/ #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "recycle.h" void acid_effect ( void *vo, int level, int dam, int target ) { if ( target == TARGET_ROOM ) /* nail objects on the floor */ { ROOM_INDEX_DATA *room = ( ROOM_INDEX_DATA * ) vo; OBJ_DATA *obj, *obj_next; for ( obj = room->contents; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; acid_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_CHAR ) /* do the effect on a victim */ { CHAR_DATA *victim = ( CHAR_DATA * ) vo; OBJ_DATA *obj, *obj_next; /* let's toast some gear */ for ( obj = victim->carrying; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; acid_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_OBJ ) /* toast an object */ { OBJ_DATA *obj = ( OBJ_DATA * ) vo; OBJ_DATA *t_obj, *n_obj; int chance; char *msg; if ( IS_OBJ_STAT ( obj, ITEM_BURN_PROOF ) || IS_OBJ_STAT ( obj, ITEM_NOPURGE ) || number_range ( 0, 4 ) == 0 ) return; chance = level / 4 + dam / 10; if ( chance > 25 ) chance = ( chance - 25 ) / 2 + 25; if ( chance > 50 ) chance = ( chance - 50 ) / 2 + 50; if ( IS_OBJ_STAT ( obj, ITEM_BLESS ) ) chance -= 5; chance -= obj->level * 2; switch ( obj->item_type ) { default: return; case ITEM_CONTAINER: case ITEM_PIT: case ITEM_CORPSE_PC: case ITEM_CORPSE_NPC: msg = "$p fumes and dissolves."; break; case ITEM_ARMOR: msg = "$p is pitted and etched."; break; case ITEM_CLOTHING: msg = "$p is corroded into scrap."; break; case ITEM_STAFF: case ITEM_WAND: chance -= 10; msg = "$p corrodes and breaks."; break; case ITEM_SCROLL: chance += 10; msg = "$p is burned into waste."; break; } chance = URANGE ( 5, chance, 95 ); if ( number_percent ( ) > chance ) return; if ( obj->carried_by != NULL ) xact_new ( msg, obj->carried_by, obj, NULL, TO_ALL, POS_RESTING, VERBOSE_BURN ); else if ( obj->in_room != NULL && obj->in_room->people != NULL ) xact_new ( msg, obj->in_room->people, obj, NULL, TO_ALL, POS_RESTING, VERBOSE_BURN ); if ( obj->item_type == ITEM_ARMOR ) /* etch it */ { AFFECT_DATA *paf; bool af_found = FALSE; int i; affect_enchant ( obj ); for ( paf = obj->affected; paf != NULL; paf = paf->next ) { if ( paf->location == APPLY_AC ) { af_found = TRUE; paf->type = -1; paf->modifier += 1; paf->level = UMAX ( paf->level, level ); break; } } if ( !af_found ) /* needs a new affect */ { paf = new_affect ( ); paf->type = -1; paf->level = level; paf->duration = -1; paf->location = APPLY_AC; paf->modifier = 1; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; } if ( obj->carried_by != NULL && obj->wear_loc != WEAR_NONE ) for ( i = 0; i < 4; i++ ) obj->carried_by->armor[i] += 1; return; } /* get rid of the object */ if ( obj->contains ) /* dump contents */ { for ( t_obj = obj->contains; t_obj != NULL; t_obj = n_obj ) { n_obj = t_obj->next_content; obj_from_obj ( t_obj ); if ( obj->in_room != NULL ) obj_to_room ( t_obj, obj->in_room ); else if ( obj->carried_by != NULL ) obj_to_room ( t_obj, obj->carried_by->in_room ); else { extract_obj ( t_obj ); continue; } acid_effect ( t_obj, level / 2, dam / 2, TARGET_OBJ ); } } extract_obj ( obj ); return; } } void cold_effect ( void *vo, int level, int dam, int target ) { if ( target == TARGET_ROOM ) /* nail objects on the floor */ { ROOM_INDEX_DATA *room = ( ROOM_INDEX_DATA * ) vo; OBJ_DATA *obj, *obj_next; for ( obj = room->contents; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; cold_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_CHAR ) /* whack a character */ { CHAR_DATA *victim = ( CHAR_DATA * ) vo; OBJ_DATA *obj, *obj_next; /* hunger! (warmth sucked out */ if ( !IS_NPC ( victim ) ) gain_condition ( victim, COND_HUNGER, dam / 20 ); /* let's toast some gear */ for ( obj = victim->carrying; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; cold_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_OBJ ) /* toast an object */ { OBJ_DATA *obj = ( OBJ_DATA * ) vo; int chance; char *msg; if ( IS_OBJ_STAT ( obj, ITEM_BURN_PROOF ) || IS_OBJ_STAT ( obj, ITEM_NOPURGE ) || number_range ( 0, 4 ) == 0 ) return; chance = level / 4 + dam / 10; if ( chance > 25 ) chance = ( chance - 25 ) / 2 + 25; if ( chance > 50 ) chance = ( chance - 50 ) / 2 + 50; if ( IS_OBJ_STAT ( obj, ITEM_BLESS ) ) chance -= 5; chance -= obj->level * 2; switch ( obj->item_type ) { default: return; case ITEM_POTION: msg = "$p freezes and shatters!"; chance += 25; break; case ITEM_DRINK_CON: msg = "$p freezes and shatters!"; chance += 5; break; } chance = URANGE ( 5, chance, 95 ); if ( number_percent ( ) > chance ) return; if ( obj->carried_by != NULL ) xact_new ( msg, obj->carried_by, obj, NULL, TO_ALL, POS_RESTING, VERBOSE_BURN ); else if ( obj->in_room != NULL && obj->in_room->people != NULL ) xact_new ( msg, obj->in_room->people, obj, NULL, TO_ALL, POS_RESTING, VERBOSE_BURN ); extract_obj ( obj ); return; } } void fire_effect ( void *vo, int level, int dam, int target ) { if ( target == TARGET_ROOM ) /* nail objects on the floor */ { ROOM_INDEX_DATA *room = ( ROOM_INDEX_DATA * ) vo; OBJ_DATA *obj, *obj_next; for ( obj = room->contents; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; fire_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_CHAR ) /* do the effect on a victim */ { CHAR_DATA *victim = ( CHAR_DATA * ) vo; OBJ_DATA *obj, *obj_next; /* if (!IS_AFFECTED(victim,AFF_BLIND) && !saves_spell(level / 4 + dam / 20, victim,DAM_FIRE)) { AFFECT_DATA af; act("$n is blinded by smoke!",victim,NULL,NULL,TO_ROOM); act("Your eyes tear up from smoke...you can't see a thing!", victim,NULL,NULL,TO_CHAR); af.where = TO_AFFECTS; af.type = ; af.level = level; af.duration = number_range(0,level/10); af.location = APPLY_HITROLL; af.modifier = level/-10; af.bitvector = AFF_BLIND; affect_to_char(victim,&af); }*/ /* getting thirsty */ if ( !IS_NPC ( victim ) ) gain_condition ( victim, COND_THIRST, dam / 20 ); /* let's toast some gear! */ for ( obj = victim->carrying; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; fire_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_OBJ ) /* toast an object */ { OBJ_DATA *obj = ( OBJ_DATA * ) vo; OBJ_DATA *t_obj, *n_obj; int chance; char *msg; if ( IS_OBJ_STAT ( obj, ITEM_BURN_PROOF ) || IS_OBJ_STAT ( obj, ITEM_NOPURGE ) || number_range ( 0, 4 ) == 0 ) return; chance = level / 4 + dam / 10; if ( chance > 25 ) chance = ( chance - 25 ) / 2 + 25; if ( chance > 50 ) chance = ( chance - 50 ) / 2 + 50; if ( IS_OBJ_STAT ( obj, ITEM_BLESS ) ) chance -= 5; chance -= obj->level * 2; switch ( obj->item_type ) { default: return; case ITEM_CONTAINER: case ITEM_PIT: msg = "$p ignites and burns!"; break; case ITEM_POTION: chance += 25; msg = "$p bubbles and boils!"; break; case ITEM_SCROLL: chance += 50; msg = "$p crackles and burns!"; break; case ITEM_STAFF: chance += 10; msg = "$p smokes and chars!"; break; case ITEM_WAND: msg = "$p sparks and sputters!"; break; case ITEM_FOOD: msg = "$p blackens and crisps!"; break; case ITEM_PILL: msg = "$p melts and drips!"; break; } chance = URANGE ( 5, chance, 95 ); if ( number_percent ( ) > chance ) return; if ( obj->carried_by != NULL ) xact_new ( msg, obj->carried_by, obj, NULL, TO_ALL, POS_RESTING, VERBOSE_BURN ); else if ( obj->in_room != NULL && obj->in_room->people != NULL ) xact_new ( msg, obj->in_room->people, obj, NULL, TO_ALL, POS_RESTING, VERBOSE_BURN ); if ( obj->contains ) { /* dump the contents */ for ( t_obj = obj->contains; t_obj != NULL; t_obj = n_obj ) { n_obj = t_obj->next_content; obj_from_obj ( t_obj ); if ( obj->in_room != NULL ) obj_to_room ( t_obj, obj->in_room ); else if ( obj->carried_by != NULL ) obj_to_room ( t_obj, obj->carried_by->in_room ); else { extract_obj ( t_obj ); continue; } fire_effect ( t_obj, level / 2, dam / 2, TARGET_OBJ ); } } extract_obj ( obj ); return; } } void poison_effect ( void *vo, int level, int dam, int target ) { if ( target == TARGET_ROOM ) /* nail objects on the floor */ { ROOM_INDEX_DATA *room = ( ROOM_INDEX_DATA * ) vo; OBJ_DATA *obj, *obj_next; for ( obj = room->contents; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; poison_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_CHAR ) /* do the effect on a victim */ { CHAR_DATA *victim = ( CHAR_DATA * ) vo; OBJ_DATA *obj, *obj_next; /* chance of poisoning */ if ( !saves_spell ( level / 4 + dam / 20, victim, DAM_POISON ) ) { AFFECT_DATA af; send_to_char ( "You feel poison coursing through your veins.\n\r", victim ); act ( "$n looks very ill.", victim, NULL, NULL, TO_ROOM ); af.where = TO_AFFECTS; af.type = gsn_poison; af.level = level; af.duration = level / 2; af.location = APPLY_STR; af.modifier = -1; af.bitvector = AFF_POISON; affect_join ( victim, &af ); } /* equipment */ for ( obj = victim->carrying; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; poison_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_OBJ ) /* do some poisoning */ { OBJ_DATA *obj = ( OBJ_DATA * ) vo; int chance; if ( IS_OBJ_STAT ( obj, ITEM_BURN_PROOF ) || IS_OBJ_STAT ( obj, ITEM_BLESS ) || number_range ( 0, 4 ) == 0 ) return; chance = level / 4 + dam / 10; if ( chance > 25 ) chance = ( chance - 25 ) / 2 + 25; if ( chance > 50 ) chance = ( chance - 50 ) / 2 + 50; chance -= obj->level * 2; switch ( obj->item_type ) { default: return; case ITEM_FOOD: break; case ITEM_DRINK_CON: if ( obj->value[0] == obj->value[1] ) return; break; } chance = URANGE ( 5, chance, 95 ); if ( number_percent ( ) > chance ) return; obj->value[3] = 1; return; } } void shock_effect ( void *vo, int level, int dam, int target ) { if ( target == TARGET_ROOM ) { ROOM_INDEX_DATA *room = ( ROOM_INDEX_DATA * ) vo; OBJ_DATA *obj, *obj_next; for ( obj = room->contents; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; shock_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_CHAR ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; OBJ_DATA *obj, *obj_next; /* daze and confused? */ if ( !saves_spell ( level / 4 + dam / 20, victim, DAM_LIGHTNING ) ) { send_to_char ( "Your muscles stop responding.\n\r", victim ); DAZE_STATE ( victim, UMAX ( 12, level / 4 + dam / 20 ) ); } /* toast some gear */ for ( obj = victim->carrying; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; shock_effect ( obj, level, dam, TARGET_OBJ ); } return; } if ( target == TARGET_OBJ ) { OBJ_DATA *obj = ( OBJ_DATA * ) vo; int chance; char *msg; if ( IS_OBJ_STAT ( obj, ITEM_BURN_PROOF ) || IS_OBJ_STAT ( obj, ITEM_NOPURGE ) || number_range ( 0, 4 ) == 0 ) return; chance = level / 4 + dam / 10; if ( chance > 25 ) chance = ( chance - 25 ) / 2 + 25; if ( chance > 50 ) chance = ( chance - 50 ) / 2 + 50; if ( IS_OBJ_STAT ( obj, ITEM_BLESS ) ) chance -= 5; chance -= obj->level * 2; switch ( obj->item_type ) { default: return; case ITEM_WAND: case ITEM_STAFF: chance += 10; msg = "$p overloads and explodes!"; break; case ITEM_JEWELRY: chance -= 10; msg = "$p is fused into a worthless lump."; } chance = URANGE ( 5, chance, 95 ); if ( number_percent ( ) > chance ) return; if ( obj->carried_by != NULL ) act ( msg, obj->carried_by, obj, NULL, TO_ALL ); else if ( obj->in_room != NULL && obj->in_room->people != NULL ) act ( msg, obj->in_room->people, obj, NULL, TO_ALL ); extract_obj ( obj ); return; } }