diff --git a/data/json/items/tool/deployable.json b/data/json/items/tool/deployable.json index 8b6694d82acf..67257f0326b7 100644 --- a/data/json/items/tool/deployable.json +++ b/data/json/items/tool/deployable.json @@ -140,6 +140,29 @@ }, "flags": [ "ALLOWS_REMOTE_USE" ] }, + { + "id": "folding_skateboard", + "type": "TOOL", + "category": "tools", + "name": { "str": "skateboard" }, + "description": "This is a skateboard.", + "weight": "2898 g", + "volume": "3750 ml", + "price": "350 USD", + "price_postapoc": "20 USD", + "to_hit": -5, + "bashing": 10, + "material": "aluminum", + "symbol": "0", + "color": "light_gray", + "use_action": { + "type": "unfold_vehicle", + "vehicle_name": "skateboard", + "unfold_msg": "You lay the skateboard down on the ground.", + "moves": 0 + }, + "flags": [ "ALLOWS_REMOTE_USE" ] + }, { "id": "generic_folded_vehicle", "type": "TOOL", diff --git a/data/json/items/vehicle/frames.json b/data/json/items/vehicle/frames.json index f2d6b5a4d098..b3bd9f841b78 100644 --- a/data/json/items/vehicle/frames.json +++ b/data/json/items/vehicle/frames.json @@ -120,5 +120,20 @@ "price": "35 USD", "price_postapoc": "1 USD", "copy-from": "foldframe" + }, + { + "type": "GENERIC", + "id": "frame_wood_deck", + "name": { "str": "skateboard deck" }, + "symbol": "]", + "description": "A small skateboard frame made of thin layers of wood glued together.", + "weight": "1500 g", + "to_hit": -5, + "color": "brown", + "material": [ "wood" ], + "volume": "8750 ml", + "price": 1000, + "price_postapoc": 50, + "copy-from": "foldframe" } ] diff --git a/data/json/items/vehicle/wheel.json b/data/json/items/vehicle/wheel.json index 73ed6a0096fe..54ef015e25ef 100644 --- a/data/json/items/vehicle/wheel.json +++ b/data/json/items/vehicle/wheel.json @@ -160,6 +160,39 @@ "diameter": 4, "width": 1 }, + { + "id": "wheel_skateboard", + "category": "veh_parts", + "type": "WHEEL", + "name": { "str": "set of skateboard wheels", "str_pl": "sets of skateboard wheels" }, + "description": "A set of skateboard wheels.", + "weight": "1500 g", + "volume": "1250 ml", + "price": "20 USD", + "price_postapoc": "1 USD", + "bashing": 6, + "to_hit": -1, + "material": [ "steel", "plastic" ], + "symbol": "]", + "color": "dark_gray", + "diameter": 2, + "width": 1 + }, + { + "id": "wheel_mount_skateboard", + "type": "GENERIC", + "category": "veh_parts", + "name": { "str": "pair of skateboard trucks", "str_pl": "pairs of skateboard trucks" }, + "description": "A pair metal skateboard trucks, for attaching wheels to.", + "weight": "600 g", + "volume": "250 ml", + "price": 200, + "price_postapoc": 20, + "to_hit": -2, + "material": [ "steel" ], + "symbol": "]", + "color": "dark_gray" + }, { "id": "wheel_10", "category": "veh_parts", diff --git a/data/json/mapgen/park_skate.json b/data/json/mapgen/park_skate.json index 6e09e0ce6c51..9a4a2a35cc20 100644 --- a/data/json/mapgen/park_skate.json +++ b/data/json/mapgen/park_skate.json @@ -59,7 +59,9 @@ { "vehicle": "bicycle", "x": 10, "y": 7, "chance": 3, "status": 0, "rotation": 270 }, { "vehicle": "bicycle", "x": 17, "y": 8, "chance": 2, "status": 0, "rotation": 180 }, { "vehicle": "scooter", "x": 16, "y": 12, "chance": 5 }, - { "vehicle": "bicycle", "x": 16, "y": 19, "chance": 7 } + { "vehicle": "bicycle", "x": 16, "y": 19, "chance": 7 }, + { "vehicle": "skateboard", "x": 12, "y": 6, "chance": 3, "status": 0 }, + { "vehicle": "skateboard", "x": 19, "y": 10, "chance": 2, "status": 0 } ] } } diff --git a/data/json/professions.json b/data/json/professions.json index abedb1e131bb..8e16b6e0c428 100644 --- a/data/json/professions.json +++ b/data/json/professions.json @@ -4320,10 +4320,10 @@ { "type": "profession", "id": "skaterkid", - "name": { "male": "Skater Boy", "female": "Skater Girl" }, + "name": { "male": "Skater Boy (Rollerblades)", "female": "Skater Girl (Rollerblades)" }, "description": "You love to skate! At least now the grown-ups aren't telling you where you can't roll.", "points": 1, - "skills": [ { "level": 1, "name": "dodge" } ], + "skills": [ { "level": 1, "name": "dodge" }, { "level": 2, "name": "swimming" } ], "traits": [ "PROF_SKATER" ], "items": { "both": { @@ -4346,6 +4346,35 @@ "female": [ "boy_shorts" ] } }, + { + "type": "profession", + "id": "skaterkid_board", + "name": { "male": "Skater Boy (Skateboard)", "female": "Skater Girl (Skateboard)" }, + "description": "You love to skate! You've probably spent more time on a skateboard than off. Things have gotten pretty bad, but at least the grown-ups aren't telling you where you can't roll.", + "points": 1, + "skills": [ { "level": 2, "name": "driving" }, { "level": 2, "name": "swimming" } ], + "traits": [ "PROF_SKATER" ], + "items": { + "both": { + "items": [ + "hoodie", + "jeans", + "socks", + "elbow_pads", + "knee_pads", + "gloves_fingerless", + "helmet_skid", + "sneakers", + "folding_skateboard", + "wristwatch", + "smart_phone", + "sports_drink" + ] + }, + "male": [ "briefs" ], + "female": [ "boy_shorts" ] + } + }, { "type": "profession", "id": "jdelinquent", diff --git a/data/json/vehicleparts/frames.json b/data/json/vehicleparts/frames.json index 0c1b318f43cf..0767823bfa76 100644 --- a/data/json/vehicleparts/frames.json +++ b/data/json/vehicleparts/frames.json @@ -173,6 +173,40 @@ "flags": [ "MOUNTABLE" ], "damage_reduction": { "all": 84 } }, + { + "id": "frame_wood_deck", + "type": "vehicle_part", + "name": { "str": "skateboard deck" }, + "copy-from": "frame_wood_light", + "item": "frame_wood_deck", + "symbol": "]", + "looks_like": "frame_wood", + "durability": 100, + "fuel_type": "muscle", + "power": 140, + "muscle_power_factor": 30, + "m2c": 45, + "description": "A light wooden skateboard deck. Other skateboard components can be mounted on it.", + "breaks_into": [ { "item": "splinter", "count": [ 3, 5 ] } ], + "requirements": { + "install": { "skills": [ [ "fabrication", 0 ] ], "time": "0 m" }, + "removal": { "skills": [ [ "fabrication", 0 ] ], "time": "0 m" }, + "repair": { "skills": [ [ "fabrication", 0 ] ], "time": "5 m", "using": [ [ "adhesive", 1 ] ] } + }, + "flags": [ + "MOUNTABLE", + "INITIAL_PART", + "SEAT", + "ENGINE", + "E_STARTS_INSTANTLY", + "NONBELTABLE", + "MUSCLE_LEGS", + "SEAT_REQUIRES_BALANCE", + "BOARDABLE", + "CONTROLS" + ], + "damage_reduction": { "all": 2 } + }, { "id": "frame_cover", "copy-from": "frame", diff --git a/data/json/vehicleparts/vp_flags.json b/data/json/vehicleparts/vp_flags.json index 862bb3d10e55..812766f64022 100644 --- a/data/json/vehicleparts/vp_flags.json +++ b/data/json/vehicleparts/vp_flags.json @@ -240,5 +240,21 @@ "type": "json_flag", "context": [ "vehicle_part" ], "requires_flag": "ROOF" + }, + { + "id": "SEAT_REQUIRES_BALANCE", + "context": [ "vehicle_part" ], + "type": "json_flag" + }, + { + "id": "WHEEL_MOUNT_SKATEBOARD", + "context": [ "vehicle_part" ], + "type": "json_flag" + }, + { + "id": "NEEDS_WHEEL_MOUNT_SKATEBOARD", + "context": [ "vehicle_part" ], + "type": "json_flag", + "requires_flag": "WHEEL_MOUNT_SKATEBOARD" } ] diff --git a/data/json/vehicleparts/wheel.json b/data/json/vehicleparts/wheel.json index b3da1945e44c..d03c9a7b8b5a 100644 --- a/data/json/vehicleparts/wheel.json +++ b/data/json/vehicleparts/wheel.json @@ -350,6 +350,55 @@ }, "flags": [ "WHEEL", "NEEDS_JACKING", "STABLE", "FOLDABLE", "STEERABLE" ] }, + { + "id": "wheel_skateboard", + "type": "vehicle_part", + "name": { "str": "skateboard wheels" }, + "item": "wheel_skateboard", + "location": "under", + "color": "dark_gray", + "symbol": "o", + "broken_symbol": "x", + "durability": 70, + "description": "A set of four small wheels, for a skateboard.", + "damage_modifier": 50, + "folded_volume": "1250 ml", + "wheel_type": "standard", + "contact_area": 4, + "requirements": { + "removal": { "skills": [ [ "mechanics", 0 ] ], "time": "1 m", "qualities": [ { "id": "WRENCH", "level": 2 } ] }, + "install": { "skills": [ [ "mechanics", 0 ] ], "time": "1 m", "qualities": [ { "id": "WRENCH", "level": 2 } ] } + }, + "flags": [ "WHEEL", "NEEDS_WHEEL_MOUNT_SKATEBOARD", "STABLE", "STEERABLE" ] + }, + { + "id": "wheel_mount_skateboard", + "type": "vehicle_part", + "name": { "str": "skateboard trucks" }, + "item": "wheel_mount_skateboard", + "location": "axle", + "symbol": "-", + "broken_symbol": "x", + "damage_modifier": 80, + "folded_volume": "200 ml", + "durability": 120, + "description": "A pair of skateboard trucks, for attaching wheels to.", + "flags": [ "WHEEL_MOUNT_SKATEBOARD" ], + "requirements": { + "removal": { + "skills": [ [ "mechanics", 0 ] ], + "time": "3 m", + "qualities": [ { "id": "WRENCH", "level": 2 }, { "id": "SCREW", "level": 1 } ] + }, + "install": { + "skills": [ [ "mechanics", 0 ] ], + "time": "3 m", + "qualities": [ { "id": "WRENCH", "level": 2 }, { "id": "SCREW", "level": 1 } ] + } + }, + "breaks_into": [ { "item": "scrap", "count": [ 0, 1 ] } ], + "damage_reduction": { "all": 10 } + }, { "id": "wheel_10", "type": "vehicle_part", diff --git a/data/json/vehicles/bikes.json b/data/json/vehicles/bikes.json index 45bbd13d7a5d..0b2d4532a552 100644 --- a/data/json/vehicles/bikes.json +++ b/data/json/vehicles/bikes.json @@ -292,5 +292,12 @@ "parts": [ "frame_carbon_vertical", "wheel_mount_light", "wheel_bicycle_rear", "basketsm_bike_rear" ] } ] + }, + { + "id": "skateboard", + "type": "vehicle", + "name": "Skateboard", + "blueprint": [ "$" ], + "parts": [ { "x": 0, "y": 0, "parts": [ "frame_wood_deck", "wheel_mount_skateboard", "wheel_skateboard" ] } ] } ] diff --git a/data/json/vehicles/carts.json b/data/json/vehicles/carts.json index 55ff473e455d..4df91d6fdf67 100644 --- a/data/json/vehicles/carts.json +++ b/data/json/vehicles/carts.json @@ -296,7 +296,7 @@ { "id": "wheelchair", "type": "vehicle", - "name": "Foldable wheelchair", + "name": "Wheelchair", "blueprint": [ "#" ], "parts": [ { "x": 0, "y": 0, "part": "folding_frame" }, diff --git a/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj index 7730f8fd07b0..b03081f6c2aa 100644 --- a/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj @@ -39,10 +39,9 @@ --clean-after-build - StaticLibrary - v142 + v143 MultiByte @@ -52,7 +51,6 @@ false false - @@ -134,15 +132,17 @@ NotUsing - + + NotUsing - + + - + @@ -154,4 +154,4 @@ - + \ No newline at end of file diff --git a/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj index 8eebabe990f9..e69fcb4e48e4 100644 --- a/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj @@ -41,7 +41,7 @@ Application - v142 + v143 MultiByte @@ -148,4 +148,4 @@ - + \ No newline at end of file diff --git a/msvc-full-features/Cataclysm-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-vcpkg-static.vcxproj index bfdabb88cc81..56b8caf0ac8a 100644 --- a/msvc-full-features/Cataclysm-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-vcpkg-static.vcxproj @@ -41,7 +41,7 @@ Application - v142 + v143 MultiByte @@ -165,4 +165,4 @@ - + \ No newline at end of file diff --git a/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj b/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj index aeacba199e97..b3c8b1511e89 100644 --- a/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj +++ b/msvc-full-features/JsonFormatter-vcpkg-static.vcxproj @@ -41,7 +41,7 @@ Application - v142 + v143 MultiByte @@ -161,4 +161,4 @@ - + \ No newline at end of file diff --git a/src/character.cpp b/src/character.cpp index 8a9a6eceafde..f6e70a23604d 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -8742,26 +8742,46 @@ void Character::on_hit( Creature *source, bodypart_id bp_hit, source->add_effect( effect_blind, 2_turns ); } } - if( worn_with_flag( flag_REQUIRES_BALANCE ) && !has_effect( effect_downed ) ) { + + map &here = get_map(); + const optional_vpart_position veh_part = here.veh_at( pos() ); + bool in_skater_vehicle = in_vehicle && veh_part.part_with_feature( "SEAT_REQUIRES_BALANCE", false ); + + if( ( worn_with_flag( flag_REQUIRES_BALANCE ) || in_skater_vehicle ) && !is_on_ground() ) { int rolls = 4; - if( worn_with_flag( flag_ROLLER_ONE ) ) { - rolls += 2; - } - if( has_trait( trait_PROF_SKATER ) ) { - rolls--; - } - if( has_trait( trait_DEFT ) ) { - rolls--; - } + if( worn_with_flag( flag_ROLLER_ONE ) && !in_skater_vehicle ) { + if( worn_with_flag( flag_REQUIRES_BALANCE ) && !has_effect( effect_downed ) ) { + int rolls = 4; + if( worn_with_flag( flag_ROLLER_ONE ) ) { + rolls += 2; + } + if( has_trait( trait_PROF_SKATER ) ) { + rolls--; + } + if( has_trait( trait_DEFT ) ) { + rolls--; + } - if( stability_roll() < dice( rolls, 10 ) ) { - if( !is_player() ) { - if( u_see ) { - add_msg( _( "%1$s loses their balance while being hit!" ), name ); + if( stability_roll() < dice( rolls, 10 ) ) { + if( !is_player() ) { + if( u_see ) { + add_msg( _( "%1$s loses their balance while being hit!" ), name ); + } + } else { + add_msg( m_bad, _( "You lose your balance while being hit!" ) ); + } + if( in_skater_vehicle ) { + g->fling_creature( this, rng_float( 0_degrees, 360_degrees ), 10 ); + } + // This kind of downing is not subject to immunity. + add_effect( effect_downed, 2_turns, bodypart_str_id::NULL_ID(), 0, true ); } } else { add_msg( m_bad, _( "You lose your balance while being hit!" ) ); } + if( in_skater_vehicle ) { + g->fling_creature( this, rng_float( 0_degrees, 360_degrees ), 10 ); + } // This kind of downing is not subject to immunity. add_effect( effect_downed, 2_turns, bodypart_str_id::NULL_ID(), 0, true ); } diff --git a/src/vehicle_move.cpp b/src/vehicle_move.cpp index 137e84a38ba7..72c24f6f70ce 100644 --- a/src/vehicle_move.cpp +++ b/src/vehicle_move.cpp @@ -51,6 +51,11 @@ static const itype_id fuel_type_battery( "battery" ); static const skill_id skill_driving( "driving" ); +static const trait_id trait_DEFT("DEFT"); +static const trait_id trait_PROF_SKATER("PROF_SKATER"); +static const trait_id trait_DEFT( "DEFT" ); +static const trait_id trait_PROF_SKATER( "PROF_SKATER" ); + static const efftype_id effect_harnessed( "harnessed" ); static const efftype_id effect_pet( "pet" ); static const efftype_id effect_stunned( "stunned" ); @@ -1687,6 +1692,18 @@ units::angle map::shake_vehicle( vehicle &veh, const int velocity_before, if( psg ) { ///\EFFECT_STR reduces chance of being thrown from your seat when not wearing a seatbelt move_resist = psg->str_cur * 150 + 500; + if( veh.part( ps ).info().has_flag( "SEAT_REQUIRES_BALANCE" ) ) { + // Much harder to resist being thrown on a skateboard-like vehicle. + // Penalty mitigated by Deft and Skater. + int resist_penalty = 500; + if( psg->has_trait( trait_PROF_SKATER ) ) { + resist_penalty -= 150; + } + if( psg->has_trait( trait_DEFT ) ) { + resist_penalty -= 150; + } + move_resist -= resist_penalty; + } } else { int pet_resist = 0; if( pet != nullptr ) { diff --git a/src/vehicle_use.cpp b/src/vehicle_use.cpp index 150c5e28af83..bd7eb8151986 100644 --- a/src/vehicle_use.cpp +++ b/src/vehicle_use.cpp @@ -887,6 +887,7 @@ void vehicle::use_controls( const tripoint &pos ) bool vehicle::fold_up() { const bool can_be_folded = is_foldable(); + const bool is_convertible = ( tags.contains( "convertible" ) ); if( !( can_be_folded || is_convertible ) ) { debugmsg( _( "Tried to fold non-folding vehicle %s" ), name ); @@ -912,7 +913,8 @@ bool vehicle::fold_up() add_msg( _( "You let go of %s as you fold it." ), name ); } - std::string itype_id = "folding_bicycle"; + std::string itype_id = "generic_folded_vehicle"; + // Determine the item type from tags for( const auto &elem : tags ) { if( elem.compare( 0, 12, "convertible:" ) == 0 ) { itype_id = elem.substr( 12 ); @@ -920,10 +922,16 @@ bool vehicle::fold_up() } } - // create a folding [non]bicycle item - detached_ptr bicycle = item::spawn( can_be_folded ? "generic_folded_vehicle" : - "folding_bicycle", - calendar::turn ); + // Decide the spawn type based on item and folding state + std::string spawn_type; + if( itype_id == "folding_bicycle" || itype_id == "folding_skateboard" ) { + spawn_type = itype_id; + } else { + spawn_type = "generic_folded_vehicle"; // Handle unexpected cases + } + + // Create the item + detached_ptr bicycle = item::spawn( spawn_type, calendar::turn ); // Drop stuff in containers on ground for( const vpart_reference &vp : get_any_parts( "CARGO" ) ) { @@ -949,13 +957,19 @@ bool vehicle::fold_up() debugmsg( "Error storing vehicle: %s", e.c_str() ); } - if( can_be_folded ) { + // i dont understand what the can_be_folded check was for here. + // seems to only evaluate true if vehicle has a part with FOLDING tag. + // the folding bicycle does not? instead the item itself seems to turn the vehicle into folding + if( spawn_type == "generic_folded_vehicle" ) { bicycle->set_var( "weight", to_milligram( total_mass() ) ); bicycle->set_var( "volume", total_folded_volume() / units::legacy_volume_factor ); - bicycle->set_var( "name", string_format( _( "folded %s" ), name ) ); + // remove "folded" from name to allow for more flexibility with folded vehicle names. also lowers first character + bicycle->set_var( "name", string_format( _( "%s" ), ( name.empty() ? name : std::string( 1, + std::tolower( name[0] ) ) + name.substr( 1 ) ) ) ); bicycle->set_var( "vehicle_name", name ); // TODO: a better description? - bicycle->set_var( "description", string_format( _( "A folded %s." ), name ) ); + bicycle->set_var( "description", string_format( _( "A folded %s." ), + ( name.empty() ? name : std::string( 1, std::tolower( name[0] ) ) + name.substr( 1 ) ) ) ); } g->m.add_item_or_charges( global_part_pos3( 0 ), std::move( bicycle ) );