diff --git a/data/json/obsolete.json b/data/json/obsolete.json index 63a885cd3100b..a3d829a233b8a 100644 --- a/data/json/obsolete.json +++ b/data/json/obsolete.json @@ -1124,6 +1124,54 @@ "removal": { "skills": [ [ "mechanics", 3 ] ] } } }, + { + "abstract": "door_abstract", + "breaks_into": "ig_vp_frame", + "broken_color": "cyan", + "broken_symbol": "&", + "color": "cyan", + "damage_modifier": 80, + "damage_reduction": { "all": 21 }, + "description": "A door. Has a window so you can see out of it, even when closed.", + "durability": 225, + "flags": [ "CARGO", "OBSTACLE", "OPENABLE", "BOARDABLE", "WINDOW" ], + "item": "frame", + "location": "center", + "looks_like": "t_door_metal_c", + "name": { "str": "door" }, + "requirements": { + "install": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_bolt", 1 ] ] }, + "repair": { "skills": [ [ "mechanics", 3 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } + }, + "size": 10, + "symbol": "+", + "type": "vehicle_part" + }, + { + "copy-from": "door_abstract", + "id": "door_front_left", + "symbol": "y", + "type": "vehicle_part" + }, + { + "copy-from": "door_abstract", + "id": "door_front_right", + "symbol": "u", + "type": "vehicle_part" + }, + { + "copy-from": "door_abstract", + "id": "door_rear_left", + "symbol": "b", + "type": "vehicle_part" + }, + { + "copy-from": "door_abstract", + "id": "door_rear_right", + "symbol": "n", + "type": "vehicle_part" + }, { "type": "terrain", "id": "t_gas_tank", diff --git a/data/json/vehicleparts/boards.json b/data/json/vehicleparts/boards.json index 7f3730de70a72..c094644ae4355 100644 --- a/data/json/vehicleparts/boards.json +++ b/data/json/vehicleparts/boards.json @@ -1,14 +1,30 @@ [ { - "abstract": "board", + "abstract": "base_board_abstract", "type": "vehicle_part", - "name": { "str": "board" }, - "item": "sheet_metal", "location": "center", + "standard_symbols": true, + "symbols": { + "horizontal_front": "T", + "horizontal_rear": "B", + "horizontal_2_front": "=", + "horizontal_2_rear": "=", + "vertical_left": "j", + "vertical_right": "j", + "vertical_T_left": "[", + "vertical_T_right": "]", + "vertical_2_left": "H", + "vertical_2_right": "H" + }, + "flags": [ "OBSTACLE", "NO_ROOF_NEEDED" ] + }, + { + "abstract": "board_abstract", + "copy-from": "base_board_abstract", + "type": "vehicle_part", + "item": "sheet_metal", "durability": 120, - "description": "A metal wall. Keeps zombies outside the vehicle and prevents people from seeing through it.", "breaks_into": "ig_vp_sheet_metal", - "flags": [ "OPAQUE", "OBSTACLE", "FULL_BOARD", "NO_ROOF_NEEDED" ], "requirements": { "install": { "skills": [ [ "mechanics", 1 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] }, "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, @@ -17,50 +33,60 @@ "damage_reduction": { "all": 28 } }, { - "abstract": "clothboard", + "id": "board", + "type": "vehicle_part", + "copy-from": "board_abstract", + "name": { "str": "board" }, + "description": "A metal wall. Keeps zombies outside the vehicle and prevents people from seeing through it.", + "extend": { "flags": [ "OPAQUE", "FULL_BOARD" ] } + }, + { + "id": "halfboard", + "copy-from": "board_abstract", + "type": "vehicle_part", + "name": { "str": "quarterpanel" }, + "description": "A half-height metal wall. Keeps zombies outside the vehicle but allows people to see over it.", + "proportional": { "durability": 0.8 }, + "extend": { "flags": [ "HALF_BOARD" ] } + }, + { + "abstract": "clothboard_abstract", + "copy-from": "base_board_abstract", "type": "vehicle_part", - "name": { "str": "cloth board" }, "item": "sheet", - "location": "center", "broken_color": "dark_gray", "durability": 15, - "description": "A cloth wall. Keeps zombies outside the vehicle and prevents people from seeing through it.", "folded_volume": "3750 ml", "breaks_into": "ig_vp_cloth", "requirements": { "install": { "skills": [ [ "mechanics", 1 ] ], "time": "30 m", "using": [ [ "vehicle_nail_install", 1 ] ] }, "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "15 m", "using": [ [ "vehicle_nail_removal", 1 ] ] }, "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "adhesive", 2 ] ] } - }, - "flags": [ "OPAQUE", "OBSTACLE", "FOLDABLE", "FULL_BOARD", "NO_ROOF_NEEDED" ] + } }, { - "abstract": "cloth_halfboard", - "copy-from": "clothboard", + "id": "clothboard", + "copy-from": "clothboard_abstract", "type": "vehicle_part", - "name": { "str": "cloth quarterpanel" }, - "description": "A half-height cloth wall. Keeps zombies outside the vehicle but allows people to see over it.", - "proportional": { "durability": 0.8 }, - "extend": { "flags": [ "HALF_BOARD" ] }, - "delete": { "flags": [ "OPAQUE", "FULL_BOARD" ] } + "name": { "str": "cloth board" }, + "description": "A cloth wall. Keeps zombies outside the vehicle and prevents people from seeing through it.", + "extend": { "flags": [ "OPAQUE", "FULL_BOARD" ] } }, { - "abstract": "halfboard", - "copy-from": "board", + "abstract": "cloth_halfboard", + "copy-from": "clothboard_abstract", "type": "vehicle_part", - "name": { "str": "quarterpanel" }, - "description": "A half-height metal wall. Keeps zombies outside the vehicle but allows people to see over it.", + "name": { "str": "cloth quarterpanel" }, + "description": "A half-height cloth wall. Keeps zombies outside the vehicle but allows people to see over it.", "proportional": { "durability": 0.8 }, - "extend": { "flags": [ "HALF_BOARD" ] }, - "delete": { "flags": [ "OPAQUE", "FULL_BOARD" ] }, - "damage_reduction": { "all": 28 } + "extend": { "flags": [ "HALF_BOARD" ] } }, { - "abstract": "stowboard", + "id": "stowboard", "type": "vehicle_part", + "copy-from": "base_board_abstract", "name": { "str": "stow board" }, "item": "sheet_metal", - "location": "center", "color": "white", "broken_symbol": "#", "broken_color": "light_gray", @@ -72,11 +98,11 @@ "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, "repair": { "skills": [ [ "mechanics", 3 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } }, - "flags": [ "OBSTACLE", "OPAQUE", "CARGO", "COVERED", "FULL_BOARD", "NO_ROOF_NEEDED", "LOCKABLE_CARGO" ], + "extend": { "flags": [ "OPAQUE", "CARGO", "COVERED", "FULL_BOARD", "LOCKABLE_CARGO" ] }, "damage_reduction": { "all": 28 } }, { - "abstract": "hdstowboard", + "id": "hdstowboard", "copy-from": "stowboard", "type": "vehicle_part", "name": { "str": "heavy duty stow board" }, @@ -84,15 +110,13 @@ "color": "brown", "broken_color": "dark_gray", "proportional": { "durability": 4.15, "size": 0.76 }, - "flags": [ "OBSTACLE", "OPAQUE", "CARGO", "COVERED", "FULL_BOARD", "NO_ROOF_NEEDED", "LOCKABLE_CARGO" ], "damage_reduction": { "all": 72, "cut": 80, "stab": 80 } }, { - "abstract": "hdboard", + "abstract": "hdboard_abstract", "type": "vehicle_part", - "name": { "str": "heavy duty board" }, + "copy-from": "base_board_abstract", "item": "steel_plate", - "location": "center", "color": "dark_gray", "durability": 450, "description": "A strong metal wall. Keeps zombies outside the vehicle and prevents people from seeing through it.", @@ -102,56 +126,64 @@ "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } }, - "flags": [ "OPAQUE", "OBSTACLE", "FULL_BOARD", "NO_ROOF_NEEDED" ], "damage_reduction": { "all": 75, "cut": 80, "stab": 80 } }, { - "abstract": "hdhalfboard", - "copy-from": "hdboard", + "id": "hdboard", + "type": "vehicle_part", + "copy-from": "hdboard_abstract", + "name": { "str": "heavy duty board" }, + "description": "A strong metal wall. Keeps zombies outside the vehicle and prevents people from seeing through it.", + "extend": { "flags": [ "OPAQUE", "FULL_BOARD" ] } + }, + { + "id": "hdhalfboard", + "copy-from": "hdboard_abstract", "type": "vehicle_part", "name": { "str": "heavy duty quarterpanel" }, "description": "A half-height strong metal wall. Keeps zombies outside the vehicle but allows people to see over it.", "proportional": { "durability": 0.8 }, - "extend": { "flags": [ "HALF_BOARD" ] }, - "delete": { "flags": [ "OPAQUE", "FULL_BOARD" ] }, - "damage_reduction": { "all": 75, "cut": 80, "stab": 80 } + "extend": { "flags": [ "HALF_BOARD" ] } }, { - "abstract": "woodboard", + "abstract": "woodboard_abstract", "type": "vehicle_part", - "name": { "str": "wooden board" }, + "copy-from": "base_board_abstract", "item": "wood_plate", - "location": "center", "color": "brown", "broken_color": "brown", "durability": 100, - "description": "A wooden wall. Keeps zombies outside the vehicle and prevents people from seeing through it.", "breaks_into": "ig_vp_wood_plate", "requirements": { "install": { "skills": [ [ "mechanics", 1 ] ], "time": "30 m", "using": [ [ "vehicle_nail_install", 1 ] ] }, "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "15 m", "using": [ [ "vehicle_nail_removal", 1 ] ] }, "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "adhesive", 2 ] ] } }, - "flags": [ "OPAQUE", "OBSTACLE", "FULL_BOARD", "NO_ROOF_NEEDED" ], "damage_reduction": { "all": 16, "cut": 8, "stab": 8 } }, { - "abstract": "woodhalfboard", - "copy-from": "woodboard", + "id": "woodboard", + "type": "vehicle_part", + "copy-from": "woodboard_abstract", + "name": { "str": "wooden board" }, + "description": "A wooden wall. Keeps zombies outside the vehicle and prevents people from seeing through it.", + "extend": { "flags": [ "OPAQUE", "FULL_BOARD" ] } + }, + { + "id": "woodhalfboard", + "copy-from": "woodboard_abstract", "type": "vehicle_part", "name": { "str": "wooden quarterpanel" }, "description": "A half-height wooden wall. Keeps zombies outside the vehicle but allows people to see over it.", "proportional": { "durability": 0.8 }, - "extend": { "flags": [ "HALF_BOARD" ] }, - "delete": { "flags": [ "OPAQUE", "FULL_BOARD" ] }, - "damage_reduction": { "all": 16, "cut": 8, "stab": 8 } + "extend": { "flags": [ "HALF_BOARD" ] } }, { - "abstract": "xlhalfboard", + "id": "xlhalfboard", "type": "vehicle_part", + "copy-from": "base_board_abstract", "name": { "str": "extra light quarterpanel" }, "item": "pipe", - "location": "center", "looks_like": "halfboard", "durability": 96, "description": "A half-height thin metal wall. Keeps zombies outside the vehicle but allows people to see over it.", @@ -161,627 +193,7 @@ "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } }, - "flags": [ "OBSTACLE", "HALF_BOARD", "NO_ROOF_NEEDED" ], + "extend": { "flags": [ "HALF_BOARD" ] }, "damage_reduction": { "all": 8 } - }, - { - "id": "halfboard_cover", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "^" - }, - { - "id": "board_horizontal", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "clothboard_horizontal", - "copy-from": "clothboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "cloth_halfboard_horizontal", - "copy-from": "cloth_halfboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "halfboard_horizontal", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "stowboard_horizontal", - "copy-from": "stowboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "hdstowboard_horizontal", - "copy-from": "hdstowboard", - "type": "vehicle_part", - "looks_like": "stowboard_horizontal", - "symbol": "h" - }, - { - "id": "hdboard_horizontal", - "copy-from": "hdboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "hdhalfboard_horizontal", - "copy-from": "hdhalfboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "woodboard_horizontal", - "copy-from": "woodboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "woodhalfboard_horizontal", - "copy-from": "woodhalfboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "xlhalfboard_horizontal", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "board_horizontal_front", - "looks_like": "board_horizontal", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "T" - }, - { - "id": "halfboard_horizontal_front", - "looks_like": "halfboard_horizontal", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "T" - }, - { - "id": "xlhalfboard_horizontal_front", - "looks_like": "halfboard_horizontal_front", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "T" - }, - { - "id": "board_horizontal_rear", - "looks_like": "board_horizontal", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "B" - }, - { - "id": "halfboard_horizontal_rear", - "looks_like": "halfboard_horizontal", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "B" - }, - { - "id": "xlhalfboard_horizontal_rear", - "looks_like": "halfboard_horizontal_rear", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "B" - }, - { - "id": "cloth_halfboard_horizontal_2", - "copy-from": "cloth_halfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "halfboard_horizontal_2", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "hdhalfboard_horizontal_2", - "copy-from": "hdhalfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "woodhalfboard_horizontal_2", - "copy-from": "woodhalfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "xlhalfboard_horizontal_2", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "halfboard_horizontal_2_front", - "looks_like": "halfboard_horizontal_2", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "halfboard_horizontal_2_rear", - "looks_like": "halfboard_horizontal_2", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "xlhalfboard_horizontal_2_front", - "looks_like": "xlhalfboard_horizontal_2", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "xlhalfboard_horizontal_2_rear", - "looks_like": "xlhalfboard_horizontal_2", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "board_ne", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "clothboard_ne", - "copy-from": "clothboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "cloth_halfboard_ne", - "looks_like": "clothboard_ne", - "copy-from": "cloth_halfboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "halfboard_ne", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "stowboard_ne", - "copy-from": "stowboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "hdstowboard_ne", - "copy-from": "hdstowboard", - "type": "vehicle_part", - "looks_like": "stowboard_ne", - "symbol": "u" - }, - { - "id": "hdboard_ne", - "looks_like": "board_ne", - "copy-from": "hdboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "hdhalfboard_ne", - "looks_like": "halfboard_ne", - "copy-from": "hdhalfboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "woodboard_ne", - "copy-from": "woodboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "woodhalfboard_ne", - "looks_like": "woodboard_ne", - "copy-from": "woodhalfboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "xlhalfboard_ne", - "looks_like": "halfboard_ne", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "board_nw", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "clothboard_nw", - "copy-from": "clothboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "cloth_halfboard_nw", - "looks_like": "clothboard_nw", - "copy-from": "cloth_halfboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "halfboard_nw", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "stowboard_nw", - "copy-from": "stowboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "hdstowboard_nw", - "copy-from": "hdstowboard", - "type": "vehicle_part", - "looks_like": "stowboard_nw", - "symbol": "y" - }, - { - "id": "hdboard_nw", - "looks_like": "board_nw", - "copy-from": "hdboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "hdhalfboard_nw", - "looks_like": "halfboard_nw", - "copy-from": "hdhalfboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "woodboard_nw", - "copy-from": "woodboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "woodhalfboard_nw", - "looks_like": "woodboard_nw", - "copy-from": "woodhalfboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "xlhalfboard_nw", - "looks_like": "xlhalfboard_nw", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "board_se", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "clothboard_se", - "copy-from": "clothboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "cloth_halfboard_se", - "looks_like": "clothboard_se", - "copy-from": "cloth_halfboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "halfboard_se", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "stowboard_se", - "copy-from": "stowboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "hdstowboard_se", - "copy-from": "hdstowboard", - "type": "vehicle_part", - "looks_like": "stowboard_se", - "symbol": "n" - }, - { - "id": "hdboard_se", - "looks_like": "board_se", - "copy-from": "hdboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "hdhalfboard_se", - "looks_like": "halfboard_se", - "copy-from": "hdhalfboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "woodboard_se", - "copy-from": "woodboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "woodhalfboard_se", - "looks_like": "woodboard_se", - "copy-from": "woodhalfboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "xlhalfboard_se", - "looks_like": "halfboard_se", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "board_sw", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "clothboard_sw", - "copy-from": "clothboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "cloth_halfboard_sw", - "looks_like": "clothboard_sw", - "copy-from": "cloth_halfboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "halfboard_sw", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "stowboard_sw", - "copy-from": "stowboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "hdstowboard_sw", - "copy-from": "hdstowboard", - "type": "vehicle_part", - "looks_like": "stowboard_sw", - "symbol": "b" - }, - { - "id": "hdboard_sw", - "looks_like": "board_sw", - "copy-from": "hdboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "hdhalfboard_sw", - "looks_like": "halfboard_sw", - "copy-from": "hdhalfboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "woodboard_sw", - "copy-from": "woodboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "woodhalfboard_sw", - "looks_like": "woodboard_sw", - "copy-from": "woodhalfboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "xlhalfboard_sw", - "looks_like": "halfboard_sw", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "board_vertical", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "clothboard_vertical", - "copy-from": "clothboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "cloth_halfboard_vertical", - "copy-from": "cloth_halfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "halfboard_vertical", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "stowboard_vertical", - "copy-from": "stowboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "hdstowboard_vertical", - "copy-from": "hdstowboard", - "type": "vehicle_part", - "looks_like": "stowboard_vertical", - "symbol": "j" - }, - { - "id": "hdboard_vertical", - "copy-from": "hdboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "hdhalfboard_vertical", - "copy-from": "hdhalfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "woodboard_vertical", - "copy-from": "woodboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "woodhalfboard_vertical", - "copy-from": "woodhalfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "xlhalfboard_vertical", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "board_vertical_left", - "looks_like": "board_vertical", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "halfboard_vertical_left", - "looks_like": "halfboard_vertical", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "xlhalfboard_vertical_left", - "looks_like": "xlhalfboard_vertical", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "board_vertical_right", - "looks_like": "board_vertical", - "copy-from": "board", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "halfboard_vertical_right", - "looks_like": "halfboard_vertical", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "xlhalfboard_vertical_right", - "looks_like": "xlhalfboard_vertical", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "cloth_halfboard_vertical_2", - "copy-from": "cloth_halfboard", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "halfboard_vertical_2", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "hdhalfboard_vertical_2", - "copy-from": "hdhalfboard", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "xlhalfboard_vertical_2", - "copy-from": "xlhalfboard", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "halfboard_vertical_2_left", - "looks_like": "halfboard_vertical_2", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "halfboard_vertical_2_right", - "looks_like": "halfboard_vertical_2", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "halfboard_vertical_T_right", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "]" - }, - { - "id": "halfboard_vertical_T_left", - "copy-from": "halfboard", - "type": "vehicle_part", - "symbol": "[" } ] diff --git a/data/json/vehicleparts/doors.json b/data/json/vehicleparts/doors.json index d57ef6a614be6..785cdfdfcbe7f 100644 --- a/data/json/vehicleparts/doors.json +++ b/data/json/vehicleparts/doors.json @@ -1,6 +1,6 @@ [ { - "abstract": "door_abstract", + "id": "door", "breaks_into": "ig_vp_frame", "broken_color": "cyan", "broken_symbol": "&", @@ -21,6 +21,7 @@ }, "size": 10, "symbol": "+", + "symbols": { "ne": "u", "nw": "y", "se": "b", "sw": "n", "vertical_left": "L", "vertical_right": "n", "front": "T", "rear": "B" }, "type": "vehicle_part" }, { @@ -214,12 +215,6 @@ "symbol": "+", "type": "vehicle_part" }, - { - "copy-from": "door_abstract", - "id": "door", - "symbol": "+", - "type": "vehicle_part" - }, { "copy-from": "door_opaque_abstract", "id": "door_opaque", @@ -267,53 +262,5 @@ "id": "hdhatch_opaque", "symbol": "+", "type": "vehicle_part" - }, - { - "copy-from": "door_abstract", - "id": "door_front_left", - "symbol": "y", - "type": "vehicle_part" - }, - { - "copy-from": "door_abstract", - "id": "door_vertical_left", - "symbol": "L", - "type": "vehicle_part" - }, - { - "copy-from": "door_abstract", - "id": "door_front_right", - "symbol": "u", - "type": "vehicle_part" - }, - { - "copy-from": "door_abstract", - "id": "door_rear_left", - "symbol": "b", - "type": "vehicle_part" - }, - { - "copy-from": "door_abstract", - "id": "door_vertical_right", - "symbol": "R", - "type": "vehicle_part" - }, - { - "copy-from": "door_abstract", - "id": "door_rear_right", - "symbol": "n", - "type": "vehicle_part" - }, - { - "copy-from": "door_abstract", - "id": "door_front", - "symbol": "T", - "type": "vehicle_part" - }, - { - "copy-from": "door_abstract", - "id": "door_rear", - "symbol": "B", - "type": "vehicle_part" } ] diff --git a/data/json/vehicleparts/frames.json b/data/json/vehicleparts/frames.json index c33698dc5e5d4..85a07d19f5394 100644 --- a/data/json/vehicleparts/frames.json +++ b/data/json/vehicleparts/frames.json @@ -40,11 +40,12 @@ "damage_reduction": { "all": 12 } }, { - "abstract": "frame", + "id": "frame", "type": "vehicle_part", "name": { "str": "frame" }, "item": "frame", "location": "structure", + "standard_symbols": true, "durability": 400, "description": "A metal framework. Other vehicle components can be mounted on it, and it can be attached to other frames to increase the vehicle's size.", "breaks_into": "ig_vp_frame", @@ -53,15 +54,16 @@ "removal": { "skills": [ [ "mechanics", 1 ] ], "time": "10 m", "using": "vehicle_weld_removal" }, "repair": { "skills": [ [ "mechanics", 1 ] ], "time": "5 m", "using": [ [ "welding_standard", 5 ] ] } }, - "flags": [ "MOUNTABLE" ], + "flags": [ "MOUNTABLE", "INITIAL_PART" ], "damage_reduction": { "all": 52 } }, { - "abstract": "frame_wood", + "id": "frame_wood", "type": "vehicle_part", "name": { "str": "wooden frame" }, "item": "frame_wood", "location": "structure", + "standard_symbols": true, "color": "brown", "broken_color": "brown", "durability": 150, @@ -80,6 +82,7 @@ "name": { "str": "light wooden frame" }, "item": "frame_wood_light", "location": "structure", + "standard_symbols": true, "color": "brown", "broken_color": "brown", "durability": 100, @@ -92,11 +95,12 @@ "damage_reduction": { "all": 46 } }, { - "abstract": "hdframe", + "id": "hdframe", "type": "vehicle_part", "name": { "str": "heavy duty frame" }, "item": "hdframe", "location": "structure", + "standard_symbols": true, "color": "dark_gray", "durability": 760, "description": "A heavy metal framework. Other vehicle components can be mounted on it, and it can be attached to other frames to increase the vehicle's size. Increased mass makes it more resistant to damage in collisions.", @@ -106,15 +110,16 @@ "removal": { "skills": [ [ "mechanics", 1 ] ], "time": "20 m", "using": "vehicle_weld_removal" }, "repair": { "skills": [ [ "mechanics", 3 ] ], "time": "10 m", "using": [ [ "welding_standard", 10 ] ] } }, - "flags": [ "MOUNTABLE" ], + "flags": [ "MOUNTABLE", "INITIAL_PART" ], "damage_reduction": { "all": 112 } }, { - "abstract": "xlframe", + "id": "xlframe", "type": "vehicle_part", "name": { "str": "extra light frame" }, "item": "xlframe", "location": "structure", + "standard_symbols": true, "color": "light_gray", "durability": 150, "description": "A light metal framework. Other vehicle components can be mounted on it, and it can be attached to other frames to increase the vehicle's size.", @@ -126,310 +131,5 @@ }, "flags": [ "MOUNTABLE" ], "damage_reduction": { "all": 28 } - }, - { - "id": "frame_cover", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "^" - }, - { - "id": "frame_wood_cover", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "^" - }, - { - "id": "frame_wood_light_cover", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "^" - }, - { - "id": "hdframe_cover", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "^" - }, - { - "id": "xlframe_cover", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "^" - }, - { - "id": "frame_cross", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "c", - "extend": { "flags": [ "INITIAL_PART" ] } - }, - { - "id": "frame_wood_cross", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "c", - "extend": { "flags": [ "INITIAL_PART" ] } - }, - { - "id": "frame_wood_light_cross", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "c", - "extend": { "flags": [ "INITIAL_PART" ] } - }, - { - "id": "hdframe_cross", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "c", - "extend": { "flags": [ "INITIAL_PART" ] } - }, - { - "id": "xlframe_cross", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "c", - "extend": { "flags": [ "INITIAL_PART" ] } - }, - { - "id": "frame_horizontal", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "frame_wood_horizontal", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "frame_wood_light_horizontal", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "hdframe_horizontal", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "xlframe_horizontal", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "h" - }, - { - "id": "frame_horizontal_2", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "frame_wood_horizontal_2", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "frame_wood_light_horizontal_2", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "hdframe_horizontal_2", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "xlframe_horizontal_2", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "=" - }, - { - "id": "frame_ne", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "frame_wood_ne", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "frame_wood_light_ne", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "hdframe_ne", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "xlframe_ne", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "u" - }, - { - "id": "frame_nw", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "frame_wood_nw", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "frame_wood_light_nw", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "hdframe_nw", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "xlframe_nw", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "y" - }, - { - "id": "frame_se", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "frame_wood_se", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "frame_wood_light_se", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "hdframe_se", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "xlframe_se", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "n" - }, - { - "id": "frame_sw", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "frame_wood_sw", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "frame_wood_light_sw", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "hdframe_sw", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "xlframe_sw", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "b" - }, - { - "id": "frame_vertical", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "frame_wood_vertical", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "frame_wood_light_vertical", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "hdframe_vertical", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "xlframe_vertical", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "j" - }, - { - "id": "frame_vertical_2", - "copy-from": "frame", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "frame_wood_vertical_2", - "copy-from": "frame_wood", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "frame_wood_light_vertical_2", - "copy-from": "frame_wood_light", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "hdframe_vertical_2", - "copy-from": "hdframe", - "type": "vehicle_part", - "symbol": "H" - }, - { - "id": "xlframe_vertical_2", - "copy-from": "xlframe", - "type": "vehicle_part", - "symbol": "H" } ] diff --git a/data/json/vehicleparts/lights.json b/data/json/vehicleparts/lights.json index c13d49af51785..48f52e722f14c 100644 --- a/data/json/vehicleparts/lights.json +++ b/data/json/vehicleparts/lights.json @@ -218,11 +218,12 @@ "extend": { "flags": [ "ODDTURN" ] } }, { - "id": "lit_aisle_horizontal", + "id": "lit_aisle", "type": "vehicle_part", "name": { "str": "aisle with lights" }, "item": "sheet_metal_lit", "location": "center", + "symbols": { "horizontal": "#", "vertical": "H" }, "symbol": "=", "broken_symbol": "#", "color": "white", @@ -242,11 +243,5 @@ "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } }, "flags": [ "AISLE", "BOARDABLE", "AISLE_LIGHT", "ENABLED_DRAINS_EPOWER" ] - }, - { - "id": "lit_aisle_vertical", - "copy-from": "lit_aisle_horizontal", - "type": "vehicle_part", - "symbol": "H" } ] diff --git a/data/json/vehicleparts/mirrors.json b/data/json/vehicleparts/mirrors.json index 4af3c6720f0ab..d5b196455341b 100644 --- a/data/json/vehicleparts/mirrors.json +++ b/data/json/vehicleparts/mirrors.json @@ -1,10 +1,11 @@ [ { "type": "vehicle_part", - "abstract": "wing_mirror_abstract", + "id": "wing_mirror", "name": { "str": "wing mirror" }, "symbol": "o", "color": "light_cyan", + "symbols": { "left": "o", "right": "o" }, "broken_symbol": "*", "broken_color": "dark_gray", "damage_modifier": 10, @@ -21,26 +22,6 @@ "flags": [ "VISION", "PROTRUSION", "UNMOUNT_ON_DAMAGE", "FOLDABLE" ], "breaks_into": [ { "item": "glass_shard", "count": [ 0, 16 ] } ] }, - { - "copy-from": "wing_mirror_abstract", - "id": "wing_mirror", - "symbol": "o", - "type": "vehicle_part" - }, - { - "copy-from": "wing_mirror_abstract", - "id": "wing_mirror_left", - "looks_like": "wing_mirror", - "symbol": "o", - "type": "vehicle_part" - }, - { - "copy-from": "wing_mirror_abstract", - "id": "wing_mirror_right", - "looks_like": "wing_mirror", - "symbol": "o", - "type": "vehicle_part" - }, { "type": "vehicle_part", "id": "inboard_mirror", diff --git a/data/json/vehicleparts/vehicle_parts.json b/data/json/vehicleparts/vehicle_parts.json index c6022bf68fe43..385f0c851441b 100644 --- a/data/json/vehicleparts/vehicle_parts.json +++ b/data/json/vehicleparts/vehicle_parts.json @@ -327,9 +327,9 @@ }, { "type": "vehicle_part", - "id": "aisle_horizontal", + "id": "aisle", "name": { "str": "aisle" }, - "symbol": "=", + "symbols": { "horizontal": "H", "vertical": "=" }, "looks_like": "t_metal_floor", "color": "white", "broken_symbol": "#", @@ -349,31 +349,9 @@ }, { "type": "vehicle_part", - "id": "aisle_vertical", - "name": { "str": "aisle" }, - "symbol": "H", - "looks_like": "aisle_horizontal", - "color": "white", - "broken_symbol": "#", - "broken_color": "light_gray", - "durability": 400, - "description": "An aisle.", - "item": "sheet_metal", - "location": "center", - "requirements": { - "install": { "skills": [ [ "mechanics", 1 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] }, - "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - }, - "flags": [ "AISLE", "BOARDABLE" ], - "breaks_into": "ig_vp_sheet_metal", - "damage_reduction": { "all": 28 } - }, - { - "type": "vehicle_part", - "id": "wooden_aisle_horizontal", + "id": "wooden_aisle", "name": { "str": "wooden aisle" }, - "symbol": "=", + "symbols": { "horizontal": "H", "vertical": "=" }, "looks_like": "t_floor", "color": "brown", "broken_symbol": "#", @@ -391,28 +369,6 @@ "breaks_into": [ { "item": "splinter", "count": [ 7, 9 ] }, { "item": "nail", "charges": [ 5, 10 ] } ], "damage_reduction": { "all": 16 } }, - { - "type": "vehicle_part", - "id": "wooden_aisle_vertical", - "name": { "str": "wooden aisle" }, - "symbol": "H", - "looks_like": "wooden_aisle_horizontal", - "color": "brown", - "broken_symbol": "#", - "broken_color": "brown", - "durability": 200, - "description": "An aisle.", - "item": "frame_wood", - "location": "center", - "requirements": { - "install": { "skills": [ [ "mechanics", 1 ] ], "time": "30 m", "using": [ [ "vehicle_nail_install", 1 ] ] }, - "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "15 m", "using": [ [ "vehicle_nail_removal", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "adhesive", 2 ] ] } - }, - "flags": [ "AISLE", "BOARDABLE" ], - "breaks_into": [ { "item": "splinter", "count": [ 7, 9 ] }, { "item": "nail", "charges": [ 5, 10 ] } ], - "damage_reduction": { "all": 16 } - }, { "type": "vehicle_part", "id": "trunk_floor", @@ -500,9 +456,9 @@ }, { "type": "vehicle_part", - "id": "blade_horizontal", + "id": "blade", "name": { "str": "blade" }, - "symbol": "-", + "symbols": { "horizontal": "-", "vertical": "|" }, "color": "white", "broken_symbol": "x", "broken_color": "white", @@ -520,29 +476,6 @@ "flags": [ "SHARP", "PROTRUSION", "FOLDABLE" ], "breaks_into": [ { "item": "steel_chunk", "prob": 50 } ] }, - { - "type": "vehicle_part", - "id": "blade_vertical", - "name": { "str": "blade" }, - "symbol": "|", - "color": "white", - "broken_symbol": "x", - "broken_color": "white", - "damage_modifier": 250, - "durability": 200, - "description": "A blade, welded to the vehicle, for cutting up zombies.", - "item": "blade", - "folded_volume": "750 ml", - "location": "structure", - "requirements": { - "install": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] }, - "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, - "repair": { "skills": [ [ "mechanics", 3 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - }, - "flags": [ "SHARP", "PROTRUSION", "FOLDABLE" ], - "breaks_into": [ { "item": "steel_chunk", "prob": 50 } ], - "damage_reduction": { "all": 12 } - }, { "type": "vehicle_part", "id": "spike", diff --git a/data/json/vehicleparts/windshields.json b/data/json/vehicleparts/windshields.json index 466805664b7e4..e472ecd61af85 100644 --- a/data/json/vehicleparts/windshields.json +++ b/data/json/vehicleparts/windshields.json @@ -1,7 +1,26 @@ [ { - "abstract": "windshield_abstract", + "id": "windshield", + "type": "vehicle_part", "breaks_into": [ { "count": [ 25, 50 ], "item": "glass_shard" } ], + "symbol": "\"", + "symbols": { + "nw": "y", + "ne": "u", + "sw": "b", + "se": "n", + "nw_edge": "y", + "ne_edge": "u", + "sw_edge": "b", + "se_edge": "n", + "vertical": "j", + "vertical_left": "j", + "vertical_right": "H", + "horizontal_front": "T", + "horizontal_front_edge": "^", + "horizontal_rear": "B", + "horizontal_rear_edge": "=" + }, "broken_color": "light_gray", "broken_symbol": "0", "color": "light_cyan", @@ -17,13 +36,30 @@ "install": { "skills": [ [ "mechanics", 1 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] }, "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, "repair": { "skills": [ [ "mechanics", 2 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - }, - "symbol": "\"", - "type": "vehicle_part" + } }, { - "abstract": "reinforced_windshield_abstract", + "id": "reinforced_windshield", + "type": "vehicle_part", "breaks_into": [ { "count": [ 25, 50 ], "item": "glass_shard" }, { "count": [ 4, 8 ], "item": "wire" } ], + "symbol": "\"", + "symbols": { + "nw": "y", + "ne": "u", + "sw": "b", + "se": "n", + "nw_edge": "y", + "ne_edge": "u", + "sw_edge": "b", + "se_edge": "n", + "vertical": "j", + "vertical_left": "j", + "vertical_right": "H", + "horizontal_front": "T", + "horizontal_front_edge": "^", + "horizontal_rear": "B", + "horizontal_rear_edge": "=" + }, "broken_color": "light_gray", "broken_symbol": "0", "color": "light_blue", @@ -40,116 +76,6 @@ "install": { "skills": [ [ "mechanics", 4 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] }, "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_weld_removal", 1 ] ] }, "repair": { "skills": [ [ "mechanics", 5 ] ], "time": "60 m", "using": [ [ "welding_standard", 5 ] ] } - }, - "symbol": "\"", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield", - "symbol": "\"", - "type": "vehicle_part" - }, - { - "copy-from": "reinforced_windshield_abstract", - "id": "reinforced_windshield", - "symbol": "\"", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_nw", - "symbol": "y", - "type": "vehicle_part" - }, - { - "copy-from": "reinforced_windshield_abstract", - "id": "reinforced_windshield_nw", - "symbol": "y", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_ne", - "symbol": "u", - "type": "vehicle_part" - }, - { - "copy-from": "reinforced_windshield_abstract", - "id": "reinforced_windshield_ne", - "symbol": "u", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_sw", - "symbol": "b", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_se", - "symbol": "n", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_nw_edge", - "symbol": "y", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_ne_edge", - "symbol": "u", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_sw_edge", - "symbol": "b", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_se_edge", - "symbol": "n", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_vertical_left", - "symbol": "j", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_vertical_right", - "symbol": "H", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_horizontal_front_edge", - "symbol": "^", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_horizontal_front", - "symbol": "T", - "type": "vehicle_part" - }, - { - "copy-from": "reinforced_windshield_abstract", - "id": "reinforced_windshield_horizontal_front", - "symbol": "T", - "type": "vehicle_part" - }, - { - "copy-from": "windshield_abstract", - "id": "windshield_horizontal_rear", - "symbol": "B", - "type": "vehicle_part" + } } ] diff --git a/data/json/vehicles/cars.json b/data/json/vehicles/cars.json index a31ae5273ffba..70c6c42d99fde 100644 --- a/data/json/vehicles/cars.json +++ b/data/json/vehicles/cars.json @@ -27,8 +27,8 @@ ] }, { "x": 0, "y": 1, "parts": [ "frame_vertical_2", "roof", "reclining_seat", "seatbelt" ] }, - { "x": 0, "y": -1, "parts": [ "frame_vertical", "door_front_left" ] }, - { "x": 0, "y": 2, "parts": [ "frame_vertical", "door_front_right" ] }, + { "x": 0, "y": -1, "parts": [ "frame_vertical", "door_nw" ] }, + { "x": 0, "y": 2, "parts": [ "frame_vertical", "door_ne" ] }, { "x": 1, "y": -1, "parts": [ "frame_horizontal", "windshield_nw" ] }, { "x": 1, "y": 0, "parts": [ "frame_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": 1, "parts": [ "frame_horizontal", "windshield_horizontal_front" ] }, @@ -109,9 +109,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 2, "part": "frame_vertical" }, - { "x": 0, "y": 2, "part": "door_front_right" }, + { "x": 0, "y": 2, "part": "door_ne" }, { "x": 1, "y": 0, "part": "frame_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "frame_horizontal" }, @@ -263,9 +263,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 2, "part": "frame_vertical" }, - { "x": 0, "y": 2, "part": "door_front_right" }, + { "x": 0, "y": 2, "part": "door_ne" }, { "x": -1, "y": 0, "part": "frame_vertical_2" }, { "x": -1, "y": 0, "part": "seat" }, { "x": -1, "y": 0, "part": "seatbelt" }, @@ -275,9 +275,9 @@ { "x": -1, "y": 1, "part": "seatbelt" }, { "x": -1, "y": 1, "part": "roof" }, { "x": -1, "y": -1, "part": "frame_vertical" }, - { "x": -1, "y": -1, "part": "door_rear_left" }, + { "x": -1, "y": -1, "part": "door_sw" }, { "x": -1, "y": 2, "part": "frame_vertical" }, - { "x": -1, "y": 2, "part": "door_rear_right" }, + { "x": -1, "y": 2, "part": "door_se" }, { "x": 1, "y": 0, "part": "frame_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "frame_horizontal" }, @@ -360,9 +360,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 2, "part": "frame_vertical" }, - { "x": 0, "y": 2, "part": "door_front_right" }, + { "x": 0, "y": 2, "part": "door_ne" }, { "x": -1, "y": 0, "part": "frame_vertical_2" }, { "x": -1, "y": 0, "part": "seat" }, { "x": -1, "y": 0, "part": "seatbelt" }, @@ -372,9 +372,9 @@ { "x": -1, "y": 1, "part": "seatbelt" }, { "x": -1, "y": 1, "part": "roof" }, { "x": -1, "y": -1, "part": "frame_vertical" }, - { "x": -1, "y": -1, "part": "door_rear_left" }, + { "x": -1, "y": -1, "part": "door_sw" }, { "x": -1, "y": 2, "part": "frame_vertical" }, - { "x": -1, "y": 2, "part": "door_rear_right" }, + { "x": -1, "y": 2, "part": "door_se" }, { "x": 1, "y": 0, "part": "frame_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "frame_horizontal" }, @@ -506,8 +506,8 @@ { "x": 0, "y": 2, "parts": [ "frame_vertical", "door" ] }, { "x": -1, "y": 0, "parts": [ "frame_vertical_2", "seat", "seatbelt", "roof" ] }, { "x": -1, "y": 1, "parts": [ "frame_vertical_2", "seat", "seatbelt", "roof" ] }, - { "x": -1, "y": -1, "parts": [ "frame_vertical", "door_front_left" ] }, - { "x": -1, "y": 2, "parts": [ "frame_vertical", "door_front_right" ] }, + { "x": -1, "y": -1, "parts": [ "frame_vertical", "door_nw" ] }, + { "x": -1, "y": 2, "parts": [ "frame_vertical", "door_ne" ] }, { "x": 1, "y": 0, "parts": [ "frame_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": 1, "parts": [ "frame_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": -1, "parts": [ "frame_vertical", "windshield_nw" ] }, @@ -564,9 +564,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_rear_left" }, + { "x": 0, "y": -1, "part": "door_sw" }, { "x": 0, "y": 2, "part": "frame_vertical" }, - { "x": 0, "y": 2, "part": "door_rear_right" }, + { "x": 0, "y": 2, "part": "door_se" }, { "x": 1, "y": 0, "part": "frame_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "frame_horizontal" }, @@ -635,9 +635,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 2, "part": "frame_vertical" }, - { "x": 0, "y": 2, "part": "door_front_right" }, + { "x": 0, "y": 2, "part": "door_ne" }, { "x": 1, "y": 0, "part": "frame_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "frame_horizontal" }, @@ -662,7 +662,7 @@ { "x": 2, "y": 2, "parts": [ "wheel_mount_medium_steerable", "wheel" ] }, { "x": 2, "y": 2, "part": "headlight" }, { "x": -1, "y": -1, "part": "frame_vertical" }, - { "x": -1, "y": -1, "part": "door_rear_left" }, + { "x": -1, "y": -1, "part": "door_sw" }, { "x": -1, "y": 0, "part": "frame_vertical_2" }, { "x": -1, "y": 0, "part": "seat" }, { "x": -1, "y": 0, "part": "seatbelt" }, @@ -672,7 +672,7 @@ { "x": -1, "y": 1, "part": "seatbelt" }, { "x": -1, "y": 1, "part": "roof" }, { "x": -1, "y": 2, "part": "frame_vertical" }, - { "x": -1, "y": 2, "part": "door_rear_right" }, + { "x": -1, "y": 2, "part": "door_se" }, { "x": -2, "y": -1, "part": "frame_sw" }, { "x": -2, "y": -1, "parts": [ "wheel_mount_medium", "wheel" ] }, { "x": -2, "y": -1, "part": "tank_medium", "fuel": "gasoline" }, @@ -722,9 +722,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 2, "part": "frame_vertical" }, - { "x": 0, "y": 2, "part": "door_front_right" }, + { "x": 0, "y": 2, "part": "door_ne" }, { "x": 1, "y": 0, "part": "frame_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "frame_horizontal" }, @@ -801,9 +801,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_rear_left" }, + { "x": 0, "y": -1, "part": "door_sw" }, { "x": 0, "y": 2, "part": "frame_vertical" }, - { "x": 0, "y": 2, "part": "door_rear_right" }, + { "x": 0, "y": 2, "part": "door_se" }, { "x": -1, "y": 0, "part": "frame_vertical_2" }, { "x": -1, "y": 0, "part": "windshield" }, { "x": -1, "y": 0, "part": "roof" }, @@ -894,9 +894,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "xlframe_vertical" }, - { "x": 0, "y": -1, "part": "door_rear_left" }, + { "x": 0, "y": -1, "part": "door_sw" }, { "x": 0, "y": 2, "part": "xlframe_vertical" }, - { "x": 0, "y": 2, "part": "door_rear_right" }, + { "x": 0, "y": 2, "part": "door_se" }, { "x": 1, "y": 0, "part": "xlframe_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "xlframe_horizontal" }, @@ -960,8 +960,8 @@ { "x": 0, "y": 0, "parts": [ "xlframe_vertical_2", "seat", "seatbelt", "controls" ] }, { "x": 0, "y": 0, "parts": [ "dashboard", "vehicle_alarm", "horn_car", "roof" ] }, { "x": 0, "y": 1, "parts": [ "xlframe_vertical_2", "seat", "seatbelt", "roof" ] }, - { "x": 0, "y": -1, "parts": [ "xlframe_vertical", "door_front_right" ] }, - { "x": 0, "y": 2, "parts": [ "xlframe_vertical", "door_front_left" ] }, + { "x": 0, "y": -1, "parts": [ "xlframe_vertical", "door_ne" ] }, + { "x": 0, "y": 2, "parts": [ "xlframe_vertical", "door_nw" ] }, { "x": 1, "y": 0, "parts": [ "xlframe_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": 1, "parts": [ "xlframe_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": -1, "parts": [ "xlframe_vertical", "windshield_nw" ] }, @@ -1019,9 +1019,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "xlframe_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 2, "part": "xlframe_vertical" }, - { "x": 0, "y": 2, "part": "door_front_right" }, + { "x": 0, "y": 2, "part": "door_ne" }, { "x": -1, "y": 0, "part": "xlframe_vertical_2" }, { "x": -1, "y": 0, "part": "seat" }, { "x": -1, "y": 0, "part": "seatbelt" }, @@ -1031,9 +1031,9 @@ { "x": -1, "y": 1, "part": "seatbelt" }, { "x": -1, "y": 1, "part": "roof" }, { "x": -1, "y": -1, "part": "xlframe_vertical" }, - { "x": -1, "y": -1, "part": "door_rear_left" }, + { "x": -1, "y": -1, "part": "door_sw" }, { "x": -1, "y": 2, "part": "xlframe_vertical" }, - { "x": -1, "y": 2, "part": "door_rear_right" }, + { "x": -1, "y": 2, "part": "door_se" }, { "x": 1, "y": 0, "part": "xlframe_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "xlframe_horizontal" }, @@ -1122,10 +1122,10 @@ { "x": -1, "y": 0, "part": "headlight" }, { "x": 0, "y": 1, "part": "xlframe_cross" }, { "x": 0, "y": 1, "parts": [ "wheel_mount_medium_steerable", "wheel" ] }, - { "x": 0, "y": 1, "part": "door_front_left" }, + { "x": 0, "y": 1, "part": "door_ne" }, { "x": 0, "y": -1, "part": "xlframe_cross" }, { "x": 0, "y": -1, "parts": [ "wheel_mount_medium_steerable", "wheel" ] }, - { "x": 0, "y": -1, "part": "door_front_right" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 2, "part": "xlframe_ne" }, { "x": 0, "y": -2, "part": "xlframe_nw" }, { "x": -2, "y": 0, "part": "xlframe_horizontal" }, @@ -1134,9 +1134,9 @@ { "x": -2, "y": 0, "part": "windshield_horizontal_rear" }, { "x": -2, "y": 0, "part": "roof" }, { "x": -2, "y": 1, "part": "xlframe_cross" }, - { "x": -2, "y": 1, "part": "windshield" }, + { "x": -2, "y": 1, "part": "windshield_se" }, { "x": -2, "y": -1, "part": "xlframe_cross" }, - { "x": -2, "y": -1, "part": "windshield" }, + { "x": -2, "y": -1, "part": "windshield_sw" }, { "x": -2, "y": 2, "part": "xlframe_sw" }, { "x": -2, "y": 2, "part": "solar_panel_v2" }, { "x": -2, "y": -2, "part": "xlframe_se" }, @@ -1146,11 +1146,11 @@ { "x": -3, "y": -2, "part": "xlframe_se" }, { "x": -3, "y": -2, "part": "solar_panel_v2" }, { "x": 1, "y": 0, "part": "xlframe_horizontal" }, - { "x": 1, "y": 0, "part": "windshield" }, + { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "xlframe_ne" }, - { "x": 1, "y": 1, "part": "windshield" }, + { "x": 1, "y": 1, "part": "windshield_ne" }, { "x": 1, "y": -1, "part": "xlframe_nw" }, - { "x": 1, "y": -1, "part": "windshield" }, + { "x": 1, "y": -1, "part": "windshield_nw" }, { "x": -3, "y": 0, "part": "xlframe_horizontal" }, { "x": -3, "y": 0, "part": "solar_panel_v2" }, { "x": -3, "y": 1, "part": "xlframe_se" }, @@ -1198,9 +1198,9 @@ { "x": 0, "y": 1, "part": "seatbelt" }, { "x": 0, "y": 1, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 2, "part": "frame_vertical" }, - { "x": 0, "y": 2, "part": "door_front_right" }, + { "x": 0, "y": 2, "part": "door_ne" }, { "x": -1, "y": 0, "part": "frame_vertical_2" }, { "x": -1, "y": 0, "part": "seat" }, { "x": -1, "y": 0, "part": "seatbelt" }, @@ -1210,9 +1210,9 @@ { "x": -1, "y": 1, "part": "seatbelt" }, { "x": -1, "y": 1, "part": "roof" }, { "x": -1, "y": -1, "part": "frame_vertical" }, - { "x": -1, "y": -1, "part": "door_rear_left" }, + { "x": -1, "y": -1, "part": "door_sw" }, { "x": -1, "y": 2, "part": "frame_vertical" }, - { "x": -1, "y": 2, "part": "door_rear_right" }, + { "x": -1, "y": 2, "part": "door_se" }, { "x": 1, "y": 0, "part": "frame_horizontal" }, { "x": 1, "y": 0, "part": "windshield_horizontal_front" }, { "x": 1, "y": 1, "part": "frame_horizontal" }, @@ -1304,14 +1304,14 @@ { "x": 0, "y": 0, "parts": [ "stereo", "horn_car", "storage_battery" ] }, { "x": 0, "y": 1, "parts": [ "xlframe_vertical_2", "roof" ] }, { "x": 0, "y": 1, "parts": [ "reclining_seat", "seatbelt", "storage_battery" ] }, - { "x": 0, "y": -1, "parts": [ "xlframe_vertical", "door_front_left" ] }, - { "x": 0, "y": 2, "parts": [ "xlframe_vertical", "door_front_right" ] }, + { "x": 0, "y": -1, "parts": [ "xlframe_vertical", "door_nw" ] }, + { "x": 0, "y": 2, "parts": [ "xlframe_vertical", "door_ne" ] }, { "x": -1, "y": 0, "parts": [ "xlframe_vertical_2", "roof" ] }, { "x": -1, "y": 0, "parts": [ "seat", "seatbelt" ] }, { "x": -1, "y": 1, "parts": [ "xlframe_vertical_2", "roof" ] }, { "x": -1, "y": 1, "parts": [ "seat", "seatbelt" ] }, - { "x": -1, "y": -1, "parts": [ "xlframe_vertical", "door_rear_left" ] }, - { "x": -1, "y": 2, "parts": [ "xlframe_vertical", "door_rear_right" ] }, + { "x": -1, "y": -1, "parts": [ "xlframe_vertical", "door_sw" ] }, + { "x": -1, "y": 2, "parts": [ "xlframe_vertical", "door_se" ] }, { "x": 1, "y": -1, "parts": [ "xlframe_horizontal", "windshield_nw" ] }, { "x": 1, "y": 0, "parts": [ "xlframe_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": 1, "parts": [ "xlframe_horizontal", "windshield_horizontal_front" ] }, @@ -1378,8 +1378,8 @@ { "x": 0, "y": 0, "parts": [ "stereo", "horn_car", "storage_battery" ] }, { "x": 0, "y": 1, "parts": [ "xlframe_vertical_2", "roof" ] }, { "x": 0, "y": 1, "parts": [ "reclining_seat", "seatbelt" ] }, - { "x": 0, "y": -1, "parts": [ "xlframe_vertical", "door_front_left" ] }, - { "x": 0, "y": 2, "parts": [ "xlframe_vertical", "door_front_right" ] }, + { "x": 0, "y": -1, "parts": [ "xlframe_vertical", "door_nw" ] }, + { "x": 0, "y": 2, "parts": [ "xlframe_vertical", "door_ne" ] }, { "x": 1, "y": -1, "parts": [ "xlframe_horizontal", "windshield_nw" ] }, { "x": 1, "y": 0, "parts": [ "xlframe_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": 1, "parts": [ "xlframe_horizontal", "windshield_horizontal_front" ] }, @@ -1397,12 +1397,12 @@ "y": 2, "parts": [ "xlframe_ne", "halfboard_ne", "wheel_mount_medium_steerable", "wheel", "headlight" ] }, - { "x": -1, "y": -1, "parts": [ "xlframe_vertical", "door_rear_left" ] }, + { "x": -1, "y": -1, "parts": [ "xlframe_vertical", "door_sw" ] }, { "x": -1, "y": 0, "parts": [ "xlframe_vertical_2", "roof" ] }, { "x": -1, "y": 0, "parts": [ "seat", "seatbelt" ] }, { "x": -1, "y": 1, "parts": [ "xlframe_vertical_2", "roof" ] }, { "x": -1, "y": 1, "parts": [ "seat", "seatbelt" ] }, - { "x": -1, "y": 2, "parts": [ "xlframe_vertical", "door_rear_right" ] }, + { "x": -1, "y": 2, "parts": [ "xlframe_vertical", "door_se" ] }, { "x": -2, "y": -1, "parts": [ "xlframe_vertical", "halfboard_vertical_left" ] }, { "x": -2, "y": 0, "parts": [ "xlframe_vertical", "trunk", "roof", "solar_panel" ] }, { "x": -2, "y": 1, "parts": [ "xlframe_vertical", "trunk", "roof", "solar_panel" ] }, diff --git a/data/json/vehicles/custom_vehicles.json b/data/json/vehicles/custom_vehicles.json index 5f2edc0e905cb..e4b1fa0503374 100644 --- a/data/json/vehicles/custom_vehicles.json +++ b/data/json/vehicles/custom_vehicles.json @@ -13,9 +13,9 @@ { "x": 0, "y": 0, "parts": [ "frame_vertical_2", "reclining_seat", "seatbelt" ] }, { "x": 0, "y": 0, "parts": [ "controls", "dashboard", "vehicle_clock", "vehicle_alarm" ] }, { "x": 0, "y": 0, "parts": [ "horn_car", "roof" ] }, - { "x": 0, "y": -1, "parts": [ "frame_vertical", "door_front_left", "roof" ] }, + { "x": 0, "y": -1, "parts": [ "frame_vertical", "door_nw", "roof" ] }, { "x": 0, "y": 1, "parts": [ "frame_vertical_2", "reclining_seat", "seatbelt", "roof" ] }, - { "x": 0, "y": 2, "parts": [ "frame_vertical", "door_front_right", "roof" ] }, + { "x": 0, "y": 2, "parts": [ "frame_vertical", "door_ne", "roof" ] }, { "x": 1, "y": -1, "parts": [ "frame_vertical", "windshield_nw" ] }, { "x": 1, "y": 0, "parts": [ "frame_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": 1, "parts": [ "frame_horizontal", "windshield_horizontal_front" ] }, @@ -64,9 +64,9 @@ "parts": [ { "x": 0, "y": 0, "parts": [ "frame_vertical_2", "seat", "seatbelt", "controls" ] }, { "x": 0, "y": 0, "parts": [ "dashboard", "stereo", "horn_car", "roof" ] }, - { "x": 0, "y": -1, "parts": [ "frame_vertical", "door_front_left" ] }, + { "x": 0, "y": -1, "parts": [ "frame_vertical", "door_nw" ] }, { "x": 0, "y": 1, "parts": [ "frame_vertical_2", "seat", "seatbelt", "roof" ] }, - { "x": 0, "y": 2, "parts": [ "frame_vertical", "door_front_right" ] }, + { "x": 0, "y": 2, "parts": [ "frame_vertical", "door_ne" ] }, { "x": 1, "y": -1, "parts": [ "frame_vertical", "windshield_nw", "rebar_plate" ] }, { "x": 1, "y": 0, "parts": [ "frame_horizontal", "windshield_horizontal_front" ] }, { "x": 1, "y": 0, "part": "rebar_plate" }, @@ -75,9 +75,9 @@ { "x": 1, "y": 2, "parts": [ "frame_vertical", "windshield_ne", "rebar_plate" ] }, { "x": 2, "y": -1, "parts": [ "frame_nw", "halfboard_nw", "wheel_mount_medium_steerable" ] }, { "x": 2, "y": -1, "parts": [ "wheel", "spring_plate", "headlight" ] }, - { "x": 2, "y": 0, "parts": [ "frame_horizontal", "halfboard_horizontal", "engine_v6" ] }, - { "x": 2, "y": 0, "parts": [ "alternator_car", "battery_car" ] }, - { "x": 2, "y": 1, "parts": [ "frame_horizontal", "halfboard_horizontal" ] }, + { "x": 2, "y": 0, "parts": [ "frame_horizontal", "halfboard_horizontal_front" ] }, + { "x": 2, "y": 0, "parts": [ "engine_v6", "alternator_car", "battery_car" ] }, + { "x": 2, "y": 1, "parts": [ "frame_horizontal", "halfboard_horizontal_front" ] }, { "x": 2, "y": 2, "parts": [ "frame_ne", "halfboard_ne", "wheel_mount_medium_steerable" ] }, { "x": 2, "y": 2, "parts": [ "wheel", "spring_plate", "headlight" ] }, { "x": 3, "y": -1, "part": "ram_spiked" }, diff --git a/data/json/vehicles/vans_busses.json b/data/json/vehicles/vans_busses.json index 8d2f47eb1d0f3..5aab23a4f0e5a 100644 --- a/data/json/vehicles/vans_busses.json +++ b/data/json/vehicles/vans_busses.json @@ -165,9 +165,9 @@ { "x": 0, "y": 2, "part": "seatbelt" }, { "x": 0, "y": 2, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": 3, "part": "frame_vertical" }, - { "x": 0, "y": 3, "part": "door_front_right" }, + { "x": 0, "y": 3, "part": "door_ne" }, { "x": 1, "y": 1, "part": "frame_horizontal" }, { "x": 1, "y": 1, "part": "windshield_horizontal_front" }, { "x": 1, "y": 0, "part": "frame_horizontal" }, @@ -1707,10 +1707,10 @@ { "x": 0, "y": 0, "part": "horn_car" }, { "x": 0, "y": 0, "part": "roof" }, { "x": 0, "y": 3, "part": "frame_vertical" }, - { "x": 0, "y": 3, "part": "door_front_right" }, + { "x": 0, "y": 3, "part": "door_ne" }, { "x": 0, "y": 3, "part": "roof" }, { "x": 0, "y": -1, "part": "frame_vertical" }, - { "x": 0, "y": -1, "part": "door_front_left" }, + { "x": 0, "y": -1, "part": "door_nw" }, { "x": 0, "y": -1, "part": "roof" }, { "x": 1, "y": 1, "part": "frame_vertical_2" }, { "x": 1, "y": 1, "part": "windshield_horizontal_front" }, @@ -1764,7 +1764,7 @@ { "x": -2, "y": 0, "part": "seat" }, { "x": -2, "y": 0, "part": "roof" }, { "x": -2, "y": 3, "part": "frame_vertical" }, - { "x": -2, "y": 3, "part": "door_front_right" }, + { "x": -2, "y": 3, "part": "door_ne" }, { "x": -2, "y": 3, "part": "v_curtain" }, { "x": -2, "y": 3, "part": "roof" }, { "x": -2, "y": -1, "part": "frame_vertical" }, diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 4e549d5940ed5..3eb632bcd0825 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -1828,7 +1828,11 @@ Vehicle components when installed on a vehicle. ```C++ "id": "wheel", // Unique identifier "name": "wheel", // Displayed name -"symbol": "0", // ASCII character displayed when part is working +"symbol": "0", // (Optional) ASCII character displayed when part is working +"symbols": { // (Optional) ASCII characters displayed when the part is working, + "left": "0", "right": "0" // listed by variant suffix. See below for more on variants +"standard_symbols: false, // (Optional) Use the standard ASCII characters for variants + // must have one of symbol, symbols, or standard_symbols "looks_like": "small_wheel", // (Optional) hint to tilesets if this part has no tile, // use the looks_like tile. "color": "dark_gray", // Color used when part is working @@ -1887,6 +1891,28 @@ Vehicle components when installed on a vehicle. }, ``` +#### Symbols and Variants +Vehicle parts can have multiple identical variants that use different symbols (and potentially +tileset sprites). They are declared by the `"standard_symbols"` boolean or the "symbols" object. +Variants are used in the vehicle prototype as a suffix following the part id (ie `id_variant`), such as `"frame_nw"` or `"halfboard_cover"`. + +setting `"standard_symbols"` to true gives the vehicle the following variants: +``` +"cover": "^", "cross": "c", "horizontal": "h", "horizontal_2": "=", "vertical": "j", +"vertical_2": "H", "ne": "u", "nw": "y", "se": "n", "sw": "b" +``` + +Otherwise, variants can use any of the following suffices: +``` +"cover", "cross", "cross_unconnected", "front", "rear", "left," "right", +"horizontal", "horizontal_front", "horizontal_front_edge", +"horizontal_rear", "horizontal_rear_edge", +"horizontal_2", "horizontal_2_front", "horizontal_2_rear", +"vertical", "vertical_right", "vertical_left", "vertical_T_right", "vertical_T_left", +"vertical_2", "vertical_2_right", "vertical_2_left", +"ne", "nw", "se", "sw", "ne_edge", "nw_edge", "se_edge", "sw_edge" +``` + Unless specified as optional, the following fields are mandatory for parts with appropriate flag and are ignored otherwise. #### The following optional fields are specific to CARGO or FLUIDTANK parts. ```c++ @@ -2018,7 +2044,8 @@ See also VEHICLE_JSON.md {"x": 0, "y": 0, "part": "box"}, // Part definition, positive x direction is to the left, positive y is to the right {"x": 0, "y": 0, "part": "casters"} // See vehicle_parts.json for part ids ] - /* Important! Vehicle parts must be defined in the same order you would install + /* Important! Vehicle parts must be defined in the + * same order you would install * them in the game (ie, frames and mount points first). * You also cannot break the normal rules of installation * (you can't stack non-stackable part flags). */ diff --git a/doc/VEHICLES_JSON.md b/doc/VEHICLES_JSON.md index 7ff5304542834..05f61b0ce5a92 100644 --- a/doc/VEHICLES_JSON.md +++ b/doc/VEHICLES_JSON.md @@ -22,10 +22,10 @@ Vehicle prototypes do not currently accept copy-from { "x": 0, "y": 1, "parts": [ "frame", "seat" ] }, // Arrays of parts on the same space { "x": 0, "y": 1, "parts": [ { "part": "tank", "fuel": "gasoline" }, "battery_car" }, { "x": 0, "y": 1, "part": "stereo" }, // parts arrays and part may be mixed on the same space - { "x": 1, "y": 0, "parts": [ "frame", "wheel" ] }, - { "x": 1, "y": 1, "parts": [ "frame", "wheel" ] }, - { "x": -1, "y": 0, "parts": [ "frame", "wheel" ] }, - { "x": -1, "y": 1, "parts": [ "frame", "wheel" ] } + { "x": 1, "y": 0, "parts": [ "frame_cover", "wheel_mount_medium", "wheel" ] }, + { "x": 1, "y": 1, "parts": [ "frame_cross", "wheel_mount_medium", "wheel" ] }, + { "x": -1, "y": 0, "parts": [ "frame_cover", "wheel_mount_medium", "wheel" ] }, + { "x": -1, "y": 1, "parts": [ "frame_cross", "wheel_mount_medium", "wheel" ] } ], "items": [ // Item spawn list { "x": 0, "y": 0, "items": "helmet_army" }, // individual item @@ -51,6 +51,11 @@ with any of the optional keys "ammo", "ammo_types", "ammo_qty", or "fuel" as ab Several different lines can have the same X, Y co-ordinates and each one adds additional parts to that location. Parts must be added in the correct order ie: A wheel hub must be added prior to the wheel, but after the frame. +#### PARTID and variants +Some parts can be installed with different symbols (and tileset sprites) in different locations. The different symbols can either be different parts (usually generated with copy-from) or the same part with a `"symbols"` or `"standard_symbols"` entry. In the latter case, the different symbols are variants of the part. + +If a part has variants, the specific variant can be specified in the vehicle prototype by appending the variant to the part id after a `_` symbol. Thus, `"frame_cross"` is the `"cross"` variant of the `"frame"` part. + ### Items list The items list contains an arbitrary number of lines. Each line is of the form: { "x": X, "y": Y, TYPE: DATA }, diff --git a/src/cata_tiles.cpp b/src/cata_tiles.cpp index 02ade2d9a7caa..7eb5b675d0ee1 100644 --- a/src/cata_tiles.cpp +++ b/src/cata_tiles.cpp @@ -1553,11 +1553,19 @@ const tile_type *cata_tiles::find_tile_looks_like( std::string &id, TILE_CATEGOR } else if( category == C_VEHICLE_PART ) { // vehicle parts start with vp_ for their tiles, but not their IDs const vpart_id new_vpid( looks_like.substr( 3 ) ); - if( !new_vpid.is_valid() ) { - return nullptr; + // check the base id for a vehicle with variant parts + vpart_id base_vpid; + std::string variant_id; + std::tie( base_vpid, variant_id ) = get_vpart_id_variant( new_vpid ); + if( base_vpid.is_valid() ) { + looks_like = "vp_" + base_vpid.str(); + } else { + if( !new_vpid.is_valid() ) { + return nullptr; + } + const vpart_info &new_vpi = new_vpid.obj(); + looks_like = "vp_" + new_vpi.looks_like; } - const vpart_info &new_vpi = new_vpid.obj(); - looks_like = "vp_" + new_vpi.looks_like; } else if( category == C_ITEM ) { if( !item::type_is_defined( itype_id( looks_like ) ) ) { if( looks_like.substr( 0, 7 ) == "corpse_" ) { @@ -2676,10 +2684,10 @@ bool cata_tiles::draw_vpart( const tripoint &p, lit_level ll, int &height_3d, // with the vehicle part json ids // get the vpart_id char part_mod = 0; - const vpart_id &vp_id = veh.part_id_string( veh_part, part_mod ); + const std::string &vp_id = veh.part_id_string( veh_part, part_mod ); const int subtile = part_mod == 1 ? open_ : part_mod == 2 ? broken : 0; const int rotation = veh.face.dir(); - const std::string vpname = "vp_" + vp_id.str(); + const std::string vpname = "vp_" + vp_id; avatar &you = get_avatar(); if( !veh.forward_velocity() && !veh.player_in_control( you ) && here.check_seen_cache( p ) ) { diff --git a/src/editmap.cpp b/src/editmap.cpp index 5bd1f7ddb0f8b..e7b5639a85e03 100644 --- a/src/editmap.cpp +++ b/src/editmap.cpp @@ -644,7 +644,8 @@ void editmap::draw_main_ui_overlay() const vehicle &veh = vp->vehicle(); const int veh_part = vp->part_index(); char part_mod = 0; - const vpart_id &vp_id = veh.part_id_string( veh_part, part_mod ); + const vpart_id &vp_id = vpart_id( veh.part_id_string( veh_part, + part_mod ) ); const cata::optional cargopart = vp.part_with_feature( "CARGO", true ); bool draw_highlight = cargopart && !veh.get_items( cargopart->part_index() ).empty(); int veh_dir = veh.face.dir(); diff --git a/src/iuse.cpp b/src/iuse.cpp index 1cf0d36293a7b..a7fff9259bda7 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -9170,10 +9170,10 @@ int iuse::tow_attach( player *p, item *it, bool, const tripoint & ) } const vpart_id vpid( it->typeId().str() ); point vcoords = source_vp->mount(); - vehicle_part source_part( vpid, vcoords, item( *it ) ); + vehicle_part source_part( vpid, "", vcoords, item( *it ) ); source_veh->install_part( vcoords, source_part ); vcoords = target_vp->mount(); - vehicle_part target_part( vpid, vcoords, item( *it ) ); + vehicle_part target_part( vpid, "", vcoords, item( *it ) ); target_veh->install_part( vcoords, target_part ); if( p->has_item( *it ) ) { @@ -9406,13 +9406,13 @@ int iuse::cable_attach( player *p, item *it, bool, const tripoint & ) const vpart_id vpid( it->typeId().str() ); point vcoords = source_vp->mount(); - vehicle_part source_part( vpid, vcoords, item( *it ) ); + vehicle_part source_part( vpid, "", vcoords, item( *it ) ); source_part.target.first = target_global; source_part.target.second = here.getabs( target_veh->global_pos3() ); source_veh->install_part( vcoords, source_part ); vcoords = target_vp->mount(); - vehicle_part target_part( vpid, vcoords, item( *it ) ); + vehicle_part target_part( vpid, "", vcoords, item( *it ) ); tripoint source_global( it->get_var( "source_x", 0 ), it->get_var( "source_y", 0 ), it->get_var( "source_z", 0 ) ); diff --git a/src/json.cpp b/src/json.cpp index 393df82305c9a..ec21a481a915b 100644 --- a/src/json.cpp +++ b/src/json.cpp @@ -1935,7 +1935,7 @@ JsonValue JsonObject::get_member( const std::string &name ) const { const auto iter = positions.find( name ); if( !jsin || iter == positions.end() ) { - throw_error( "requested non-existing member \"" + name + "\"" ); + throw_error( "requested non-existing member \"" + name + "\" in " + str() ); } mark_visited( name ); return JsonValue( *jsin, iter->second ); diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 4e8cb57a7873d..3e82b67e09177 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -2639,6 +2639,8 @@ void vehicle_part::deserialize( JsonIn &jsin ) legacy_fuel = itype_id( dep->second.second ); } + std::tie( pid, variant ) = get_vpart_id_variant( pid ); + // if we don't know what type of part it is, it'll cause problems later. if( !pid.is_valid() ) { if( pid.str() == "wheel_underbody" ) { @@ -2648,6 +2650,9 @@ void vehicle_part::deserialize( JsonIn &jsin ) } } id = pid; + if( variant.empty() ) { + data.read( "variant", variant ); + } if( data.has_object( "base" ) ) { data.read( "base", base ); @@ -2725,6 +2730,9 @@ void vehicle_part::serialize( JsonOut &json ) const { json.start_object(); json.member( "id", id.str() ); + if( !variant.empty() ) { + json.member( "variant", variant ); + } json.member( "base", base ); json.member( "mount_dx", mount.x ); json.member( "mount_dy", mount.y ); @@ -2884,9 +2892,10 @@ void vehicle::deserialize( JsonIn &jsin ) } for( const vpart_reference &vp : get_any_parts( "TURRET" ) ) { - install_part( vp.mount(), vpart_id( "turret_mount" ), false ); + install_part( vp.mount(), vpart_id( "turret_mount" ) ); - //Forcibly set turrets' targeting mode to manual if no turret control unit is present on turret's tile on loading save + //Forcibly set turrets' targeting mode to manual if no turret control unit is + //present on turret's tile on loading save if( !has_part( global_part_pos3( vp.part() ), "TURRET_CONTROLS" ) ) { vp.part().enabled = false; } @@ -2899,23 +2908,23 @@ void vehicle::deserialize( JsonIn &jsin ) // Add vehicle mounts to cars that are missing them. for( const vpart_reference &vp : get_any_parts( "NEEDS_WHEEL_MOUNT_LIGHT" ) ) { if( vp.info().has_flag( "STEERABLE" ) ) { - install_part( vp.mount(), vpart_id( "wheel_mount_light_steerable" ), false ); + install_part( vp.mount(), vpart_id( "wheel_mount_light_steerable" ) ); } else { - install_part( vp.mount(), vpart_id( "wheel_mount_light" ), false ); + install_part( vp.mount(), vpart_id( "wheel_mount_light" ) ); } } for( const vpart_reference &vp : get_any_parts( "NEEDS_WHEEL_MOUNT_MEDIUM" ) ) { if( vp.info().has_flag( "STEERABLE" ) ) { - install_part( vp.mount(), vpart_id( "wheel_mount_medium_steerable" ), false ); + install_part( vp.mount(), vpart_id( "wheel_mount_medium_steerable" ) ); } else { - install_part( vp.mount(), vpart_id( "wheel_mount_medium" ), false ); + install_part( vp.mount(), vpart_id( "wheel_mount_medium" ) ); } } for( const vpart_reference &vp : get_any_parts( "NEEDS_WHEEL_MOUNT_HEAVY" ) ) { if( vp.info().has_flag( "STEERABLE" ) ) { - install_part( vp.mount(), vpart_id( "wheel_mount_heavy_steerable" ), false ); + install_part( vp.mount(), vpart_id( "wheel_mount_heavy_steerable" ) ); } else { - install_part( vp.mount(), vpart_id( "wheel_mount_heavy" ), false ); + install_part( vp.mount(), vpart_id( "wheel_mount_heavy" ) ); } } diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index f613cadb78f84..2e4e97d28d884 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -133,7 +133,8 @@ player_activity veh_interact::serialize_activity() if( pt->is_broken() ) { time = vp->install_time( player_character ); } else if( pt->base.max_damage() > 0 ) { - time = vp->repair_time( player_character ) * pt->base.damage() / pt->base.max_damage(); + time = vp->repair_time( player_character ) * pt->base.damage() / + pt->base.max_damage(); } } break; @@ -164,6 +165,7 @@ player_activity veh_interact::serialize_activity() res.values.push_back( -dd.y ); // values[5] res.values.push_back( veh->index_of_part( vpt ) ); // values[6] res.str_values.push_back( vp->get_id().str() ); + res.str_values.push_back( sel_vpart_variant ); res.targets.emplace_back( std::move( target ) ); return res; @@ -1009,7 +1011,8 @@ void veh_interact::do_install() size_t &tab = install_info->tab = 0; while( true ) { - sel_vpart_info = tab_vparts.empty() ? nullptr : tab_vparts[pos]; // filtered list can be empty + // filtered list can be empty + sel_vpart_info = tab_vparts.empty() ? nullptr : tab_vparts[pos]; bool can_install = can_install_part(); @@ -1045,24 +1048,30 @@ void veh_interact::do_install() default: break; } - // Modifying a vehicle with rotors will make in not flightworthy (until we've got a better model) + // Modifying a vehicle with rotors will make in not flightworthy + // (until we've got a better model) // It can only be the player doing this - an npc won't work well with query_yn if( veh->would_prevent_flyable( *sel_vpart_info ) ) { if( query_yn( - _( "Installing this part will mean that this vehicle is no longer flightworthy. Continue?" ) ) ) { + _( "Installing this part will mean that this vehicle is no longer " + "flightworthy. Continue?" ) ) ) { veh->set_flyable( false ); } else { return; } } if( veh->is_foldable() && !sel_vpart_info->has_flag( "FOLDABLE" ) && - !query_yn( _( "Installing this part will make the vehicle unfoldable. Continue?" ) ) ) { + !query_yn( _( "Installing this part will make the vehicle unfoldable. " + " Continue?" ) ) ) { return; } const auto &shapes = vpart_shapes[ sel_vpart_info->name() + sel_vpart_info->item.str() ]; int selected_shape = -1; - if( shapes.size() > 1 ) { // more than one shape available, display selection + // more than one shape available, display selection + size_t num_vpart_shapes = shapes.size(); + size_t num_shapes_total = num_vpart_shapes + sel_vpart_info->symbols.size(); + if( num_shapes_total > 0 ) { std::vector shape_ui_entries; for( size_t i = 0; i < shapes.size(); i++ ) { uilist_entry entry( i, true, 0, shapes[i]->name() ); @@ -1071,6 +1080,22 @@ void veh_interact::do_install() entry.extratxt.color = shapes[i]->color; shape_ui_entries.push_back( entry ); } + size_t j = num_vpart_shapes; + for( const auto &vp_variant : sel_vpart_info->symbols ) { + std::string disp_name = sel_vpart_info->name(); + for( const auto &vp_variant_pair : vpart_variants ) { + if( vp_variant_pair.first == vp_variant.first ) { + disp_name += " " + _( vp_variant_pair.second ); + break; + } + } + uilist_entry entry( j, true, 0, disp_name ); + entry.extratxt.left = 1; + entry.extratxt.sym = special_symbol( vp_variant.second ); + entry.extratxt.color = sel_vpart_info->color; + shape_ui_entries.push_back( entry ); + j += 1; + } sort_uilist_entries_by_line_drawing( shape_ui_entries ); uilist smenu; smenu.settext( _( "Choose shape:" ) ); @@ -1089,14 +1114,30 @@ void veh_interact::do_install() } else { // only one shape available, default to first one selected_shape = 0; } - if( selected_shape >= 0 && static_cast( selected_shape ) < shapes.size() ) { - sel_vpart_info = shapes[selected_shape]; + if( selected_shape >= 0 && + static_cast( selected_shape ) < num_shapes_total ) { + if( static_cast( selected_shape ) < num_vpart_shapes ) { + sel_vpart_info = shapes[selected_shape]; + sel_vpart_variant.clear(); + } else { + size_t offset = static_cast( selected_shape ) - num_vpart_shapes; + size_t j = 0; + for( const auto &vp_variant : sel_vpart_info->symbols ) { + if( j == offset ) { + sel_vpart_variant = vp_variant.first; + break; + } else { + j += 1; + } + } + } sel_cmd = 'i'; return; } } } else if( action == "QUIT" ) { sel_vpart_info = nullptr; + sel_vpart_variant.clear(); break; } else if( action == "PREV_TAB" || action == "NEXT_TAB" || action == "FILTER" || action == "REPAIR" ) { @@ -1109,7 +1150,8 @@ void veh_interact::do_install() tab = ( tab < tab_list.size() - 1 ) ? tab + 1 : 0; } - copy_if( can_mount.begin(), can_mount.end(), back_inserter( tab_vparts ), tab_filters[tab] ); + copy_if( can_mount.begin(), can_mount.end(), back_inserter( tab_vparts ), + tab_filters[tab] ); } else { move_in_list( pos, action, tab_vparts.size(), 2 ); } @@ -2950,7 +2992,8 @@ void veh_interact::complete_vehicle( player &p ) optional_vpart_position vp = here.veh_at( here.getlocal( tripoint( p.activity.values[0], p.activity.values[1], p.posz() ) ) ); if( !vp ) { - // so the vehicle could have lost some of its parts from other NPCS works during this player/NPCs activity. + // so the vehicle could have lost some of its parts from other NPCS works + // during this player/NPCs activity. // check the vehicle points that were stored at beginning of activity. if( !p.activity.coord_set.empty() ) { for( const auto pt : p.activity.coord_set ) { @@ -2971,6 +3014,7 @@ void veh_interact::complete_vehicle( player &p ) point d( p.activity.values[4], p.activity.values[5] ); int vehicle_part = p.activity.values[6]; const vpart_id part_id( p.activity.str_values[0] ); + const std::string &variant_id = p.activity.str_values[1]; const vpart_info &vpinfo = part_id.obj(); @@ -2981,7 +3025,8 @@ void veh_interact::complete_vehicle( player &p ) const auto reqs = vpinfo.install_requirements(); if( !reqs.can_make_with_inventory( inv, is_crafting_component ) ) { - add_msg( m_info, _( "You don't meet the requirements to install the %s." ), vpinfo.name() ); + add_msg( m_info, _( "You don't meet the requirements to install the %s." ), + vpinfo.name() ); break; } @@ -2996,7 +3041,8 @@ void veh_interact::complete_vehicle( player &p ) } if( base.is_null() ) { if( !p.has_trait( trait_DEBUG_HS ) ) { - add_msg( m_info, _( "Could not find base part in requirements for %s." ), vpinfo.name() ); + add_msg( m_info, _( "Could not find base part in requirements for %s." ), + vpinfo.name() ); break; } else { base = item( vpinfo.item ); @@ -3010,9 +3056,10 @@ void veh_interact::complete_vehicle( player &p ) p.invalidate_crafting_inventory(); int partnum = !base.is_null() ? veh->install_part( d, part_id, - std::move( base ) ) : -1; + std::move( base ), variant_id ) : -1; if( partnum < 0 ) { - debugmsg( "complete_vehicle install part fails dx=%d dy=%d id=%s", d.x, d.y, part_id.c_str() ); + debugmsg( "complete_vehicle install part fails dx=%d dy=%d id=%s", + d.x, d.y, part_id.c_str() ); break; } @@ -3023,14 +3070,16 @@ void veh_interact::complete_vehicle( player &p ) if( vpinfo.has_flag( VPFLAG_CONE_LIGHT ) || vpinfo.has_flag( VPFLAG_WIDE_CONE_LIGHT ) || vpinfo.has_flag( VPFLAG_HALF_CIRCLE_LIGHT ) ) { - // Stash offset and set it to the location of the part so look_around will start there. + // Stash offset and set it to the location of the part so look_around will + // start there. const tripoint old_view_offset = p.view_offset; const tripoint offset = veh->global_pos3() + q; p.view_offset = offset - p.pos(); point delta; do { - popup( _( "Press space, choose a facing direction for the new %s and confirm with enter." ), + popup( _( "Press space, choose a facing direction for the new %s and " + "confirm with enter." ), vpinfo.name() ); const cata::optional chosen = g->look_around(); if( !chosen ) { @@ -3063,8 +3112,8 @@ void veh_interact::complete_vehicle( player &p ) here.board_vehicle( vehp, pl ); } - p.add_msg_if_player( m_good, _( "You install a %1$s into the %2$s." ), veh->part( partnum ).name(), - veh->name ); + p.add_msg_if_player( m_good, _( "You install a %1$s into the %2$s." ), + veh->part( partnum ).name(), veh->name ); for( const auto &sk : vpinfo.install_skills ) { p.practice( sk.first, veh_utils::calc_xp_gain( vpinfo, sk.first, p ) ); @@ -3093,10 +3142,12 @@ void veh_interact::complete_vehicle( player &p ) if( pt.remaining_ammo_capacity() ) { //~ 1$s vehicle name, 2$s tank name - p.add_msg_if_player( m_good, _( "You refill the %1$s's %2$s." ), veh->name, pt.name() ); + p.add_msg_if_player( m_good, _( "You refill the %1$s's %2$s." ), + veh->name, pt.name() ); } else { //~ 1$s vehicle name, 2$s tank name - p.add_msg_if_player( m_good, _( "You completely refill the %1$s's %2$s." ), veh->name, pt.name() ); + p.add_msg_if_player( m_good, _( "You completely refill the %1$s's %2$s." ), + veh->name, pt.name() ); } if( src->contents.legacy_front().charges == 0 ) { @@ -3110,7 +3161,8 @@ void veh_interact::complete_vehicle( player &p ) pt.base.reload( p, std::move( src ), qty ); //~ 1$s vehicle name, 2$s reactor name - p.add_msg_if_player( m_good, _( "You refuel the %1$s's %2$s." ), veh->name, pt.name() ); + p.add_msg_if_player( m_good, _( "You refuel the %1$s's %2$s." ), + veh->name, pt.name() ); } else { debugmsg( "vehicle part is not reloadable" ); @@ -3126,14 +3178,18 @@ void veh_interact::complete_vehicle( player &p ) if( vehicle_part >= veh->part_count() ) { vehicle_part = veh->get_next_shifted_index( vehicle_part, p ); if( vehicle_part == -1 ) { - p.add_msg_if_player( m_info, _( "The %s has already been removed by someone else." ), + p.add_msg_if_player( m_info, + //~ 1$s is the vehicle part name + _( "The %1$s has already been removed by someone else." ), vpinfo.name() ); return; } } const auto reqs = vpinfo.removal_requirements(); if( !reqs.can_make_with_inventory( inv, is_crafting_component ) ) { - add_msg( m_info, _( "You don't meet the requirements to remove the %s." ), vpinfo.name() ); + //~ 1$s is the vehicle part name + add_msg( m_info, _( "You don't meet the requirements to remove the %1$s." ), + vpinfo.name() ); break; } for( const auto &e : reqs.get_components() ) { @@ -3159,11 +3215,12 @@ void veh_interact::complete_vehicle( player &p ) } if( veh->is_towing() || veh->is_towed() ) { std::cout << "vehicle is towing/towed" << std::endl; - vehicle *other_veh = veh->is_towing() ? veh->tow_data.get_towed() : veh->tow_data.get_towed_by(); + vehicle *other_veh = veh->is_towing() ? veh->tow_data.get_towed() : + veh->tow_data.get_towed_by(); if( other_veh ) { std::cout << "other veh exists" << std::endl; - other_veh->remove_part( other_veh->part_with_feature( other_veh->get_tow_part(), "TOW_CABLE", - true ) ); + other_veh->remove_part( other_veh->part_with_feature( other_veh->get_tow_part(), + "TOW_CABLE", true ) ); other_veh->tow_data.clear_towing(); } veh->tow_data.clear_towing(); @@ -3213,7 +3270,8 @@ void veh_interact::complete_vehicle( player &p ) get_map().clear_vehicle_point_from_cache( veh, part_pos ); } } - // This will be part of an NPC "job" where they need to clean up the acitivty items afterwards + // This will be part of an NPC "job" where they need to clean up the acitivty + // items afterwards if( p.is_npc() ) { for( item &it : resulting_items ) { it.set_var( "activity_var", p.name ); diff --git a/src/veh_interact.h b/src/veh_interact.h index 83623b6b486ec..a65953bc0488a 100644 --- a/src/veh_interact.h +++ b/src/veh_interact.h @@ -74,6 +74,7 @@ class veh_interact int overview_limit = 0; const vpart_info *sel_vpart_info = nullptr; + std::string sel_vpart_variant; //Command currently being run by the player char sel_cmd = ' '; diff --git a/src/veh_type.cpp b/src/veh_type.cpp index 3e7993f3cef36..6b3cd2a19b2ad 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -136,6 +136,34 @@ static std::map abstract_parts; static DynamicDataLoader::deferred_json deferred; +std::pair get_vpart_str_variant( const std::string &vpid ) +{ + for( const auto &vp_variant_pair : vpart_variants ) { + const std::string &vp_variant = vp_variant_pair.first; + const size_t loc = vpid.rfind( "_" + vp_variant ); + if( loc != std::string::npos && ( ( loc + vp_variant.size() + 1 ) == vpid.size() ) ) { + return std::make_pair( vpid.substr( 0, loc ), vp_variant ); + } + } + return std::make_pair( vpid, "" ); +} + +std::pair get_vpart_id_variant( const vpart_id &vpid ) +{ + std::string final_vpid; + std::string variant_id; + std::tie( final_vpid, variant_id ) = get_vpart_str_variant( vpid.str() ); + return std::make_pair( vpart_id( final_vpid ), variant_id ); +} + +std::pair get_vpart_id_variant( const std::string &vpid ) +{ + std::string final_vpid; + std::string variant_id; + std::tie( final_vpid, variant_id ) = get_vpart_str_variant( vpid ); + return std::make_pair( vpart_id( final_vpid ), variant_id ); +} + /** @relates string_id */ template<> bool string_id::is_valid() const @@ -149,9 +177,16 @@ const vpart_info &string_id::obj() const { const auto found = vpart_info_all.find( *this ); if( found == vpart_info_all.end() ) { - debugmsg( "Tried to get invalid vehicle part: %s", c_str() ); - static const vpart_info null_part{}; - return null_part; + vpart_id base_id; + std::string variant; + std::tie( base_id, variant ) = get_vpart_id_variant( *this ); + const auto var_found = vpart_info_all.find( base_id ); + if( var_found == vpart_info_all.end() ) { + debugmsg( "Tried to get invalid vehicle part: %s", c_str() ); + static const vpart_info null_part{}; + return null_part; + } + return var_found->second; } return found->second; } @@ -323,10 +358,19 @@ void vpart_info::load( const JsonObject &jo, const std::string &src ) } } + std::string temp_id; + std::string variant_id; if( jo.has_string( "abstract" ) ) { def.id = vpart_id( jo.get_string( "abstract" ) ); } else { - def.id = vpart_id( jo.get_string( "id" ) ); + temp_id = jo.get_string( "id" ); + std::tie( def.id, variant_id ) = get_vpart_id_variant( temp_id ); + if( !variant_id.empty() ) { + const auto base = vpart_info_all.find( def.id ); + if( base != vpart_info_all.end() ) { + def = base->second; + } + } } assign( jo, "name", def.name_ ); @@ -384,10 +428,30 @@ void vpart_info::load( const JsonObject &jo, const std::string &src ) def.repair_moves ); } - if( jo.has_member( "symbol" ) ) { + if( jo.has_string( "symbol" ) ) { + int symbol = jo.get_string( "symbol" )[ 0 ]; + if( variant_id.empty() ) { + def.sym = symbol; + } else { + def.symbols[ variant_id ] = symbol; + } def.sym = jo.get_string( "symbol" )[ 0 ]; } - if( jo.has_member( "broken_symbol" ) ) { + if( jo.has_bool( "standard_symbols" ) && jo.get_bool( "standard_symbols" ) ) { + for( const auto &variant : vpart_variants_standard ) { + def.symbols[ variant.first ] = variant.second; + } + } + if( jo.has_object( "symbols" ) ) { + JsonObject jo_variants = jo.get_object( "symbols" ); + for( const auto &vp_variant_pair : vpart_variants ) { + const std::string &vp_variant = vp_variant_pair.first; + if( jo_variants.has_string( vp_variant ) ) { + def.symbols[ vp_variant ] = jo_variants.get_string( vp_variant )[ 0 ]; + } + } + } + if( jo.has_string( "broken_symbol" ) ) { def.sym_broken = jo.get_string( "broken_symbol" )[ 0 ]; } jo.read( "looks_like", def.looks_like ); @@ -584,7 +648,7 @@ void vpart_info::check() debugmsg( "Vehicle part %s breaks into non-existent item group %s.", part.id.c_str(), part.breaks_into_group.c_str() ); } - if( part.sym == 0 ) { + if( part.sym == 0 && part.symbols.empty() ) { debugmsg( "vehicle part %s does not define a symbol", part.id.c_str() ); } if( part.sym_broken == 0 ) { @@ -962,7 +1026,8 @@ vehicle_prototype &vehicle_prototype::operator=( vehicle_prototype && ) = defaul */ void vehicle_prototype::load( const JsonObject &jo ) { - vehicle_prototype &vproto = vtypes[ vproto_id( jo.get_string( "id" ) ) ]; + vproto_id vid = vproto_id( jo.get_string( "id" ) ); + vehicle_prototype &vproto = vtypes[ vid ]; // If there are already parts defined, this vehicle prototype overrides an existing one. // If the json contains a name, it means a completely new prototype (replacing the // original one), therefore the old data has to be cleared. @@ -975,12 +1040,13 @@ void vehicle_prototype::load( const JsonObject &jo ) vproto.name = jo.get_string( "name" ); } - vgroups[vgroup_id( jo.get_string( "id" ) )].add_vehicle( vproto_id( jo.get_string( "id" ) ), 100 ); + vgroups[ vgroup_id( vid.str() ) ].add_vehicle( vid, 100 ); const auto add_part_obj = [&]( const JsonObject & part, point pos ) { part_def pt; pt.pos = pos; - pt.part = vpart_id( part.get_string( "part" ) ); + std::tie( pt.part, pt.variant ) = get_vpart_id_variant( part.get_string( "part" ) ); + const std::string parts = part.get_string( "part" ); assign( part, "ammo", pt.with_ammo, true, 0, 100 ); assign( part, "ammo_types", pt.ammo_types, true ); @@ -993,7 +1059,8 @@ void vehicle_prototype::load( const JsonObject &jo ) const auto add_part_string = [&]( const std::string & part, point pos ) { part_def pt; pt.pos = pos; - pt.part = vpart_id( part ); + std::tie( pt.part, pt.variant ) = get_vpart_id_variant( part ); + vproto.parts.push_back( pt ); }; @@ -1029,8 +1096,8 @@ void vehicle_prototype::load( const JsonObject &jo ) // constrain both with_magazine and with_ammo to [0-100] next_spawn.with_magazine = std::max( std::min( spawn_info.get_int( "magazine", next_spawn.with_magazine ), 100 ), 0 ); - next_spawn.with_ammo = std::max( std::min( spawn_info.get_int( "ammo", next_spawn.with_ammo ), - 100 ), 0 ); + next_spawn.with_ammo = std::max( std::min( spawn_info.get_int( "ammo", + next_spawn.with_ammo ), 100 ), 0 ); if( spawn_info.has_array( "items" ) ) { //Array of items that all spawn together (i.e. jack+tire) @@ -1075,7 +1142,7 @@ void vehicle_prototype::finalize() blueprint.name = _( proto.name ); blueprint.suspend_refresh(); - for( auto &pt : proto.parts ) { + for( part_def &pt : proto.parts ) { const itype *base = item::find_type( pt.part->item ); if( !pt.part.is_valid() ) { @@ -1083,7 +1150,7 @@ void vehicle_prototype::finalize() continue; } - if( blueprint.install_part( pt.pos, pt.part ) < 0 ) { + if( blueprint.install_part( pt.pos, pt.part, pt.variant ) < 0 ) { debugmsg( "init_vehicles: '%s' part '%s'(%d) can't be installed to %d,%d", blueprint.name, pt.part.c_str(), blueprint.part_count(), pt.pos.x, pt.pos.y ); @@ -1091,13 +1158,16 @@ void vehicle_prototype::finalize() if( !base->gun ) { if( pt.with_ammo ) { - debugmsg( "init_vehicles: non-turret %s with ammo in %s", pt.part.c_str(), id.c_str() ); + debugmsg( "init_vehicles: non-turret %s with ammo in %s", pt.part.c_str(), + id.c_str() ); } if( !pt.ammo_types.empty() ) { - debugmsg( "init_vehicles: non-turret %s with ammo_types in %s", pt.part.c_str(), id.c_str() ); + debugmsg( "init_vehicles: non-turret %s with ammo_types in %s", + pt.part.c_str(), id.c_str() ); } if( pt.ammo_qty.first > 0 || pt.ammo_qty.second > 0 ) { - debugmsg( "init_vehicles: non-turret %s with ammo_qty in %s", pt.part.c_str(), id.c_str() ); + debugmsg( "init_vehicles: non-turret %s with ammo_qty in %s", + pt.part.c_str(), id.c_str() ); } } else { @@ -1117,11 +1187,13 @@ void vehicle_prototype::finalize() if( type_can_contain( *base, pt.fuel ) || base->magazine ) { if( !item::type_is_defined( pt.fuel ) ) { - debugmsg( "init_vehicles: tank %s specified invalid fuel in %s", pt.part.c_str(), id.c_str() ); + debugmsg( "init_vehicles: tank %s specified invalid fuel in %s", + pt.part.c_str(), id.c_str() ); } } else { if( !pt.fuel.is_null() ) { - debugmsg( "init_vehicles: non-fuel store part %s with fuel in %s", pt.part.c_str(), id.c_str() ); + debugmsg( "init_vehicles: non-fuel store part %s with fuel in %s", + pt.part.c_str(), id.c_str() ); } } diff --git a/src/veh_type.h b/src/veh_type.h index d953088017606..54c8e109a43f0 100644 --- a/src/veh_type.h +++ b/src/veh_type.h @@ -140,18 +140,53 @@ struct transform_terrain_data { time_duration post_field_age = 0_turns; }; +const std::vector> vpart_variants = { + { "cover", "Cover" }, { "cross_unconnected", "Unconnected Cross" }, { "cross", "Cross" }, + { "horizontal_front", "Front Horizontal" }, + { "horizontal_front_edge", "Front Edge Horizontal" }, + { "horizontal_rear", "Rear Horizontal" }, + { "horizontal_rear_edge", "Rear Edge Horizontal" }, + { "horizontal_2_front", "Front Thick Horizontal" }, + { "horizontal_2_rear", "Rear Thick Horizontal" }, + { "ne_edge", "Front Right Corner" }, { "nw_edge", "Front Left Corner" }, + { "se_edge", "Rear Right Corner" }, { "sw_edge", "Rear Left Corner" }, + { "vertical_right", "Right Vertical", }, { "vertical_left", "Left Vertical" }, + { "vertical_2_right", "Right Thick Vertical" }, + { "vertical_2_left", "Left Thick Vertical" }, + { "vertical_T_right", "Right T Joint" }, { "vertical_T_left", "Left T Joint" }, + // these have to be last to avoid false positives + { "vertical", "Vertical" }, { "horizontal", "Horizontal" }, + { "vertical_2", "Thick Vertical" }, { "horizontal_2", "Thick Horizontal" }, + { "ne", "Front Right" }, { "nw", "Front Left" }, + { "se", "Rear Right" }, { "sw", "Rear Left" }, + { "front", "Front" }, { "rear", "Rear" }, + { "left", "Left" }, { "right", "Right" } +}; + +const std::map vpart_variants_standard = { + { "cover", '^' }, { "cross", 'c' }, + { "horizontal", 'h' }, { "horizontal_2", '=' }, { "vertical", 'j' }, { "vertical_2", 'H' }, + { "ne", 'u' }, { "nw", 'y' }, { "se", 'n' }, { "sw", 'b' } +}; +std::pair get_vpart_str_variant( const std::string &vpid ); +std::pair get_vpart_id_variant( const vpart_id &vpid ); +std::pair get_vpart_id_variant( const std::string &vpid ); + class vpart_info { - private: - /** Unique identifier for this part */ - vpart_id id; + public: + static void load_engine( cata::optional &eptr, const JsonObject &jo, + const itype_id &fuel_type ); + static void load_wheel( cata::optional &whptr, const JsonObject &jo ); + static void load_workbench( cata::optional &wbptr, const JsonObject &jo ); + static void load_rotor( cata::optional &roptr, const JsonObject &jo ); + static void load( const JsonObject &jo, const std::string &src ); + static void finalize(); + static void check(); + static void reset(); - cata::optional engine_info; - cata::optional wheel_info; - cata::optional rotor_info; - cata::optional workbench_info; + static const std::map &all(); - public: /** Translated name of a part */ std::string name() const; @@ -159,74 +194,16 @@ class vpart_info return id; } - /** base item for this part */ - itype_id item; - - /** What slot of the vehicle tile does this part occupy? */ - std::string location; - - /** Color of part for different states */ - nc_color color = c_light_gray; - nc_color color_broken = c_light_gray; - - /** - * Symbol of part which will be translated as follows: - * y, u, n, b to NW, NE, SE, SW lines correspondingly - * h, j, c to horizontal, vertical, cross correspondingly - */ - int sym = 0; - char sym_broken = '#'; - - /** hint to tilesets for what tile to use if this part doesn't have one */ - std::string looks_like; - - /** Maximum damage part can sustain before being destroyed */ - int durability = 0; - - /** A text description of the part as a vehicle part */ - translation description; - - /** Damage modifier (percentage) used when damaging other entities upon collision */ - int dmg_mod = 100; - - /** - * Electrical power, flat rate (watts); positive for generation, negative for consumption - * For motor consumption scaled with powertrain demand see @ref energy_consumption instead - */ - int epower = 0; - - /** - * Energy consumed by engines and motors (watts) when delivering max @ref power - * Includes waste. Gets scaled based on powertrain demand. - */ - int energy_consumption = 0; - - /** - * For engines and motors this is maximum output (watts) - * For alternators is engine power consumed (negative value) - */ - int power = 0; - - /** Emissions of part */ - std::set emissions; - - /** Fuel type of engine or tank */ - itype_id fuel_type = itype_id::NULL_ID(); - - /** Default ammo (for turrets) */ - itype_id default_ammo = itype_id::NULL_ID(); - - /** Volume of a foldable part when folded */ - units::volume folded_volume = 0_ml; - - /** Cargo location volume */ - units::volume size = 0_ml; - - /** Mechanics skill required to install item */ - int difficulty = 0; - - /** Legacy parts don't specify installation requirements */ - bool legacy = true; + const std::set &get_flags() const { + return flags; + } + bool has_flag( const std::string &flag ) const { + return flags.count( flag ) != 0; + } + bool has_flag( const vpart_bitflags flag ) const { + return bitflags.test( flag ); + } + void set_flag( const std::string &flag ); /** Format the description for display */ int format_description( std::string &msg, const nc_color &format_color, int width ) const; @@ -234,24 +211,12 @@ class vpart_info /** Installation requirements for this component */ requirement_data install_requirements() const; - /** Required skills to install this component */ - std::map install_skills; - - /** Installation time (in moves) for component (@see install_time), default 1 hour */ - int install_moves = to_moves( 1_hours ); - /** Installation time (in moves) for this component accounting for player skills */ int install_time( const player &p ) const; /** Requirements for removal of this component */ requirement_data removal_requirements() const; - /** Required skills to remove this component */ - std::map removal_skills; - - /** Removal time (in moves) for component (@see removal_time), default is half @ref install_moves */ - int removal_moves = -1; - /** Removal time (in moves) for this component accounting for player skills */ int removal_time( const player &p ) const; @@ -261,38 +226,9 @@ class vpart_info /** Returns whether or not the part is repairable */ bool is_repairable() const; - /** Required skills to repair this component */ - std::map repair_skills; - - /** Repair time (in moves) to fully repair a component (@see repair_time) */ - int repair_moves = to_moves( 1_hours ); - /** Repair time (in moves) to fully repair this component, accounting for player skills */ int repair_time( const player &p ) const; - /** @ref item_group this part breaks into when destroyed */ - std::string breaks_into_group = "EMPTY_GROUP"; - - /** Tool qualities this vehicle part can provide when installed */ - std::map qualities; - - /** seatbelt (str), muffler (%), horn (vol), light (intensity), recharing (power) */ - int bonus = 0; - - /** cargo weight modifier (percentage) */ - int cargo_weight_modifier = 100; - - /** Flat decrease of damage of a given type. */ - std::array damage_reduction = {}; - - /* Contains data for terrain transformer parts */ - transform_terrain_data transform_terrain; - - /*Comfort data for sleeping in vehicles*/ - int comfort = 0; - int floor_bedding_warmth = 0; - int bonus_fire_warmth_feet = 300; - /** * @name Engine specific functions * @@ -322,9 +258,6 @@ class vpart_info const cata::optional &get_workbench_info() const; private: - /** Name from vehicle part definition which if set overrides the base item name */ - translation name_; - std::set flags; // flags checked so often that things slow down due to string cmp std::bitset bitflags; @@ -334,35 +267,37 @@ class vpart_info std::vector> removal_reqs; std::vector> repair_reqs; + cata::optional engine_info; + cata::optional wheel_info; + cata::optional rotor_info; + cata::optional workbench_info; + + /** Unique identifier for this part */ + vpart_id id; + + /** Name from vehicle part definition which if set overrides the base item name */ + translation name_; + public: + /* map of standard variant names to symbols */ + std::map symbols; - // z-ordering, inferred from location, cached here - int z_order = 0; - // Display order in vehicle interact display - int list_order = 0; + /** Required skills to install, repair, or remove this component */ + std::map install_skills; + std::map repair_skills; + std::map removal_skills; - const std::set &get_flags() const { - return flags; - } - bool has_flag( const std::string &flag ) const { - return flags.count( flag ) != 0; - } - bool has_flag( const vpart_bitflags flag ) const { - return bitflags.test( flag ); - } - void set_flag( const std::string &flag ); + /** @ref item_group this part breaks into when destroyed */ + std::string breaks_into_group = "EMPTY_GROUP"; - static void load_engine( cata::optional &eptr, const JsonObject &jo, - const itype_id &fuel_type ); - static void load_wheel( cata::optional &whptr, const JsonObject &jo ); - static void load_workbench( cata::optional &wbptr, const JsonObject &jo ); - static void load_rotor( cata::optional &roptr, const JsonObject &jo ); - static void load( const JsonObject &jo, const std::string &src ); - static void finalize(); - static void check(); - static void reset(); + /** Flat decrease of damage of a given type. */ + std::array damage_reduction = {}; - static const std::map &all(); + /** Tool qualities this vehicle part can provide when installed */ + std::map qualities; + + /** Emissions of part */ + std::set emissions; /** * Exhaust emissions of part @@ -371,6 +306,99 @@ class vpart_info * otherwise, it is emitted in place */ std::set exhaust; + + /** Color of part for different states */ + nc_color color = c_light_gray; + nc_color color_broken = c_light_gray; + + /* Contains data for terrain transformer parts */ + transform_terrain_data transform_terrain; + + /** Fuel type of engine or tank */ + itype_id fuel_type = itype_id::NULL_ID(); + + /** Default ammo (for turrets) */ + itype_id default_ammo = itype_id::NULL_ID(); + + /** Volume of a foldable part when folded */ + units::volume folded_volume = 0_ml; + + /** Cargo location volume */ + units::volume size = 0_ml; + + /** hint to tilesets for what tile to use if this part doesn't have one */ + std::string looks_like; + + /** A text description of the part as a vehicle part */ + translation description; + + /** base item for this part */ + itype_id item; + + /** What slot of the vehicle tile does this part occupy? */ + std::string location; + + /** + * Symbol of part which will be translated as follows: + * y, u, n, b to NW, NE, SE, SW lines correspondingly + * h, j, c to horizontal, vertical, cross correspondingly + */ + int sym = 0; + int sym_broken = '#'; + + /** Maximum damage part can sustain before being destroyed */ + int durability = 0; + + /** Damage modifier (percentage) used when damaging other entities upon collision */ + int dmg_mod = 100; + + /** + * Electrical power, flat rate (watts); positive for generation, negative for consumption + * For motor consumption scaled with powertrain demand see @ref energy_consumption instead + */ + int epower = 0; + + /** + * Energy consumed by engines and motors (watts) when delivering max @ref power + * Includes waste. Gets scaled based on powertrain demand. + */ + int energy_consumption = 0; + + /** + * For engines and motors this is maximum output (watts) + * For alternators is engine power consumed (negative value) + */ + int power = 0; + + /** Mechanics skill required to install item */ + int difficulty = 0; + + /** Installation time (in moves) for component (@see install_time), default 1 hour */ + int install_moves = to_moves( 1_hours ); + /** Repair time (in moves) to fully repair a component (@see repair_time) */ + int repair_moves = to_moves( 1_hours ); + /** Removal time (in moves) for component (@see removal_time), + * default is half @ref install_moves */ + int removal_moves = -1; + + /** seatbelt (str), muffler (%), horn (vol), light (intensity), recharing (power) */ + int bonus = 0; + + /** cargo weight modifier (percentage) */ + int cargo_weight_modifier = 100; + + /*Comfort data for sleeping in vehicles*/ + int comfort = 0; + int floor_bedding_warmth = 0; + int bonus_fire_warmth_feet = 300; + + // z-ordering, inferred from location, cached here + int z_order = 0; + // Display order in vehicle interact display + int list_order = 0; + + /** Legacy parts don't specify installation requirements */ + bool legacy = true; }; struct vehicle_item_spawn { @@ -392,6 +420,7 @@ struct vehicle_prototype { struct part_def { point pos; vpart_id part; + std::string variant; int with_ammo = 0; std::set ammo_types; std::pair ammo_qty = { -1, -1 }; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 7fdd89b0665c9..2a84fd29559b7 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -310,7 +310,7 @@ bool vehicle::remote_controlled( const Character &p ) const * loading from a game saved before the vehicle construction rules overhaul). */ void vehicle::add_missing_frames() { - static const vpart_id frame_id( "frame_vertical" ); + static const vpart_id frame_id( "frame" ); //No need to check the same spot more than once std::set locations_checked; for( vehicle_part &i : parts ) { @@ -328,7 +328,7 @@ void vehicle::add_missing_frames() } if( !found ) { // Install missing frame - parts.emplace_back( frame_id, i.mount, item( frame_id->item ) ); + parts.emplace_back( frame_id, "vertical", i.mount, item( frame_id->item ) ); } } } @@ -1636,20 +1636,22 @@ bool vehicle::is_connected( const vehicle_part &to, const vehicle_part &from, * @param force Skip check of whether we can mount the part here. * @return false if the part could not be installed, true otherwise. */ -int vehicle::install_part( const point &dp, const vpart_id &id, bool force ) +int vehicle::install_part( const point &dp, const vpart_id &id, const std::string &variant_id, + bool force ) { if( !( force || can_mount( dp, id ) ) ) { return -1; } - return install_part( dp, vehicle_part( id, dp, item( id.obj().item ) ) ); + return install_part( dp, vehicle_part( id, variant_id, dp, item( id.obj().item ) ) ); } -int vehicle::install_part( const point &dp, const vpart_id &id, item &&obj, bool force ) +int vehicle::install_part( const point &dp, const vpart_id &id, item &&obj, + const std::string &variant_id, bool force ) { if( !( force || can_mount( dp, id ) ) ) { return -1; } - return install_part( dp, vehicle_part( id, dp, std::move( obj ) ) ); + return install_part( dp, vehicle_part( id, variant_id, dp, std::move( obj ) ) ); } int vehicle::install_part( const point &dp, const vehicle_part &new_part ) diff --git a/src/vehicle.h b/src/vehicle.h index 033c10d0c2587..e3e77fcf989c4 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -217,7 +217,8 @@ struct vehicle_part { vehicle_part(); /** DefaultConstructible */ - vehicle_part( const vpart_id &vp, const point &dp, item &&obj ); + vehicle_part( const vpart_id &vp, const std::string &variant_id, const point &dp, + item &&obj ); /** Check this instance is non-null (not default constructed) */ explicit operator bool() const; @@ -448,6 +449,9 @@ struct vehicle_part { private: /** What type of part is this? */ vpart_id id; + /** If it's a part with variants, which variant it is */ + std::string variant; + /** As a performance optimization we cache the part information here on first lookup */ mutable const vpart_info *info_cache = nullptr; @@ -886,13 +890,15 @@ class vehicle bool can_unmount( int p, std::string &reason ) const; // install a new part to vehicle - int install_part( const point &dp, const vpart_id &id, bool force = false ); + int install_part( const point &dp, const vpart_id &id, const std::string &variant = "", + bool force = false ); // Install a copy of the given part, skips possibility check int install_part( const point &dp, const vehicle_part &part ); /** install item specified item to vehicle as a vehicle part */ - int install_part( const point &dp, const vpart_id &id, item &&obj, bool force = false ); + int install_part( const point &dp, const vpart_id &id, item &&obj, + const std::string &variant = "", bool force = false ); // find a single tile wide vehicle adjacent to a list of part indices bool try_to_rack_nearby_vehicle( const std::vector> &list_of_racks ); @@ -1087,7 +1093,7 @@ class vehicle // get symbol for map char part_sym( int p, bool exact = false ) const; - vpart_id part_id_string( int p, char &part_mod ) const; + std::string part_id_string( int p, char &part_mod ) const; // get color for map nc_color part_color( int p, bool exact = false ) const; diff --git a/src/vehicle_display.cpp b/src/vehicle_display.cpp index 2ea45ccc40c7b..538332957b4ab 100644 --- a/src/vehicle_display.cpp +++ b/src/vehicle_display.cpp @@ -40,42 +40,55 @@ char vehicle::part_sym( const int p, const bool exact ) const const int displayed_part = exact ? p : part_displayed_at( parts[p].mount ); - if( part_flag( displayed_part, VPFLAG_OPENABLE ) && parts[displayed_part].open ) { + const vehicle_part &vp = parts.at( displayed_part ); + const vpart_info &vp_info = part_info( displayed_part ); + + if( part_flag( displayed_part, VPFLAG_OPENABLE ) && vp.open ) { // open door return '\''; } else { - return parts[ displayed_part ].is_broken() ? - part_info( displayed_part ).sym_broken : part_info( displayed_part ).sym; + if( vp.is_broken() ) { + return vp_info.sym_broken; + } else if( vp.variant.empty() ) { + return vp_info.sym; + } else { + const auto vp_symbol = vp_info.symbols.find( vp.variant ); + if( vp_symbol == vp_info.symbols.end() ) { + return vp_info.sym; + } else { + return vp_symbol->second; + } + } } } // similar to part_sym(int p) but for use when drawing SDL tiles. Called only by cata_tiles // during draw_vpart vector returns at least 1 element, max of 2 elements. If 2 elements the // second denotes if it is open or damaged -vpart_id vehicle::part_id_string( const int p, char &part_mod ) const +std::string vehicle::part_id_string( const int p, char &part_mod ) const { part_mod = 0; if( p < 0 || p >= static_cast( parts.size() ) || parts[p].removed ) { - return vpart_id::NULL_ID(); + return ""; } int displayed_part = part_displayed_at( parts[p].mount ); if( displayed_part < 0 || displayed_part >= static_cast( parts.size() ) || parts[ displayed_part ].removed ) { - return vpart_id::NULL_ID(); + return ""; } - const vpart_id idinfo = parts[displayed_part].id; + const vehicle_part &vp = parts.at( displayed_part ); - if( part_flag( displayed_part, VPFLAG_OPENABLE ) && parts[displayed_part].open ) { + if( part_flag( displayed_part, VPFLAG_OPENABLE ) && vp.open ) { // open part_mod = 1; - } else if( parts[ displayed_part ].is_broken() ) { + } else if( vp.is_broken() ) { // broken part_mod = 2; } - return idinfo; + return vp.id.str() + ( vp.variant.empty() ? "" : "_" + vp.variant ); } nc_color vehicle::part_color( const int p, const bool exact ) const diff --git a/src/vehicle_part.cpp b/src/vehicle_part.cpp index 543a400e53f7a..e6b336d0cdfdd 100644 --- a/src/vehicle_part.cpp +++ b/src/vehicle_part.cpp @@ -40,8 +40,9 @@ static const itype_id itype_muscle( "muscle" ); vehicle_part::vehicle_part() : id( vpart_id::NULL_ID() ) {} -vehicle_part::vehicle_part( const vpart_id &vp, const point &dp, item &&obj ) - : mount( dp ), id( vp ), base( std::move( obj ) ) +vehicle_part::vehicle_part( const vpart_id &vp, const std::string &variant_id, const point &dp, + item &&obj ) + : mount( dp ), id( vp ), variant( variant_id ), base( std::move( obj ) ) { // Mark base item as being installed as a vehicle part base.item_tags.insert( "VEHICLE" ); diff --git a/tests/npc_test.cpp b/tests/npc_test.cpp index 3b3bc4fbf4d89..1a5c1650a13a7 100644 --- a/tests/npc_test.cpp +++ b/tests/npc_test.cpp @@ -307,7 +307,7 @@ TEST_CASE( "npc-movement" ) const ter_id t_floor( "t_floor" ); const furn_id f_rubble( "f_rubble" ); const furn_id f_null( "f_null" ); - const vpart_id vpart_frame_vertical( "frame_vertical" ); + const vpart_id vpart_frame_vertical( "frame" ); const vpart_id vpart_seat( "seat" ); g->place_player( tripoint( 60, 60, 0 ) ); diff --git a/tests/vehicle_turrets_test.cpp b/tests/vehicle_turrets_test.cpp index 2b3c95597e323..e8c2c93d3c960 100644 --- a/tests/vehicle_turrets_test.cpp +++ b/tests/vehicle_turrets_test.cpp @@ -67,10 +67,11 @@ TEST_CASE( "vehicle_turret", "[vehicle] [gun] [magazine] [.]" ) vehicle *veh = here.add_vehicle( vproto_id( "none" ), point( 65, 65 ), 270, 0, 0 ); REQUIRE( veh ); - const int idx = veh->install_part( point_zero, e->get_id(), true ); + const int idx = veh->install_part( point_zero, e->get_id(), "", true ); REQUIRE( idx >= 0 ); - REQUIRE( veh->install_part( point_zero, vpart_id( "storage_battery" ), true ) >= 0 ); + REQUIRE( veh->install_part( point_zero, vpart_id( "storage_battery" ), "", + true ) >= 0 ); veh->charge_battery( 10000 ); auto ammo = @@ -81,7 +82,7 @@ TEST_CASE( "vehicle_turret", "[vehicle] [gun] [magazine] [.]" ) REQUIRE( tank ); INFO( tank->get_id().str() ); - auto tank_idx = veh->install_part( point_zero, tank->get_id(), true ); + auto tank_idx = veh->install_part( point_zero, tank->get_id(), "", true ); REQUIRE( tank_idx >= 0 ); REQUIRE( veh->part( tank_idx ).ammo_set( ammo->default_ammotype() ) );