Skip to content

Commit

Permalink
feat(balance): rework how ranged bash data checks destroy_threshold (
Browse files Browse the repository at this point in the history
…#4223)

* feat(balance): rework how ranged bash data checks `destroy_threshold`

* style(autofix.ci): automated formatting

* commit for remote

* style(autofix.ci): automated formatting

* Update map.cpp

* screm

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
chaosvolt and autofix-ci[bot] authored Feb 22, 2024
1 parent 24a73c5 commit d7e779b
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 48 deletions.
12 changes: 6 additions & 6 deletions data/json/furniture_and_terrain/furniture-barriers.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"sound_fail": "whump.",
"items": [ { "item": "bag_canvas", "count": [ 10, 16 ] }, { "item": "material_soil", "charges": [ 40, 48 ] } ],
"//": "reduction and destroy_threshold equal to str_max of full-sized wall version, designed for ballistic protection",
"ranged": { "reduction": [ 80, 80 ], "destroy_threshold": 80, "block_unaimed_chance": "50%" }
"ranged": { "reduction": [ 100, 100 ], "destroy_threshold": 100, "block_unaimed_chance": "50%" }
}
},
{
Expand All @@ -70,13 +70,13 @@
"deconstruct": { "items": [ { "item": "earthbag", "count": 20 } ], "furn_set": "f_earthbag_half" },
"bash": {
"str_min": 24,
"str_max": 80,
"str_max": 100,
"sound": "rrrip!",
"sound_fail": "whump.",
"furn_set": "f_earthbag_half",
"items": [ { "item": "bag_canvas", "count": [ 15, 20 ] }, { "item": "material_soil", "charges": [ 50, 60 ] } ],
"//": "reduction equal to str_max due to being designed for ballistic protection",
"ranged": { "reduction": [ 80, 80 ], "destroy_threshold": 80 }
"ranged": { "reduction": [ 100, 100 ], "destroy_threshold": 100 }
}
},
{
Expand Down Expand Up @@ -127,7 +127,7 @@
"sound_fail": "whump.",
"items": [ { "item": "bag_canvas", "count": [ 10, 16 ] }, { "item": "material_sand", "charges": [ 800, 960 ] } ],
"//": "reduction and destroy_threshold equal to str_max of full-sized wall version, designed for ballistic protection",
"ranged": { "reduction": [ 80, 80 ], "destroy_threshold": 80, "block_unaimed_chance": "50%" }
"ranged": { "reduction": [ 100, 100 ], "destroy_threshold": 100, "block_unaimed_chance": "50%" }
}
},
{
Expand All @@ -144,13 +144,13 @@
"deconstruct": { "items": [ { "item": "sandbag", "count": 20 } ], "furn_set": "f_sandbag_half" },
"bash": {
"str_min": 24,
"str_max": 80,
"str_max": 100,
"sound": "rrrip!",
"sound_fail": "whump.",
"furn_set": "f_sandbag_half",
"items": [ { "item": "bag_canvas", "count": [ 15, 20 ] }, { "item": "material_sand", "charges": [ 1000, 1200 ] } ],
"//": "reduction equal to str_max due to being designed for ballistic protection",
"ranged": { "reduction": [ 80, 80 ], "destroy_threshold": 80 }
"ranged": { "reduction": [ 100, 100 ], "destroy_threshold": 100 }
}
}
]
36 changes: 18 additions & 18 deletions data/json/furniture_and_terrain/terrain-doors.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
"flags": [ "TRANSPARENT", "DOOR", "NOITEM", "CONNECT_TO_WALL", "MINEABLE", "BLOCK_WIND" ],
"open": "t_laminated_door_glass_o",
"bash": {
"str_min": 100,
"str_max": 180,
"str_min": 60,
"str_max": 200,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_mdoor_frame",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] }, { "item": "scrap", "count": [ 3, 5 ] } ],
"//": "half that of ballistic glass doors",
"ranged": { "reduction": [ 20, 20 ], "reduction_laser": [ 0, 5 ], "destroy_threshold": 20 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 30, 30 ], "reduction_laser": [ 0, 5 ], "destroy_threshold": 60 }
}
},
{
Expand All @@ -37,8 +37,8 @@
"flags": [ "TRANSPARENT", "FLAT", "CONNECT_TO_WALL", "ROAD", "MINEABLE" ],
"close": "t_laminated_door_glass_c",
"bash": {
"str_min": 100,
"str_max": 180,
"str_min": 60,
"str_max": 200,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
Expand All @@ -60,16 +60,16 @@
"flags": [ "TRANSPARENT", "DOOR", "NOITEM", "CONNECT_TO_WALL", "MINEABLE", "BLOCK_WIND" ],
"open": "t_ballistic_door_glass_o",
"bash": {
"str_min": 200,
"str_min": 100,
"str_max": 400,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_mdoor_frame",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] }, { "item": "scrap", "count": [ 3, 5 ] } ],
"//": "matches that of the other ballistic glass doors",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 5 ], "destroy_threshold": 40 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 50, 50 ], "reduction_laser": [ 0, 5 ], "destroy_threshold": 100 }
}
},
{
Expand All @@ -85,7 +85,7 @@
"flags": [ "TRANSPARENT", "FLAT", "CONNECT_TO_WALL", "ROAD", "MINEABLE" ],
"close": "t_ballistic_door_glass_c",
"bash": {
"str_min": 200,
"str_min": 100,
"str_max": 400,
"sound": "glass breaking!",
"sound_fail": "whack!",
Expand All @@ -108,16 +108,16 @@
"flags": [ "TRANSPARENT", "DOOR", "NOITEM", "CONNECT_TO_WALL", "MINEABLE", "BLOCK_WIND" ],
"open": "t_reinforced_door_glass_o",
"bash": {
"str_min": 40,
"str_min": 80,
"str_max": 210,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_mdoor_frame",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] }, { "item": "wire", "prob": 20 }, { "item": "scrap", "count": [ 3, 5 ] } ],
"//": "reduction and destroy_threshold both match str_min for ballistic/reinforced glass doors",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 40 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 80 }
}
},
{
Expand All @@ -133,16 +133,16 @@
"flags": [ "TRANSPARENT", "DOOR", "NOITEM", "CONNECT_TO_WALL", "MINEABLE" ],
"open": "t_reinforced_door_glass_lab_o",
"bash": {
"str_min": 40,
"str_min": 80,
"str_max": 210,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_thconc_floor",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] }, { "item": "wire", "prob": 20 }, { "item": "scrap", "count": [ 3, 5 ] } ],
"//": "reduction and destroy_threshold both match str_min for ballistic/reinforced glass doors",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 40 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 80 }
}
},
{
Expand All @@ -158,7 +158,7 @@
"flags": [ "TRANSPARENT", "FLAT", "CONNECT_TO_WALL", "ROAD", "MINEABLE" ],
"close": "t_reinforced_door_glass_c",
"bash": {
"str_min": 40,
"str_min": 80,
"str_max": 210,
"sound": "glass breaking!",
"sound_fail": "whack!",
Expand All @@ -181,7 +181,7 @@
"flags": [ "TRANSPARENT", "FLAT", "CONNECT_TO_WALL", "ROAD", "MINEABLE" ],
"close": "t_reinforced_door_glass_lab_c",
"bash": {
"str_min": 40,
"str_min": 80,
"str_max": 210,
"sound": "glass breaking!",
"sound_fail": "whack!",
Expand Down
32 changes: 16 additions & 16 deletions data/json/furniture_and_terrain/terrain-walls.json
Original file line number Diff line number Diff line change
Expand Up @@ -1062,16 +1062,16 @@
"roof": "t_flat_roof",
"flags": [ "TRANSPARENT", "NOITEM", "WALL", "NO_SCENT", "AUTO_WALL_SYMBOL", "MINEABLE", "BLOCK_WIND" ],
"bash": {
"str_min": 100,
"str_max": 180,
"str_min": 60,
"str_max": 200,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_floor",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] } ],
"//": "half that of ballistic glass doors",
"ranged": { "reduction": [ 20, 20 ], "reduction_laser": [ 0, 5 ], "destroy_threshold": 20 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 30, 30 ], "reduction_laser": [ 0, 5 ], "destroy_threshold": 60 }
}
},
{
Expand All @@ -1087,16 +1087,16 @@
"roof": "t_flat_roof",
"flags": [ "TRANSPARENT", "NOITEM", "WALL", "NO_SCENT", "AUTO_WALL_SYMBOL", "MINEABLE", "BLOCK_WIND" ],
"bash": {
"str_min": 200,
"str_min": 100,
"str_max": 400,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_floor",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] } ],
"//": "matches that of ballistic glass doors",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 40 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 50, 50 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 100 }
}
},
{
Expand All @@ -1111,16 +1111,16 @@
"roof": "t_flat_roof",
"flags": [ "TRANSPARENT", "NOITEM", "WALL", "NO_SCENT", "AUTO_WALL_SYMBOL", "MINEABLE", "BLOCK_WIND" ],
"bash": {
"str_min": 40,
"str_min": 80,
"str_max": 210,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_floor",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] }, { "item": "wire", "prob": 20 } ],
"//": "matches that of ballistic glass doors",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 40 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 80 }
}
},
{
Expand All @@ -1135,16 +1135,16 @@
"flags": [ "NOITEM", "WALL", "NO_SCENT", "AUTO_WALL_SYMBOL", "OPENCLOSE_INSIDE", "MINEABLE", "BLOCK_WIND" ],
"open": "t_reinforced_glass_shutter_open",
"bash": {
"str_min": 60,
"str_min": 80,
"str_max": 210,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_floor",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] }, { "item": "wire", "prob": 20 }, { "item": "scrap", "count": [ 3, 5 ] } ],
"//": "matches that of ballistic glass doors, increased laser protection since closed shutters",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 1, 10 ], "destroy_threshold": 40 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 1, 10 ], "destroy_threshold": 80 }
}
},
{
Expand All @@ -1160,16 +1160,16 @@
"flags": [ "TRANSPARENT", "NOITEM", "WALL", "NO_SCENT", "AUTO_WALL_SYMBOL", "OPENCLOSE_INSIDE", "MINEABLE", "BLOCK_WIND" ],
"close": "t_reinforced_glass_shutter",
"bash": {
"str_min": 40,
"str_min": 80,
"str_max": 210,
"sound": "glass breaking!",
"sound_fail": "whack!",
"sound_vol": 20,
"sound_fail_vol": 14,
"ter_set": "t_floor",
"items": [ { "item": "glass_shard", "count": [ 3, 6 ] }, { "item": "wire", "prob": 20 }, { "item": "scrap", "count": [ 3, 5 ] } ],
"//": "matches that of ballistic glass doors",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 40 }
"//": "reduction half str_min for ballistic-style glass, destroy_threshold equal to str_min for glass",
"ranged": { "reduction": [ 40, 40 ], "reduction_laser": [ 0, 8 ], "destroy_threshold": 80 }
}
},
{
Expand Down
25 changes: 18 additions & 7 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3807,9 +3807,12 @@ void map::crush( const tripoint &p )
void map::shoot( const tripoint &origin, const tripoint &p, projectile &proj, const bool hit_items )
{
float initial_damage = 0.0;
float initial_arpen = 0.0;
float initial_armor_mult = 1.0;
for( const damage_unit &dam : proj.impact ) {
initial_damage += dam.amount * dam.damage_multiplier;
initial_damage += dam.res_pen;
initial_arpen += dam.res_pen;
initial_armor_mult *= dam.res_mult;
}
if( initial_damage < 0 ) {
return;
Expand Down Expand Up @@ -3839,13 +3842,17 @@ void map::shoot( const tripoint &origin, const tripoint &p, projectile &proj, co
if( furn.bash.ranged ) {
double range = rl_dist( origin, p );
const ranged_bash_info &rfi = *furn.bash.ranged;
float destroy_roll = dam * rng_float( 0.9, 1.1 );
if( !hit_items && ( !check( rfi.block_unaimed_chance ) || ( rfi.block_unaimed_chance < 100_pct &&
range <= 1 ) ) ) {
// Nothing, it's a miss or we're shooting over nearby furniture
} else if( rfi.reduction_laser && proj.has_effect( ammo_effect_LASER ) ) {
dam -= rng( rfi.reduction_laser->min, rfi.reduction_laser->max );
dam -= std::max( ( rng( rfi.reduction_laser->min,
rfi.reduction_laser->max ) - initial_arpen ) * initial_armor_mult, 0.0f );
} else {
dam -= rng( rfi.reduction.min, rfi.reduction.max );
// Roll damage reduction value, reduce result by arpen, multiply by any armor mult, then finally set to zero if negative result
dam -= std::max( ( rng( rfi.reduction.min,
rfi.reduction.max ) - initial_arpen ) * initial_armor_mult, 0.0f );
// Only print if we hit something we can see enemies through, so we know cover did its job
if( get_avatar().sees( p ) && rfi.block_unaimed_chance < 100_pct ) {
if( dam <= 0 ) {
Expand All @@ -3854,7 +3861,7 @@ void map::shoot( const tripoint &origin, const tripoint &p, projectile &proj, co
add_msg( _( "The shot hits the %s and punches through!" ), furnname( p ) );
}
}
if( dam > rfi.destroy_threshold ) {
if( destroy_roll > rfi.destroy_threshold ) {
bash_params params{0, false, true, hit_items, 1.0, false};
bash_furn_success( p, params );
}
Expand All @@ -3865,13 +3872,17 @@ void map::shoot( const tripoint &origin, const tripoint &p, projectile &proj, co
} else if( ter.bash.ranged ) {
double range = rl_dist( origin, p );
const ranged_bash_info &ri = *ter.bash.ranged;
float destroy_roll = dam * rng_float( 0.9, 1.1 );
if( !hit_items && ( !check( ri.block_unaimed_chance ) || ( ri.block_unaimed_chance < 100_pct &&
range <= 1 ) ) ) {
// Nothing, it's a miss or we're shooting over nearby terrain
} else if( ri.reduction_laser && proj.has_effect( ammo_effect_LASER ) ) {
dam -= rng( ri.reduction_laser->min, ri.reduction_laser->max );
dam -= std::max( ( rng( ri.reduction_laser->min,
ri.reduction_laser->max ) - initial_arpen ) * initial_armor_mult, 0.0f );
} else {
dam -= rng( ri.reduction.min, ri.reduction.max );
// Roll damage reduction value, reduce result by arpen, multiply by any armor mult, then finally set to zero if negative result
dam -= std::max( ( rng( ri.reduction.min,
ri.reduction.max ) - initial_arpen ) * initial_armor_mult, 0.0f );
// Only print if we hit something we can see enemies through, so we know cover did its job
if( get_avatar().sees( p ) && ri.block_unaimed_chance < 100_pct ) {
if( dam <= 0 ) {
Expand All @@ -3880,7 +3891,7 @@ void map::shoot( const tripoint &origin, const tripoint &p, projectile &proj, co
add_msg( _( "The shot hits the %s and punches through!" ), tername( p ) );
}
}
if( dam > ri.destroy_threshold ) {
if( destroy_roll > ri.destroy_threshold ) {
bash_params params{0, false, true, hit_items, 1.0, false};
bash_ter_success( p, params );
}
Expand Down
3 changes: 2 additions & 1 deletion src/mapdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ struct ranged_bash_info {
numeric_interval<int> reduction; // Damage reduction when shot. Rolled like rng(min, max).
// As above, but for lasers. If set, lasers won't destroy us.
std::optional<numeric_interval<int>> reduction_laser;
int destroy_threshold = 0; // If reduced dmg is still above this value, destroy us.
int destroy_threshold =
0; // If dmg (times 0.9 to 1.1) before reduction is above this value, destroy us.
bool flammable = false; // If true, getting hit with any heat damage creates a fire.
units::probability block_unaimed_chance =
100_pct; // Chance to intercept projectiles not aimed at this tile
Expand Down

0 comments on commit d7e779b

Please sign in to comment.