diff --git a/color.cpp b/color.cpp index 8a28c8b0af843..4b83f40e61baf 100644 --- a/color.cpp +++ b/color.cpp @@ -1,4 +1,5 @@ #include "color.h" +#include "output.h" #define HILIGHT COLOR_BLUE void init_colors() @@ -408,3 +409,46 @@ nc_color int_to_color(int key) } return c_black; } + +/** + * Given the name of a color, returns the nc_color constant that matches. If + * no match is found, c_white is returned. + * @param new_color The color to get, as a std::string. + * @return The nc_color constant that matches the input. + */ +nc_color color_from_string(std::string new_color){ + if("red"==new_color){ + return c_red; + } else if("blue"==new_color){ + return c_blue; + } else if("green"==new_color){ + return c_green; + } else if("light_cyan"==new_color){ + return c_ltcyan; + } else if("brown"==new_color){ + return c_brown; + } else if("light_red"==new_color){ + return c_ltred; + } else if("white"==new_color){ + return c_white; + } else if("light_blue"==new_color){ + return c_ltblue; + } else if("yellow"==new_color){ + return c_yellow; + } else if("magenta"==new_color){ + return c_magenta; + } else if("cyan"==new_color){ + return c_cyan; + } else if("light_gray"==new_color){ + return c_ltgray; + } else if("dark_gray"==new_color){ + return c_dkgray; + } else if("light_green"==new_color){ + return c_ltgreen; + } else if("pink"==new_color){ + return c_pink; + } else { + debugmsg("Received invalid color property %s. Color is required.", new_color.c_str()); + return c_white; + } +} diff --git a/color.h b/color.h index 43c44975f82a8..540f8f5de4e8e 100644 --- a/color.h +++ b/color.h @@ -5,6 +5,7 @@ #define _COLOR_LIST_ #include "cursesdef.h" +#include void init_colors(); @@ -169,6 +170,7 @@ c_unset = COLOR_PAIR(31), int color_to_int(nc_color col); nc_color int_to_color(int key); +nc_color color_from_string(std::string color); void setattr(nc_color &col, col_attribute attr); diff --git a/data/raw/vehicle_parts.json b/data/raw/vehicle_parts.json new file mode 100644 index 0000000000000..4fa90f1e6134d --- /dev/null +++ b/data/raw/vehicle_parts.json @@ -0,0 +1,999 @@ +[ + { + "name": "null part", + "symbol": "?", + "color": "red", + "broken_symbol": "?", + "broken_color": "red", + "durability": 100, + "item": "NULL", + "difficulty": 0, + "flags": [] + }, + { + "name": "seat", + "symbol": "#", + "color": "red", + "broken_symbol": "*", + "broken_color": "red", + "damage_modifier": 60, + "durability": 300, + "item": "seat", + "difficulty": 1, + "flags": [ + "OVER", "SEAT", "BOARDABLE", "CARGO", "NO_REINFORCE", "ANCHOR_POINT" + ] + }, + { + "name": "saddle", + "symbol": "#", + "color": "red", + "broken_symbol": "*", + "broken_color": "red", + "damage_modifier": 20, + "durability": 200, + "item": "saddle", + "difficulty": 1, + "flags": [ + "OVER", "SEAT", "BOARDABLE", "NO_REINFORCE" + ] + }, + { + "name": "bed", + "symbol": "#", + "color": "magenta", + "broken_symbol": "*", + "broken_color": "magenta", + "damage_modifier": 60, + "durability": 300, + "item": "seat", + "difficulty": 1, + "flags": [ + "OVER", "BED", "BOARDABLE", "CARGO", "NO_REINFORCE" + ] + }, + { + "name": "frame", + "symbol": "h", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "j", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "c", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "y", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "u", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "n", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "b", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "=", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "H", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "frame", + "symbol": "^", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "handle", + "symbol": "^", + "color": "light_cyan", + "broken_symbol": "#", + "broken_color": "light_cyan", + "durability": 300, + "item": "frame", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER" + ] + }, + { + "name": "board", + "symbol": "h", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 1000, + "item": "steel_plate", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER", "OPAQUE", "OBSTACLE" + ] + }, + { + "name": "board", + "symbol": "j", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 1000, + "item": "steel_plate", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER", "OPAQUE", "OBSTACLE" + ] + }, + { + "name": "board", + "symbol": "y", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 1000, + "item": "steel_plate", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER", "OPAQUE", "OBSTACLE" + ] + }, + { + "name": "board", + "symbol": "u", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 1000, + "item": "steel_plate", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER", "OPAQUE", "OBSTACLE" + ] + }, + { + "name": "board", + "symbol": "n", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 1000, + "item": "steel_plate", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER", "OPAQUE", "OBSTACLE" + ] + }, + { + "name": "board", + "symbol": "b", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 1000, + "item": "steel_plate", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER", "OPAQUE", "OBSTACLE" + ] + }, + { + "name": "aisle", + "symbol": "=", + "color": "white", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "INTERNAL", "OVER", "NO_REINFORCE", "AISLE", "BOARDABLE" + ] + }, + { + "name": "aisle", + "symbol": "H", + "color": "white", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "INTERNAL", "OVER", "NO_REINFORCE", "AISLE", "BOARDABLE" + ] + }, + { + "name": "floor trunk", + "symbol": "=", + "color": "white", + "broken_symbol": "#", + "broken_color": "light_gray", + "durability": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "INTERNAL", "OVER", "NO_REINFORCE", "AISLE", "BOARDABLE", "CARGO" + ] + }, + { + "name": "roof", + "symbol": "#", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "dark_gray", + "durability": 1000, + "item": "steel_plate", + "difficulty": 1, + "flags": [ + "INTERNAL", "ROOF" + ] + }, + { + "name": "door", + "symbol": "+", + "color": "cyan", + "broken_symbol": "&", + "broken_color": "cyan", + "damage_modifier": 80, + "durability": 200, + "item": "frame", + "difficulty": 2, + "flags": [ + "EXTERNAL", "OBSTACLE", "OPENABLE", "BOARDABLE" + ] + }, + { + "name": "opaque door", + "symbol": "+", + "color": "cyan", + "broken_symbol": "&", + "broken_color": "cyan", + "damage_modifier": 80, + "durability": 200, + "item": "frame", + "difficulty": 2, + "flags": [ + "EXTERNAL", "OBSTACLE", "OPAQUE", "OPENABLE", "BOARDABLE" + ] + }, + { + "name": "internal door", + "symbol": "+", + "color": "cyan", + "broken_symbol": "&", + "broken_color": "cyan", + "damage_modifier": 75, + "durability": 75, + "item": "frame", + "difficulty": 2, + "flags": [ + "EXTERNAL", "OBSTACLE", "OPAQUE", "OPENABLE", "ROOF", "NO_REINFORCE", "BOARDABLE" + ] + }, + { + "name": "windshield", + "symbol": "\"", + "color": "light_cyan", + "broken_symbol": "0", + "broken_color": "light_gray", + "damage_modifier": 70, + "durability": 50, + "item": "glass_sheet", + "difficulty": 1, + "flags": [ + "OVER", "OBSTACLE", "NO_REINFORCE" + ] + }, + { + "name": "blade", + "symbol": "-", + "color": "white", + "broken_symbol": "x", + "broken_color": "white", + "damage_modifier": 250, + "durability": 100, + "item": "blade", + "difficulty": 2, + "flags": [ + "EXTERNAL", "UNMOUNT_ON_DAMAGE", "SHARP", "NO_REINFORCE" + ] + }, + { + "name": "blade", + "symbol": "|", + "color": "white", + "broken_symbol": "x", + "broken_color": "white", + "damage_modifier": 350, + "durability": 100, + "item": "blade", + "difficulty": 2, + "flags": [ + "EXTERNAL", "UNMOUNT_ON_DAMAGE", "SHARP", "NO_REINFORCE" + ] + }, + { + "name": "spike", + "symbol": ".", + "color": "white", + "broken_symbol": "x", + "broken_color": "white", + "damage_modifier": 300, + "durability": 100, + "item": "spike", + "difficulty": 2, + "flags": [ + "EXTERNAL", "UNMOUNT_ON_DAMAGE", "SHARP", "NO_REINFORCE" + ] + }, + { + "name": "wheel", + "symbol": "0", + "color": "dark_gray", + "broken_symbol": "x", + "broken_color": "light_gray", + "damage_modifier": 50, + "durability": 200, + "wheel_width": 9, + "item": "wheel", + "difficulty": 4, + "flags": [ + "EXTERNAL", "MOUNT_OVER", "WHEEL", "MOUNT_POINT", "VARIABLE_SIZE" + ] + }, + { + "name": "wide wheel", + "symbol": "O", + "color": "dark_gray", + "broken_symbol": "x", + "broken_color": "light_gray", + "damage_modifier": 50, + "durability": 400, + "wheel_width": 14, + "item": "wheel_wide", + "difficulty": 5, + "flags": [ + "EXTERNAL", "MOUNT_OVER", "WHEEL", "MOUNT_POINT", "VARIABLE_SIZE" + ] + }, + { + "name": "wide wheel (underbody)", + "symbol": "H", + "color": "dark_gray", + "broken_symbol": "x", + "broken_color": "light_gray", + "damage_modifier": 50, + "durability": 400, + "wheel_width": 14, + "item": "wheel_wide", + "difficulty": 6, + "flags": [ + "EXTERNAL", "MOUNT_INNER", "WHEEL", "MOUNT_POINT", "VARIABLE_SIZE" + ] + }, + { + "name": "bicycle wheel", + "symbol": "|", + "color": "dark_gray", + "broken_symbol": "x", + "broken_color": "light_gray", + "damage_modifier": 50, + "durability": 40, + "wheel_width": 2, + "item": "wheel_bicycle", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_OVER", "WHEEL", "MOUNT_POINT", "VARIABLE_SIZE" + ] + }, + { + "name": "motorbike wheel", + "symbol": "o", + "color": "dark_gray", + "broken_symbol": "x", + "broken_color": "light_gray", + "damage_modifier": 50, + "durability": 90, + "wheel_width": 4, + "item": "wheel_motorbike", + "difficulty": 2, + "flags": [ + "EXTERNAL", "MOUNT_OVER", "WHEEL", "MOUNT_POINT", "VARIABLE_SIZE" + ] + }, + { + "name": "small wheel", + "symbol": "o", + "color": "dark_gray", + "broken_symbol": "x", + "broken_color": "light_gray", + "damage_modifier": 50, + "durability": 70, + "wheel_width": 6, + "item": "wheel_small", + "difficulty": 2, + "flags": [ + "EXTERNAL", "MOUNT_OVER", "WHEEL", "MOUNT_POINT", "VARIABLE_SIZE" + ] + }, + { + "name": "casters", + "symbol": "o", + "color": "dark_gray", + "broken_symbol": "x", + "broken_color": "light_gray", + "damage_modifier": 50, + "durability": 70, + "wheel_width": 6, + "item": "wheel_caster", + "difficulty": 1, + "flags": [ + "EXTERNAL", "MOUNT_POINT", "MOUNT_INNER", "WHEEL", "VARIABLE_SIZE" + ] + }, + { + "name": "1-cylinder engine", + "symbol": "*", + "color": "light_red", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 150, + "power": 40, + "fuel_type": "gasoline", + "item": "1cyl_combustion", + "difficulty": 2, + "flags": [ + "INTERNAL", "ENGINE", "VARIABLE_SIZE" + ] + }, + { + "name": "V-twin engine", + "symbol": "*", + "color": "light_red", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 200, + "power": 120, + "fuel_type": "gasoline", + "item": "v2_combustion", + "difficulty": 2, + "flags": [ + "INTERNAL", "ENGINE", "VARIABLE_SIZE" + ] + }, + { + "name": "Inline-4 engine", + "symbol": "*", "color": "light_red", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 300, + "power": 300, + "fuel_type": "gasoline", + "item": "i4_combustion", + "difficulty": 3, + "flags": [ + "INTERNAL", "ENGINE", "VARIABLE_SIZE" + ] + }, + { + "name": "V6 engine", + "symbol": "*", + "color": "light_red", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 400, + "power": 800, + "fuel_type": "gasoline", + "item": "v6_combustion", + "difficulty": 4, + "flags": [ + "INTERNAL", "ENGINE", "VARIABLE_SIZE" + ] + }, + { + "name": "V8 engine", + "symbol": "*", + "color": "light_red", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 400, + "power": 800, + "fuel_type": "gasoline", + "item": "v8_combustion", + "difficulty": 4, + "flags": [ + "INTERNAL", "ENGINE", "VARIABLE_SIZE" + ] + }, + { + "name": "electric motor", + "symbol": "*", + "color": "yellow", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 200, + "power": 70, + "fuel_type": "battery", + "item": "motor", + "difficulty": 3, + "flags": [ + "INTERNAL", "ENGINE" + ] + }, + { + "name": "large electric motor", + "symbol": "*", + "color": "yellow", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 400, + "power": 350, + "fuel_type": "battery", + "item": "motor_large", + "difficulty": 4, + "flags": [ + "INTERNAL", "ENGINE" + ] + }, + { + "name": "plasma engine", + "symbol": "*", + "color": "light_blue", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 250, + "power": 400, + "fuel_type": "plasma", + "item": "plasma_engine", + "difficulty": 6, + "flags": [ + "INTERNAL", "ENGINE" + ] + }, + { + "name": "Foot pedals", + "symbol": "*", + "color": "light_gray", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 50, + "durability": 50, + "power": 70, + "fuel_type": "muscle", + "item": "foot_crank", + "difficulty": 1, + "flags": [ + "INTERNAL", "ENGINE" + ] + }, + { + "name": "gasoline tank", + "symbol": "O", + "color": "light_red", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 150, + "size": 3000, + "fuel_type": "gasoline", + "item": "metal_tank", + "difficulty": 1, + "flags": [ + "INTERNAL", "FUEL_TANK" + ] + }, + { + "name": "storage battery", + "symbol": "O", + "color": "yellow", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 300, + "size": 100000, + "fuel_type": "battery", + "item": "storage_battery", + "difficulty": 2, + "flags": [ + "INTERNAL", "FUEL_TANK" + ] + }, + { + "name": "minireactor", + "symbol": "O", + "color": "light_green", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 700, + "size": 10000, + "fuel_type": "plutonium", + "item": "minireactor", + "difficulty": 7, + "flags": [ + "INTERNAL", "FUEL_TANK" + ] + }, + { + "name": "hydrogen tank", + "symbol": "O", + "color": "light_blue", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 150, + "size": 3000, + "fuel_type": "plasma", + "item": "metal_tank", + "difficulty": 1, + "flags": [ + "INTERNAL", "FUEL_TANK" + ] + }, + { + "name": "water tank", + "symbol": "O", + "color": "light_cyan", + "broken_symbol": "#", + "broken_color": "red", + "damage_modifier": 80, + "durability": 150, + "size": 400, + "fuel_type": "water", + "item": "metal_tank", + "difficulty": 1, + "flags": [ + "INTERNAL", "FUEL_TANK" + ] + }, + { + "name": "trunk", + "symbol": "H", + "color": "brown", + "broken_symbol": "#", + "broken_color": "brown", + "damage_modifier": 80, + "durability": 300, + "size": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "OVER", "CARGO" + ] + }, + { + "name": "box", + "symbol": "o", + "color": "brown", + "broken_symbol": "#", + "broken_color": "brown", + "damage_modifier": 60, + "durability": 100, + "size": 400, + "item": "frame", + "difficulty": 1, + "flags": [ + "OVER", "CARGO", "BOARDABLE" + ] + }, + { + "name": "controls", + "symbol": "$", + "color": "light_gray", + "broken_symbol": "$", + "broken_color": "red", + "damage_modifier": 10, + "durability": 250, + "item": "vehicle_controls", + "difficulty": 3, + "flags": [ + "INTERNAL", "CONTROLS" + ] + }, + { + "name": "muffler", + "symbol": "/", + "color": "light_gray", + "broken_symbol": "/", + "broken_color": "light_gray", + "damage_modifier": 10, + "durability": 150, + "bonus": 40, + "item": "muffler", + "difficulty": 2, + "flags": [ + "INTERNAL", "MUFFLER" + ] + }, + { + "name": "seatbelt", + "symbol": ",", + "color": "light_gray", + "broken_symbol": ",", + "broken_color": "red", + "damage_modifier": 10, + "durability": 200, + "bonus": 25, + "item": "rope_6", + "difficulty": 1, + "flags": [ + "INTERNAL", "SEATbelt" + ] + }, + { + "name": "solar panel", + "symbol": "#", + "color": "yellow", + "broken_symbol": "x", + "broken_color": "yellow", + "damage_modifier": 10, + "durability": 20, + "power": 30, + "item": "solar_panel", + "difficulty": 6, + "flags": [ + "OVER", "SOLAR_PANEL" + ] + }, + { + "name": "kitchen unit", + "symbol": "&", + "color": "light_cyan", + "broken_symbol": "x", + "broken_color": "light_cyan", + "damage_modifier": 10, + "durability": 20, + "item": "kitchen_unit", + "difficulty": 4, + "flags": [ + "OVER", "CARGO", "NO_REINFORCE", "OBSTACLE", "KITCHEN" + ] + }, + { + "name": "welding rig", + "symbol": "&", + "color": "light_red", + "broken_symbol": "x", + "broken_color": "light_red", + "damage_modifier": 10, + "durability": 20, + "item": "weldrig", + "difficulty": 4, + "flags": [ + "OVER", "CARGO", "NO_REINFORCE", "OBSTACLE", "WELDRIG" + ] + }, + { + "name": "mounted M249", + "symbol": "t", + "color": "cyan", + "broken_symbol": "#", + "broken_color": "cyan", + "damage_modifier": 80, + "durability": 400, + "fuel_type": "223", + "item": "m249", + "difficulty": 6, + "flags": [ + "OVER", "TURRET", "CARGO" + ] + }, + { + "name": "mounted flamethrower", + "symbol": "t", + "color": "dark_gray", + "broken_symbol": "#", + "broken_color": "dark_gray", + "damage_modifier": 80, + "durability": 400, + "fuel_type": "gasoline", + "item": "flamethrower", + "difficulty": 7, + "flags": [ + "OVER", "TURRET" + ] + }, + { + "name": "mounted plasma gun", + "symbol": "t", + "color": "light_blue", + "broken_symbol": "#", + "broken_color": "light_blue", + "damage_modifier": 80, + "durability": 400, + "fuel_type": "plasma", + "item": "plasma_rifle", + "difficulty": 7, + "flags": [ + "OVER", "TURRET" + ] + }, + { + "name": "mounted fusion gun", + "symbol": "t", + "color": "magenta", + "broken_symbol": "#", + "broken_color": "magenta", + "damage_modifier": 80, + "durability": 400, + "fuel_type": "battery", + "item": "ftk93", + "difficulty": 7, + "flags": [ + "OVER", "TURRET" + ] + }, + { + "name": "steel plating", + "symbol": ")", + "color": "light_cyan", + "broken_symbol": ")", + "broken_color": "light_cyan", + "durability": 1000, + "item": "steel_plate", + "difficulty": 3, + "flags": [ + "INTERNAL", "ARMOR" + ] + }, + { + "name": "superalloy plating", + "symbol": ")", + "color": "dark_gray", + "broken_symbol": ")", + "broken_color": "dark_gray", + "durability": 900, + "item": "alloy_plate", + "difficulty": 4, + "flags": [ + "INTERNAL", "ARMOR" + ] + }, + { + "name": "spiked plating", + "symbol": ")", + "color": "red", + "broken_symbol": ")", + "broken_color": "red", + "damage_modifier": 150, + "durability": 900, + "item": "spiked_plate", + "difficulty": 3, + "flags": [ + "INTERNAL", "ARMOR", "SHARP" + ] + }, + { + "name": "hard plating", + "symbol": ")", + "color": "cyan", + "broken_symbol": ")", + "broken_color": "cyan", + "durability": 2300, + "item": "hard_plate", + "difficulty": 4, + "flags": [ + "INTERNAL", "ARMOR" + ] + }, + { + "name": "head light", + "symbol": "*", + "color": "white", + "broken_symbol": "*", + "broken_color": "white", + "damage_modifier": 10, + "durability": 20, + "par1": 480, + "item": "flashlight", + "difficulty": 1, + "flags": [ + "INTERNAL", "LIGHT" + ] + } +] diff --git a/game.cpp b/game.cpp index 8cc7975db8e9f..60fc273c9c5b5 100644 --- a/game.cpp +++ b/game.cpp @@ -103,6 +103,7 @@ game::game() : init_missions(); // Set up mission templates (SEE missiondef.cpp) init_construction(); // Set up constructables (SEE construction.cpp) init_traits_mutations(); + init_vehicle_parts(); // Set up vehicle parts (SEE veh_typedef.cpp) init_vehicles(); // Set up vehicles (SEE veh_typedef.cpp) init_autosave(); // Set up autosave init_diseases(); // Set up disease lookup table @@ -5864,7 +5865,7 @@ void game::open() int vpart; vehicle *veh = m.veh_at(openx, openy, vpart); - if (veh && veh->part_flag(vpart, vpf_openable)) { + if (veh && veh->part_flag(vpart, "OPENABLE")) { if (veh->parts[vpart].open) { add_msg(_("That door is already open.")); u.moves += 100; @@ -5912,7 +5913,7 @@ void game::close() if (mon_at(closex, closey) != -1) add_msg(_("There's a %s in the way!"), z[mon_at(closex, closey)].name().c_str()); - else if (veh && veh->part_flag(vpart, vpf_openable) && + else if (veh && veh->part_flag(vpart, "OPENABLE") && veh->parts[vpart].open) { veh->parts[vpart].open = 0; veh->insides_dirty = true; @@ -6125,7 +6126,7 @@ bool game::vehicle_near () bool game::pl_refill_vehicle (vehicle &veh, int part, bool test) { - if (!veh.part_flag(part, vpf_fuel_tank)) + if (!veh.part_flag(part, "FUEL_TANK")) return false; item* it = NULL; item *p_itm = NULL; @@ -6413,7 +6414,7 @@ void game::control_vehicle() std::string message = veh->use_controls(); if (!message.empty()) add_msg(message.c_str()); - } else if (veh && veh->part_with_feature(veh_part, vpf_controls) >= 0 + } else if (veh && veh->part_with_feature(veh_part, "CONTROLS") >= 0 && u.in_vehicle) { u.controlling_vehicle = true; add_msg(_("You take control of the %s."), veh->name.c_str()); @@ -6426,7 +6427,7 @@ void game::control_vehicle() add_msg(_("No vehicle there.")); return; } - if (veh->part_with_feature(veh_part, vpf_controls) < 0) { + if (veh->part_with_feature(veh_part, "CONTROLS") < 0) { add_msg(_("No controls there.")); return; } @@ -6445,8 +6446,8 @@ void game::examine() int veh_part = 0; vehicle *veh = m.veh_at (examx, examy, veh_part); if (veh) { - int vpcargo = veh->part_with_feature(veh_part, vpf_cargo, false); - int vpkitchen = veh->part_with_feature(veh_part, vpf_kitchen, true); + int vpcargo = veh->part_with_feature(veh_part, "CARGO", false); + int vpkitchen = veh->part_with_feature(veh_part, "KITCHEN", true); if ((vpcargo >= 0 && veh->parts[vpcargo].items.size() > 0) || vpkitchen >= 0) pickup(examx, examy, 0); else if (u.in_vehicle) @@ -6826,7 +6827,7 @@ void advanced_inv_update_area( advanced_inv_area &area, game *g ) { int vp = 0; area.veh = g->m.veh_at( u.posx+area.offx,u.posy+area.offy, vp ); if ( area.veh ) { - area.vstor = area.veh->part_with_feature(vp, vpf_cargo, false); + area.vstor = area.veh->part_with_feature(vp, "CARGO", false); } if ( area.vstor >= 0 ) { area.desc = area.veh->name; @@ -8380,11 +8381,11 @@ void game::pickup(int posx, int posy, int min) int k_part = 0; vehicle *veh = m.veh_at (posx, posy, veh_part); if (min != -1 && veh) { - k_part = veh->part_with_feature(veh_part, vpf_kitchen); - veh_part = veh->part_with_feature(veh_part, vpf_cargo, false); + k_part = veh->part_with_feature(veh_part, "KITCHEN"); + veh_part = veh->part_with_feature(veh_part, "CARGO", false); from_veh = veh && veh_part >= 0 && veh->parts[veh_part].items.size() > 0 && - query_yn(_("Get items from %s?"), veh->part_info(veh_part).name); + query_yn(_("Get items from %s?"), veh->part_info(veh_part).name.c_str()); if (!from_veh && k_part >= 0) { if (veh->fuel_left("water")) { @@ -9206,7 +9207,7 @@ void game::drop(char chInput) bool to_veh = false; vehicle *veh = m.veh_at(u.posx, u.posy, veh_part); if (veh) { - veh_part = veh->part_with_feature (veh_part, vpf_cargo); + veh_part = veh->part_with_feature (veh_part, "CARGO"); to_veh = veh_part >= 0; } if (dropped.size() == 1 || same) { @@ -9216,7 +9217,7 @@ void game::drop(char chInput) dropped.size()), dropped[0].tname(this).c_str(), veh->name.c_str(), - veh->part_info(veh_part).name); + veh->part_info(veh_part).name.c_str()); } else { add_msg(ngettext("You drop your %s.", "You drop your %ss.", dropped.size()), @@ -9225,7 +9226,7 @@ void game::drop(char chInput) } else { if (to_veh) { add_msg(_("You put several items in the %s's %s."), - veh->name.c_str(), veh->part_info(veh_part).name); + veh->name.c_str(), veh->part_info(veh_part).name.c_str()); } else { add_msg(_("You drop several items.")); } @@ -9259,7 +9260,7 @@ void game::drop_in_direction() bool to_veh = false; vehicle *veh = m.veh_at(dirx, diry, veh_part); if (veh) { - veh_part = veh->part_with_feature (veh_part, vpf_cargo); + veh_part = veh->part_with_feature (veh_part, "CARGO"); to_veh = veh->type != veh_null && veh_part >= 0; } @@ -9294,7 +9295,7 @@ void game::drop_in_direction() dropped.size()), dropped[0].tname(this).c_str(), veh->name.c_str(), - veh->part_info(veh_part).name); + veh->part_info(veh_part).name.c_str()); } else if (can_move_there) { add_msg(ngettext("You drop your %s on the %s.", "You drop your %ss on the %s.", dropped.size()), @@ -9309,7 +9310,7 @@ void game::drop_in_direction() } else { if (to_veh) { add_msg(_("You put several items in the %s's %s."), - veh->name.c_str(), veh->part_info(veh_part).name); + veh->name.c_str(), veh->part_info(veh_part).name.c_str()); } else if (can_move_there) { add_msg(_("You drop several items on the %s."), m.name(dirx, diry).c_str()); @@ -10207,7 +10208,7 @@ void game::pldrive(int x, int y) { u.in_vehicle = false; return; } - int pctr = veh->part_with_feature (part, vpf_controls); + int pctr = veh->part_with_feature (part, "CONTROLS"); if (pctr < 0) { add_msg (_("You can't drive the vehicle from here. You need controls!")); return; @@ -10365,7 +10366,7 @@ void game::plmove(int dx, int dy) } bool veh_closed_door = false; if (veh1) { - dpart = veh1->part_with_feature (vpart1, vpf_openable); + dpart = veh1->part_with_feature (vpart1, "OPENABLE"); veh_closed_door = dpart >= 0 && !veh1->parts[dpart].open; } @@ -10378,7 +10379,7 @@ void game::plmove(int dx, int dy) } else if (veh1 != veh0) { add_msg(_("There is another vehicle in the way.")); return; - } else if (veh1->part_with_feature(vpart1, vpf_boardable) < 0) { + } else if (veh1->part_with_feature(vpart1, "BOARDABLE") < 0) { add_msg(_("That part of the vehicle is currently unsafe.")); return; } @@ -10459,7 +10460,7 @@ void game::plmove(int dx, int dy) int gy = grabbed_vehicle->global_y(); for( int ep = 0; ep < grabbed_vehicle->external_parts.size(); ep++ ) { const int p = grabbed_vehicle->external_parts[ ep ]; - if( grabbed_vehicle->part_flag( p, vpf_wheel ) && one_in(2) ) + if( grabbed_vehicle->part_flag( p, "WHEEL" ) && one_in(2) ) grabbed_vehicle->handle_trap( gx + grabbed_vehicle->parts[p].precalc_dx[0] + dx, gy + grabbed_vehicle->parts[p].precalc_dy[0] + dy, p ); } @@ -10489,7 +10490,7 @@ void game::plmove(int dx, int dy) ( u.has_trait("PARKOUR") && m.move_cost(x, y) > 4 )) { if (veh1 && m.move_cost(x,y) != 2) - add_msg(_("Moving past this %s is slow!"), veh1->part_info(vpart1).name); + add_msg(_("Moving past this %s is slow!"), veh1->part_info(vpart1).name.c_str()); else add_msg(_("Moving past this %s is slow!"), m.name(x, y).c_str()); } @@ -10562,7 +10563,7 @@ void game::plmove(int dx, int dy) } // If the new tile is a boardable part, board it - if (veh1 && veh1->part_with_feature(vpart1, vpf_boardable) >= 0) + if (veh1 && veh1->part_with_feature(vpart1, "BOARDABLE") >= 0) m.board_vehicle(this, u.posx, u.posy, &u); if (m.tr_at(x, y) != tr_null) { // We stepped on a trap! @@ -10631,7 +10632,7 @@ void game::plmove(int dx, int dy) } } - if (veh1 && veh1->part_with_feature(vpart1, vpf_controls) >= 0 + if (veh1 && veh1->part_with_feature(vpart1, "CONTROLS") >= 0 && u.in_vehicle) add_msg(_("There are vehicle controls here. %s to drive."), press_x(ACTION_CONTROL_VEHICLE).c_str() ); @@ -10672,7 +10673,7 @@ void game::plmove(int dx, int dy) u.posx += (tunneldist + 1) * (x - u.posx); //move us the number of tiles we tunneled in the x direction, plus 1 for the last tile u.posy += (tunneldist + 1) * (y - u.posy); //ditto for y add_msg(_("You quantum tunnel through the %d-tile wide barrier!"), tunneldist); - if (m.veh_at(u.posx, u.posy, vpart1) && m.veh_at(u.posx, u.posy, vpart1)->part_with_feature(vpart1, vpf_boardable) >= 0) + if (m.veh_at(u.posx, u.posy, vpart1) && m.veh_at(u.posx, u.posy, vpart1)->part_with_feature(vpart1, "BOARDABLE") >= 0) m.board_vehicle(this, u.posx, u.posy, &u); } else //or you couldn't tunnel due to lack of energy @@ -10685,7 +10686,7 @@ void game::plmove(int dx, int dy) veh1->insides_dirty = true; u.moves -= 100; add_msg (_("You open the %s's %s."), veh1->name.c_str(), - veh1->part_info(dpart).name); + veh1->part_info(dpart).name.c_str()); } else if (m.has_flag(swimmable, x, y)) { // Dive into water! // Requires confirmation if we were on dry land previously diff --git a/game.h b/game.h index b2d097cbe3341..e580ebc46cf63 100644 --- a/game.h +++ b/game.h @@ -364,6 +364,7 @@ void load_artifacts(); // Load artifact data void init_construction(); // Initializes construction "recipes" void init_missions(); // Initializes mission templates void init_traits_mutations(); // Initializes mutation "tech tree" + void init_vehicle_parts(); // Initializes vehicle part types void init_vehicles(); // Initializes vehicle types void init_autosave(); // Initializes autosave parameters void init_diseases(); // Initializes disease lookup table. diff --git a/inventory.cpp b/inventory.cpp index 82bfbad071cb5..69044ad0a9412 100644 --- a/inventory.cpp +++ b/inventory.cpp @@ -557,8 +557,8 @@ void inventory::form_from_map(game *g, point origin, int range) vehicle *veh = g->m.veh_at(x, y, vpart); if (veh) { - const int kpart = veh->part_with_feature(vpart, vpf_kitchen); - const int weldpart = veh->part_with_feature(vpart, vpf_weldrig); + const int kpart = veh->part_with_feature(vpart, "KITCHEN"); + const int weldpart = veh->part_with_feature(vpart, "WELDRIG"); if (kpart >= 0) { item hotplate(g->itypes["hotplate"], 0); diff --git a/item_factory.cpp b/item_factory.cpp index 181bb02d53e76..5cde73eaedd59 100644 --- a/item_factory.cpp +++ b/item_factory.cpp @@ -710,44 +710,6 @@ void Item_factory::load_item_groups_from( game *g, const std::string file_name ) } } -//Grab color, with appropriate error handling -nc_color Item_factory::color_from_string(std::string new_color){ - if("red"==new_color){ - return c_red; - } else if("blue"==new_color){ - return c_blue; - } else if("green"==new_color){ - return c_green; - } else if("light_cyan"==new_color){ - return c_ltcyan; - } else if("brown"==new_color){ - return c_brown; - } else if("light_red"==new_color){ - return c_ltred; - } else if("white"==new_color){ - return c_white; - } else if("light_blue"==new_color){ - return c_ltblue; - } else if("yellow"==new_color){ - return c_yellow; - } else if("magenta"==new_color){ - return c_magenta; - } else if("cyan"==new_color){ - return c_cyan; - } else if("light_gray"==new_color){ - return c_ltgray; - } else if("dark_gray"==new_color){ - return c_dkgray; - } else if("light_green"==new_color){ - return c_ltgreen; - } else if("pink"==new_color){ - return c_pink; - } else { - debugmsg("Received invalid color property %s. Color is required.", new_color.c_str()); - return c_white; - } -} - Use_function Item_factory::use_from_string(std::string function_name){ std::map::iterator found_function = iuse_function_list.find(function_name); diff --git a/item_factory.h b/item_factory.h index eb649798b50ec..6b00f164dff7c 100644 --- a/item_factory.h +++ b/item_factory.h @@ -55,7 +55,6 @@ class Item_factory void load_item_templates_from(const std::string file_name) throw (std::string); void load_item_groups_from(game *g, const std::string file_name) throw (std::string); - nc_color color_from_string(std::string color); Use_function use_from_string(std::string name); void tags_from_json(catajson tag_list, std::set &tags); unsigned flags_from_json(catajson flags, std::string flag_type=""); diff --git a/lightmap.cpp b/lightmap.cpp index 3a787dace0db3..6df3bdc254604 100644 --- a/lightmap.cpp +++ b/lightmap.cpp @@ -156,7 +156,7 @@ void map::generate_lightmap(game* g) float iteration=1.0; for (std::vector::iterator part = vehs[v].v->external_parts.begin(); part != vehs[v].v->external_parts.end(); ++part) { - int dpart = vehs[v].v->part_with_feature(*part , vpf_light); + int dpart = vehs[v].v->part_with_feature(*part , "LIGHT"); if (dpart >= 0) { veh_luminance += ( vehs[v].v->part_info(dpart).power / iteration ); iteration=iteration * 1.1; @@ -168,7 +168,7 @@ void map::generate_lightmap(game* g) int px = vehs[v].x + vehs[v].v->parts[*part].precalc_dx[0]; int py = vehs[v].y + vehs[v].v->parts[*part].precalc_dy[0]; if(INBOUNDS(px, py)) { - int dpart = vehs[v].v->part_with_feature(*part , vpf_light); + int dpart = vehs[v].v->part_with_feature(*part , "LIGHT"); if (dpart >= 0) { apply_light_arc(px, py, dir + vehs[v].v->parts[dpart].direction, veh_luminance, 45); diff --git a/map.cpp b/map.cpp index 2b61e11bc6cc6..f6b385d422e3a 100644 --- a/map.cpp +++ b/map.cpp @@ -204,10 +204,10 @@ void map::board_vehicle(game *g, int x, int y, player *p) return; } - const int seat_part = veh->part_with_feature (part, vpf_boardable); + const int seat_part = veh->part_with_feature (part, "BOARDABLE"); if (part < 0) { debugmsg ("map::board_vehicle: boarding %s (not boardable)", - veh->part_info(part).name); + veh->part_info(part).name.c_str()); return; } if (veh->parts[seat_part].has_flag(vehicle_part::passenger_flag)) { @@ -237,10 +237,10 @@ void map::unboard_vehicle(game *g, const int x, const int y) debugmsg ("map::unboard_vehicle: vehicle not found"); return; } - const int seat_part = veh->part_with_feature (part, vpf_boardable, false); + const int seat_part = veh->part_with_feature (part, "BOARDABLE", false); if (part < 0) { debugmsg ("map::unboard_vehicle: unboarding %s (not boardable)", - veh->part_info(part).name); + veh->part_info(part).name.c_str()); return; } player *psg = veh->get_passenger(seat_part); @@ -474,7 +474,7 @@ bool map::vehproceed(game* g){ int num_wheels = 0, submerged_wheels = 0; for (int ep = 0; ep < veh->external_parts.size(); ep++) { const int p = veh->external_parts[ep]; - if (veh->part_flag(p, vpf_wheel)){ + if (veh->part_flag(p, "WHEEL")){ num_wheels++; const int px = x + veh->parts[p].precalc_dx[0]; const int py = y + veh->parts[p].precalc_dy[0]; @@ -563,8 +563,8 @@ bool map::vehproceed(game* g){ veh_collision c = veh_veh_colls[0]; vehicle* veh2 = (vehicle*) c.target; g->add_msg(_("The %1$s's %2$s collides with the %3$s's %4$s."), - veh->name.c_str(), veh->part_info(c.part).name, - veh2->name.c_str(), veh2->part_info(c.target_part).name); + veh->name.c_str(), veh->part_info(c.part).name.c_str(), + veh2->name.c_str(), veh2->part_info(c.target_part).name.c_str()); // for reference, a cargo truck weighs ~25300, a bicycle 690, // and 38mph is 3800 'velocity' @@ -629,7 +629,7 @@ bool map::vehproceed(game* g){ continue; } const int throw_roll = rng (vel2/100, vel2/100 * 2); - const int psblt = veh->part_with_feature (ppl[ps], vpf_seatbelt); + const int psblt = veh->part_with_feature (ppl[ps], "SEATBELT"); const int sb_bonus = psblt >= 0? veh->part_info(psblt).bonus : 0; bool throw_from_seat = throw_roll > (psg->str_cur + sb_bonus) * 3; @@ -644,7 +644,7 @@ bool map::vehproceed(game* g){ g->fling_player_or_monster(psg, 0, mdir.dir() + rng(0, 60) - 30, (vel2/100 - sb_bonus < 10 ? 10 : vel2/100 - sb_bonus)); - } else if (veh->part_with_feature (ppl[ps], vpf_controls) >= 0) { + } else if (veh->part_with_feature (ppl[ps], "CONTROLS") >= 0) { // FIXME: should actually check if passenger is in control, // not just if there are controls there. const int lose_ctrl_roll = rng (0, imp); @@ -674,7 +674,7 @@ bool map::vehproceed(game* g){ if (can_move) { for (int ep = 0; ep < veh->external_parts.size(); ep++) { const int p = veh->external_parts[ep]; - if (veh->part_flag(p, vpf_wheel) && one_in(2)) + if (veh->part_flag(p, "WHEEL") && one_in(2)) if (displace_water (x + veh->parts[p].precalc_dx[0], y + veh->parts[p].precalc_dy[0]) && pl_ctrl) g->add_msg(_("You hear a splash!")); veh->handle_trap(x + veh->parts[p].precalc_dx[0], @@ -859,11 +859,11 @@ int map::move_cost(const int x, const int y, const vehicle *ignored_vehicle) int vpart = -1; vehicle *veh = veh_at(x, y, vpart); if (veh && veh != ignored_vehicle) { // moving past vehicle cost - const int dpart = veh->part_with_feature(vpart, vpf_obstacle); - if (dpart >= 0 && (!veh->part_flag(dpart, vpf_openable) || !veh->parts[dpart].open)) { + const int dpart = veh->part_with_feature(vpart, "OBSTACLE"); + if (dpart >= 0 && (!veh->part_flag(dpart, "OPENABLE") || !veh->parts[dpart].open)) { return 0; } else { - const int ipart = veh->part_with_feature(vpart, vpf_aisle); + const int ipart = veh->part_with_feature(vpart, "AISLE"); if (ipart >= 0) return 2; return 8; @@ -900,9 +900,9 @@ bool map::trans(const int x, const int y) vehicle *veh = veh_at(x, y, vpart); bool tertr; if (veh) { - tertr = !veh->part_flag(vpart, vpf_opaque) || veh->parts[vpart].hp <= 0; + tertr = !veh->part_flag(vpart, "OPAQUE") || veh->parts[vpart].hp <= 0; if (!tertr) { - const int dpart = veh->part_with_feature(vpart, vpf_openable); + const int dpart = veh->part_with_feature(vpart, "OPENABLE"); if (dpart >= 0 && veh->parts[dpart].open) tertr = true; // open opaque door } @@ -934,8 +934,8 @@ bool map::has_flag(const t_flag flag, const int x, const int y) int vpart; vehicle *veh = veh_at(x, y, vpart); if (veh && veh->parts[vpart].hp > 0 && // if there's a vehicle part here... - veh->part_with_feature (vpart, vpf_obstacle) >= 0) {// & it is obstacle... - const int p = veh->part_with_feature (vpart, vpf_openable); + veh->part_with_feature (vpart, "OBSTACLE") >= 0) {// & it is obstacle... + const int p = veh->part_with_feature (vpart, "OPENABLE"); if (p < 0 || !veh->parts[p].open) // and not open door return true; } @@ -2709,8 +2709,8 @@ std::list map::use_charges(const point origin, const int range, const ityp vehicle *veh = veh_at(x, y, vpart); if (veh) { // check if a vehicle part is present to provide water/power - const int kpart = veh->part_with_feature(vpart, vpf_kitchen); - const int weldpart = veh->part_with_feature(vpart, vpf_weldrig); + const int kpart = veh->part_with_feature(vpart, "KITCHEN"); + const int weldpart = veh->part_with_feature(vpart, "WELDRIG"); if (kpart >= 0) { // we have a kitchen, now to see what to drain ammotype ftype = "NULL"; @@ -4089,8 +4089,8 @@ void map::build_map_cache(game *g) if (vehs[v].v->is_inside(*part)) { outside_cache[px][py] = false; } - if (vehs[v].v->part_flag(*part, vpf_opaque) && vehs[v].v->parts[*part].hp > 0) { - int dpart = vehs[v].v->part_with_feature(*part , vpf_openable); + if (vehs[v].v->part_flag(*part, "OPAQUE") && vehs[v].v->parts[*part].hp > 0) { + int dpart = vehs[v].v->part_with_feature(*part , "OPENABLE"); if (dpart < 0 || !vehs[v].v->parts[dpart].open) { transparency_cache[px][py] = LIGHT_TRANSPARENCY_SOLID; } diff --git a/player.cpp b/player.cpp index be41ae8cbcd75..a507c50918c87 100644 --- a/player.cpp +++ b/player.cpp @@ -696,11 +696,11 @@ void player::update_bodytemp(game *g) { floor_bedding_warmth -= 1000; } - else if (veh && veh->part_with_feature (vpart, vpf_seat) >= 0) + else if (veh && veh->part_with_feature (vpart, "SEAT") >= 0) { floor_bedding_warmth += 200; } - else if (veh && veh->part_with_feature (vpart, vpf_bed) >= 0) + else if (veh && veh->part_with_feature (vpart, "BED") >= 0) { floor_bedding_warmth += 300; } @@ -2989,7 +2989,7 @@ void player::disp_status(WINDOW *w, WINDOW *w2, game *g) bool has_turrets = false; for (int p = 0; p < veh->parts.size(); p++) { - if (veh->part_flag (p, vpf_turret)) { + if (veh->part_flag (p, "TURRET")) { has_turrets = true; break; } @@ -7677,8 +7677,8 @@ void player::try_to_sleep(game *g) if (furn_at_pos == f_bed || furn_at_pos == f_makeshift_bed || trap_at_pos == tr_cot || trap_at_pos == tr_rollmat || furn_at_pos == f_armchair || furn_at_pos == f_sofa || - (veh && veh->part_with_feature (vpart, vpf_seat) >= 0) || - (veh && veh->part_with_feature (vpart, vpf_bed) >= 0)) + (veh && veh->part_with_feature (vpart, "SEAT") >= 0) || + (veh && veh->part_with_feature (vpart, "BED") >= 0)) g->add_msg(_("This is a comfortable place to sleep.")); else if (ter_at_pos != t_floor) g->add_msg( @@ -7702,11 +7702,11 @@ bool player::can_sleep(game *g) const trap_id trap_at_pos = g->m.tr_at(posx, posy); const ter_id ter_at_pos = g->m.ter(posx, posy); const furn_id furn_at_pos = g->m.furn(posx, posy); - if ((veh && veh->part_with_feature (vpart, vpf_bed) >= 0) || + if ((veh && veh->part_with_feature (vpart, "BED") >= 0) || furn_at_pos == f_makeshift_bed || trap_at_pos == tr_cot || furn_at_pos == f_sofa) sleepy += 4; - else if ((veh && veh->part_with_feature (vpart, vpf_seat) >= 0) || + else if ((veh && veh->part_with_feature (vpart, "SEAT") >= 0) || trap_at_pos == tr_rollmat || furn_at_pos == f_armchair) sleepy += 3; else if (furn_at_pos == f_bed) diff --git a/veh_interact.cpp b/veh_interact.cpp index 832ec6815e34e..22ec592cf0b6d 100644 --- a/veh_interact.cpp +++ b/veh_interact.cpp @@ -253,7 +253,7 @@ void veh_interact::do_install(int reason) int dif_eng = 0; for (int p = 0; p < veh->parts.size(); p++) { - if (veh->part_flag (p, vpf_engine)) + if (veh->part_flag (p, "ENGINE")) { engines++; dif_eng = dif_eng / 2 + 12; @@ -277,7 +277,7 @@ void veh_interact::do_install(int reason) wprintz(w_msg, c_ltgray, rm_prefix(_(", and level ")).c_str()); wprintz(w_msg, has_skill? c_ltgreen : c_red, "%d", vpart_list[sel_part].difficulty); wprintz(w_msg, c_ltgray, rm_prefix(_(" skill in mechanics.")).c_str()); - bool eng = vpart_list[sel_part].flags & mfb (vpf_engine); + bool eng = vpart_list[sel_part].has_flag("ENGINE"); bool has_skill2 = !eng || (g->u.skillLevel("mechanics") >= dif_eng); if (engines && eng) // already has engine { @@ -681,11 +681,11 @@ void veh_interact::move_cursor (int dx, int dy) { need_repair.push_back (i); } - if (veh->part_flag(p, vpf_fuel_tank) && veh->parts[p].amount < veh->part_info(p).size) + if (veh->part_flag(p, "FUEL_TANK") && veh->parts[p].amount < veh->part_info(p).size) { ptank = p; } - if (veh->part_flag(p, vpf_wheel) && veh->parts[p].amount < veh->part_info(p).size) + if (veh->part_flag(p, "WHEEL") && veh->parts[p].amount < veh->part_info(p).size) { wheel = p; } @@ -840,9 +840,9 @@ void veh_interact::display_list (int pos) itype_id itm = vpart_list[can_mount[i]].item; bool has_comps = crafting_inv.has_amount(itm, 1); bool has_skill = g->u.skillLevel("mechanics") >= vpart_list[can_mount[i]].difficulty; - bool is_wheel = vpart_list[can_mount[i]].flags & mfb(vpf_wheel); + bool is_wheel = vpart_list[can_mount[i]].has_flag("WHEEL"); nc_color col = has_comps && (has_skill || is_wheel) ? c_white : c_dkgray; - mvwprintz(w_list, y, 3, pos == i? hilite (col) : col, vpart_list[can_mount[i]].name); + mvwprintz(w_list, y, 3, pos == i? hilite (col) : col, vpart_list[can_mount[i]].name.c_str()); mvwputch (w_list, y, 1, vpart_list[can_mount[i]].color, special_symbol (vpart_list[can_mount[i]].sym)); } @@ -1004,7 +1004,7 @@ void complete_vehicle (game *g) } g->add_msg (_("You install a %s into the %s."), - vpart_list[part].name, veh->name.c_str()); + vpart_list[part].name.c_str(), veh->name.c_str()); g->u.practice (g->turn, "mechanics", vpart_list[part].difficulty * 5 + 20); break; case 'r': @@ -1023,7 +1023,7 @@ void complete_vehicle (game *g) g->consume_tools(&g->u, tools, true); veh->parts[part].hp = veh->part_info(part).durability; g->add_msg (_("You repair the %s's %s."), - veh->name.c_str(), veh->part_info(part).name); + veh->name.c_str(), veh->part_info(part).name.c_str()); g->u.practice (g->turn, "mechanics", (vpart_list[part].difficulty + dd) * 5 + 20); break; case 'f': @@ -1053,7 +1053,7 @@ void complete_vehicle (game *g) else { g->add_msg (_("You remove %s%s from %s."), broken? rm_prefix(_("broken ")).c_str() : "", - veh->part_info(part).name, veh->name.c_str()); + veh->part_info(part).name.c_str(), veh->name.c_str()); veh->remove_part (part); } break; @@ -1064,13 +1064,13 @@ void complete_vehicle (game *g) parts = veh->parts_at_relative( dx, dy ); if( parts.size() ) { item removed_wheel; - replaced_wheel = veh->part_with_feature( parts[0], vpf_wheel, false ); + replaced_wheel = veh->part_with_feature( parts[0], "WHEEL", false ); broken = veh->parts[replaced_wheel].hp <= 0; if( replaced_wheel != -1 ) { removed_wheel = veh->item_from_part( replaced_wheel ); veh->remove_part( replaced_wheel ); g->add_msg( _("You replace one of the %s's tires with %s."), - veh->name.c_str(), vpart_list[part].name ); + veh->name.c_str(), vpart_list[part].name.c_str() ); } else { debugmsg( "no wheel to remove when changing wheels." ); return; diff --git a/veh_type.h b/veh_type.h index 88ec78dd1bf36..ce4276bcdc9e1 100644 --- a/veh_type.h +++ b/veh_type.h @@ -95,51 +95,15 @@ enum vpart_id num_vparts }; -enum vpart_flags -{ - vpf_external, // can be mounted as external part - vpf_internal, // can be mounted inside other part - vpf_mount_point, // allows mounting other parts to it - vpf_mount_inner, // allows mounting internal parts inside it (or over it) - vpf_mount_over, // allows mounting parts like cargo trunk over it - vpf_anchor_point, // Allows secure attachment of a seatbelt - vpf_opaque, // can't see through it - vpf_obstacle, // can't pass through it - vpf_openable, // can open/close it - vpf_no_reinforce, // can't reinforce this part with armor plates - vpf_sharp, // cutting damage instead of bashing - vpf_unmount_on_damage, // when damaged, part is unmounted, rather than broken - vpf_boardable, // part can carry passengers - -// functional flags (only one of each can be mounted per tile) - vpf_over, // can be mounted over other part - vpf_roof, // is a roof (cover) - vpf_wheel, // this part touches ground (trigger traps) - vpf_seat, // is seat - vpf_bed, // is bed (like seat, but can't be boarded) - vpf_aisle, // is aisle (no extra movement cost) - vpf_engine, // is engine - vpf_kitchen, // is kitchen - vpf_weldrig, // is welding rig - vpf_fuel_tank, // is fuel tank - vpf_cargo, // is cargo - vpf_controls, // is controls - vpf_muffler, // is muffler - vpf_seatbelt, // is seatbelt - vpf_solar_panel, // is solar panel - vpf_turret, // is turret - vpf_armor, // is armor plating - vpf_light, // generates light arc - vpf_variable_size, // has 'bigness' for power, wheel radius, etc. - vpf_func_begin = vpf_over, - vpf_func_end = vpf_light, - - num_vpflags -}; - +/* Flag info: + * INTERNAL - Can be mounted inside other parts + * ANCHOR_POINT - Allows secure seatbelt attachment + * OVER - Can be mounted over other parts + * VARIABLE_SIZE - Has 'bigness' for power, wheel radius, etc + * Other flags are self-explanatory in their names. */ struct vpart_info { - const char *name; // part name + std::string name; // part name long sym; // symbol of part as if it's looking north nc_color color; // color char sym_broken; // symbol of broken part as if it's looking north @@ -154,170 +118,17 @@ struct vpart_info int wheel_width;// wheel width in inches. car could be 9, bicycle could be 2. int bonus; // seatbelt (str), muffler (%) }; - int par2; std::string fuel_type; // engine, fuel tank itype_id item; // corresponding item int difficulty; // installation difficulty (mechanics requirement) - unsigned long flags; // flags -}; - -// following symbols will be translated: -// y, u, n, b to NW, NE, SE, SW lines correspondingly -// h, j, c to horizontal, vertical, cross correspondingly -const vpart_info vpart_list[num_vparts] = -{ // name sym color sym_b color_b dmg dur par1 par2 fuel item - { "null part", '?', c_red, '?', c_red, 100, 100, 0, 0, "NULL", "null", 0, - 0 }, - { "seat", '#', c_red, '*', c_red, 60, 300, 0, 0, "NULL", "seat", 1, - mfb(vpf_over) | mfb(vpf_seat) | mfb(vpf_boardable) | mfb(vpf_cargo) | - mfb(vpf_no_reinforce) | mfb(vpf_anchor_point) }, - { "saddle", '#', c_red, '*', c_red, 20, 200, 0, 0, "NULL", "saddle", 1, - mfb(vpf_over) | mfb(vpf_seat) | mfb(vpf_boardable) | - mfb(vpf_no_reinforce) }, - { "bed", '#', c_magenta, '*', c_magenta, 60, 300, 0, 0, "NULL", "seat", 1, - mfb(vpf_over) | mfb(vpf_bed) | mfb(vpf_boardable) | - mfb(vpf_cargo) | mfb(vpf_no_reinforce) }, - { "frame", 'h', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", 'j', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", 'c', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", 'y', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", 'u', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", 'n', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", 'b', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", '=', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", 'H', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "frame", '^', c_ltgray, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "handle", '^', c_ltcyan, '#', c_ltcyan, 100, 300, 0, 0, "NULL", "frame", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) }, - { "board", 'h', c_ltgray, '#', c_ltgray, 100, 1000, 0, 0, "NULL", "steel_plate", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) | mfb(vpf_opaque) | mfb(vpf_obstacle) }, - { "board", 'j', c_ltgray, '#', c_ltgray, 100, 1000, 0, 0, "NULL", "steel_plate", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) | mfb(vpf_opaque) | mfb(vpf_obstacle) }, - { "board", 'y', c_ltgray, '#', c_ltgray, 100, 1000, 0, 0, "NULL", "steel_plate", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) | mfb(vpf_opaque) | mfb(vpf_obstacle) }, - { "board", 'u', c_ltgray, '#', c_ltgray, 100, 1000, 0, 0, "NULL", "steel_plate", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) | mfb(vpf_opaque) | mfb(vpf_obstacle) }, - { "board", 'n', c_ltgray, '#', c_ltgray, 100, 1000, 0, 0, "NULL", "steel_plate", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) | mfb(vpf_opaque) | mfb(vpf_obstacle) }, - { "board", 'b', c_ltgray, '#', c_ltgray, 100, 1000, 0, 0, "NULL", "steel_plate", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb (vpf_mount_inner) | mfb(vpf_opaque) | mfb(vpf_obstacle) }, - { "aisle", '=', c_white, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_internal) | mfb(vpf_over) | mfb(vpf_no_reinforce) | mfb(vpf_aisle) | mfb(vpf_boardable) }, - { "aisle", 'H', c_white, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_internal) | mfb(vpf_over) | mfb (vpf_no_reinforce) | mfb(vpf_aisle) | mfb(vpf_boardable) }, - { "floor trunk", '=', c_white, '#', c_ltgray, 100, 400, 0, 0, "NULL", "frame", 1, - mfb(vpf_internal) | mfb(vpf_over) | mfb (vpf_no_reinforce) | mfb(vpf_aisle) | mfb(vpf_boardable) | mfb(vpf_cargo) }, - { "roof", '#', c_ltgray, '#', c_dkgray, 100, 1000, 0, 0, "NULL", "steel_plate", 1, - mfb(vpf_internal) | mfb(vpf_roof) }, - { "door", '+', c_cyan, '&', c_cyan, 80, 200, 0, 0, "NULL", "frame", 2, - mfb(vpf_external) | mfb(vpf_obstacle) | mfb(vpf_openable) | mfb(vpf_boardable) }, - { "opaque door",'+', c_cyan, '&', c_cyan, 80, 200, 0, 0, "NULL", "frame", 2, - mfb(vpf_external) | mfb(vpf_obstacle) | mfb(vpf_opaque) | mfb(vpf_openable) | mfb(vpf_boardable) }, - { "internal door", '+', c_cyan, '&', c_cyan, 75, 75, 0, 0, "NULL", "frame", 2, - mfb(vpf_external) | mfb(vpf_obstacle) | mfb(vpf_opaque) | mfb(vpf_openable) | mfb(vpf_roof) | mfb(vpf_no_reinforce) | mfb(vpf_boardable) }, - { "windshield", '"', c_ltcyan, '0', c_ltgray, 70, 50, 0, 0, "NULL", "glass_sheet", 1, - mfb(vpf_over) | mfb(vpf_obstacle) | mfb(vpf_no_reinforce) }, - { "blade", '-', c_white, 'x', c_white, 250, 100, 0, 0, "NULL", "blade", 2, - mfb(vpf_external) | mfb(vpf_unmount_on_damage) | mfb(vpf_sharp) | mfb(vpf_no_reinforce) }, - { "blade", '|', c_white, 'x', c_white, 350, 100, 0, 0, "NULL", "blade", 2, - mfb(vpf_external) | mfb(vpf_unmount_on_damage) | mfb(vpf_sharp) | mfb(vpf_no_reinforce) }, - { "spike", '.', c_white, 'x', c_white, 300, 100, 0, 0, "NULL", "spike", 2, - mfb(vpf_external) | mfb(vpf_unmount_on_damage) | mfb(vpf_sharp) | mfb(vpf_no_reinforce) }, - -// wheel_width(inches) - { "wheel", '0', c_dkgray, 'x', c_ltgray, 50, 200, 9, 0, "NULL", "wheel", 4, - mfb(vpf_external) | mfb (vpf_mount_over) | mfb(vpf_wheel) | mfb(vpf_mount_point) | mfb(vpf_variable_size) }, - { "wide wheel", 'O', c_dkgray, 'x', c_ltgray, 50, 400, 14, 0, "NULL", "wheel_wide", 5, - mfb(vpf_external) | mfb (vpf_mount_over) | mfb(vpf_wheel) | mfb(vpf_mount_point) | mfb(vpf_variable_size) }, - { "wide wheel (underbody)", 'H', c_dkgray, 'x', c_ltgray, 50, 400, 14, 0, "NULL", "wheel_wide", 6, - mfb(vpf_external) | mfb (vpf_mount_inner) | mfb(vpf_wheel) | mfb(vpf_mount_point) | mfb(vpf_variable_size) }, - { "bicycle wheel",'|', c_dkgray, 'x', c_ltgray, 50, 40, 2, 0, "NULL", "wheel_bicycle", 1, - mfb(vpf_external) | mfb (vpf_mount_over) | mfb(vpf_wheel) | mfb(vpf_mount_point) | mfb(vpf_variable_size) }, - { "motorbike wheel",'o',c_dkgray, 'x', c_ltgray, 50, 90, 4, 0, "NULL", "wheel_motorbike", 2, - mfb(vpf_external) | mfb (vpf_mount_over) | mfb(vpf_wheel) | mfb(vpf_mount_point) | mfb(vpf_variable_size) }, - { "small wheel", 'o',c_dkgray, 'x', c_ltgray, 50, 70, 6, 0, "NULL", "wheel_small", 2, - mfb(vpf_external) | mfb (vpf_mount_over) | mfb(vpf_wheel) | mfb(vpf_mount_point) | mfb(vpf_variable_size) }, - { "casters", 'o',c_dkgray, 'x', c_ltgray, 50, 70, 6, 0, "NULL", "wheel_caster", 1, - mfb(vpf_external) | mfb(vpf_mount_point) | mfb(vpf_mount_inner) | mfb(vpf_wheel) | mfb(vpf_variable_size) }, -// - { "1-cylinder engine", '*', c_ltred, '#', c_red, 80, 150, 40, 0, "gasoline", "1cyl_combustion", 2, - mfb(vpf_internal) | mfb(vpf_engine) | mfb(vpf_variable_size) }, - { "V-twin engine", '*', c_ltred, '#', c_red, 80, 200, 120, 0, "gasoline", "v2_combustion", 2, - mfb(vpf_internal) | mfb(vpf_engine) | mfb(vpf_variable_size) }, - { "Inline-4 engine", '*', c_ltred, '#', c_red, 80, 300, 300, 0, "gasoline", "i4_combustion", 3, - mfb(vpf_internal) | mfb(vpf_engine) | mfb(vpf_variable_size) }, - { "V6 engine", '*', c_ltred, '#', c_red, 80, 400, 800, 0, "gasoline", "v6_combustion", 4, - mfb(vpf_internal) | mfb(vpf_engine) | mfb(vpf_variable_size) }, - { "V8 engine", '*', c_ltred, '#', c_red, 80, 400, 800, 0, "gasoline", "v8_combustion", 4, - mfb(vpf_internal) | mfb(vpf_engine) | mfb(vpf_variable_size) }, - { "electric motor", '*', c_yellow, '#', c_red, 80, 200, 70, 0, "battery", "motor", 3, - mfb(vpf_internal) | mfb(vpf_engine) }, - { "large electric motor", '*', c_yellow, '#', c_red, 80, 400, 350, 0, "battery", "motor_large", 4, - mfb(vpf_internal) | mfb(vpf_engine) }, - { "plasma engine", '*', c_ltblue, '#', c_red, 80, 250, 400, 0, "plasma", "plasma_engine", 6, - mfb(vpf_internal) | mfb(vpf_engine) }, - { "Foot pedals", '*', c_ltgray, '#', c_red, 50, 50, 70, 0, "muscle", "foot_crank", 1, - mfb(vpf_internal) | mfb(vpf_engine) }, -// capacity type - { "gasoline tank", 'O', c_ltred, '#', c_red, 80, 150, 3000, 0, "gasoline", "metal_tank", 1, - mfb(vpf_internal) | mfb(vpf_fuel_tank) }, - { "storage battery", 'O', c_yellow, '#', c_red, 80, 300, 100000, 0, "battery", "storage_battery", 2, - mfb(vpf_internal) | mfb(vpf_fuel_tank) }, - { "minireactor", 'O', c_ltgreen, '#', c_red, 80, 700, 10000, 0, "plutonium", "minireactor", 7, - mfb(vpf_internal) | mfb(vpf_fuel_tank) }, - { "hydrogen tank", 'O', c_ltblue, '#', c_red, 80, 150, 3000, 0, "plasma", "metal_tank", 1, - mfb(vpf_internal) | mfb(vpf_fuel_tank) }, - { "water tank", 'O', c_ltcyan, '#', c_red, 80, 150, 400, 0, "water", "metal_tank", 1, - mfb(vpf_internal) | mfb(vpf_fuel_tank) }, - { "trunk", 'H', c_brown, '#', c_brown, 80, 300, 400, 0, "NULL", "frame", 1, - mfb(vpf_over) | mfb(vpf_cargo) }, - { "box", 'o', c_brown, '#', c_brown, 60, 100, 400, 0, "NULL", "frame", 1, - mfb(vpf_over) | mfb(vpf_cargo) | mfb(vpf_boardable) }, - - { "controls", '$', c_ltgray, '$', c_red, 10, 250, 0, 0, "NULL", "vehicle_controls", 3, - mfb(vpf_internal) | mfb(vpf_controls) }, -// bonus - { "muffler", '/', c_ltgray, '/', c_ltgray, 10, 150, 40, 0, "NULL", "muffler", 2, - mfb(vpf_internal) | mfb(vpf_muffler) }, - { "seatbelt", ',', c_ltgray, ',', c_red, 10, 200, 25, 0, "NULL", "rope_6", 1, - mfb(vpf_internal) | mfb(vpf_seatbelt) }, - { "solar panel", '#', c_yellow, 'x', c_yellow, 10, 20, 30, 0, "NULL", "solar_panel", 6, - mfb(vpf_over) | mfb(vpf_solar_panel) }, - { "kitchen unit", '&', c_ltcyan, 'x', c_ltcyan, 10, 20, 0, 0, "NULL", "kitchen_unit", 4, - mfb(vpf_over) | mfb(vpf_cargo) | mfb(vpf_no_reinforce) | mfb(vpf_obstacle) | mfb(vpf_kitchen) }, - { "welding rig", '&', c_ltred, 'x', c_ltred, 10, 20, 0, 0, "NULL", "weldrig", 4, - mfb(vpf_over) | mfb(vpf_cargo) | mfb(vpf_no_reinforce) | mfb(vpf_obstacle) | mfb(vpf_weldrig) }, - { "mounted M249", 't', c_cyan, '#', c_cyan, 80, 400, 0, 0, "223", "m249", 6, - mfb(vpf_over) | mfb(vpf_turret) | mfb(vpf_cargo) }, - { "mounted flamethrower", 't', c_dkgray, '#', c_dkgray, 80, 400, 0, 0, "gasoline", "flamethrower", 7, - mfb(vpf_over) | mfb(vpf_turret) }, - { "mounted plasma gun", 't', c_ltblue, '#', c_ltblue, 80, 400, 0, 0, "plasma", "plasma_rifle", 7, - mfb(vpf_over) | mfb(vpf_turret) }, - { "mounted fusion gun", 't', c_magenta, '#', c_magenta, 80, 400, 0, 0, "battery", "ftk93", 7, - mfb(vpf_over) | mfb(vpf_turret) }, + std::set flags; // flags - { "steel plating", ')', c_ltcyan, ')', c_ltcyan, 100, 1000, 0, 0, "NULL", "steel_plate", 3, - mfb(vpf_internal) | mfb(vpf_armor) }, - { "superalloy plating",')', c_dkgray, ')', c_dkgray, 100, 900, 0, 0, "NULL", "alloy_plate", 4, - mfb(vpf_internal) | mfb(vpf_armor) }, - { "spiked plating", ')', c_red, ')', c_red, 150, 900, 0, 0, "NULL", "spiked_plate", 3, - mfb(vpf_internal) | mfb(vpf_armor) | mfb(vpf_sharp) }, - { "hard plating", ')', c_cyan, ')', c_cyan, 100, 2300, 0, 0, "NULL", "hard_plate", 4, - mfb(vpf_internal) | mfb(vpf_armor) }, - { "head light", '*', c_white, '*', c_white, 10, 20, 480, 0, "NULL", "flashlight", 1, - mfb(vpf_internal) | mfb(vpf_light) } + bool has_flag(const std::string flag) { + return flags.count(flag) != 0; + } }; +extern vpart_info vpart_list[num_vparts]; enum vhtype_id { diff --git a/veh_typedef.cpp b/veh_typedef.cpp index 581678ef06426..aedf514785394 100644 --- a/veh_typedef.cpp +++ b/veh_typedef.cpp @@ -1,5 +1,7 @@ #include "vehicle.h" #include "game.h" +#include "item_factory.h" +#include "catajson.h" // GENERAL GUIDELINES // When adding a new vehicle, you MUST REMEMBER to insert it in the vhtype_id enum @@ -26,6 +28,81 @@ // vpart_id enum in veh_type.h file // If you use wrong config, installation of part will fail +vpart_info vpart_list[num_vparts]; + +// Note on the 'symbol' flag in vehicle parts - +// the following symbols will be translated: +// y, u, n, b to NW, NE, SE, SW lines correspondingly +// h, j, c to horizontal, vertical, cross correspondingly +/** + * Reads in the vehicle parts from a json file. + */ +void game::init_vehicle_parts() +{ + catajson vehicle_parts_json("data/raw/vehicle_parts.json", true); + + if (!json_good()) { + throw (std::string)"data/raw/vehicle_parts.json wasn't found"; + } + + unsigned int index = 0; + for (vehicle_parts_json.set_begin(); vehicle_parts_json.has_curr() && json_good(); vehicle_parts_json.next()) + { + catajson next_json = vehicle_parts_json.curr(); + vpart_info next_part; + + next_part.name = next_json.get("name").as_string(); + next_part.sym = next_json.get("symbol").as_char(); + next_part.color = color_from_string(next_json.get("color").as_string()); + next_part.sym_broken = next_json.get("broken_symbol").as_char(); + next_part.color_broken = color_from_string(next_json.get("broken_color").as_string()); + next_part.dmg_mod = next_json.has("damage_modifier") ? next_json.get("damage_modifier").as_int() : 100; + next_part.durability = next_json.get("durability").as_int(); + //Handle the par1 union as best we can by accepting any ONE of its elements + int element_count = next_json.has("par1") ? 1 : 0 + + next_json.has("power") ? 1 : 0 + + next_json.has("size") ? 1 : 0 + + next_json.has("wheel_width") ? 1 : 0 + + next_json.has("bonus") ? 1 : 0; + if(element_count == 0) { + //If not specified, assume 0 + next_part.par1 = 0; + } else if(element_count == 1) { + if(next_json.has("par1")) { + next_part.par1 = next_json.get("par1").as_int(); + } else if(next_json.has("power")) { + next_part.par1 = next_json.get("power").as_int(); + } else if(next_json.has("size")) { + next_part.par1 = next_json.get("size").as_int(); + } else if(next_json.has("wheel_width")) { + next_part.par1 = next_json.get("wheel_width").as_int(); + } else { //bonus + next_part.par1 = next_json.get("bonus").as_int(); + } + } else { + //Too many + debugmsg("Error parsing vehicle part '%s': \ + Use AT MOST one of: par1, power, size, wheel_width, bonus", + next_part.name.c_str()); + //Keep going to produce more messages if other parts are wrong + next_part.par1 = 0; + } + next_part.fuel_type = next_json.has("fuel_type") ? next_json.get("fuel_type").as_string() : "NULL"; + next_part.item = next_json.get("item").as_string(); + next_part.difficulty = next_json.get("difficulty").as_int(); + next_part.flags = next_json.get("flags").as_tags(); + + vpart_list[index] = next_part; + + index++; + } + + if(!json_good()) { + exit(1); + } + +} + void game::init_vehicles() { vehicle *veh; @@ -36,7 +113,7 @@ void game::init_vehicles() #define VEHICLE(nm) { veh = new vehicle(this, (vhtype_id)index++); veh->name = nm; vtypes.push_back(veh); } #define PART(mdx, mdy, id) { pi = veh->install_part(mdx, mdy, id); \ - if (pi < 0) debugmsg("init_vehicles: '%s' part '%s'(%d) can't be installed to %d,%d", veh->name.c_str(), vpart_list[id].name, veh->parts.size(), mdx, mdy); } + if (pi < 0) debugmsg("init_vehicles: '%s' part '%s'(%d) can't be installed to %d,%d", veh->name.c_str(), vpart_list[id].name.c_str(), veh->parts.size(), mdx, mdy); } // name VEHICLE (_("Bicycle")); diff --git a/vehicle.cpp b/vehicle.cpp index 6a54abe2e5098..ac92babb49ad3 100644 --- a/vehicle.cpp +++ b/vehicle.cpp @@ -59,7 +59,7 @@ bool vehicle::player_in_control (player *p) vehicle *veh = g->m.veh_at (p->posx, p->posy, veh_part); if (veh && veh != this) return false; - return part_with_feature(veh_part, vpf_controls, false) >= 0 && p->controlling_vehicle; + return part_with_feature(veh_part, "CONTROLS", false) >= 0 && p->controlling_vehicle; } void vehicle::load (std::ifstream &stin) @@ -224,7 +224,7 @@ void vehicle::init_state(game* g, int init_veh_fuel, int init_veh_status) for (int p = 0; p < parts.size(); p++) { - if (part_flag(p, vpf_variable_size)){ // generate its bigness attribute.? + if (part_flag(p, "VARIABLE_SIZE")){ // generate its bigness attribute.? if(!consistent_bignesses[parts[p].id]){ //generate an item for this type, & cache its bigness item tmp (g->itypes[part_info(p).item], 0); @@ -232,13 +232,16 @@ void vehicle::init_state(game* g, int init_veh_fuel, int init_veh_status) } parts[p].bigness = consistent_bignesses[parts[p].id]; } - if (part_flag(p, vpf_fuel_tank)) // set fuel status + if (part_flag(p, "FUEL_TANK")) { // set fuel status parts[p].amount = part_info(p).size * veh_fuel_mult / 100; + } - if (part_flag(p, vpf_openable)) // doors are closed + if (part_flag(p, "OPENABLE")) { // doors are closed parts[p].open = 0; - if (part_flag(p, vpf_boardable)) // no passengers + } + if (part_flag(p, "BOARDABLE")) { // no passengers parts[p].remove_flag(vehicle_part::passenger_flag); + } // initial vehicle damage if (veh_status == 0) { @@ -256,15 +259,19 @@ void vehicle::init_state(game* g, int init_veh_fuel, int init_veh_status) parts[p].hp= ((float)(roll-broken) / (unhurt-broken)) * part_info(p).durability; } else // new. + { parts[p].hp= part_info(p).durability; + } if (destroyEngine) { // vehicle is disabled because engine is dead - if (part_flag(p, vpf_engine)) + if (part_flag(p, "ENGINE")) { parts[p].hp= 0; + } } if (destroyTires) { // vehicle is disabled because flat tires - if (part_flag(p, vpf_wheel)) + if (part_flag(p, "WHEEL")) { parts[p].hp= 0; + } } } } @@ -284,10 +291,12 @@ std::string vehicle::use_controls() bool has_lights = false; bool has_turrets = false; for (int p = 0; p < parts.size(); p++) { - if (part_flag(p, vpf_light)) + if (part_flag(p, "LIGHT")) { has_lights = true; - else if (part_flag(p, vpf_turret)) + } + else if (part_flag(p, "TURRET")) { has_turrets = true; + } } // Lights if they are there - Note you can turn them on even when damaged, they just don't work @@ -297,7 +306,7 @@ std::string vehicle::use_controls() curent++; } - // Turrents: off or burst mode + // Turrets: off or burst mode if (has_turrets) { options_choice.push_back(toggle_turrets); options_message.push_back(uimenu_entry((0 == turret_mode) ? _("Switch turrets to burst mode") : _("Disable turrets"), 't')); @@ -361,7 +370,7 @@ std::string vehicle::use_controls() for (int p = 0; p < parts.size(); p++) { part_hps << parts[p].hp << " "; - if( part_flag( p, vpf_cargo ) ) { + if( part_flag( p, "CARGO" ) ) { for( std::vector::iterator it = parts[p].items.begin(); it != parts[p].items.end(); ++it) { g->m.add_item_or_charges( g->u.posx, g->u.posy, *it ); @@ -384,7 +393,7 @@ std::string vehicle::use_controls() return message; } -const vpart_info& vehicle::part_info (int index) +vpart_info& vehicle::part_info (int index) { vpart_id id = vp_null; if (index < 0 || index >= parts.size()) @@ -399,38 +408,75 @@ const vpart_info& vehicle::part_info (int index) // engines & solar panels all have power. // engines consume, whilst panels provide. int vehicle::part_power (int index){ - if (!part_flag(index, vpf_engine) && - !part_flag(index, vpf_solar_panel)) + if (!part_flag(index, "ENGINE") && + !part_flag(index, "SOLAR_PANEL")) { return 0; //not an engine. - if(parts[index].hp <= 0) + } + if(parts[index].hp <= 0) { return 0; //broken. - if(part_flag (index, vpf_variable_size)){ // example: 2.42-L V-twin engine + } + if(part_flag (index, "VARIABLE_SIZE")){ // example: 2.42-L V-twin engine return parts[index].bigness; } else // example: foot crank + { return part_info(index).power; + } +} + +/** + * Returns whether or not the specified flag is allowed to be stacked. For + * example, you can have multiple INTERNAL or OPAQUE parts, but only one + * WHEEL or ENGINE per square. + * @param vpart_flag The flag to check. + * @return true if multiple parts with that flag can be placed in the same + * square, false if not. + */ +bool vehicle::can_stack_vpart_flag(std::string vpart_flag) { + + if (vpart_flag == "EXTERNAL" || + vpart_flag == "INTERNAL" || + vpart_flag == "MOUNT_POINT" || + vpart_flag == "MOUNT_INNER" || + vpart_flag == "MOUNT_OVER" || + vpart_flag == "ANCHOR_POINT" || + vpart_flag == "OPAQUE" || + vpart_flag == "OBSTACLE" || + vpart_flag == "OPENABLE" || + vpart_flag == "NO_REINFORCE" || + vpart_flag == "SHARP" || + vpart_flag == "UNMOUNT_ON_DAMAGE" || + vpart_flag == "BOARDABLE") { + return true; + } else { + return false; + } + } bool vehicle::can_mount (int dx, int dy, vpart_id id) { - if (id <= 0 || id >= num_vparts) + if (id <= 0 || id >= num_vparts) { return false; - bool n3ar = parts.size() < 1 || (vpart_list[id].flags & mfb(vpf_internal)) - || (vpart_list[id].flags & mfb(vpf_over)); // first and internal parts needs no mount point - if (!n3ar) + } + bool n3ar = parts.size() < 1 || vpart_list[id].has_flag("INTERNAL") + || vpart_list[id].has_flag("OVER"); // first and internal parts needs no mount point + if (!n3ar) { for (int i = 0; i < 4; i++) { int ndx = i < 2? (i == 0? -1 : 1) : 0; int ndy = i < 2? 0 : (i == 2? - 1: 1); std::vector parts_n3ar = parts_at_relative (dx + ndx, dy + ndy); - if (parts_n3ar.size() < 1) + if (parts_n3ar.size() < 1) { continue; - if (part_flag(parts_n3ar[0], vpf_mount_point)) + } + if (part_flag(parts_n3ar[0], "MOUNT_POINT")) { n3ar = true; break; } } + } if (!n3ar) { return false; // no point to mount @@ -439,30 +485,30 @@ bool vehicle::can_mount (int dx, int dy, vpart_id id) std::vector parts_here = parts_at_relative (dx, dy); if (parts_here.size() < 1) { - int res = vpart_list[id].flags & mfb(vpf_external); + int res = vpart_list[id].has_flag("EXTERNAL"); return res; // can be mounted if first and external } // Override for replacing a tire. - if( vpart_list[id].flags & mfb(vpf_wheel) && - -1 != part_with_feature(parts_here[0], vpf_wheel, false) ) + if( vpart_list[id].has_flag("WHEEL") && + -1 != part_with_feature(parts_here[0], "WHEEL", false) ) { return true; } - int flags1 = part_info(parts_here[0]).flags; - if ((vpart_list[id].flags & mfb(vpf_armor)) && flags1 & mfb(vpf_no_reinforce)) + vpart_info existing_part = part_info(parts_here[0]); + if ((vpart_list[id].has_flag("ARMOR")) && existing_part.has_flag("NO_REINFORCE")) { return false; // trying to put armor plates on non-reinforcable part } // Seatbelts require an anchor point - if( vpart_list[id].flags & mfb(vpf_seatbelt) ) + if( vpart_list[id].has_flag("SEATBELT") ) { bool anchor_found = false; for( std::vector::iterator it = parts_here.begin(); it != parts_here.end(); ++it ) { - if( part_info(*it).flags & mfb(vpf_anchor_point) ) + if( part_info(*it).has_flag("ANCHOR_POINT") ) { anchor_found = true; } @@ -473,20 +519,26 @@ bool vehicle::can_mount (int dx, int dy, vpart_id id) } } - for (int vf = vpf_func_begin; vf <= vpf_func_end; vf++) - if ((vpart_list[id].flags & mfb(vf)) && part_with_feature(parts_here[0], vf, false) >= 0) - { + std::set vpart_flags = vpart_list[id].flags; + for (std::set::iterator flag_iterator = vpart_flags.begin(); + flag_iterator != vpart_flags.end(); ++flag_iterator) { + std::string next_flag = *flag_iterator; + if(part_with_feature(parts_here[0], next_flag, false) >= 0 + && !can_stack_vpart_flag(next_flag)) { return false; // this part already has inner part with same unique feature } + } - bool allow_inner = flags1 & mfb(vpf_mount_inner); - bool allow_over = flags1 & mfb(vpf_mount_over); - bool this_inner = vpart_list[id].flags & mfb(vpf_internal); - bool this_over = (vpart_list[id].flags & mfb(vpf_over)) || (vpart_list[id].flags & mfb(vpf_armor)); - if (allow_inner && (this_inner || this_over)) + bool allow_inner = existing_part.has_flag("MOUNT_INNER"); + bool allow_over = existing_part.has_flag("MOUNT_OVER"); + bool this_inner = vpart_list[id].has_flag("INTERNAL"); + bool this_over = (vpart_list[id].has_flag("OVER")) || (vpart_list[id].has_flag("ARMOR")); + if (allow_inner && (this_inner || this_over)) { return true; // can mount as internal part or over it - if (allow_over && this_over) + } + if (allow_over && this_over) { return true; // can mount as part over + } return false; } @@ -507,14 +559,16 @@ bool vehicle::can_unmount (int p) return false; // unmounting 0, 0 part anly allowed as last part } - if (!part_flag (p, vpf_mount_point)) + if (!part_flag (p, "MOUNT_POINT")) { return true; + } for (int i = 0; i < 4; i++) { int ndx = i < 2? (i == 0? -1 : 1) : 0; int ndy = i < 2? 0 : (i == 2? - 1: 1); - if (!(dx + ndx) && !(dy + ndy)) + if (!(dx + ndx) && !(dy + ndy)) { continue; // 0, 0 point is main mount + } if (parts_at_relative (dx + ndx, dy + ndy).size() > 0) { int cnt = 0; @@ -523,11 +577,12 @@ bool vehicle::can_unmount (int p) int jdx = j < 2? (j == 0? -1 : 1) : 0; int jdy = j < 2? 0 : (j == 2? - 1: 1); std::vector pc = parts_at_relative (dx + ndx + jdx, dy + ndy + jdy); - if (pc.size() > 0 && part_with_feature (pc[0], vpf_mount_point) >= 0) + if (pc.size() > 0 && part_with_feature (pc[0], "MOUNT_POINT") >= 0) cnt++; } - if (cnt < 2) + if (cnt < 2) { return false; + } } } return true; @@ -535,8 +590,9 @@ bool vehicle::can_unmount (int p) int vehicle::install_part (int dx, int dy, vpart_id id, int hp, bool force) { - if (!force && !can_mount (dx, dy, id)) + if (!force && !can_mount (dx, dy, id)) { return -1; // no money -- no ski! + } // if this is first part, add this part to list of external parts if (parts_at_relative (dx, dy).size () < 1) external_parts.push_back (parts.size()); @@ -636,22 +692,27 @@ std::vector vehicle::internal_parts (int p) return res; } -int vehicle::part_with_feature (int p, unsigned int f, bool unbroken) +int vehicle::part_with_feature (int part, std::string flag, bool unbroken) { - if (part_flag(p, f)) - return p; - std::vector parts_here = internal_parts (p); - for (int i = 0; i < parts_here.size(); i++) - if (part_flag(parts_here[i], f) && (!unbroken || parts[parts_here[i]].hp > 0)) + if (part_flag(part, flag)) { + return part; + } + std::vector parts_here = internal_parts (part); + for (int i = 0; i < parts_here.size(); i++) { + if (part_flag(parts_here[i], flag) && (!unbroken || parts[parts_here[i]].hp > 0)) { return parts_here[i]; + } + } return -1; } -bool vehicle::part_flag (int p, unsigned int f) +bool vehicle::part_flag (int part, std::string flag) { - if (p < 0 || p >= parts.size()) + if (part < 0 || part >= parts.size()) { return false; - return (bool) (part_info(p).flags & mfb (f)); + } else { + return part_info(part).has_flag(flag); + } } int vehicle::part_at(int dx, int dy) @@ -675,38 +736,44 @@ int vehicle::global_part_at(int x, int y) char vehicle::part_sym (int p) { - if (p < 0 || p >= parts.size()) + if (p < 0 || p >= parts.size()) { return 0; + } std::vector ph = internal_parts (p); - int po = part_with_feature(p, vpf_over, false); + int po = part_with_feature(p, "OVER", false); int pd = po < 0? p : po; - if (part_flag (pd, vpf_openable) && parts[pd].open) + if (part_flag (pd, "OPENABLE") && parts[pd].open) { return '\''; // open door + } return parts[pd].hp <= 0? part_info(pd).sym_broken : part_info(pd).sym; } nc_color vehicle::part_color (int p) { - if (p < 0 || p >= parts.size()) + if (p < 0 || p >= parts.size()) { return c_black; - int parm = part_with_feature(p, vpf_armor, false); - int po = part_with_feature(p, vpf_over, false); + } + int parm = part_with_feature(p, "ARMOR", false); + int po = part_with_feature(p, "OVER", false); int pd = po < 0? p : po; - if (parts[p].blood > 200) + if (parts[p].blood > 200) { return c_red; - else - if (parts[p].blood > 0) + } + else if (parts[p].blood > 0) { return c_ltred; + } - if (parts[pd].hp <= 0) + if (parts[pd].hp <= 0) { return part_info(pd).color_broken; + } // first, check if there's a part over. then, if armor here (projects its color on part) - if (po >= 0) + if (po >= 0) { return part_info(po).color; - else - if (parm >= 0) + } + else if (parm >= 0) { return part_info(parm).color; + } return part_info(pd).color; } @@ -741,25 +808,26 @@ void vehicle::print_part_desc (void *w, int y1, int width, int p, int hl) std::stringstream nom; //part name // part bigness, if that's relevant. - if (part_flag(pl[i], vpf_variable_size)){ - if (part_flag(pl[i], vpf_engine)){ //bigness == liters + if (part_flag(pl[i], "VARIABLE_SIZE")){ + if (part_flag(pl[i], "ENGINE")){ //bigness == liters nom << rmp_format(_("%4.2f-Liter "), (float)(parts[pl[i]].bigness) / 100); } - else if (part_flag(pl[i], vpf_wheel)){ //bigness == inches + else if (part_flag(pl[i], "WHEEL")){ //bigness == inches nom << rmp_format(_("%d\" "), parts[pl[i]].bigness); } } nom << part_info(pl[i]).name; std::string partname = nom.str(); - bool armor = part_flag(pl[i], vpf_armor); + bool armor = part_flag(pl[i], "ARMOR"); mvwprintz(win, y, 2, i == hl? hilite(col_cond) : col_cond, partname.c_str()); mvwprintz(win, y, 1, i == hl? hilite(c_ltgray) : c_ltgray, armor? "(" : (i? "-" : "[")); mvwprintz(win, y, 2 + utf8_width(partname.c_str()), i == hl? hilite(c_ltgray) : c_ltgray, armor? ")" : (i? "-" : "]")); // mvwprintz(win, y, 3 + strlen(part_info(pl[i]).name), c_ltred, "%d", parts[pl[i]].blood); - if (i == 0) + if (i == 0) { mvwprintz(win, y, width-5, c_ltgray, is_inside(pl[i])? " In " : "Out "); + } y++; } } @@ -825,33 +893,39 @@ void vehicle::precalc_mounts (int idir, int dir) std::vector vehicle::boarded_parts() { std::vector res; - for (int p = 0; p < parts.size(); p++) - if (part_flag (p, vpf_boardable) && - parts[p].has_flag(vehicle_part::passenger_flag)) + for (int p = 0; p < parts.size(); p++) { + if (part_flag (p, "BOARDABLE") && + parts[p].has_flag(vehicle_part::passenger_flag)) { res.push_back (p); + } + } return res; } int vehicle::free_seat() { - for (int p = 0; p < parts.size(); p++) - if (part_flag (p, vpf_boardable) && !parts[p].has_flag(vehicle_part::passenger_flag)) - return p; - - return -1; + for (int p = 0; p < parts.size(); p++) { + if (part_flag (p, "BOARDABLE") && + !parts[p].has_flag(vehicle_part::passenger_flag)) { + return p; + } + } + return -1; } player *vehicle::get_passenger (int p) { - p = part_with_feature (p, vpf_boardable, false); + p = part_with_feature (p, "BOARDABLE", false); if (p >= 0 && parts[p].has_flag(vehicle_part::passenger_flag)) { const int player_id = parts[p].passenger_id; - if( player_id == g->u.getID()) + if( player_id == g->u.getID()) { return &g->u; + } int npcdex = g->npc_by_id (player_id); - if (npcdex >= 0) + if (npcdex >= 0) { return g->active_npc[npcdex]; + } } return 0; } @@ -872,10 +946,12 @@ int vehicle::total_mass () for (int i = 0; i < parts.size(); i++) { m += g->itypes[part_info(i).item]->weight; - for (int j = 0; j < parts[i].items.size(); j++) + for (int j = 0; j < parts[i].items.size(); j++) { m += parts[i].items[j].type->weight; - if (part_flag(i,vpf_boardable) && parts[i].has_flag(vehicle_part::passenger_flag)) + } + if (part_flag(i,"BOARDABLE") && parts[i].has_flag(vehicle_part::passenger_flag)) { m += 81500; // TODO: get real weight + } } return m/1000; } @@ -883,20 +959,24 @@ int vehicle::total_mass () int vehicle::fuel_left (ammotype ftype, bool for_engine) { int fl = 0; - for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_fuel_tank) && + for (int p = 0; p < parts.size(); p++) { + if (part_flag(p, "FUEL_TANK") && (ftype == part_info(p).fuel_type || - (for_engine && ftype == "battery" && part_info(p).fuel_type == "plutonium"))) + (for_engine && ftype == "battery" && part_info(p).fuel_type == "plutonium"))) { fl += parts[p].amount; + } + } return fl; } int vehicle::fuel_capacity (ammotype ftype) { int cap = 0; - for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_fuel_tank) && ftype == part_info(p).fuel_type) + for (int p = 0; p < parts.size(); p++) { + if (part_flag(p, "FUEL_TANK") && ftype == part_info(p).fuel_type) { cap += part_info(p).size; + } + } return cap; } @@ -904,7 +984,7 @@ int vehicle::refill (ammotype ftype, int amount) { for (int p = 0; p < parts.size(); p++) { - if (part_flag(p, vpf_fuel_tank) && + if (part_flag(p, "FUEL_TANK") && part_info(p).fuel_type == ftype && parts[p].amount < part_info(p).size) { @@ -928,7 +1008,7 @@ int vehicle::drain (ammotype ftype, int amount) { int drained = 0; for (int p = 0; p < parts.size(); p++) { - if (part_flag(p, vpf_fuel_tank) && part_info(p).fuel_type == ftype && parts[p].amount > 0) { + if (part_flag(p, "FUEL_TANK") && part_info(p).fuel_type == ftype && parts[p].amount > 0) { if (parts[p].amount > (amount - drained)) { parts[p].amount -= (amount - drained); drained = amount; @@ -949,16 +1029,18 @@ int vehicle::basic_consumption (ammotype ftype) ftype = "battery"; int cnt = 0; int fcon = 0; - for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_engine) && + for (int p = 0; p < parts.size(); p++) { + if (part_flag(p, "ENGINE") && ftype == part_info(p).fuel_type && parts[p].hp > 0) { fcon += part_power(p); cnt++; } - if (fcon < 100 && cnt > 0) + } + if (fcon < 100 && cnt > 0) { fcon = 100; + } return fcon; } @@ -967,7 +1049,7 @@ int vehicle::total_power (bool fueled) int pwr = 0; int cnt = 0; for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_engine) && + if (part_flag(p, "ENGINE") && (fuel_left (part_info(p).fuel_type, true) || !fueled || part_info(p).fuel_type == "muscle") && parts[p].hp > 0) @@ -975,8 +1057,9 @@ int vehicle::total_power (bool fueled) pwr += part_power(p); cnt++; } - if (cnt > 1) + if (cnt > 1) { pwr = pwr * 4 / (4 + cnt -1); + } return pwr; } @@ -984,7 +1067,7 @@ int vehicle::solar_power () { int pwr = 0; for (int p = 0; p < parts.size(); p++) { - if (part_flag(p, vpf_solar_panel) && parts[p].hp > 0) { + if (part_flag(p, "SOLAR_PANEL") && parts[p].hp > 0) { int part_x = global_x() + parts[p].precalc_dx[0]; int part_y = global_y() + parts[p].precalc_dy[0]; // Can't use g->in_sunlight() because it factors in vehicle roofs. @@ -1011,7 +1094,7 @@ int vehicle::safe_velocity (bool fueled) int pwrs = 0; int cnt = 0; for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_engine) && + if (part_flag(p, "ENGINE") && (fuel_left (part_info(p).fuel_type, true) || !fueled || part_info(p).fuel_type == "muscle") && parts[p].hp > 0) @@ -1026,8 +1109,9 @@ int vehicle::safe_velocity (bool fueled) pwrs += part_power(p) * m2c / 100; cnt++; } - if (cnt > 0) + if (cnt > 0) { pwrs = pwrs * 4 / (4 + cnt -1); + } return (int) (pwrs * k_dynamics() * k_mass()) * 80; } @@ -1036,12 +1120,14 @@ int vehicle::noise (bool fueled, bool gas_only) int pwrs = 0; int cnt = 0; int muffle = 100; - for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_muffler) && parts[p].hp > 0 && part_info(p).bonus < muffle) + for (int p = 0; p < parts.size(); p++) { + if (part_flag(p, "MUFFLER") && parts[p].hp > 0 && part_info(p).bonus < muffle) { muffle = part_info(p).bonus; + } + } - for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_engine) && + for (int p = 0; p < parts.size(); p++) { + if (part_flag(p, "ENGINE") && (fuel_left (part_info(p).fuel_type, true) || !fueled || part_info(p).fuel_type == "muscle") && parts[p].hp > 0) @@ -1063,6 +1149,7 @@ int vehicle::noise (bool fueled, bool gas_only) cnt++; } } + } return pwrs; } @@ -1073,7 +1160,7 @@ float vehicle::wheels_area (int *cnt) for (int i = 0; i < external_parts.size(); i++) { int p = external_parts[i]; - if (part_flag(p, vpf_wheel) && + if (part_flag(p, "WHEEL") && parts[p].hp > 0) { int width = part_info(p).wheel_width; @@ -1083,8 +1170,9 @@ float vehicle::wheels_area (int *cnt) count++; } } - if (cnt) + if (cnt) { *cnt = count; + } return total_area; } @@ -1092,23 +1180,28 @@ float vehicle::k_dynamics () { const int max_obst = 13; int obst[max_obst]; - for (int o = 0; o < max_obst; o++) + for (int o = 0; o < max_obst; o++) { obst[o] = 0; + } for (int i = 0; i < external_parts.size(); i++) { int p = external_parts[i]; - int frame_size = part_flag(p, vpf_obstacle)? 30 : 10; + int frame_size = part_flag(p, "OBSTACLE")? 30 : 10; int pos = parts[p].mount_dy + max_obst / 2; - if (pos < 0) + if (pos < 0) { pos = 0; - if (pos >= max_obst) + } + if (pos >= max_obst) { pos = max_obst -1; - if (obst[pos] < frame_size) + } + if (obst[pos] < frame_size) { obst[pos] = frame_size; + } } int frame_obst = 0; - for (int o = 0; o < max_obst; o++) + for (int o = 0; o < max_obst; o++) { frame_obst += obst[o]; + } float ae0 = 200.0; float fr0 = 1000.0; float wa = wheels_area(); @@ -1155,9 +1248,10 @@ bool vehicle::valid_wheel_config () for (int i = 0; i < external_parts.size(); i++) { int p = external_parts[i]; - if (!part_flag(p, vpf_wheel) || - parts[p].hp <= 0) + if (!part_flag(p, "WHEEL") || + parts[p].hp <= 0) { continue; + } if (!count) { x1 = x2 = parts[p].mount_dx; @@ -1173,8 +1267,9 @@ bool vehicle::valid_wheel_config () y2 = parts[p].mount_dy; count++; } - if (count < 2) + if (count < 2) { return false; + } float xo = 0, yo = 0; float wo = 0, w2; for (int p = 0; p < parts.size(); p++) @@ -1212,7 +1307,7 @@ void vehicle::consume_fuel () // and for electric engines: // - if j is 0, then we're looking for plutonium (it's first) // - otherwise we're looking for batteries (second) - if (part_flag(p, vpf_fuel_tank) && + if (part_flag(p, "FUEL_TANK") && (part_info(p).fuel_type == (elec? (j ? "battery" : "plutonium") : ftypes[ft])) && parts[p].amount > 0) { @@ -1278,7 +1373,7 @@ void vehicle::thrust (int thd) int strn = (int) (strain () * strain() * 100); for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_engine) && + if (part_flag(p, "ENGINE") && (fuel_left (part_info(p).fuel_type, true)) && parts[p].hp > 0 && rng (1, 100) < strn) { @@ -1424,9 +1519,10 @@ veh_collision vehicle::part_collision (int part, int x, int y, bool just_detect) return ret; } - int parm = part_with_feature (part, vpf_armor); - if (parm < 0) + int parm = part_with_feature (part, "ARMOR"); + if (parm < 0) { parm = part; + } int dmg_mod = part_info(parm).dmg_mod; // let's calculate type of collision & mass of object we hit int mass = total_mass(); @@ -1535,16 +1631,17 @@ veh_collision vehicle::part_collision (int part, int x, int y, bool just_detect) if (pl_ctrl) { if (snd.length() > 0) - g->add_msg (_("Your %s's %s rams into a %s with a %s"), name.c_str(), part_info(part).name, obs_name.c_str(), snd.c_str()); + g->add_msg (_("Your %s's %s rams into a %s with a %s"), name.c_str(), part_info(part).name.c_str(), obs_name.c_str(), snd.c_str()); else - g->add_msg (_("Your %s's %s rams into a %s."), name.c_str(), part_info(part).name, obs_name.c_str()); + g->add_msg (_("Your %s's %s rams into a %s."), name.c_str(), part_info(part).name.c_str(), obs_name.c_str()); } else if (snd.length() > 0) g->add_msg (_("You hear a %s"), snd.c_str()); } - if (part_flag(part, vpf_sharp) && smashed) + if (part_flag(part, "SHARP") && smashed) { imp2 /= 2; + } int imp1 = imp - imp2; int vel1 = imp1 * k_mvel * 100 / mass; int vel2 = imp2 * k_mvel * 100 / mass2; @@ -1554,28 +1651,33 @@ veh_collision vehicle::part_collision (int part, int x, int y, bool just_detect) int dam = imp1 * dmg_mod / 100; if (z) { - int z_armor = part_flag(part, vpf_sharp)? z->type->armor_cut : z->type->armor_bash; - if (z_armor < 0) + int z_armor = part_flag(part, "SHARP")? z->type->armor_cut : z->type->armor_bash; + if (z_armor < 0) { z_armor = 0; - if (z) + } + if (z) { dam -= z_armor; + } } if (dam < 0) dam = 0; - if (part_flag(part, vpf_sharp)) + if (part_flag(part, "SHARP")) { parts[part].blood += (20 + dam) * 5; - else - if (dam > rng (10, 30)) + } else if (dam > rng (10, 30)) { parts[part].blood += (10 + dam / 2) * 5; + } int turns_stunned = rng (0, dam) > 10? rng (1, 2) + (dam > 40? rng (1, 2) : 0) : 0; - if (part_flag(part, vpf_sharp)) + if (part_flag(part, "SHARP")) { turns_stunned = 0; - if (turns_stunned > 6) + } + if (turns_stunned > 6) { turns_stunned = 6; - if (turns_stunned > 0 && z) + } + if (turns_stunned > 0 && z) { z->add_effect(ME_STUNNED, turns_stunned); + } std::string dname; if (z) @@ -1584,7 +1686,7 @@ veh_collision vehicle::part_collision (int part, int x, int y, bool just_detect) dname = ph->name; if (pl_ctrl) g->add_msg (_("Your %s's %s rams into %s, inflicting %d damage%s!"), - name.c_str(), part_info(part).name, dname.c_str(), dam, + name.c_str(), part_info(part).name.c_str(), dname.c_str(), dam, turns_stunned > 0 && z? _(" and stunning it") : ""); int angle = (100 - degree) * 2 * (one_in(2)? 1 : -1); @@ -1603,7 +1705,7 @@ veh_collision vehicle::part_collision (int part, int x, int y, bool just_detect) g->fling_player_or_monster (ph, 0, move.dir() + angle, vel2 / 100); } - if (part_flag(part, vpf_sharp)) + if (part_flag(part, "SHARP")) { field &local_field = g->m.field_at(x, y); if (local_field.findField(fd_blood) && @@ -1660,12 +1762,14 @@ veh_collision vehicle::part_collision (int part, int x, int y, bool just_detect) void vehicle::handle_trap (int x, int y, int part) { - int pwh = part_with_feature (part, vpf_wheel); - if (pwh < 0) + int pwh = part_with_feature (part, "WHEEL"); + if (pwh < 0) { return; + } trap_id t = g->m.tr_at(x, y); - if (t == tr_null) + if (t == tr_null) { return; + } int noise = 0; int chance = 100; int expl = 0; @@ -1751,7 +1855,7 @@ void vehicle::handle_trap (int x, int y, int part) default:; } if (msg.size() > 0 && g->u_see(x, y)) - g->add_msg (msg.c_str(), name.c_str(), part_info(part).name, g->traps[t]->name.c_str()); + g->add_msg (msg.c_str(), name.c_str(), part_info(part).name.c_str(), g->traps[t]->name.c_str()); if (noise > 0) g->sound (x, y, noise, snd); if (wreckit && chance >= rng (1, 100)) @@ -1762,8 +1866,9 @@ void vehicle::handle_trap (int x, int y, int part) // total volume of all the things int vehicle::stored_volume(int part) { - if (!part_flag(part, vpf_cargo)) + if (!part_flag(part, "CARGO")) { return 0; + } int cur_volume = 0; for (int i = 0; i < parts[part].items.size(); i++) { cur_volume += parts[part].items[i].volume(); @@ -1809,17 +1914,20 @@ bool vehicle::add_item (int part, item itm) // const int max_weight = ?! // TODO: weight limit, calc per vpart & vehicle stats, not a hard user limit. // add creaking sounds and damage to overloaded vpart, outright break it past a certian point, or when hitting bumps etc - if (!part_flag(part, vpf_cargo)) + if (!part_flag(part, "CARGO")) { return false; + } if (parts[part].items.size() >= max_storage) return false; it_ammo *ammo = dynamic_cast (itm.type); - if (part_flag(part, vpf_turret)) + if (part_flag(part, "TURRET")) { if (!ammo || (ammo->type != part_info(part).fuel_type || ammo->type == "gasoline" || - ammo->type == "plasma")) + ammo->type == "plasma")) { return false; + } + } int cur_volume = 0; int add_volume = itm.volume(); bool tryaddcharges=(itm.charges != -1 && (itm.is_food() || itm.is_ammo())); @@ -1875,11 +1983,13 @@ void vehicle::gain_moves (int mp) for (int ep = 0; ep < external_parts.size(); ep++) { int p = external_parts[ep]; - if (parts[p].blood > 0) + if (parts[p].blood > 0) { parts[p].blood--; - int p_eng = part_with_feature (p, vpf_engine, false); - if (p_eng < 0 || parts[p_eng].hp > 0 || parts[p_eng].amount < 1) + } + int p_eng = part_with_feature (p, "ENGINE", false); + if (p_eng < 0 || parts[p_eng].hp > 0 || parts[p_eng].amount < 1) { continue; + } parts[p_eng].amount--; int x = global_x() + parts[p_eng].precalc_dx[0]; int y = global_y() + parts[p_eng].precalc_dy[0]; @@ -1916,7 +2026,7 @@ void vehicle::find_exhaust () { int en = -1; for (int p = 0; p < parts.size(); p++) - if (part_flag(p, vpf_engine) && part_info(p).fuel_type == "gasoline") + if (part_flag(p, "ENGINE") && part_info(p).fuel_type == "gasoline") { en = p; break; @@ -1942,7 +2052,7 @@ void vehicle::refresh_insides () for (int ep = 0; ep < external_parts.size(); ep++) { int p = external_parts[ep]; - if (part_with_feature(p, vpf_roof) < 0 || parts[p].hp <= 0) + if (part_with_feature(p, "ROOF") < 0 || parts[p].hp <= 0) { // if there's no roof (or it's broken) -- it's outside! /* debugmsg ("part%d/%d(%s)%d,%d no roof=false", p, external_parts.size(), part_info(p).name, parts[p].mount_dx, parts[p].mount_dy);*/ @@ -1960,18 +2070,20 @@ void vehicle::refresh_insides () for (int j = 0; j < parts_n3ar.size(); j++) { int pn = parts_n3ar[j]; - if (parts[pn].hp <= 0) + if (parts[pn].hp <= 0) { continue; // it's broken = can't cover - if (part_flag(pn, vpf_roof)) + } + if (part_flag(pn, "ROOF")) { // another roof -- cover cover = true; break; } else - if (part_flag(pn, vpf_obstacle)) + if (part_flag(pn, "OBSTACLE")) { // found an obstacle, like board or windshield or door - if (parts[pn].inside || (part_flag(pn, vpf_openable) && parts[pn].open)) + if (parts[pn].inside || (part_flag(pn, "OPENABLE") && parts[pn].open)) { continue; // door and it's open -- can't cover + } cover = true; break; } @@ -1990,24 +2102,28 @@ void vehicle::refresh_insides () bool vehicle::is_inside (int p) { - if (p < 0 || p >= parts.size()) + if (p < 0 || p >= parts.size()) { return false; - if (insides_dirty) + } + if (insides_dirty) { refresh_insides (); + } return parts[p].inside; } void vehicle::unboard_all () { std::vector bp = boarded_parts (); - for (int i = 0; i < bp.size(); i++) + for (int i = 0; i < bp.size(); i++) { g->m.unboard_vehicle (g, global_x() + parts[bp[i]].precalc_dx[0], global_y() + parts[bp[i]].precalc_dy[0]); + } } int vehicle::damage (int p, int dmg, int type, bool aimed) { - if (dmg < 1) + if (dmg < 1) { return dmg; + } std::vector pl = internal_parts (p); pl.insert (pl.begin(), p); @@ -2015,8 +2131,8 @@ int vehicle::damage (int p, int dmg, int type, bool aimed) { bool found_obs = false; for (int i = 0; i < pl.size(); i++) - if (part_flag (pl[i], vpf_obstacle) && - (!part_flag (pl[i], vpf_openable) || !parts[pl[i]].open)) + if (part_flag (pl[i], "OBSTACLE") && + (!part_flag (pl[i], "OPENABLE") || !parts[pl[i]].open)) { found_obs = true; break; @@ -2024,7 +2140,7 @@ int vehicle::damage (int p, int dmg, int type, bool aimed) if (!found_obs) // not aimed at this tile and no obstacle here -- fly through return dmg; } - int parm = part_with_feature (p, vpf_armor); + int parm = part_with_feature (p, "ARMOR"); int pdm = pl[rng (0, pl.size()-1)]; int dres; if (parm < 0) @@ -2035,7 +2151,7 @@ int vehicle::damage (int p, int dmg, int type, bool aimed) // covered by armor -- damage armor first dres = damage_direct (parm, dmg, type); // half damage for internal part(over parts not covered) - damage_direct (pdm, part_flag(pdm, vpf_over)? dmg : dmg / 2, type); + damage_direct (pdm, part_flag(pdm, "OVER")? dmg : dmg / 2, type); } return dres; } @@ -2072,7 +2188,7 @@ int vehicle::damage_direct (int p, int dmg, int type) parts[p].hp = 0; if (!parts[p].hp && last_hp > 0) insides_dirty = true; - if (part_flag(p, vpf_fuel_tank)) + if (part_flag(p, "FUEL_TANK")) { ammotype ft = part_info(p).fuel_type; if (ft == "gasoline" || ft == "plasma") @@ -2091,7 +2207,7 @@ int vehicle::damage_direct (int p, int dmg, int type) } } else - if (parts[p].hp <= 0 && part_flag(p, vpf_unmount_on_damage)) + if (parts[p].hp <= 0 && part_flag(p, "UNMOUNT_ON_DAMAGE")) { g->m.spawn_item(global_x() + parts[p].precalc_dx[0], global_y() + parts[p].precalc_dy[0], @@ -2106,7 +2222,7 @@ int vehicle::damage_direct (int p, int dmg, int type) void vehicle::leak_fuel (int p) { - if (!part_flag(p, vpf_fuel_tank)) + if (!part_flag(p, "FUEL_TANK")) return; ammotype ft = part_info(p).fuel_type; if (ft == "gasoline") @@ -2132,7 +2248,7 @@ void vehicle::leak_fuel (int p) void vehicle::fire_turret (int p, bool burst) { - if (!part_flag (p, vpf_turret)) + if (!part_flag (p, "TURRET")) return; it_gun *gun = dynamic_cast (g->itypes[part_info(p).item]); if (!gun) @@ -2157,7 +2273,7 @@ void vehicle::fire_turret (int p, bool burst) charges *= 10; // hacky, too for (int p = 0; p < parts.size(); p++) { - if (part_flag(p, vpf_fuel_tank) && + if (part_flag(p, "FUEL_TANK") && part_info(p).fuel_type == amt && parts[p].amount > 0) { @@ -2217,9 +2333,9 @@ bool vehicle::fire_turret_internal (int p, it_gun &gun, it_ammo &ammo, int charg if (traj[i].x == g->u.posx && traj[i].y == g->u.posy) return false; // won't shoot at player if (g->u_see(x, y)) - g->add_msg(_("The %s fires its %s!"), name.c_str(), part_info(p).name); + g->add_msg(_("The %s fires its %s!"), name.c_str(), part_info(p).name.c_str()); player tmp; - tmp.name = rmp_format(_("The %s"), part_info(p).name); + tmp.name = rmp_format(_("The %s"), part_info(p).name.c_str()); tmp.skillLevel(gun.skill_used).level(1); tmp.skillLevel("gun").level(0); tmp.recoil = abs(velocity) / 100 / 4; diff --git a/vehicle.h b/vehicle.h index 8040c83ccb04e..0f6b544d3d135 100644 --- a/vehicle.h +++ b/vehicle.h @@ -151,7 +151,7 @@ struct vehicle_part * coords. If it shows debug messages that it can't add parts, when you start * the game, you did something wrong. * There are a few rules: some parts are external, so one should be the first part - * at given mount point (tile). They require some part in neighbouring tile (with `vpf_mount_point` flag) to + * at given mount point (tile). They require some part in neighbouring tile (with the "MOUNT_POINT" flag) to * be mounted to. Other parts are internal or placed over. They can only be installed on top * of external part. Some functional parts can be only in single instance per tile, i. e., * no two engines at one mount point. @@ -162,6 +162,8 @@ class vehicle private: game *g; + bool can_stack_vpart_flag(std::string vpart_flag); + public: vehicle (game *ag=0, vhtype_id type_id = veh_null, int veh_init_fuel = -1, int veh_init_status = -1); ~vehicle (); @@ -182,7 +184,7 @@ class vehicle std::string use_controls(); // get vpart type info for part number (part at given vector index) - const vpart_info& part_info (int index); + vpart_info& part_info (int index); // get vpart powerinfo for part number, accounting for variable-sized parts. int part_power (int index); @@ -213,11 +215,11 @@ class vehicle // returns the list of indeces of parts inside (or over) given std::vector internal_parts (int p); -// returns index of part, inner to given, with certain flag (WARNING: without mfb!), or -1 - int part_with_feature (int p, unsigned int f, bool unbroken = true); +// returns index of part, inner to given, with certain flag, or -1 + int part_with_feature (int p, std::string f, bool unbroken = true); -// returns true if given flag is present for given part index (WARNING: without mfb!) - bool part_flag (int p, unsigned int f); +// returns true if given flag is present for given part index + bool part_flag (int p, std::string f); // Translate seat-relative mount coords into tile coords void coord_translate (int reldx, int reldy, int &dx, int &dy);