1212#include < string>
1313#include < tuple>
1414
15+ #include " ammo_effect.h"
1516#include " anatomy.h"
1617#include " body_part_set.h"
1718#include " cached_options.h"
@@ -85,6 +86,7 @@ static const ammo_effect_str_id ammo_effect_FOAMCRETE( "FOAMCRETE" );
8586static const ammo_effect_str_id ammo_effect_IGNITE ( " IGNITE" );
8687static const ammo_effect_str_id ammo_effect_INCENDIARY ( " INCENDIARY" );
8788static const ammo_effect_str_id ammo_effect_LARGE_BEANBAG ( " LARGE_BEANBAG" );
89+ static const ammo_effect_str_id ammo_effect_LIQUID ( " LIQUID" );
8890static const ammo_effect_str_id ammo_effect_MAGIC ( " MAGIC" );
8991static const ammo_effect_str_id ammo_effect_NOGIB ( " NOGIB" );
9092static const ammo_effect_str_id ammo_effect_NO_DAMAGE_SCALING ( " NO_DAMAGE_SCALING" );
@@ -939,11 +941,27 @@ double Creature::accuracy_projectile_attack( dealt_projectile_attack &attack ) c
939941 return attack.missed_by + std::max ( 0.0 , std::min ( 1.0 , dodge_rescaled ) );
940942}
941943
942- void projectile::apply_effects_nodamage ( Creature &target, Creature *source ) const
944+ void projectile::apply_effects_nodamage ( Creature &target, Creature *source,
945+ const dealt_damage_instance &dealt_dam, bool soaked_through ) const
943946{
947+ bool is_liquid = proj_effects.count ( ammo_effect_LIQUID );
944948 if ( proj_effects.count ( ammo_effect_BOUNCE ) ) {
945949 target.add_effect ( effect_source ( source ), effect_bounced, 1_turns );
946950 }
951+
952+ for ( const ammo_effect_str_id &proj_effect : proj_effects ) {
953+ for ( const on_hit_effect &on_hit_eff : proj_effect->on_hit_effects ) {
954+ if ( on_hit_eff.need_touch_skin && is_liquid && !soaked_through ) {
955+ continue ;
956+ }
957+ if ( on_hit_eff.bp_to_hit ) {
958+ if ( on_hit_eff.bp_to_hit != dealt_dam.bp_hit ) {
959+ continue ;
960+ }
961+ }
962+ target.add_effect ( on_hit_eff.effect , on_hit_eff.duration , false , on_hit_eff.intensity );
963+ }
964+ }
947965}
948966
949967void projectile::apply_effects_damage ( Creature &target, Creature *source,
@@ -1266,8 +1284,6 @@ void Creature::deal_projectile_attack( Creature *source, dealt_projectile_attack
12661284 return ;
12671285 }
12681286
1269- proj.apply_effects_nodamage ( *this , source );
1270-
12711287 projectile_attack_results hit_selection = select_body_part_projectile_attack ( proj, goodhit,
12721288 missed_by );
12731289 // Create a copy that records whether the attack is a crit.
@@ -1296,15 +1312,16 @@ void Creature::deal_projectile_attack( Creature *source, dealt_projectile_attack
12961312 }
12971313 }
12981314
1299- if ( attack.proj .proj_effects .count ( " LIQUID" ) > 0 ) {
1315+ bool soaked_through = false ;
1316+ if ( attack.proj .proj_effects .count ( ammo_effect_LIQUID ) > 0 ) {
13001317 if ( Character *char_target = as_character () ) {
13011318 // clothing_wetness_mult returns the effective permeability of the armor on bp_hit
13021319 // as a float between 0 and 1
13031320 // 0 permeability means no liquid touches the skin and the damage is negated
13041321 // 1 permeability means all liquid touches the skin and no damage is negated
13051322 float permeability = char_target->worn .clothing_wetness_mult ( hit_selection.bp_hit );
13061323 permeability = std::clamp ( permeability, 0 .0f , 1 .0f );
1307-
1324+ soaked_through = permeability > 0 ;
13081325 impact.mult_damage ( permeability );
13091326 }
13101327 }
@@ -1317,6 +1334,8 @@ void Creature::deal_projectile_attack( Creature *source, dealt_projectile_attack
13171334
13181335 proj.apply_effects_damage ( *this , source, dealt_dam, goodhit < accuracy_critical );
13191336
1337+ proj.apply_effects_nodamage ( *this , source, dealt_dam, soaked_through );
1338+
13201339 if ( print_messages ) {
13211340 messaging_projectile_attack ( source, hit_selection, dealt_dam.total_damage () );
13221341 }
0 commit comments