/**************************************************************************/ // trap.cpp - Kerenos's Trap code /*************************************************************************** * 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 "trap.h" #include "olc.h" // very little commenting, if you don't know what's going on here, you have // no business looking at this code since it's pretty darned basic :) int get_sublevels_for_level(int level); void make_corpse( char_data *ch, char_data *killer ); void trapdamage(char_data *ch, OBJ_DATA *obj); void do_fearful(char_data *ch ); void do_trapset( char_data *ch, char *argument) { OBJ_DATA *obj; bool changed = false; char arg1[MIL]; char arg2[MIL]; char arg3[MIL]; if (!HAS_SECURITY(ch,1)) { do_huh( ch, "" ); return; } argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); argument = one_argument(argument, arg3); if (arg1[0] == '\0' || arg2[0] == '\0' ) { ch->println("Syntax: trapset <object> <`=Cfield`x> <`yvalue`x>"); ch->println("`=CField`x: move, get, room, open, damage, charge, modifier"); ch->println("`yValue`x: Move> north, south, east, west, up, down,"); ch->println(" northeast, northwest, southeast, southwest, all"); ch->println(" Damage> help dam-type"); ch->print(" Modifier> Difficulty of trap ( +/-75 pos is easy, neg is harder )"); ch->println(" get, open, room> no values"); return; } if ( ( obj = get_obj_here(ch, arg1) ) == NULL) { ch->println("You must be in the same room as the object you are trapping."); return; } if ( !IS_BUILDER( ch, obj->pIndexData->area, BUILDRESTRICT_OBJECTS ) && !IS_IMMORTAL(ch)) { ch->println("trapset: Invalid security for setting traps on object. You are not"); ch->println(" a valid builder for this area."); return; } if (!str_cmp( arg2, "move") ) { int dir = 0; if (arg3[0] == '\0') { ch->println("Syntax: trapset <object> move <direction>"); return; } if (!str_cmp( arg3, "all" )) { dir = 10; } else { dir = dir_lookup( arg3 ); } switch ( dir ) { case DIR_NORTH: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_NORTH ); ch->println("You set a trap for northward movement!"); break; case DIR_EAST: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_EAST ); ch->println("You set a trap for eastward movement!"); break; case DIR_WEST: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_WEST ); ch->println("You set a trap for westward movement!"); break; case DIR_SOUTH: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_SOUTH ); ch->println("You set a trap for southward movement!"); break; case DIR_UP: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_UP ); ch->println("You set a trap for upward movement!"); break; case DIR_DOWN: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_DOWN ); ch->println("You set a trap for downward movement!"); break; case DIR_NORTHEAST: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_NORTHEAST ); ch->println("You set a trap for northeastern movement!"); break; case DIR_NORTHWEST: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_NORTHWEST ); ch->println("You set a trap for northwestern movement!"); break; case DIR_SOUTHEAST: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_SOUTHEAST ); ch->println("You set a trap for southeastern movement!"); break; case DIR_SOUTHWEST: SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_SOUTHWEST ); ch->println("You set a trap for southwest movement!"); break; case 10: // hack for all directions *blush* well, it's cute... :) SET_BIT( obj->trap_trig, TRAP_TRIG_MOVE ); SET_BIT( obj->trap_trig, TRAP_TRIG_NORTH ); SET_BIT( obj->trap_trig, TRAP_TRIG_EAST ); SET_BIT( obj->trap_trig, TRAP_TRIG_SOUTH ); SET_BIT( obj->trap_trig, TRAP_TRIG_WEST ); SET_BIT( obj->trap_trig, TRAP_TRIG_UP ); SET_BIT( obj->trap_trig, TRAP_TRIG_DOWN ); SET_BIT( obj->trap_trig, TRAP_TRIG_NORTHEAST ); SET_BIT( obj->trap_trig, TRAP_TRIG_NORTHWEST ); SET_BIT( obj->trap_trig, TRAP_TRIG_SOUTHEAST ); SET_BIT( obj->trap_trig, TRAP_TRIG_SOUTHWEST ); ch->println("You set a trap for ALL movement!!!"); break; case -1: // invalid direction type ch->println("Invalid direction. Try north, east, south, west, up, down"); ch->println(" northeast, northwest, southeast, southwest, or all"); break; default: ch->println("Something strange happened, note to code about traps and invalid directions."); break; } changed = true; } if ( !str_cmp( arg2, "get" )) { SET_BIT( obj->trap_trig, TRAP_TRIG_OBJECT ); ch->println("The trap will now spring when someone tries to `=Cget`x this object."); changed = true; } if ( !str_cmp( arg2, "room" )) { SET_BIT( obj->trap_trig, TRAP_TRIG_ROOM ); ch->println("The trap will now affect the whole room, area affect!"); changed = true; } if ( !str_cmp( arg2, "open" )) { SET_BIT( obj->trap_trig, TRAP_TRIG_OPEN ); ch->println("The trap will trigger when the object is opened!"); changed = true; } if ( !str_cmp( arg2, "modifier" )) { int chance; if ( arg3[0] == '\0' ) { ch->println("No modifier specified. Use any number from -75 to 75."); ch->println(" The modifier number will be added to the player's remove traps"); ch->println(" skill, so negative numbers make the trap harder to disarm, and"); ch->println(" positive ones make the trap easier to remove."); return; } if (( chance = atoi(arg3) ) > 75 || chance < -75 ) { ch->println("Current allowed range is -75 to 75."); return; } obj->trap_modifier = chance; ch->printlnf("Trap modifier now set to %d.", chance ); changed = true; } if ( !str_cmp( arg2, "damage" )) { int dtype; if ( arg3[0] == '\0' ) { ch->println("No dam-type specified. Try one of the following."); do_help( ch, "dam-type" ); return; } dtype = flag_value( damtype_types, arg3 ); if ( dtype ==NO_FLAG ) { ch->printlnf("'%s' is not a recognized damtype.", arg3 ); do_help( ch, "dam-type" ); return; } ch->printlnf("The trap will now do damage of type '%s'.", flag_string( damtype_types, dtype )); obj->trap_dtype = dtype; changed = true; } if ( !str_cmp( arg2, "charge" )) { int val = 0; if (arg3[0] == '\0') { ch->println("You need to specify how many charges."); return; } if (( val = atoi(arg3) ) > 100 || val < 0) { ch->println("Current allowed range is 1 to 100."); return; } obj->trap_charge = val; ch->printlnf("The trap now has %d charges.", val ); changed = true; } if ( !changed ) { do_trapset( ch, "" ); // redisplay the syntax } else { SET_BIT( obj->extra2_flags, OBJEXTRA2_TRAP ); SET_BIT( obj->pIndexData->extra2_flags, OBJEXTRA2_TRAP ); obj->pIndexData->trap_trig = obj->trap_trig; obj->pIndexData->trap_dtype = obj->trap_dtype; obj->pIndexData->trap_charge = obj->trap_charge; obj->pIndexData->trap_modifier = obj->trap_modifier; // area changed, saved in next maintenace SET_BIT( obj->pIndexData->area->olc_flags, OLCAREA_CHANGED ); } return; } /**************************************************************************/ void do_trapremove(char_data *ch, char *argument) { OBJ_DATA *obj; char arg1[MIL]; argument = one_argument(argument, arg1); if (!HAS_SECURITY(ch,1)) { do_huh( ch, "" ); return; } if (( obj = get_obj_here( ch, arg1 )) == NULL) { ch->println("That isn't here!"); return; } if ( !IS_BUILDER( ch, obj->pIndexData->area, BUILDRESTRICT_OBJECTS ) && !IS_IMMORTAL(ch)) { ch->println("trapremove: Invalid security for setting traps on object. You are not"); ch->println(" a valid builder for this area."); return; } if ( !IS_SET( obj->extra2_flags, OBJEXTRA2_TRAP )) { ch->println("That object was not marked as a trap, no change ocurred."); return; } REMOVE_BIT(obj->extra2_flags, OBJEXTRA2_TRAP); REMOVE_BIT(obj->pIndexData->extra2_flags, OBJEXTRA2_TRAP); SET_BIT( obj->pIndexData->area->olc_flags, OLCAREA_CHANGED ); obj->trap_dtype = 0; obj->trap_trig = 0; obj->trap_charge = 0; obj->trap_modifier = 0; obj->pIndexData->trap_trig = obj->trap_trig; obj->pIndexData->trap_dtype = obj->trap_dtype; obj->pIndexData->trap_charge = obj->trap_charge; obj->pIndexData->trap_modifier = obj->trap_modifier; ch->println("Trap removed."); return; } /**************************************************************************/ void do_trapshow(char_data *ch, char *argument) { char arg1[MIL]; OBJ_DATA *obj; argument = one_argument(argument, arg1); if (!HAS_SECURITY(ch,1)) { do_huh( ch, "" ); return; } if (( obj = get_obj_here(ch, arg1) ) == NULL) { ch->println("That is not here!"); return; } if ( !IS_BUILDER( ch, obj->pIndexData->area, BUILDRESTRICT_OBJECTS ) && !IS_IMMORTAL(ch)) { ch->println("trapset: Invalid security for setting traps on object. You are not"); ch->println(" a valid builder for this area."); return; } if ( !IS_TRAPPED( obj )) { ch->println("That object in not registered as a trap."); return; } ch->printlnf("`yItem: `x%s `yVNUM: `x%d", obj->short_descr, obj->pIndexData->vnum ); ch->printlnf("`yDamage Type: `x%s", flag_string( damtype_types, obj->trap_dtype )); if ( obj->trap_trig == 0 ) { ch->println("`RThe trap has no trigger set!`x"); } else { if ( IS_SET( obj->trap_trig, TRAP_TRIG_MOVE )) { ch->print("`yThis trap is triggered when a player moves:`x\r\n "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_NORTH )) ch->print("north "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_EAST )) ch->print("east "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_SOUTH )) ch->print("south "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_WEST )) ch->print("west "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_UP )) ch->print("up "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_DOWN )) ch->print("down "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_NORTHEAST )) ch->print("northeast "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_NORTHWEST )) ch->print("northwest "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_SOUTHEAST )) ch->print("southeast "); if ( IS_SET( obj->trap_trig, TRAP_TRIG_SOUTHWEST )) ch->print("southwest "); ch->println(""); } if ( IS_SET( obj->trap_trig, TRAP_TRIG_OBJECT )) ch->println("`yThe trap is set when a player `=Cgets`y this object."); if ( IS_SET( obj->trap_trig, TRAP_TRIG_OPEN )) ch->println("`yThe trap is set off when object is `=Copened`y."); if ( IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) ch->println("`RThe trap affects the whole room!"); } ch->printlnf("`yTrap Charges left: `x%d", obj->trap_charge ); ch->printlnf("`yTrap Modifier: `x%d", obj->trap_modifier ); return; } /**************************************************************************/ bool trapcheck_get( char_data *ch, OBJ_DATA *obj ) { if ( IS_NPC( ch )) return false; if ( !IS_TRAPPED( obj )) return false; if ( IS_SET( obj->trap_trig, TRAP_TRIG_OBJECT ) && obj->trap_charge > 0 ) { trapdamage( ch, obj ); return true; } return false; } /**************************************************************************/ bool trapcheck_open( char_data *ch, OBJ_DATA *obj ) { if ( IS_NPC( ch )) return false; if ( !IS_TRAPPED( obj )) return false; if ( IS_SET( obj->trap_trig, TRAP_TRIG_OPEN ) && obj->trap_charge > 0 ) { trapdamage( ch, obj ); return true; } return false; } /**************************************************************************/ bool trapcheck_move( char_data *ch, int dir ) { OBJ_DATA *obj; OBJ_DATA *obj_next; bool found = false; if ( IS_NPC( ch )) return false; for (obj = ch->in_room->contents; obj != NULL; obj = obj_next) { obj_next = obj->next_content; if( IS_TRAPPED( obj ) && IS_SET(obj->trap_trig, TRAP_TRIG_MOVE) && obj->trap_charge > 0) { found = true; } else { found = false; } if ( found ) { if ( IS_SET( obj->trap_trig, TRAP_TRIG_NORTH ) && dir == DIR_NORTH ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_EAST ) && dir == DIR_EAST ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_SOUTH ) && dir == DIR_SOUTH ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_WEST ) && dir == DIR_WEST ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_UP ) && dir == DIR_UP ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_DOWN ) && dir == DIR_DOWN ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_NORTHEAST ) && dir == DIR_NORTHEAST ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_NORTHWEST ) && dir == DIR_NORTHWEST ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_SOUTHEAST ) && dir == DIR_SOUTHEAST ) { trapdamage( ch, obj ); return true; } if ( IS_SET( obj->trap_trig, TRAP_TRIG_SOUTHWEST ) && dir == DIR_SOUTHWEST ) { trapdamage( ch, obj ); return true; } } } return false; } /**************************************************************************/ void trapdamage(char_data *ch, OBJ_DATA *obj) { char_data *wch = NULL; AFFECT_DATA af; int dam = 0; if (obj->trap_charge <= 0) return; act("You hear a strange noise......", ch, NULL, NULL, TO_ROOM); act("Now you've done it...", ch, NULL, NULL, TO_CHAR); obj->trap_charge -= 1; switch( obj->trap_dtype ) { // Damage to the whole room is always one less in severity (multiplier) case DAM_FIRE: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { act("A fireball shoots out of $p and hits $n!", ch, obj, NULL, TO_ROOM); act("A fireball shoots out of $p and hits you!", ch, obj, NULL, TO_CHAR); dam = number_range( obj->level * 2, obj->level * 4 ); } else { act("A fireball shoots out of $p and hits everyone in the room!", ch, obj, NULL, TO_ROOM); act("A fireball shoots out of $p and hits everyone in the room!", ch, obj, NULL, TO_CHAR); dam = number_range( obj->level, obj->level * 3 ); } break; case DAM_HOLY: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( IS_GOOD( ch )) { ch->println("You are washed in pure, divine light."); return; } act("A bright beam of holy light shoots out of $p and hits $n!", ch, obj, NULL, TO_ROOM); act("A bright beam of holy light shoots out of $p and hits you!", ch, obj, NULL, TO_CHAR); dam = obj->level * 3; } else { act("A bright beam of holy light shoots out of $p everyone in the room!", ch, obj, NULL, TO_ROOM); act("A bright beam of holy light shoots out of $p everyone in the room!", ch, obj, NULL, TO_CHAR); dam = obj->level * 3; } break; case DAM_COLD: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { act("A blast of frost from $p hits $n!", ch, obj, NULL, TO_ROOM); act("A blast of frost from $p hits you!", ch, obj, NULL, TO_CHAR); dam = number_range( obj->level * 3, obj->level * 5); } else { act("A blast of frost from $p fills the room freezing you!", ch, obj, NULL, TO_ROOM); act("A blast of frost from $p fills the room freezing you!", ch, obj, NULL, TO_CHAR); dam = number_range( obj->level * 2, obj->level * 4 ); } break; case DAM_ACID: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { act("A blast of acid erupts from $p, burning your skin!", ch, obj, NULL, TO_CHAR); act("A blast of acid erupts from $p, burning $n's skin!", ch, obj, NULL, TO_ROOM); dam = number_range( obj->level * 2, obj->level * 6 ); } else { act("A blast of acid erupts from $p, burning your skin!", ch, obj, NULL, TO_ROOM); act("A blast of acid erupts from $p, burning your skin!", ch, obj, NULL, TO_CHAR); dam = number_range( obj->level * 1, obj->level * 5 ); } break; case DAM_HARM: case DAM_ENERGY: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM) ) { act("A pulse of energy from $p zaps $n!", ch, obj, NULL, TO_ROOM); act("A pulse of energy from $p zaps you!", ch, obj, NULL, TO_CHAR); dam = number_range( obj->level, obj->level * 3 ); } else { act("A pulse of energy from $p zaps you!", ch, obj, NULL, TO_ROOM); act("A pulse of energy from $p zaps you!", ch, obj, NULL, TO_CHAR); dam = number_range( obj->level, obj->level * 2 ); } break; case DAM_LIGHTNING: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM) ) { act("A bolt of lightning springs from $p and electrifies $n!", ch, obj, NULL, TO_ROOM); act("A bolt of lightning springs from $p and electrifies you!", ch, obj, NULL, TO_CHAR); dam = number_range( obj->level, obj->level * 3 ); } else { act("A bolt of lightning springs from $p and electrifies you!", ch, obj, NULL, TO_ROOM ); act("A bolt of lightning springs from $p and electrifies you!", ch, obj, NULL, TO_CHAR ); dam = number_range( obj->level, obj->level * 2 ); } break; case DAM_LIGHT: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( IS_AFFECTED( ch, AFF_BLIND )) { ch->println("A bright light washes over you but is suddenly gone."); return; } if ( saves_spell( obj->level, ch, DAM_LIGHT )) { ch->println("A bright light washes over you but is suddenly gone."); return; } else { af.where = WHERE_AFFECTS; af.type = gsn_blindness; af.level = obj->level; af.location = APPLY_HITROLL; af.modifier = -4; af.duration = obj->level; af.bitvector = AFF_BLIND; affect_to_char( ch, &af ); ch->println("You are blinded!"); act("$n appears to be blinded.",ch,NULL,NULL,TO_ROOM); } } else { act( "A bright light washes over the room.", ch, NULL, NULL, TO_CHAR ); act( "A bright light washes over the room.", ch, NULL, NULL, TO_ROOM ); for ( wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room ) { if ( IS_AFFECTED( wch, AFF_BLIND )) { wch->println("A bright light washes over you but is suddenly gone."); continue; } if ( saves_spell( obj->level, wch, DAM_LIGHT )) { wch->println("You manage to close your eyes before the light could blind you."); continue; } else { af.where = WHERE_AFFECTS; af.type = gsn_blindness; af.level = obj->level; af.location = APPLY_HITROLL; af.modifier = -4; af.duration = obj->level; af.bitvector = AFF_BLIND; affect_to_char( wch, &af ); wch->println("You are blinded!"); act( "$n appears to be blinded.", wch, NULL, NULL, TO_ROOM); } } } return; case DAM_POISON: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( IS_AFFECTED( ch, AFF_POISON )) { ch->println("You feel momentarily ill, but it passes."); return; } ch->println("Curses! You've pricked your finger on a needle."); act( "$n pricked $s finger on a little needle.", ch, NULL, NULL, TO_ROOM ); if ( saves_spell( obj->level, ch, DAM_POISON )) { ch->println("You feel momentarily ill, but it passes."); return; } else { af.where = WHERE_AFFECTS; af.type = gsn_poison; af.level = obj->level; af.duration = (obj->level/2); af.location = APPLY_ST; af.modifier = -4; af.bitvector = AFF_POISON; affect_join( ch, &af ); ch->println("You feel very sick."); act( "$n looks very ill.", ch, NULL, NULL, TO_ROOM ); return; } } else { act( "A noxious cloud seeps out from $p.", ch, obj, NULL, TO_CHAR ); act( "A noxious cloud seeps out from $p.", ch, obj, NULL, TO_ROOM ); for ( wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room ) { if ( IS_AFFECTED( wch, AFF_POISON )) { wch->println("You feel momentarily ill, but it passes."); continue; } if ( saves_spell( obj->level, wch, DAM_POISON )) { wch->println("You feel momentarily ill, but it passes."); continue; } else { af.where = WHERE_AFFECTS; af.type = gsn_poison; af.level = obj->level; af.duration = (obj->level/2); af.location = APPLY_ST; af.modifier = -4; af.bitvector = AFF_POISON; affect_join( wch, &af ); wch->println("You feel very sick."); act( "$n looks very ill.", wch, NULL, NULL, TO_ROOM ); continue; } } } return; case DAM_DISEASE: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( IS_AFFECTED( ch, AFF_PLAGUE )) { ch->println("You feel momentarily ill, but it passes."); return; } ch->println("Curses! You've pricked your finger on a needle."); act( "$n pricked $s finger on a little needle.", ch, NULL, NULL, TO_ROOM ); if ( saves_spell( obj->level, ch, DAM_DISEASE )) { ch->println("You feel momentarily ill, but it passes."); return; } else { af.where = WHERE_AFFECTS; af.type = gsn_plague; af.level = obj->level; af.duration = (obj->level/2); af.location = APPLY_ST; af.modifier = -10; af.bitvector = AFF_PLAGUE; affect_join( ch, &af ); ch->println("You scream in agony as plague sores erupt from your skin."); act( "$n screams in agony as plague sores erupt from $s skin.", ch, NULL, NULL, TO_ROOM ); return; } } else { act( "A noxious cloud seeps out from $p.", ch, obj, NULL, TO_CHAR ); act( "A noxious cloud seeps out from $p.", ch, obj, NULL, TO_ROOM ); for ( wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room ) { if ( IS_AFFECTED( wch, AFF_PLAGUE )) { wch->println("You feel momentarily ill, but it passes."); continue; } if ( saves_spell( obj->level, wch, DAM_DISEASE )) { wch->println("You feel momentarily ill, but it passes."); continue; } else { af.where = WHERE_AFFECTS; af.type = gsn_plague; af.level = obj->level; af.duration = (obj->level/2); af.location = APPLY_ST; af.modifier = -10; af.bitvector = AFF_PLAGUE; affect_join( wch, &af ); wch->println("You scream in agony as plague sores erupt from your skin."); act( "$n screams in agony as plague sores erupt from $s skin.", wch, NULL, NULL, TO_ROOM ); continue; } } } return; case DAM_DROWNING: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( is_affected( ch, gsn_otterlungs )) { ch->println("Water fills your lungs, but you are still able to breathe normally."); return; } ch->println("You start to cough as water fills your lungs."); act( "$n coughs loudly.", ch, NULL, NULL, TO_ROOM ); if ( saves_spell( obj->level, ch, DAM_DROWNING )) { ch->println("You manage to breathe the sweet, sweet air again."); return; } else { ch->println("You gasp for breath, unable to draw in air."); act( "$n gasps for breath in a futile attempt to draw in air.\r\n", ch, NULL, NULL, TO_ROOM ); dam = number_range( obj->level, obj->level * 2 ); } } else { act( "Water fills the room.", ch, obj, NULL, TO_CHAR ); act( "Water fills the room.", ch, obj, NULL, TO_ROOM ); af.where = WHERE_AFFECTS; af.type = gsn_drown; af.level = ch->level; af.duration = obj->level/2; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = ROOMAFF_UNDERWATER; affect_to_room( ch->in_room, &af ); return; // no damage per se } break; case DAM_CHARM: // puts players to sleep :) if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( IS_AFFECTED( ch, AFF_SLEEP )) return; if ( saves_spell( obj->level, ch, DAM_CHARM )) { ch->println("You stifle a yawn."); return; } af.where = WHERE_AFFECTS; af.type = gsn_sleep; af.level = number_fuzzy(obj->level); if(IS_NPC(ch)) af.duration = 4 + (obj->level/2); else af.duration = 2 + (obj->level/9); // duration reduced af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SLEEP; affect_join( ch, &af ); if ( IS_AWAKE( ch )) { ch->println("You feel very sleepy ..... zzzzzz."); act( "$n goes to sleep.", ch, NULL, NULL, TO_ROOM ); ch->position = POS_SLEEPING; } } else { for (wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room) { if ( IS_AFFECTED( wch, AFF_SLEEP )) continue; if ( saves_spell( obj->level, wch, DAM_CHARM )) { wch->println("You stifle a yawn."); continue; } af.where = WHERE_AFFECTS; af.type = gsn_sleep; af.level = number_fuzzy(obj->level); if(IS_NPC(wch)) af.duration = 4 + (obj->level/2); else af.duration = 2 + (obj->level/9); // duration reduced af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SLEEP; affect_join( wch, &af ); if ( IS_AWAKE( wch )) { ch->println("You feel very sleepy ..... zzzzzz."); act( "$n goes to sleep.", wch, NULL, NULL, TO_ROOM ); wch->position = POS_SLEEPING; } } } return; case DAM_ILLUSION: // no damage per se if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( IS_AFFECTED( ch, AFF_FEAR ) || IS_AFFECTED2( ch, AFF2_FEAR_MAGIC) ) { ch->println("A bright light flashes then disappears."); return; } if ( saves_spell( obj->level, ch, DAM_ILLUSION )) { ch->println("A bright light flashes then disappears."); return; } else { af.where = WHERE_AFFECTS; af.type = gsn_cause_fear; af.level = obj->level; af.duration = 1; if ( obj->level > 25) af.duration +=1; if ( obj->level > 50) af.duration +=1; if ( obj->level > 75) af.duration +=1; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_FEAR; affect_to_char( ch, &af ); wch->println("You panic as you are gripped by an incredible fear."); act( "$n screams and runs away.", ch, NULL, NULL, TO_ROOM ); do_fearful( wch ); /* in magic.c */ } } else { for ( wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room ) { if ( IS_AFFECTED( wch, AFF_FEAR ) || IS_AFFECTED2( wch, AFF2_FEAR_MAGIC) ) { wch->println("A bright light flashes then disappears."); continue; } if ( saves_spell( obj->level, wch, DAM_ILLUSION )) { wch->println("A bright light flashes then disappears."); continue; } af.where = WHERE_AFFECTS; af.type = gsn_cause_fear; af.level = obj->level; af.duration = 1; if ( obj->level > 25) af.duration +=1; if ( obj->level > 50) af.duration +=1; if ( obj->level > 75) af.duration +=1; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_FEAR; affect_to_char( wch, &af ); wch->println("You panic as you are gripped by an incredible fear."); act( "$n screams and runs away.", wch, NULL, NULL, TO_ROOM ); do_fearful( wch ); /* in magic.c */ } } return; case DAM_MENTAL: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( is_affected( ch, gsn_cause_headache )) { ch->println("Your head throbs."); return; } if ( saves_spell( obj->level, ch, DAM_MENTAL )) { ch->println("Your head throbs."); return; } else { af.where = WHERE_AFFECTS; af.type = gsn_cause_headache; af.level = obj->level; af.duration = obj->level; af.location = APPLY_SD; af.modifier = - obj->level/5; af.bitvector = 0; affect_to_char( ch, &af ); ch->println("Your head seems to explode with a sudden wave of indescribable pain!"); act( "$n grimaces in pain.", ch, NULL, NULL, TO_ROOM); } } else { for ( wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room ) { if ( is_affected( ch, gsn_cause_headache )) { wch->println("Your head throbs."); continue; } if ( saves_spell( obj->level, wch, DAM_MENTAL )) { wch->println("Your head throbs."); continue; } af.where = WHERE_AFFECTS; af.type = gsn_cause_headache; af.level = obj->level; af.duration = obj->level; af.location = APPLY_SD; af.modifier = - obj->level/5; af.bitvector = 0; affect_to_char( wch, &af ); wch->println("Your head seems to explode with a sudden wave of indescribable pain!"); act( "$n grimaces in pain.", wch, NULL, NULL, TO_ROOM); } } return; case DAM_NEGATIVE: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( IS_EVIL( ch )) { ch->println("You revel in your wickedness."); return; } if ( is_affected( ch, gsn_wrath )) { ch->println("You feel the taint of evil on your soul."); return; } if ( saves_spell( obj->level, ch, DAM_NEGATIVE )) { ch->println("You feel as though you want to retch."); return; } else { af.where = WHERE_AFFECTS; af.type = gsn_wrath; af.level = obj->level; af.duration = obj->level; af.location = APPLY_HIT; af.modifier = (-obj->level / 4) - 15; af.bitvector = 0; affect_join( ch, &af ); ch->println("You feel a force of great ill invade your soul."); act( "$n drops to $s knees in horror.", ch, NULL, NULL, TO_ROOM); } } else { for ( wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room ) { if ( IS_EVIL( wch )) { wch->println("You revel in your wickedness."); continue; } if ( is_affected( wch, gsn_wrath )) { wch->println("You feel the taint of evil on your soul."); continue; } if ( saves_spell( obj->level, wch, DAM_MENTAL )) { wch->println("You feel as though you want to retch."); continue; } af.where = WHERE_AFFECTS; af.type = gsn_wrath; af.level = obj->level; af.duration = obj->level; af.location = APPLY_HIT; af.modifier = (-obj->level / 4) - 15; af.bitvector = 0; affect_join( wch, &af ); wch->println("You feel a force of great ill invade your soul."); act( "$n drops to $s knees in horror.", wch, NULL, NULL, TO_ROOM); if ( wch->hit < 0 ) { raw_kill( wch, wch ); } return; } } return; case DAM_SOUND: if ( !IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { if ( is_affected( ch, gsn_deafness )) { ch->println("Your ears pop."); return; } if ( saves_spell( obj->level, ch, DAM_SOUND )) { ch->println("Your ears pop."); return; } else { af.where = WHERE_AFFECTS; af.type = gsn_deafness; af.level = obj->level; af.location = APPLY_NONE; af.modifier = 0; af.duration = 1+obj->level; af.bitvector = 0; affect_to_char( wch, &af ); ch->println("You have been deafened!"); act( "$n's ears glow for a moment.", ch, NULL, NULL, TO_ROOM ); } } else { for ( wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room ) { if ( is_affected( ch, gsn_deafness )) { wch->println("Your ears pop."); continue; } if ( saves_spell( obj->level, wch, DAM_SOUND )) { wch->println("Your ears pop."); continue; } af.where = WHERE_AFFECTS; af.type = gsn_deafness; af.level = obj->level; af.location = APPLY_NONE; af.modifier = 0; af.duration = 1+obj->level; af.bitvector = 0; affect_to_char( wch, &af ); wch->println("You have been deafened!"); act( "$n's ears glow for a moment.", wch, NULL, NULL, TO_ROOM ); } } return; case DAM_BASH: if (!IS_SET( obj->trap_trig, TRAP_TRIG_ROOM )) { act("$n sets off a trap on $p and is hit by a blunt object!", ch, obj, NULL, TO_ROOM); act("You are hit by a blunt object from $p!", ch, obj, NULL, TO_CHAR); dam = 3 * obj->level + GET_AC( ch, AC_BASH ); } else { act("$n sets off a trap on $p and you are hit by a flying object!", ch, obj, NULL, TO_ROOM); act("You are hit by a blunt object from $p!", ch, obj, NULL, TO_CHAR); } break; case DAM_PIERCE: if (!IS_SET( obj->trap_trig, TRAP_TRIG_ROOM) ) { act("$n sets of a trap on $p and is pierced in the chest!", ch, obj, NULL, TO_ROOM); act("You set off a trap on $p and are pierced through the chest!", ch, obj, NULL, TO_CHAR); dam = 3 * obj->level + GET_AC( ch, AC_PIERCE ); } else { act("$n sets off a trap on $p and you are hit by a piercing object!", ch, obj, NULL, TO_ROOM); act("You set off a trap on $p and are pierced through the chest!", ch, obj, NULL, TO_CHAR); } break; case DAM_SLASH: if (!IS_SET(obj->trap_trig, TRAP_TRIG_ROOM) ) { act("$n just got slashed by a trap on $p.", ch, obj, NULL, TO_ROOM); act("You just got slashed by a trap on $p!", ch, obj, NULL, TO_CHAR); dam = 3 * obj->level + GET_AC( ch, AC_PIERCE ); } else { act("$n set off a trap releasing a blade that slashes you!", ch, obj, NULL, TO_ROOM); act("You set off a trap releasing blades around the room..", ch, obj, NULL, TO_CHAR); act("One of the blades slashes you in the chest!", ch, obj, NULL, TO_CHAR); } break; case DAM_NONE: case DAM_OTHER: default: act( "A clicking sound comes from $p but nothing seems to have happened.", ch, obj, NULL, TO_CHAR ); act( "A clicking sound comes from $p but nothing seems to have happened.", ch, obj, NULL, TO_ROOM ); return; break; } // Moment of truth, dish out the damage if (!IS_SET(obj->trap_trig, TRAP_TRIG_ROOM)) { if ( ch->position == POS_DEAD ) return; // stop crazy builders if ( dam > 1000 ) { bugf( "Damage: %d: more than 1000 points in trap!", dam ); dam = 1000; } if ( IS_AFFECTED(ch, AFF_INVISIBLE) ) { affect_strip( ch, gsn_invisibility ); affect_strip( ch, gsn_mass_invis ); REMOVE_BIT( ch->affected_by, AFF_INVISIBLE ); act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM ); } // divide // Mods and such if ( IS_AFFECTED( ch, AFF_SANCTUARY )) dam /= 2; if ( saves_spell( obj->level, ch, obj->trap_dtype )) dam /= 2; switch( check_immune( ch, obj->trap_dtype )) { case(IS_IMMUNE): dam = 0; break; case(IS_RESISTANT): dam -= dam/2; break; case(IS_VULNERABLE): dam += dam; break; } if ( dam < 0 ) dam = 0; ch->hit -= dam; if (( IS_NPC(ch) || IS_IMMORTAL( ch )) && ch->hit < 1 ) ch->hit = 1; update_pos( ch ); switch( ch->position ) { case POS_MORTAL: act( "$n is mortally wounded, and will die soon, if not aided.", ch, NULL, NULL, TO_ROOM ); ch->println("You are mortally wounded, and will die soon, if not aided."); break; case POS_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", ch, NULL, NULL, TO_ROOM ); ch->println("You are incapacitated and will slowly die, if not aided."); break; case POS_STUNNED: act( "$n is stunned, but will probably recover.",ch, NULL, NULL, TO_ROOM); ch->println("You are stunned, but will probably recover."); break; case POS_DEAD: act( "$n is DEAD!!", ch, NULL, NULL, TO_ROOM ); ch->println("You have been `rKILLED!!`x\r\n"); break; default: if ( dam > ch->max_hit / 4 ) { ch->println("`YThat really did `rHURT!`x"); } if ( ch->hit < ch->max_hit / 4 ) { ch->println("`YYou sure are `rBLEEDING!`x"); } break; } if ( IS_NPC(ch)) { raw_kill(ch,ch); return; } if (ch->position == POS_DEAD) { sprintf( log_buf, "%s [lvl %d] got toasted by a trap at %s [lvl %d] [room %d]", ch->name, ch->level, ch->in_room->name, obj->level, ch->in_room->vnum ); log_string( log_buf ); wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0); if(ch->level<21) { if ( ch->exp > exp_per_level(ch,ch->pcdata->points) * ch->level ) { gain_exp( ch, (2 * (exp_per_level(ch,ch->pcdata->points) * ch->level - ch->exp)/3) + 50 ); } } else { int xp_amount; if(ch->level>50) { xp_amount=500+(get_sublevels_for_level( ch->level) *150); } else { xp_amount=500; } ch->printlnf("You have lost %d xp.", xp_amount); gain_exp( ch, -xp_amount); if ( IS_HERO( ch )) do_heroxp( ch, -xp_amount); if(ch->exp<exp_per_level(ch,ch->pcdata->points)* ch->level ) { drop_level(ch); // Too mean??? check_perm_damage(ch); } else { if(number_range(1,get_sublevels_for_level( ch->level+5))<2) { // Too Mean??? check_perm_damage(ch); } else { ch->println("Luckily you have not suffered serious injury."); } } } raw_kill( ch, ch ); char_data *trapname = create_mobile( limbo_mob_index_data, 0 ); replace_string(trapname->short_descr, "a trap"); make_corpse( ch, trapname ); extract_char( trapname, true ); } } else { for (wch = ch->in_room->people; wch != NULL; wch = wch->next_in_room) { if (wch == NULL) break; if ( obj->trap_dtype == DAM_BASH || obj->trap_dtype == DAM_PIERCE || obj->trap_dtype == DAM_SLASH) dam = (3 * obj->level) + GET_AC(wch,obj->trap_dtype); if ( wch->position == POS_DEAD ) continue; if ( dam > 1000 ) { bugf( "Damage: %d: more than 1000 points!", dam ); dam = 1000; } if ( IS_AFFECTED(wch, AFF_INVISIBLE) ) { affect_strip( wch, gsn_invisibility ); affect_strip( wch, gsn_mass_invis ); REMOVE_BIT( wch->affected_by, AFF_INVISIBLE ); act( "$n fades into existence.", wch, NULL, NULL, TO_ROOM ); } /* * Damage modifiers. */ if ( IS_AFFECTED( wch, AFF_SANCTUARY )) dam /= 2; if ( saves_spell( obj->level, wch, obj->trap_dtype )) dam /= 2; if ( IS_GOOD( wch ) && obj->trap_dtype == DAM_HOLY ) { wch->println("You are washed in pure, divine light."); continue; } switch( check_immune( wch, obj->trap_dtype )) { case(IS_IMMUNE): dam = 0; break; case(IS_RESISTANT): dam -= dam/2; break; case(IS_VULNERABLE): dam += dam; break; } if ( dam < 0 ) dam = 0; wch->hit -= dam; if (( IS_NPC(wch) || IS_IMMORTAL( wch )) && wch->hit < 1 ) wch->hit = 1; update_pos( wch ); switch( wch->position ) { case POS_MORTAL: act( "$n is mortally wounded, and will die soon, if not aided.", wch, NULL, NULL, TO_ROOM ); wch->println("You are mortally wounded, and will die soon, if not aided."); break; case POS_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", wch, NULL, NULL, TO_ROOM ); wch->println("You are incapacitated and will slowly die, if not aided."); break; case POS_STUNNED: act( "$n is stunned, but will probably recover.",wch, NULL, NULL, TO_ROOM); wch->println("You are stunned, but will probably recover."); break; case POS_DEAD: act( "$n is DEAD!!", wch, 0, 0, TO_ROOM ); wch->println("You have been `rKILLED!!`x\r\n"); break; default: if ( dam > wch->max_hit / 4 ) { wch->println("`YThat really did `rHURT!`x"); } if ( wch->hit < wch->max_hit / 4 ) { wch->println("`YYou sure are `rBLEEDING!`x"); } break; } if ( IS_NPC(wch)) { raw_kill(wch,wch); continue; } if (wch->position == POS_DEAD) { sprintf( log_buf, "%s [lvl %d] got toasted by a trap at %s [lvl %d] [room %d]", wch->name, wch->level, wch->in_room->name, obj->level, wch->in_room->vnum ); log_string( log_buf ); wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0); if(wch->level<21) { if ( wch->exp > exp_per_level(wch,wch->pcdata->points) * wch->level ) { gain_exp( wch, (2 * (exp_per_level(wch,wch->pcdata->points) * wch->level - wch->exp)/3) + 50 ); } } else { int xp_amount; if(wch->level>50) { xp_amount=500+(get_sublevels_for_level( wch->level) *150); } else { xp_amount=500; } wch->printlnf("You have lost %d xp.", xp_amount); gain_exp( wch, -xp_amount); if ( IS_HERO( wch )) do_heroxp( wch, -xp_amount); if(wch->exp<exp_per_level(wch,wch->pcdata->points)* wch->level ) { drop_level(wch); // Too mean??? check_perm_damage(wch); } else { if(number_range(1,get_sublevels_for_level( wch->level+5))<2) { // Too Mean??? check_perm_damage(victim); } else { wch->println("Luckily you have not suffered serious injury."); } } } raw_kill( wch, wch ); char_data *trapname = create_mobile( limbo_mob_index_data, 0 ); replace_string(trapname->short_descr, "a trap"); make_corpse( wch, trapname ); extract_char( trapname, true ); } } } return; } /**************************************************************************/ void do_search( char_data *ch, char *argument ) { OBJ_DATA *obj; char arg[MIL]; int chance; one_argument(argument, arg); if ( IS_NPC(ch)) return; if ( IS_NULLSTR( arg )) { ch->println("What do you want to search?"); return; } if (( obj = get_obj_here( ch, arg )) == NULL) { ch->println("What do you wish to search?"); return; } if ( !IS_TRAPPED( obj )) { act( "$p doesn't appear to be trapped.", ch, obj, NULL, TO_CHAR ); return; } // if players wanna spam this command, they'll get punished for it if ( ch->desc && ch->desc->repeat>5 ) { act( "Upon inspecting $p closer, you've managed to trigger a well-hidden trap.", ch, obj, NULL, TO_CHAR ); trapdamage( ch, obj ); return; } chance = ( get_skill( ch,gsn_search ) + obj->trap_modifier ) - number_percent(); if ( chance > 25 ) { act( "$p is rigged with a trap.", ch, obj, NULL, TO_CHAR ); if ( obj->trap_modifier <= 65 ) { obj->trap_modifier += 10; } } else if ( chance > -20 ) { act( "You're not entirely certain, but $p could be trapped.", ch, obj, NULL, TO_CHAR ); } else { act( "$p doesn't appear to be trapped.", ch, obj, NULL, TO_CHAR ); if ( obj->trap_modifier >= -65 ) { obj->trap_modifier -= 10; } } if ( chance < -50 ) { act( "\r\nUpon inspecting $p closer, you've managed to trigger a well-hidden trap.", ch, obj, NULL, TO_CHAR ); act( "$n inadvertently triggered a hidden trap on $p.", ch, obj, NULL, TO_ROOM ); check_improve( ch, gsn_search, false, 10 ); trapdamage( ch, obj ); } else { check_improve( ch, gsn_search, true, 10 ); } return; } /**************************************************************************/ void do_disarm_trap( char_data *ch, char *argument ) { OBJ_DATA *obj; char arg[MIL]; int chance; one_argument(argument, arg); if ( IS_NPC(ch)) return; if (( obj = get_obj_here( ch, arg )) == NULL) { ch->println("What do you wish to disarm?"); return; } if ( !IS_TRAPPED( obj )) { act( "Ok.", ch, NULL, NULL, TO_CHAR ); return; } chance = (( get_skill( ch,gsn_search ) + obj->trap_modifier ) - number_percent()) - 25; if ( chance > 25 ) { // good success, trap is gone act( "Ok.", ch, NULL, NULL, TO_CHAR ); check_improve( ch, gsn_search, true, 10 ); REMOVE_BIT( obj->extra2_flags, OBJEXTRA2_TRAP ); } else if ( chance > 0 ) { // medium success, charges lowered, could still be trapped though act( "Ok.", ch, NULL, NULL, TO_CHAR ); obj->trap_charge -= number_range( 1, 3 ); check_improve( ch, gsn_search, true, 5 ); } else { // failure, BOOOOM!!! act( "Curses! You've managed to trigger $p.", ch, obj, NULL, TO_CHAR ); check_improve( ch, gsn_search, false, 10 ); trapdamage( ch, obj ); } return; } /**************************************************************************/ /**************************************************************************/ /**************************************************************************/ /**************************************************************************/