Large diffs are not rendered by default.

@@ -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
1 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.
@@ -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);
@@ -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<Item_tag, Use_function>::iterator found_function = iuse_function_list.find(function_name);

@@ -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<std::string> &tags);
unsigned flags_from_json(catajson flags, std::string flag_type="");
@@ -156,7 +156,7 @@ void map::generate_lightmap(game* g)
float iteration=1.0;
for (std::vector<int>::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);
42 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<item> 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;
}
@@ -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)
@@ -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(_("<veh>, 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(_("<veh> 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(_("<veh>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;

Large diffs are not rendered by default.

@@ -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"));

Large diffs are not rendered by default.

@@ -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<int> 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);