From db5ad7f56f18c311652b78ca75712603c21aa755 Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Tue, 18 Aug 2020 10:17:13 -0500 Subject: [PATCH] vehicles: make shock absorbers actually absorb shock damage Add the SHOCK_ABSORBER flag to shock absorbers, and change vehicle::damage_all() so that parts on the same tile as a shock absorber take substantially less damage from transmitted shock damage in collisions. --- data/json/vehicleparts/armor.json | 5 +++-- data/json/vehicleparts/vp_flags.json | 8 +++++++- doc/JSON_FLAGS.md | 1 + src/vehicle.cpp | 13 ++++++++++--- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/data/json/vehicleparts/armor.json b/data/json/vehicleparts/armor.json index 877bc725586b9..a4ca5cdcb26fe 100644 --- a/data/json/vehicleparts/armor.json +++ b/data/json/vehicleparts/armor.json @@ -32,6 +32,7 @@ "color": "dark_gray", "broken_color": "dark_gray", "durability": 340, + "bonus": 50, "description": "A system of springs and pads, intended to cushion the effects of collisions on the interior of your vehicle.", "breaks_into": [ { "item": "scrap", "count": [ 1, 5 ] }, { "item": "spring", "count": [ 0, 4 ] } ], "requirements": { @@ -39,7 +40,7 @@ "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, "repair": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } }, - "flags": [ "ARMOR" ], - "damage_reduction": { "all": 15, "bash": 100 } + "flags": [ "SHOCK_ABSORBER" ], + "damage_reduction": { "all": 25 } } ] diff --git a/data/json/vehicleparts/vp_flags.json b/data/json/vehicleparts/vp_flags.json index 34b5a82490319..c9ec1f2429256 100644 --- a/data/json/vehicleparts/vp_flags.json +++ b/data/json/vehicleparts/vp_flags.json @@ -22,7 +22,7 @@ "id": "ARMOR", "type": "json_flag", "context": [ "vehicle_part" ], - "info": "Armor plate. Will partially protect other components on the same frame from damage." + "info": "Armor plate. Will partially protect other components on the same frame from damage from direct attacks but not from the shock damage of a distant collision." }, { "id": "BED", @@ -139,6 +139,12 @@ "info": "This part will help prevent you from being thrown from the vehicle in a collision. You will automatically enable this part when you move into a tile with it.", "requires_flag": "BELTABLE" }, + { + "id": "SHOCK_ABSORBER", + "type": "json_flag", + "context": [ "vehicle_part" ], + "info": "Armor plate. Will partially protect other components on the same frame from the shock damage of a distant collision but not from direct attacks." + }, { "id": "STABLE", "type": "json_flag", diff --git a/doc/JSON_FLAGS.md b/doc/JSON_FLAGS.md index 0b232e7acccd1..5a1be167e9b97 100644 --- a/doc/JSON_FLAGS.md +++ b/doc/JSON_FLAGS.md @@ -1444,6 +1444,7 @@ Those flags are added by the game code to specific items (for example, that spec - ```SEAT``` A seat where the player can sit or sleep. - ```SECURITY``` - ```SHARP``` Striking a monster with this part does cutting damage instead of bashing damage, and prevents stunning the monster. +- ```SHOCK_ABSORBER``` This part protects non-frame parts on the same tile from shock damage from collisions. It doesn't provide protect against diret impacts or other attacks. - ```SIMPLE_PART``` This part can be installed or removed from that otherwise prevent modification. - ```SMASH_REMOVE``` When you remove this part, instead of getting the item back, you will get the bash results. - ```SOLAR_PANEL``` Recharges vehicle batteries when exposed to sunlight. Has a 1 in 4 chance of being broken on car generation. diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a61cb93af9dfc..3149c53d76970 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -6359,9 +6359,16 @@ void vehicle::damage_all( int dmg1, int dmg2, damage_type type, const point &imp for( const vpart_reference &vp : get_all_parts() ) { const size_t p = vp.part_index(); int distance = 1 + square_dist( vp.mount(), impact ); - if( distance > 1 && part_info( p ).location == part_location_structure && - !part_info( p ).has_flag( "PROTRUSION" ) ) { - damage_direct( p, rng( dmg1, dmg2 ) / ( distance * distance ), type ); + if( distance > 1 ) { + int net_dmg = rng( dmg1, dmg2 ) / ( distance * distance ); + if( part_info( p ).location != part_location_structure || + !part_info( p ).has_flag( "PROTRUSION" ) ) { + int shock_absorber = part_with_feature( p, "SHOCK_ABSORBER", true ); + if( shock_absorber >= 0 ) { + net_dmg = std::max( 0, net_dmg - parts[ shock_absorber ].info().bonus ); + } + } + damage_direct( p, net_dmg, type ); } } }