void trapfunc::dissector( Creature *c, const tripoint &p ) { //~ the sound of a dissector dissecting sounds::sound( p, 10, _( "BRZZZAP!" ) ); if( c != nullptr ) { c->add_msg_player_or_npc( m_bad, _( "Electrical beams emit from the floor and slice your flesh!" ), _( "Electrical beams emit from the floor and slice <npcname>s flesh!" ) ); c->add_memorial_log( pgettext( "memorial_male", "Stepped into a dissector." ), pgettext( "memorial_female", "Stepped into a dissector." ) ); monster *z = dynamic_cast<monster *>( c ); player *n = dynamic_cast<player *>( c ); if( n != nullptr ) { n->deal_damage( nullptr, bp_head, damage_instance( DT_CUT, 15 ) ); n->deal_damage( nullptr, bp_torso, damage_instance( DT_CUT, 20 ) ); n->deal_damage( nullptr, bp_arm_r, damage_instance( DT_CUT, 12 ) ); n->deal_damage( nullptr, bp_arm_l, damage_instance( DT_CUT, 12 ) ); n->deal_damage( nullptr, bp_hand_r, damage_instance( DT_CUT, 10 ) ); n->deal_damage( nullptr, bp_hand_l, damage_instance( DT_CUT, 10 ) ); n->deal_damage( nullptr, bp_leg_r, damage_instance( DT_CUT, 12 ) ); n->deal_damage( nullptr, bp_leg_r, damage_instance( DT_CUT, 12 ) ); n->deal_damage( nullptr, bp_foot_l, damage_instance( DT_CUT, 10 ) ); n->deal_damage( nullptr, bp_foot_r, damage_instance( DT_CUT, 10 ) ); } else if( z != nullptr ) { z->apply_damage( nullptr, bp_torso, 60 ); if( z->is_dead() ) { z->explode(); } } c->check_dead_state(); } }
void trapfunc::goo( Creature *c, const tripoint &p ) { if( c != nullptr ) { c->add_msg_player_or_npc( m_bad, _( "You step in a puddle of thick goo." ), _( "<npcname> steps in a puddle of thick goo." ) ); c->add_memorial_log( pgettext( "memorial_male", "Stepped into thick goo." ), pgettext( "memorial_female", "Stepped into thick goo." ) ); monster *z = dynamic_cast<monster *>( c ); player *n = dynamic_cast<player *>( c ); if( n != nullptr ) { n->add_env_effect( "slimed", bp_foot_l, 6, 20 ); n->add_env_effect( "slimed", bp_foot_r, 6, 20 ); if( one_in( 3 ) ) { n->add_msg_if_player( m_bad, _( "The acidic goo eats away at your feet." ) ); n->deal_damage( nullptr, bp_foot_l, damage_instance( DT_CUT, 5 ) ); n->deal_damage( nullptr, bp_foot_r, damage_instance( DT_CUT, 5 ) ); n->check_dead_state(); } } else if( z != nullptr ) { if( z->type->id == mon_blob ) { z->set_speed_base( z->get_speed_base() + 15 ); z->set_hp( z->get_speed() ); } else { z->poly( mon_blob ); z->set_speed_base( z->get_speed_base() - 15 ); z->set_hp( z->get_speed() ); } } } g->m.remove_trap( p ); }
void trapfunc::board( Creature *c, const tripoint& ) { // tiny animals don't trigger spiked boards, they can squeeze between the nails if( c != nullptr && c->get_size() == MS_TINY ) { return; } if( c != nullptr ) { c->add_memorial_log( pgettext( "memorial_male", "Stepped on a spiked board." ), pgettext( "memorial_female", "Stepped on a spiked board." ) ); c->add_msg_player_or_npc( m_bad, _( "You step on a spiked board!" ), _( "<npcname> steps on a spiked board!" ) ); monster *z = dynamic_cast<monster *>( c ); player *n = dynamic_cast<player *>( c ); if( z != nullptr ) { z->moves -= 80; z->apply_damage( nullptr, bp_foot_l, rng( 3, 5 ) ); z->apply_damage( nullptr, bp_foot_r, rng( 3, 5 ) ); } else { c->deal_damage( nullptr, bp_foot_l, damage_instance( DT_CUT, rng( 6, 10 ) ) ); c->deal_damage( nullptr, bp_foot_r, damage_instance( DT_CUT, rng( 6, 10 ) ) ); if( ( n->has_trait( "INFRESIST" ) ) && ( one_in( 256 ) ) ) { n->add_effect( "tetanus", 1, num_bp, true ); } else if( ( !n->has_trait( "INFIMMUNE" ) || !n->has_trait( "INFRESIST" ) ) && ( one_in( 35 ) ) ) { n->add_effect( "tetanus", 1, num_bp, true ); } } c->check_dead_state(); } }
void trapfunc::lava( Creature *c, const tripoint &p ) { if( c != nullptr ) { c->add_msg_player_or_npc( m_bad, _( "The %s burns you horribly!" ), _( "The %s burns <npcname>!" ), g->m.tername( p ).c_str() ); c->add_memorial_log( pgettext( "memorial_male", "Stepped into lava." ), pgettext( "memorial_female", "Stepped into lava." ) ); monster *z = dynamic_cast<monster *>( c ); player *n = dynamic_cast<player *>( c ); if( n != nullptr ) { n->deal_damage( nullptr, bp_foot_l, damage_instance( DT_HEAT, 20 ) ); n->deal_damage( nullptr, bp_foot_r, damage_instance( DT_HEAT, 20 ) ); n->deal_damage( nullptr, bp_leg_l, damage_instance( DT_HEAT, 20 ) ); n->deal_damage( nullptr, bp_leg_r, damage_instance( DT_HEAT, 20 ) ); } else if( z != nullptr ) { // MATERIALS-TODO: use fire resistance int dam = 30; if( z->made_of( "flesh" ) || z->made_of( "iflesh" ) ) { dam = 50; } if( z->made_of( "veggy" ) ) { dam = 80; } if( z->made_of( "paper" ) || z->made_of( LIQUID ) || z->made_of( "powder" ) || z->made_of( "wood" ) || z->made_of( "cotton" ) || z->made_of( "wool" ) ) { dam = 200; } if( z->made_of( "stone" ) ) { dam = 15; } if( z->made_of( "kevlar" ) || z->made_of( "steel" ) ) { dam = 5; } z->apply_damage( nullptr, bp_torso, dam ); } c->check_dead_state(); } }
void trapfunc::caltrops( Creature *c, const tripoint& ) { // tiny animals don't trigger caltrops, they can squeeze between them if( c != nullptr && c->get_size() == MS_TINY ) { return; } if( c != nullptr ) { c->add_memorial_log( pgettext( "memorial_male", "Stepped on a caltrop." ), pgettext( "memorial_female", "Stepped on a caltrop." ) ); c->add_msg_player_or_npc( m_bad, _( "You step on a sharp metal caltrop!" ), _( "<npcname> steps on a sharp metal caltrop!" ) ); monster *z = dynamic_cast<monster *>( c ); if( z != nullptr ) { z->moves -= 80; c->apply_damage( nullptr, bp_foot_l, rng( 9, 15 ) ); c->apply_damage( nullptr, bp_foot_r, rng( 9, 15 ) ); } else { c->deal_damage( nullptr, bp_foot_l, damage_instance( DT_CUT, rng( 9, 30 ) ) ); c->deal_damage( nullptr, bp_foot_r, damage_instance( DT_CUT, rng( 9, 30 ) ) ); } c->check_dead_state(); } }
void trapfunc::pit( Creature *c, const tripoint &p ) { // tiny animals aren't hurt by falling into pits if( c != nullptr && c->get_size() == MS_TINY ) { return; } if( c != nullptr ) { const float eff = pit_effectiveness( p ); c->add_msg_player_or_npc( m_bad, _( "You fall in a pit!" ), _( "<npcname> falls in a pit!" ) ); c->add_memorial_log( pgettext( "memorial_male", "Fell in a pit." ), pgettext( "memorial_female", "Fell in a pit." ) ); c->add_effect( "in_pit", 1, num_bp, true ); monster *z = dynamic_cast<monster *>( c ); player *n = dynamic_cast<player *>( c ); if( n != nullptr ) { if( ( n->has_trait( "WINGS_BIRD" ) ) || ( ( one_in( 2 ) ) && ( n->has_trait( "WINGS_BUTTERFLY" ) ) ) ) { n->add_msg_if_player( _( "You flap your wings and flutter down gracefully." ) ); } else { int dodge = n->get_dodge(); int damage = eff * rng( 10, 20 ) - rng( dodge, dodge * 5 ); if( damage > 0 ) { n->add_msg_if_player( m_bad, _( "You hurt yourself!" ) ); n->hurtall( rng( int( damage / 2 ), damage ), n ); // like the message says \-: n->deal_damage( nullptr, bp_leg_l, damage_instance( DT_BASH, damage ) ); n->deal_damage( nullptr, bp_leg_r, damage_instance( DT_BASH, damage ) ); } else { n->add_msg_if_player( _( "You land nimbly." ) ); } } } else if( z != nullptr ) { z->apply_damage( nullptr, bp_torso, eff * rng( 10, 20 ) ); } c->check_dead_state(); } }
void monster::knock_back_from(int x, int y) { if (x == posx() && y == posy()) return; // No effect if( is_hallucination() ) { die( nullptr ); return; } point to(posx(), posy()); if (x < posx()) to.x++; if (x > posx()) to.x--; if (y < posy()) to.y++; if (y > posy()) to.y--; bool u_see = g->u.sees( to ); // First, see if we hit another monster int mondex = g->mon_at(to.x, to.y); if( mondex != -1 && g->zombie( mondex ).is_hallucination() ) { // hallucinations should not affect real monsters. If they interfer, just remove them. g->zombie( mondex ).die( this ); mondex = -1; } if (mondex != -1) { monster *z = &(g->zombie(mondex)); apply_damage( z, bp_torso, z->type->size ); add_effect("stunned", 1); if (type->size > 1 + z->type->size) { z->knock_back_from(posx(), posy()); // Chain reaction! z->apply_damage( this, bp_torso, type->size ); z->add_effect("stunned", 1); } else if (type->size > z->type->size) { z->apply_damage( this, bp_torso, type->size ); z->add_effect("stunned", 1); } z->check_dead_state(); if (u_see) add_msg(_("The %s bounces off a %s!"), name().c_str(), z->name().c_str()); return; } int npcdex = g->npc_at(to.x, to.y); if (npcdex != -1) { npc *p = g->active_npc[npcdex]; apply_damage( p, bp_torso, 3 ); add_effect("stunned", 1); p->deal_damage( this, bp_torso, damage_instance( DT_BASH, type->size ) ); if (u_see) add_msg(_("The %s bounces off %s!"), name().c_str(), p->name.c_str()); p->check_dead_state(); return; } // If we're still in the function at this point, we're actually moving a tile! if (g->m.ter_at(to.x, to.y).has_flag(TFLAG_DEEP_WATER)) { if (g->m.has_flag("LIQUID", to.x, to.y) && can_drown()) { die( nullptr ); if (u_see) { add_msg(_("The %s drowns!"), name().c_str()); } } else if (has_flag(MF_AQUATIC)) { // We swim but we're NOT in water die( nullptr ); if (u_see) { add_msg(_("The %s flops around and dies!"), name().c_str()); } } } if (g->m.move_cost(to.x, to.y) == 0) { // It's some kind of wall. apply_damage( nullptr, bp_torso, type->size ); add_effect("stunned", 2); if (u_see) { add_msg(_("The %s bounces off a %s."), name().c_str(), g->m.tername(to.x, to.y).c_str()); } } else { // It's no wall setpos(to); } check_dead_state(); }
void monster::knock_back_from( const tripoint &p ) { if( p == pos() ) { return; // No effect } if( is_hallucination() ) { die( nullptr ); return; } tripoint to = pos();; if( p.x < posx() ) { to.x++; } if( p.x > posx() ) { to.x--; } if( p.y < posy() ) { to.y++; } if( p.y > posy() ) { to.y--; } bool u_see = g->u.sees( to ); // First, see if we hit another monster if( monster *const z = g->critter_at<monster>( to ) ) { apply_damage( z, bp_torso, z->type->size ); add_effect( effect_stunned, 1 ); if( type->size > 1 + z->type->size ) { z->knock_back_from( pos() ); // Chain reaction! z->apply_damage( this, bp_torso, type->size ); z->add_effect( effect_stunned, 1 ); } else if( type->size > z->type->size ) { z->apply_damage( this, bp_torso, type->size ); z->add_effect( effect_stunned, 1 ); } z->check_dead_state(); if( u_see ) { add_msg( _( "The %1$s bounces off a %2$s!" ), name().c_str(), z->name().c_str() ); } return; } if( npc *const p = g->critter_at<npc>( to ) ) { apply_damage( p, bp_torso, 3 ); add_effect( effect_stunned, 1 ); p->deal_damage( this, bp_torso, damage_instance( DT_BASH, type->size ) ); if( u_see ) { add_msg( _( "The %1$s bounces off %2$s!" ), name().c_str(), p->name.c_str() ); } p->check_dead_state(); return; } // If we're still in the function at this point, we're actually moving a tile! if( g->m.has_flag_ter( TFLAG_DEEP_WATER, to ) ) { if( g->m.has_flag( "LIQUID", to ) && can_drown() ) { die( nullptr ); if( u_see ) { add_msg( _( "The %s drowns!" ), name().c_str() ); } } else if( has_flag( MF_AQUATIC ) ) { // We swim but we're NOT in water die( nullptr ); if( u_see ) { add_msg( _( "The %s flops around and dies!" ), name().c_str() ); } } } if( g->m.impassable( to ) ) { // It's some kind of wall. apply_damage( nullptr, bp_torso, type->size ); add_effect( effect_stunned, 2 ); if( u_see ) { add_msg( _( "The %1$s bounces off a %2$s." ), name().c_str(), g->m.obstacle_name( to ).c_str() ); } } else { // It's no wall setpos( to ); } check_dead_state(); }
void trapfunc::pit_glass( Creature *c, const tripoint &p ) { // tiny animals aren't hurt by falling into glass pits if( c != nullptr && c->get_size() == MS_TINY ) { return; } if( c != nullptr ) { c->add_msg_player_or_npc( m_bad, _( "You fall in a pit filled with glass shards!" ), _( "<npcname> falls in pit filled with glass shards!" ) ); c->add_memorial_log( pgettext( "memorial_male", "Fell into a pit filled with glass shards." ), pgettext( "memorial_female", "Fell into a pit filled with glass shards." ) ); c->add_effect( "in_pit", 1, num_bp, true ); monster *z = dynamic_cast<monster *>( c ); player *n = dynamic_cast<player *>( c ); if( n != nullptr ) { int dodge = n->get_dodge(); int damage = pit_effectiveness( p ) * rng( 15, 35 ); if( ( n->has_trait( "WINGS_BIRD" ) ) || ( ( one_in( 2 ) ) && ( n->has_trait( "WINGS_BUTTERFLY" ) ) ) ) { n->add_msg_if_player( _( "You flap your wings and flutter down gracefully." ) ); } else if( 0 == damage || rng( 5, 30 ) < dodge ) { n->add_msg_if_player( _( "You avoid the glass shards within." ) ); } else { body_part hit = num_bp; switch( rng( 1, 10 ) ) { case 1: hit = bp_leg_l; break; case 2: hit = bp_leg_r; break; case 3: hit = bp_arm_l; break; case 4: hit = bp_arm_r; break; case 5: hit = bp_foot_l; break; case 6: hit = bp_foot_r; break; case 7: case 8: case 9: case 10: hit = bp_torso; break; } n->add_msg_if_player( m_bad, _( "The glass shards slash your %s!" ), body_part_name_accusative( hit ).c_str() ); n->deal_damage( nullptr, hit, damage_instance( DT_CUT, damage ) ); if( ( n->has_trait( "INFRESIST" ) ) && ( one_in( 256 ) ) ) { n->add_effect( "tetanus", 1, num_bp, true ); } else if( ( !n->has_trait( "INFIMMUNE" ) || !n->has_trait( "INFRESIST" ) ) && ( one_in( 35 ) ) ) { n->add_effect( "tetanus", 1, num_bp, true ); } } } else if( z != nullptr ) { z->apply_damage( nullptr, bp_torso, rng( 20, 50 ) ); } c->check_dead_state(); } if( one_in( 5 ) ) { if( g->u.sees( p ) ) { add_msg( _( "The shards shatter!" ) ); } g->m.ter_set( p, t_pit ); for( int i = 0; i < 20; i++ ) { // 20 shards in a pit. if( one_in( 3 ) ) { g->m.spawn_item( p, "glass_shard" ); } } } }
void trapfunc::shotgun( Creature *c, const tripoint &p ) { sounds::sound( p, 60, _( "Kerblam!" ) ); int shots = 1; if( c != nullptr ) { c->add_msg_player_or_npc( m_neutral, _( "You trigger a shotgun trap!" ), _( "<npcname> triggers a shotgun trap!" ) ); c->add_memorial_log( pgettext( "memorial_male", "Triggered a shotgun trap." ), pgettext( "memorial_female", "Triggered a shotgun trap." ) ); monster *z = dynamic_cast<monster *>( c ); player *n = dynamic_cast<player *>( c ); if( n != nullptr ) { shots = ( one_in( 8 ) || one_in( 20 - n->str_max ) ? 2 : 1 ); if( g->m.tr_at( p ).loadid == tr_shotgun_1 ) { shots = 1; } if( rng( 5, 50 ) > n->get_dodge() ) { body_part hit = num_bp; switch( rng( 1, 10 ) ) { case 1: if( one_in( 2 ) ) { hit = bp_foot_l; } else { hit = bp_foot_r; } break; case 2: case 3: case 4: if( one_in( 2 ) ) { hit = bp_leg_l; } else { hit = bp_leg_r; } break; case 5: case 6: case 7: case 8: case 9: hit = bp_torso; break; case 10: hit = bp_head; break; } //~ %s is bodypart n->add_msg_if_player( m_bad, _( "Your %s is hit!" ), body_part_name( hit ).c_str() ); c->deal_damage( nullptr, hit, damage_instance( DT_CUT, rng( 40 * shots, 60 * shots ) ) ); } else { n->add_msg_player_or_npc( m_neutral, _( "You dodge the shot!" ), _( "<npcname> dodges the shot!" ) ); } } else if( z != nullptr ) { bool seen = g->u.sees( *z ); int chance = 0; switch( z->type->size ) { case MS_TINY: chance = 100; break; case MS_SMALL: chance = 16; break; case MS_MEDIUM: chance = 12; break; case MS_LARGE: chance = 8; break; case MS_HUGE: chance = 2; break; } shots = ( one_in( 8 ) || one_in( chance ) ? 2 : 1 ); if( g->m.tr_at( p ).loadid == tr_shotgun_1 ) { shots = 1; } if( seen ) { add_msg( m_bad, _( "A shotgun fires and hits the %s!" ), z->name().c_str() ); } z->apply_damage( nullptr, bp_torso, rng( 40 * shots, 60 * shots ) ); } c->check_dead_state(); } if( shots == 2 || g->m.tr_at( p ).loadid == tr_shotgun_1 ) { g->m.remove_trap( p ); g->m.spawn_item( p, "shotgun_sawn" ); g->m.spawn_item( p, "string_6" ); } else { g->m.add_trap( p, tr_shotgun_1 ); } }
void trapfunc::crossbow( Creature *c, const tripoint &p ) { bool add_bolt = true; if( c != nullptr ) { c->add_msg_player_or_npc( m_neutral, _( "You trigger a crossbow trap!" ), _( "<npcname> triggers a crossbow trap!" ) ); c->add_memorial_log( pgettext( "memorial_male", "Triggered a crossbow trap." ), pgettext( "memorial_female", "Triggered a crossbow trap." ) ); monster *z = dynamic_cast<monster *>( c ); player *n = dynamic_cast<player *>( c ); if( n != nullptr ) { if( !one_in( 4 ) && rng( 8, 20 ) > n->get_dodge() ) { body_part hit = num_bp; switch( rng( 1, 10 ) ) { case 1: if( one_in( 2 ) ) { hit = bp_foot_l; } else { hit = bp_foot_r; } break; case 2: case 3: case 4: if( one_in( 2 ) ) { hit = bp_leg_l; } else { hit = bp_leg_r; } break; case 5: case 6: case 7: case 8: case 9: hit = bp_torso; break; case 10: hit = bp_head; break; } //~ %s is bodypart n->add_msg_if_player( m_bad, _( "Your %s is hit!" ), body_part_name( hit ).c_str() ); c->deal_damage( nullptr, hit, damage_instance( DT_CUT, rng( 20, 30 ) ) ); add_bolt = !one_in( 10 ); } else { n->add_msg_player_or_npc( m_neutral, _( "You dodge the shot!" ), _( "<npcname> dodges the shot!" ) ); } } else if( z != nullptr ) { bool seen = g->u.sees( *z ); int chance = 0; // adapted from shotgun code - chance of getting hit depends on size switch( z->type->size ) { case MS_TINY: chance = 50; break; case MS_SMALL: chance = 8; break; case MS_MEDIUM: chance = 6; break; case MS_LARGE: chance = 4; break; case MS_HUGE: chance = 1; break; } if( one_in( chance ) ) { if( seen ) { add_msg( m_bad, _( "A bolt shoots out and hits the %s!" ), z->name().c_str() ); } z->apply_damage( nullptr, bp_torso, rng( 20, 30 ) ); add_bolt = !one_in( 10 ); } else if( seen ) { add_msg( m_neutral, _( "A bolt shoots out, but misses the %s." ), z->name().c_str() ); } } c->check_dead_state(); } g->m.remove_trap( p ); g->m.spawn_item( p, "crossbow" ); g->m.spawn_item( p, "string_6" ); if( add_bolt ) { g->m.spawn_item( p, "bolt_steel", 1, 1 ); } }