diff --git a/data/json/items/generic.json b/data/json/items/generic.json index 34d8a96a179a..bfbb7b545b4a 100644 --- a/data/json/items/generic.json +++ b/data/json/items/generic.json @@ -2665,6 +2665,30 @@ "volume": "750 ml", "category": "spare_parts" }, + { + "id": "gatling_mech_laser_salvaged", + "copy-from": "cerberus_laser", + "looks_like": "gatling_mech_laser", + "type": "GENERIC", + "color": "blue", + "name": { "str": "salvaged CMES gatling laser" }, + "description": "A rapid-fire weapon system stripped from a wrecked combat exoskeleton. No longer usable as a weapon in its current condition.", + "material": [ "superalloy", "plastic" ], + "weight": "39 kg", + "volume": "11 L" + }, + { + "id": "recon_mech_laser_salvaged", + "copy-from": "cerberus_laser", + "looks_like": "recon_mech_laser", + "type": "GENERIC", + "color": "blue", + "name": { "str": "salvaged RMES marksman laser" }, + "description": "A long-range weapon system stripped from a wrecked recon exoskeleton. No longer usable as a weapon in its current condition.", + "material": [ "superalloy", "plastic" ], + "weight": "12 kg", + "volume": "5500 ml" + }, { "id": "light_bulb", "type": "GENERIC", diff --git a/data/json/items/gun/ups.json b/data/json/items/gun/ups.json index d1f25a75d73a..8e2220d53675 100644 --- a/data/json/items/gun/ups.json +++ b/data/json/items/gun/ups.json @@ -44,14 +44,26 @@ "material": [ "superalloy", "plastic" ], "color": "blue", "range": 30, - "ranged_damage": { "damage_type": "heat", "amount": 20, "armor_penetration": 4 }, + "ranged_damage": { "damage_type": "heat", "amount": 40, "armor_penetration": 5 }, "dispersion": 100, "loudness": 12, - "ups_charges": 20, - "modes": [ [ "DEFAULT", "3 rd.", 3 ], [ "BURST", "5 rd.", 5 ], [ "AUTO", "high auto", 15 ] ], + "ups_charges": 50, + "modes": [ [ "DEFAULT", "semi", 1 ], [ "BURST", "burst", 5 ], [ "AUTO", "auto", 10 ] ], "ammo_effects": [ "LASER", "PLASMA_BUBBLE", "INCENDIARY" ], "extend": { "flags": [ "NO_UNWIELD", "NO_SALVAGE", "NO_REPAIR", "UNBREAKABLE_MELEE" ] } }, + { + "id": "gatling_mech_laser_rebuilt", + "copy-from": "gatling_mech_laser", + "type": "GUN", + "name": { "str": "rebuilt CMES gatling laser" }, + "description": "A rapid-fire weapon system stripped from a combat mech, modified for handheld use. While less efficient and too bulky to fire without proper support, its rotating-barrel laser system can still spray death downrange with ease.", + "weight": "40 kg", + "dispersion": 200, + "ups_charges": 80, + "extend": { "flags": [ "MOUNTED_GUN" ] }, + "delete": { "flags": [ "NO_UNWIELD", "NO_SALVAGE", "NO_REPAIR", "UNBREAKABLE_MELEE" ] } + }, { "id": "recon_mech_laser", "copy-from": "rifle_energy", @@ -68,13 +80,25 @@ "material": [ "superalloy", "plastic" ], "color": "blue", "range": 45, - "ranged_damage": { "damage_type": "heat", "amount": 30, "armor_penetration": 4 }, + "ranged_damage": { "damage_type": "heat", "amount": 80, "armor_penetration": 10 }, "dispersion": 15, "loudness": 1, - "ups_charges": 50, + "ups_charges": 100, "ammo_effects": [ "LASER", "PLASMA_BUBBLE", "INCENDIARY" ], "extend": { "flags": [ "NO_UNWIELD", "NO_REPAIR", "NO_SALVAGE", "UNBREAKABLE_MELEE" ] } }, + { + "id": "recon_mech_laser_rebuilt", + "copy-from": "recon_mech_laser", + "type": "GUN", + "name": { "str": "rebuilt RMES marksman laser" }, + "description": "A long-range weapon system stripped from a recon mech, modified for handheld use. While less efficient and too bulky to fire without proper support, it's still a quiet and relatively accurate marksman laser rifle.", + "weight": "13 kg", + "dispersion": 30, + "ups_charges": 160, + "extend": { "flags": [ "MOUNTED_GUN" ] }, + "delete": { "flags": [ "NO_UNWIELD", "NO_REPAIR", "NO_SALVAGE", "UNBREAKABLE_MELEE" ] } + }, { "id": "laser_cannon", "copy-from": "rifle_energy", diff --git a/data/json/monsters/mechsuits.json b/data/json/monsters/mechsuits.json index 78261c0c14ba..28a6ccc0aed5 100644 --- a/data/json/monsters/mechsuits.json +++ b/data/json/monsters/mechsuits.json @@ -43,6 +43,7 @@ "NOHEAD", "NO_BREATHE", "RIDEABLE_MECH", + "MECH_DEFENSIVE", "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_2" ] @@ -91,6 +92,7 @@ "NOHEAD", "NO_BREATHE", "RIDEABLE_MECH", + "MECH_DEFENSIVE", "PRIORITIZE_TARGETS", "PATH_AVOID_DANGER_2", "LOUDMOVES" diff --git a/data/json/recipes/weapon/ranged.json b/data/json/recipes/weapon/ranged.json index 166aa7466505..f316777764b2 100644 --- a/data/json/recipes/weapon/ranged.json +++ b/data/json/recipes/weapon/ranged.json @@ -705,6 +705,34 @@ "qualities": [ { "id": "SAW_M_FINE", "level": 1 }, { "id": "SCREW_FINE", "level": 1 } ], "components": [ [ [ "cerberus_laser", 1 ] ], [ [ "battery_ups", 1 ] ], [ [ "cable", 15 ] ] ] }, + { + "type": "recipe", + "result": "gatling_mech_laser_rebuilt", + "category": "CC_WEAPON", + "subcategory": "CSC_WEAPON_RANGED", + "skill_used": "electronics", + "skills_required": [ [ "fabrication", 5 ], [ "gun", 1 ] ], + "difficulty": 7, + "time": "30 m", + "autolearn": true, + "using": [ [ "welding_standard", 5 ], [ "steel_tiny", 2 ] ], + "qualities": [ { "id": "SAW_M_FINE", "level": 1 }, { "id": "SCREW_FINE", "level": 1 } ], + "components": [ [ [ "gatling_mech_laser_salvaged", 1 ] ], [ [ "battery_ups", 1 ] ], [ [ "cable", 25 ] ] ] + }, + { + "type": "recipe", + "result": "gatling_mech_laser_rebuilt", + "category": "CC_WEAPON", + "subcategory": "CSC_WEAPON_RANGED", + "skill_used": "electronics", + "skills_required": [ [ "fabrication", 5 ], [ "gun", 1 ] ], + "difficulty": 7, + "time": "30 m", + "autolearn": true, + "using": [ [ "welding_standard", 5 ], [ "steel_tiny", 2 ] ], + "qualities": [ { "id": "SAW_M_FINE", "level": 1 }, { "id": "SCREW_FINE", "level": 1 } ], + "components": [ [ [ "gatling_mech_laser_salvaged", 1 ] ], [ [ "battery_ups", 1 ] ], [ [ "cable", 25 ] ] ] + }, { "type": "recipe", "result": "m2browning_sawn", diff --git a/data/json/uncraft/generic.json b/data/json/uncraft/generic.json index 2f760a05cc21..203bf414b35a 100644 --- a/data/json/uncraft/generic.json +++ b/data/json/uncraft/generic.json @@ -1016,6 +1016,7 @@ "using": [ [ "soldering_standard", 30 ], [ "welding_standard", 20 ] ], "qualities": [ { "id": "SCREW", "level": 1 }, { "id": "WRENCH", "level": 1 }, { "id": "SAW_M", "level": 1 } ], "components": [ + [ [ "recon_mech_laser_salvaged", 1 ] ], [ [ "ai_module", 1 ] ], [ [ "sensor_module", 1 ] ], [ [ "memory_module", 1 ] ], @@ -1025,7 +1026,8 @@ [ [ "power_supply", 20 ] ], [ [ "storage_battery", 2 ] ], [ [ "plut_cell", 4 ] ], - [ [ "mil_plate", 15 ] ] + [ [ "mil_plate", 15 ] ], + [ [ "alloy_sheet", 25 ] ] ] }, { @@ -1046,7 +1048,8 @@ [ [ "power_supply", 20 ] ], [ [ "storage_battery", 2 ] ], [ [ "plut_cell", 4 ] ], - [ [ "mil_plate", 6 ] ] + [ [ "mil_plate", 6 ] ], + [ [ "alloy_sheet", 15 ] ] ] }, { @@ -1058,6 +1061,7 @@ "using": [ [ "soldering_standard", 30 ], [ "welding_standard", 20 ] ], "qualities": [ { "id": "SCREW", "level": 1 }, { "id": "WRENCH", "level": 1 }, { "id": "SAW_M", "level": 1 } ], "components": [ + [ [ "gatling_mech_laser_salvaged", 1 ] ], [ [ "ai_module", 1 ] ], [ [ "sensor_module", 1 ] ], [ [ "memory_module", 1 ] ], @@ -1067,7 +1071,8 @@ [ [ "power_supply", 20 ] ], [ [ "storage_battery", 2 ] ], [ [ "plut_cell", 4 ] ], - [ [ "mil_plate", 20 ] ] + [ [ "mil_plate", 20 ] ], + [ [ "alloy_sheet", 20 ] ] ] }, { diff --git a/data/json/vehicleparts/turret.json b/data/json/vehicleparts/turret.json index d138ec37036f..2c0bec43d927 100644 --- a/data/json/vehicleparts/turret.json +++ b/data/json/vehicleparts/turret.json @@ -146,6 +146,34 @@ "removal": { "skills": [ [ "mechanics", 3 ] ] } } }, + { + "id": "mounted_gatling_mech_laser_rebuilt", + "copy-from": "turret", + "type": "vehicle_part", + "name": { "str": "mounted gatling laser" }, + "item": "gatling_mech_laser_rebuilt", + "color": "blue", + "broken_color": "blue", + "breaks_into": [ { "item": "scrap", "count": 14 }, { "item": "steel_chunk", "count": 6 }, { "item": "steel_lump", "count": 2 } ], + "requirements": { + "install": { "skills": [ [ "mechanics", 6 ], [ "electronics", 6 ] ] }, + "removal": { "skills": [ [ "mechanics", 4 ] ] } + } + }, + { + "id": "mounted_recon_mech_laser_rebuilt", + "copy-from": "turret", + "type": "vehicle_part", + "name": { "str": "mounted marksman laser" }, + "item": "recon_mech_laser_rebuilt", + "color": "blue", + "broken_color": "blue", + "breaks_into": [ { "item": "scrap", "count": 14 }, { "item": "steel_chunk", "count": 6 }, { "item": "steel_lump", "count": 2 } ], + "requirements": { + "install": { "skills": [ [ "mechanics", 6 ], [ "electronics", 6 ] ] }, + "removal": { "skills": [ [ "mechanics", 4 ] ] } + } + }, { "id": "m249", "copy-from": "turret", diff --git a/src/avatar_action.cpp b/src/avatar_action.cpp index 097ee39ff1a5..d4d8a8077199 100644 --- a/src/avatar_action.cpp +++ b/src/avatar_action.cpp @@ -397,6 +397,15 @@ bool avatar_action::move( avatar &you, map &m, const tripoint &d ) if( !veh1->handle_potential_theft( you ) ) { return true; } else { + // This check must be present in both avatar_action::move and map::open_door for vehiclepart doors specifically, + // having it in just one does not prevent opening doors on horseback, for some insane reason. + if( you.is_mounted() ) { + auto mon = you.mounted_creature.get(); + if( !mon->has_flag( MF_RIDEABLE_MECH ) ) { + // Message is printed by the other check in map::open_door + return false; + } + } if( outside_vehicle ) { veh1->open_all_at( dpart ); } else { diff --git a/src/game.cpp b/src/game.cpp index 01df25027bc2..0d539b3b1f71 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -5470,7 +5470,22 @@ void game::examine( const tripoint &examp ) if( c != nullptr ) { monster *mon = dynamic_cast( c ); if( mon != nullptr ) { - add_msg( _( "There is a %s." ), mon->get_name() ); + if( mon->battery_item && mon->has_effect( effect_pet ) ) { + const itype &type = *mon->type->mech_battery; + int max_charge = type.magazine->capacity; + float charge_percent; + if( mon->battery_item ) { + charge_percent = static_cast( mon->battery_item->ammo_remaining() ) / max_charge * 100; + } else { + charge_percent = 0.0; + } + add_msg( _( "There is a %s. Battery level: %d%%" ), mon->get_name(), + static_cast( charge_percent ) ); + } else { + add_msg( _( "There is a %s." ), mon->get_name() ); + } + + if( mon->has_effect( effect_pet ) && !u.is_mounted() ) { if( monexamine::pet_menu( *mon ) ) { return; diff --git a/src/handle_action.cpp b/src/handle_action.cpp index 3db4712b11d1..78e7f0e4204f 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -1852,7 +1852,13 @@ bool game::handle_action() if( u.has_active_mutation( trait_SHELL2 ) ) { add_msg( m_info, _( "You can't open things while you're in your shell." ) ); } else if( u.is_mounted() ) { - add_msg( m_info, _( "You can't open things while you're riding." ) ); + auto mon = u.mounted_creature.get(); + if( !mon->has_flag( MF_RIDEABLE_MECH ) ) { + add_msg( m_info, _( "You can't open things while you're riding." ) ); + break; + } else { + open(); + } } else { open(); } @@ -1865,6 +1871,9 @@ bool game::handle_action() auto mon = u.mounted_creature.get(); if( !mon->has_flag( MF_RIDEABLE_MECH ) ) { add_msg( m_info, _( "You can't close things while you're riding." ) ); + break; + } else { + close(); } } else if( mouse_target ) { doors::close_door( m, u, *mouse_target ); diff --git a/src/map.cpp b/src/map.cpp index 31b1d52fb9d0..720d08f56603 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3978,11 +3978,18 @@ bool map::open_door( const tripoint &p, const bool inside, const bool check_only avatar &you = get_avatar(); const auto &ter = this->ter( p ).obj(); const auto &furn = this->furn( p ).obj(); + if( ter.open ) { if( has_flag( "OPENCLOSE_INSIDE", p ) && !inside ) { return false; } - + if( you.is_mounted() ) { + auto mon = you.mounted_creature.get(); + if( !mon->has_flag( MF_RIDEABLE_MECH ) ) { + add_msg( m_info, _( "You can't open things while you're riding." ) ); + return false; + } + } if( !check_only ) { sounds::sound( p, 6, sounds::sound_t::movement, _( "swish" ), true, "open_door", ter.id.str() ); @@ -4000,6 +4007,13 @@ bool map::open_door( const tripoint &p, const bool inside, const bool check_only if( has_flag( "OPENCLOSE_INSIDE", p ) && !inside ) { return false; } + if( you.is_mounted() ) { + auto mon = you.mounted_creature.get(); + if( !mon->has_flag( MF_RIDEABLE_MECH ) ) { + add_msg( m_info, _( "You can't open things while you're riding." ) ); + return false; + } + } if( !check_only ) { sounds::sound( p, 6, sounds::sound_t::movement, _( "swish" ), true, @@ -4011,6 +4025,13 @@ bool map::open_door( const tripoint &p, const bool inside, const bool check_only } else if( const optional_vpart_position vp = veh_at( p ) ) { int openable = vp->vehicle().next_part_to_open( vp->part_index(), true ); if( openable >= 0 ) { + if( you.is_mounted() ) { + auto mon = you.mounted_creature.get(); + if( !mon->has_flag( MF_RIDEABLE_MECH ) ) { + add_msg( m_info, _( "You can't open things while you're riding." ) ); + return false; + } + } if( !check_only ) { if( !vp->vehicle().handle_potential_theft( you ) ) { return false;