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): HEAVY_WEAPON_SUPPORT flag for large mutation and power armors #3691

Merged
merged 10 commits into from
Nov 21, 2023
8 changes: 7 additions & 1 deletion data/json/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,7 @@
"id": "MOUNTED_GUN",
"type": "json_flag",
"context": [ ],
"info": "This weapon is <bad>too unwieldy</bad> to fire on its own and <info>must be mounted</info> on a vehicle or furniture (window, table, mound of dirt, etc.) before use, <info>Large or Huge</info> mutants can fire from the hip with <bad>reduced accuracy.</bad>"
"info": "This weapon <bad>can only be fired if mounted</bad> on a vehicle or furniture (window, table, mound of dirt, etc.) to fire, <info>Large or Huge</info> mutants or those with active <info>Power Armor</info> can fire from the hip with <bad>reduced accuracy.</bad>"
},
{
"id": "MYCUS_OK",
Expand Down Expand Up @@ -2037,6 +2037,12 @@
"type": "json_flag",
"context": [ ]
},
{
"id": "HEAVY_WEAPON_SUPPORT",
"type": "json_flag",
"context": [ ],
"info": "This equipment <good>allows you to fire</good> unwieldy weapons without requiring support from mountable terrain, as a <info>Large or Huge</info> mutant could, at the expense of <bad>reduced accuracy.</bad>"
},
{
"id": "FIRE_TWOHAND",
"type": "json_flag",
Expand Down
6 changes: 3 additions & 3 deletions data/json/items/armor/power_armor.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"type": "TOOL_ARMOR",
"name": { "str": "power armor (active)", "str_pl": "suits of power armor (active)" },
"description": "These were the second wave of military combat exoskeleton, and got a lot of media attention, with popular Navy commercials featuring them heavily. It consists of a muscle-boosting exoskeleton frame with overlayed segmented alloy plating. Despite advancements over the original bulky 'tank suits', the wearer still cannot easily fit through narrow spaces, or sit down comfortably (and it ruins upholstery). There is an integrated chemical resistant bodyglove that precludes wearing other clothing. It is currently turned on, activate it to turn it off.",
"extend": { "flags": [ "CLIMATE_CONTROL", "TRADER_AVOID" ] },
"extend": { "flags": [ "CLIMATE_CONTROL", "HEAVY_WEAPON_SUPPORT", "TRADER_AVOID" ] },
"power_draw": 1500000,
"revert_to": "power_armor_basic",
"use_action": {
Expand Down Expand Up @@ -150,7 +150,7 @@
"type": "TOOL_ARMOR",
"name": { "str": "heavy power armor (active)", "str_pl": "suits of heavy power armor (active)" },
"description": "Colloquially known as a 'tank suit' in the media, these bulky exoskeletons, covered in thick segmented armor plates, were tested in military service a few years back and determined to be too heavy and expensive for regular use. Now that it's in your hands, though, you have a massive suit of power armor capable of resisting almost any small arms fire and most other forms of attack. On the other hand, it doubles your effective weight, and it's almost impossible not to bump into things. There is an integrated chemical resistant bodyglove that precludes wearing other clothing. It is currently turned on, activate it to turn it off.",
"extend": { "flags": [ "CLIMATE_CONTROL", "TRADER_AVOID" ] },
"extend": { "flags": [ "CLIMATE_CONTROL", "HEAVY_WEAPON_SUPPORT", "TRADER_AVOID" ] },
"power_draw": 2250000,
"revert_to": "power_armor_heavy",
"use_action": {
Expand Down Expand Up @@ -207,7 +207,7 @@
"type": "TOOL_ARMOR",
"name": { "str": "light power armor (active)", "str_pl": "suits of light power armor (active)" },
"description": "The final iteration of military power armor before the fall of civilization, this type - a powered exoskeleton with high-tech segmented plating - was designed for actual widespread combat use and was seen on the front lines during the last days of the cataclysm. Like the heavier suits, it is resistant to most modern weaponry, but it is light and maneuverable, and can fit into normal vehicles and doorways without fuss, a huge advantage over predecessors. Unfortunately, the world ended before it could roll out in significant numbers. There is an integrated chemical resistant bodyglove that precludes wearing other clothing. It is currently turned on, activate it to turn it off.",
"extend": { "flags": [ "CLIMATE_CONTROL", "TRADER_AVOID" ] },
"extend": { "flags": [ "CLIMATE_CONTROL", "HEAVY_WEAPON_SUPPORT", "TRADER_AVOID" ] },
"power_draw": 750000,
"revert_to": "power_armor_light",
"use_action": {
Expand Down
5 changes: 3 additions & 2 deletions data/mods/CRT_EXPANSION/items/crt_toolarmor.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
"type": "TOOL_ARMOR",
"category": "armor",
"name": { "str": "C.R.I.T. EM vest (off)", "str_pl": "C.R.I.T. EM vests (off)" },
"description": "The C.R.I.T. Spec Ops Enhanced Movement vest is embedded with high-tech filaments and reactive servos which protects its wearer and assists in movement at the cost high power usage. It is commonly worn by C.R.I.T. Spec Ops for its ease of use and manuverability. Turn it on for suit mode, extra protection and movement.",
"description": "The C.R.I.T. Spec Ops Enhanced Movement vest is embedded with high-tech filaments and reactive servos which protects its wearer and assists in movement at the cost high of power usage. It is commonly worn by C.R.I.T. Spec Ops for its ease of use and maneuverability. Turn it on for suit mode, extra protection and movement.",
"weight": "10 kg",
"volume": "6250 ml",
"price": 7000000,
Expand Down Expand Up @@ -214,7 +214,8 @@
"TRADER_AVOID",
"USE_UPS",
"NO_UNLOAD",
"OUTER"
"OUTER",
"HEAVY_WEAPON_SUPPORT"
]
},
{
Expand Down
5 changes: 4 additions & 1 deletion doc/src/content/docs/en/mod/json/reference/json_flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -761,12 +761,15 @@ List of known flags, used in both `terrain.json` and `furniture.json`.
- `DISABLE_SIGHTS` Prevents use of the base weapon sights
- `FIRE_100` Uses 100 shots per firing.
- `FIRE_50` Uses 50 shots per firing.
- `HEAVY_WEAPON_SUPPORT` Wearing this will let you hip-fire heavy weapons without needing terrain
support, like Large or Huge mutants can.
- `FIRE_TWOHAND` Gun can only be fired if player has two free hands.
- `IRREMOVABLE` Makes so that the gunmod cannot be removed.
- `MECH_BAT` This is an exotic battery designed to power military mechs.
- `MOUNTED_GUN` Gun can only be used on terrain / furniture with the "MOUNTABLE" flag, if you're a
normal human. If you're an oversized mutant (Inconveniently Large, Large, Freakishly Huge, Huge),
you can fire it regularly in exchange for dispersion and recoil penalties.
you can fire it regularly in exchange for dispersion and recoil penalties. Wearing something with
the `HEAVY_WEAPON_SUPPORT` flag also works.
- `NEVER_JAMS` Never malfunctions.
- `NO_UNLOAD` Cannot be unloaded.
- `PRIMITIVE_RANGED_WEAPON` Allows using non-gunsmith tools to repair it (but not reinforce).
Expand Down
1 change: 1 addition & 0 deletions src/flag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ const flag_id flag_FIREWOOD( "FIREWOOD" );
const flag_id flag_FIRE_100( "FIRE_100" );
const flag_id flag_FIRE_20( "FIRE_20" );
const flag_id flag_FIRE_50( "FIRE_50" );
const flag_id flag_HEAVY_WEAPON_SUPPORT( "HEAVY_WEAPON_SUPPORT" );
const flag_id flag_FIRE_TWOHAND( "FIRE_TWOHAND" );
const flag_id flag_FISH_GOOD( "FISH_GOOD" );
const flag_id flag_FISH_POOR( "FISH_POOR" );
Expand Down
1 change: 1 addition & 0 deletions src/flag.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ extern const flag_id flag_FIREWOOD;
extern const flag_id flag_FIRE_100;
extern const flag_id flag_FIRE_20;
extern const flag_id flag_FIRE_50;
extern const flag_id flag_HEAVY_WEAPON_SUPPORT;
extern const flag_id flag_FIRE_TWOHAND;
extern const flag_id flag_FISH_GOOD;
extern const flag_id flag_FISH_POOR;
Expand Down
52 changes: 25 additions & 27 deletions src/ranged.cpp
scarf005 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,6 @@ static const bionic_id bio_railgun( "bio_railgun" );
static const bionic_id bio_targeting( "bio_targeting" );
static const bionic_id bio_ups( "bio_ups" );


static const std::string flag_MOUNTABLE( "MOUNTABLE" );

static const trait_id trait_PYROMANIA( "PYROMANIA" );
static const trait_id trait_NORANGEDCRIT( "NO_RANGED_CRIT" );

Expand All @@ -151,7 +148,7 @@ static constexpr int AIF_DURATION_LIMIT = 10;

static projectile make_gun_projectile( const item &gun );
static void cycle_action( item &weap, const tripoint &pos );
bool can_use_bipod( const map &m, const tripoint &pos );
bool can_use_heavy_weapon( const Character &who, const map &m, const tripoint &pos );
dispersion_sources calculate_dispersion( const map &m, const Character &who, const item &gun,
int at_recoil, bool burst );

Expand Down Expand Up @@ -776,8 +773,12 @@ void npc::pretend_fire( npc *source, int shots, item &gun )
}
}

bool can_use_bipod( const map &m, const tripoint &pos )
bool can_use_heavy_weapon( const Character &who, const map &m, const tripoint &pos )
{
if( who.is_mounted() && who.mounted_creature->has_flag( MF_RIDEABLE_MECH ) ) {
return true;
}

// usage of any attached bipod is dependent upon terrain
if( m.has_flag_ter_or_furn( "MOUNTABLE", pos ) ) {
return true;
Expand All @@ -793,7 +794,7 @@ bool can_use_bipod( const map &m, const tripoint &pos )
dispersion_sources calculate_dispersion( const map &m, const Character &who, const item &gun,
int at_recoil, bool burst )
{
bool bipod = can_use_bipod( m, who.pos() );
bool bipod = can_use_heavy_weapon( who, m, who.pos() );

int gun_recoil = gun.gun_recoil( bipod );
int eff_recoil = at_recoil + ( burst ? ranged::burst_penalty( who, gun, gun_recoil ) : 0 );
Expand Down Expand Up @@ -939,15 +940,18 @@ int ranged::fire_gun( Character &who, const tripoint &target, int max_shots, ite
// Reset aim for bows and other reload-and-shoot weapons.
who.recoil = MAX_RECOIL;
} else {
// Hack alert: nearly every other use of can_use_heavy_weapon uses const character, except this one and gunmode_checks_weapon.
const Character &shooter = who;
scarf005 marked this conversation as resolved.
Show resolved Hide resolved
// Now actually apply recoil for the future shots
// But only for one shot, because bursts kinda suck
int gun_recoil = gun.gun_recoil( can_use_bipod( here, who.pos() ) );
int gun_recoil = gun.gun_recoil( can_use_heavy_weapon( shooter, here, shooter.pos() ) );

// If user is currently able to fire a mounted gun freely, penalize recoil based on size class.
if( gun.has_flag( flag_MOUNTED_GUN ) && !can_use_bipod( here, who.pos() ) ) {
if( who.get_size() == MS_HUGE ) {
// If user is currently able to fire a mounted gun freely, penalize dispersion
// HEAVY_WEAPON_SUPPORT flag has highest penalty, Large mutants lower penalty, no penalty for Huge mutants.
if( gun.has_flag( flag_MOUNTED_GUN ) && !can_use_heavy_weapon( shooter, here, shooter.pos() ) ) {
if( who.get_size() == MS_LARGE ) {
gun_recoil = gun_recoil * 2;
} else {
} else if( who.worn_with_flag( flag_HEAVY_WEAPON_SUPPORT ) && ( who.get_size() <= MS_MEDIUM ) ) {
gun_recoil = gun_recoil * 3;
}
}
Expand Down Expand Up @@ -1943,12 +1947,13 @@ dispersion_sources ranged::get_weapon_dispersion( const Character &who, const it
dispersion.add_multiplier( 4 );
}

// If user is currently able to fire a mounted gun freely, penalize dispersion based on size class.
if( obj.has_flag( flag_MOUNTED_GUN ) && !can_use_bipod( get_map(), who.pos() ) ) {
if( who.get_size() == MS_HUGE ) {
dispersion.add_multiplier( 2 );
} else {
dispersion.add_multiplier( 3 );
// If user is currently able to fire a mounted gun freely, penalize dispersion
// HEAVY_WEAPON_SUPPORT flag has highest penalty, Large mutants lower penalty, no penalty for Huge mutants.
if( obj.has_flag( flag_MOUNTED_GUN ) && !can_use_heavy_weapon( who, get_map(), who.pos() ) ) {
if( who.get_size() == MS_LARGE ) {
dispersion.add_range( 500 );
} else if( who.worn_with_flag( flag_HEAVY_WEAPON_SUPPORT ) && ( who.get_size() <= MS_MEDIUM ) ) {
dispersion.add_range( 1000 );
}
}

Expand Down Expand Up @@ -3772,16 +3777,9 @@ bool ranged::gunmode_checks_weapon( avatar &you, const map &m, std::vector<std::
}

if( gmode->has_flag( flag_MOUNTED_GUN ) ) {

bool mech_mount = false;
if( you.is_mounted() && you.mounted_creature->has_flag( MF_RIDEABLE_MECH ) ) {
mech_mount = true;
}

const bool v_mountable = static_cast<bool>( m.veh_at( you.pos() ).part_with_feature( "MOUNTABLE",
true ) );
bool t_mountable = m.has_flag_ter_or_furn( flag_MOUNTABLE, you.pos() );
if( !mech_mount && !t_mountable && !v_mountable && !( you.get_size() > MS_MEDIUM ) ) {
const Character &shooter = you;
if( !can_use_heavy_weapon( shooter, m, shooter.pos() ) && !( you.get_size() > MS_MEDIUM ) &&
!you.worn_with_flag( flag_HEAVY_WEAPON_SUPPORT ) ) {
messages.push_back( string_format(
_( "You must stand near acceptable terrain or furniture to fire the %s. A table, a mound of dirt, a broken window, etc." ),
gmode->tname() ) );
Expand Down
Loading