Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(balance): rework how ranged bash data checks destroy_threshold #4223

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -1041,16 +1041,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 @@ -1066,16 +1066,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 @@ -1090,16 +1090,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 @@ -1114,16 +1114,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 @@ -1139,16 +1139,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
Loading