Exemplo n.º 1
0
/**
 *Works through cached vehicle definitions and creates vehicle objects from them.
 */
void game::finalize_vehicles()
{
    int part_x = 0, part_y = 0;
    std::string part_id = "";
    vehicle *next_vehicle;

    while (vehprototypes.size() > 0){
        vehicle_prototype *proto = vehprototypes.front();
        vehprototypes.pop();

        next_vehicle = new vehicle(this, proto->id.c_str());
        next_vehicle->name = _(proto->name.c_str());

        for (int i = 0; i < proto->parts.size(); ++i)
        {
            point p = proto->parts[i].first;
            part_x = p.x;
            part_y = p.y;

            part_id = proto->parts[i].second;

            if(next_vehicle->install_part(part_x, part_y, part_id) < 0) {
                debugmsg("init_vehicles: '%s' part '%s'(%d) can't be installed to %d,%d",
                        next_vehicle->name.c_str(), part_id.c_str(),
                        next_vehicle->parts.size(), part_x, part_y);
            }
        }

        for (int i = 0; i < proto->item_spawns.size(); i++) {
            next_vehicle->item_spawns.push_back(proto->item_spawns[i]);
        }

        vtypes[next_vehicle->type] = next_vehicle;
        delete proto;
    }
}
Exemplo n.º 2
0
/**
 * Given the name of a color, returns the nc_color value that matches. If
 * no match is found, c_unset is returned.
 * Special cases:
 * {"black"           , c_black}, // missing default prefix c_
 * {"<c|h|i>_black"   , h_black}, // has prefix c_ or h_ or i_
 * {"dark_gray_red"   , c_dkgray_red}, // dark_ instead of dk
 * {"light_blue_red"  , c_ltblue_red}, // light_ instead of lt
 * @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(const std::string &color)
{
    std::string new_color = color;
    if ( new_color.substr(1, 1) != "_" ) {  //c_  //i_  //h_
        new_color = "c_" + new_color;
    }

    const std::pair<std::string, std::string> pSearch[2] = {{"light_", "lt"}, {"dark_", "dk"}};
    for (int i=0; i < 2; ++i) {
        size_t pos = 0;
        while ((pos = new_color.find(pSearch[i].first, pos)) != std::string::npos) {
            new_color.replace(pos, pSearch[i].first.length(), pSearch[i].second);
            pos += pSearch[i].second.length();
        }
    }

    const nc_color col = all_colors.name_to_color(new_color);
    if ( col > 0 ) {
        return col;
    }

    debugmsg("color_from_string: couldn't parse color: %s", color.c_str());
    return c_unset;
}
Exemplo n.º 3
0
bool monster::is_fleeing(player &u)
{
// fleefactor is by default the agressiveness of the animal, minus the
//  percentage of remaining HP times four.  So, aggresiveness of 5 has a
//  fleefactor of 2 AT MINIMUM.
 if (type->hp == 0) {
  debugmsg("%s has type->hp of 0!", type->name.c_str());
  return false;
 }

 if (friendly != 0)
  return false;

 int fleefactor = type->agro - ((4 * (type->hp - hp)) / type->hp);
 if (u.has_trait(PF_ANIMALEMPATH) && has_flag(MF_ANIMAL)) {
  if (type->agro > 0) // Agressive animals flee instead
   fleefactor -= 5;
 }
 if (u.has_trait(PF_TERRIFYING))
  fleefactor -= 1;
 if (fleefactor > 0)
  return false;
 return true;
}
Exemplo n.º 4
0
const bodypart_ids &convert_bp( body_part bp )
{
    static const std::vector<bodypart_ids> body_parts = {
        bodypart_ids( "torso" ),
        bodypart_ids( "head" ),
        bodypart_ids( "eyes" ),
        bodypart_ids( "mouth" ),
        bodypart_ids( "arm_l" ),
        bodypart_ids( "arm_r" ),
        bodypart_ids( "hand_l" ),
        bodypart_ids( "hand_r" ),
        bodypart_ids( "leg_l" ),
        bodypart_ids( "leg_r" ),
        bodypart_ids( "foot_l" ),
        bodypart_ids( "foot_r" ),
        bodypart_ids( "num_bp" ),
    };
    if( bp > num_bp || bp < bp_torso ) {
        debugmsg( "Invalid body part token %d", bp );
        return body_parts[ num_bp ];
    }

    return body_parts[static_cast<size_t>( bp )];
}
Exemplo n.º 5
0
static void
rcmptime(struct stat *st, struct subcmd *sbcmds, char **env)
{
	DIR *d;
	DIRENTRY *dp;
	char *cp;
	char *optarget;
	int len;

	debugmsg(DM_CALL, "rcmptime(%x) start", st);

	if ((d = opendir((char *) target)) == NULL) {
		error("%s: open directory failed: %s", target, SYSERR);
		return;
	}
	optarget = ptarget;
	len = ptarget - target;
	while ((dp = readdir(d)) != NULL) {
		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
			continue;
		if (len + 1 + (int)strlen(dp->d_name) >= BUFSIZ - 1) {
			error("%s/%s: Name too long\n", target, dp->d_name);
			continue;
		}
		ptarget = optarget;
		*ptarget++ = '/';
		cp = dp->d_name;
		while ((*ptarget++ = *cp++) != '\0')
			;
		ptarget--;
		cmptime(target, sbcmds, env);
	}
	(void) closedir((DIR *) d);
	ptarget = optarget;
	*ptarget = '\0';
}
Exemplo n.º 6
0
item inventory::reduce_charges_internal(const Locator &locator, long quantity)
{
    int pos = 0;
    for (invstack::iterator iter = items.begin(); iter != items.end(); ++iter) {
        if (item_matches_locator(iter->front(), locator, pos)) {
            if (!iter->front().count_by_charges()) {
                debugmsg("Tried to remove %s by charges, but item is not counted by charges",
                         iter->front().tname().c_str());
            }
            item ret = iter->front();
            if (quantity > iter->front().charges) {
                debugmsg("Charges: Tried to remove charges that does not exist, \
                          removing maximum available charges instead");
                quantity = iter->front().charges;
            }
            ret.charges = quantity;
            iter->front().charges -= quantity;
            if (iter->front().charges <= 0) {
                items.erase(iter);
            }
            return ret;
        }
        ++pos;
    }
Exemplo n.º 7
0
int ReadConfig() {
	FILE *FP;
	char buf[1024];
	char cfn[80];


	memset( &pc, 0, sizeof pc );

	/* Set nonzero config defaults */
	pc.asteriskwritetimeout = 100;
	pc.clientwritetimeout = 100;
	pc.sslclhellotimeout = 500;

	sprintf(cfn, "%s/%s", CDIR, CFILE);
	FP = fopen( cfn, "r" );

	if ( !FP ) {
		fprintf(stderr, "Unable to open config file: %s/%s!\n", CDIR, CFILE);
		exit( 1 );
	}

	if (debug)
		debugmsg("config: parsing configuration file: %s", cfn);

	while ( fgets( buf, sizeof buf, FP ) ) {
		if (*buf == ';' || *buf == '\r' || *buf == '\n' || *buf == '#') continue;
		processline(buf);
	}

	fclose(FP);

	/* initialize SSL layer with our server certfile */
	init_secure(pc.certfile);

	return 0;
}
Exemplo n.º 8
0
//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;
    }
}
Exemplo n.º 9
0
void mission_start::place_dog(game *g, mission *miss)
{
 int city_id = g->cur_om.closest_city( g->om_location() );
 point house = g->cur_om.random_house_in_city(city_id);
 npc* dev = g->find_npc(miss->npc_id);
 if (dev == NULL) {
  debugmsg("Couldn't find NPC! %d", miss->npc_id);
  return;
 }
 g->u.i_add( item(g->itypes[itm_dog_whistle], 0) );
 g->add_msg(_("%s gave you a dog whistle."), dev->name.c_str());

 miss->target = house;
// Make it seen on our map
 for (int x = house.x - 6; x <= house.x + 6; x++) {
  for (int y = house.y - 6; y <= house.y + 6; y++)
   g->cur_om.seen(x, y) = true;
 }

 tinymap doghouse(&(g->itypes), &(g->mapitems), &(g->traps));
 doghouse.load(g, house.x * 2, house.y * 2);
 doghouse.add_spawn(mon_dog, 1, SEEX, SEEY, true, -1, miss->uid);
 doghouse.save(&(g->cur_om), int(g->turn), house.x * 2, house.y * 2);
}
Exemplo n.º 10
0
void faction::load_faction_template(std::string ident)
{
    faction_map::iterator found = _all_faction.find(ident);
    if (found != _all_faction.end()) {
        id = found->second.id;
        name = found->second.name;
        likes_u = found->second.likes_u;
        respects_u = found->second.respects_u;
        known_by_u = found->second.known_by_u;
        size = found->second.size;
        power = found->second.power;
        good = found->second.good;
        strength = found->second.strength;
        sneak = found->second.sneak;
        crime = found->second.crime;
        cult = found->second.cult;
        desc = found->second.desc;

        return;
    } else {
        debugmsg("Tried to get invalid faction: %s", ident.c_str());
        return;
    }
}
Exemplo n.º 11
0
void npc_class::check_consistency()
{
    for( const auto &legacy : legacy_ids ) {
        if( !npc_class_factory.is_valid( legacy ) ) {
            debugmsg( "Missing legacy npc class %s", legacy.c_str() );
        }
    }

    for( auto &cl : npc_class_factory.get_all() ) {
        if( !item_group::group_is_defined( cl.shopkeeper_item_group ) ) {
            debugmsg( "Missing shopkeeper item group %s", cl.shopkeeper_item_group.c_str() );
        }

        if( !cl.worn_override.empty() && !item_group::group_is_defined( cl.worn_override ) ) {
            debugmsg( "Missing worn override item group %s", cl.worn_override.c_str() );
        }

        if( !cl.carry_override.empty() && !item_group::group_is_defined( cl.carry_override ) ) {
            debugmsg( "Missing carry override item group %s", cl.carry_override.c_str() );
        }

        if( !cl.weapon_override.empty() && !item_group::group_is_defined( cl.weapon_override ) ) {
            debugmsg( "Missing weapon override item group %s", cl.weapon_override.c_str() );
        }

        for( const auto &pr : cl.skills ) {
            if( !pr.first.is_valid() ) {
                debugmsg( "Invalid skill %s", pr.first.c_str() );
            }
        }

        for( const auto &pr : cl.traits ) {
            if( !pr.first.is_valid() ) {
                debugmsg( "Invalid trait %s", pr.first.c_str() );
            }
        }
    }
}
Exemplo n.º 12
0
void profession::check_definition() const
{
    check_item_definitions( legacy_starting_items );
    check_item_definitions( legacy_starting_items_female );
    check_item_definitions( legacy_starting_items_male );
    if( !no_bonus.empty() && !item::type_is_defined( no_bonus ) ) {
        debugmsg( "no_bonus item '%s' is not an itype_id", no_bonus.c_str() );
    }

    if( !item_group::group_is_defined( _starting_items ) ) {
        debugmsg( "_starting_items group is undefined" );
    }
    if( !item_group::group_is_defined( _starting_items_male ) ) {
        debugmsg( "_starting_items_male group is undefined" );
    }
    if( !item_group::group_is_defined( _starting_items_female ) ) {
        debugmsg( "_starting_items_female group is undefined" );
    }

    for( auto const &a : _starting_CBMs ) {
        if( !a.is_valid() ) {
            debugmsg( "bionic %s for profession %s does not exist", a.c_str(), id.c_str() );
        }
    }

    for( auto &t : _starting_traits ) {
        if( !t.is_valid() ) {
            debugmsg( "trait %s for profession %s does not exist", t.c_str(), id.c_str() );
        }
    }

    for( const auto &elem : _starting_skills ) {
        if( !elem.first.is_valid() ) {
            debugmsg( "skill %s for profession %s does not exist", elem.first.c_str(), id.c_str() );
        }
    }
}
Exemplo n.º 13
0
/*
 * Read input from a child process.
 */
static void
readchild(CHILD *child)
{
	char rbuf[BUFSIZ];
	ssize_t amt;

	debugmsg(DM_CALL, "[readchild(%s, %d, %d) start]", 
		 child->c_name, child->c_pid, child->c_readfd);

	/*
	 * Check that this is a valid child.
	 */
	if (child->c_name == NULL || child->c_readfd <= 0) {
		debugmsg(DM_MISC, "[readchild(%s, %d, %d) bad child]",
			 child->c_name, child->c_pid, child->c_readfd);
		return;
	}

	/*
	 * Read from child and display the result.
	 */
	while ((amt = read(child->c_readfd, rbuf, sizeof(rbuf))) > 0) {
		/* XXX remove these debug calls */
		debugmsg(DM_MISC, "[readchild(%s, %d, %d) got %zd bytes]", 
			 child->c_name, child->c_pid, child->c_readfd, amt);

		(void) xwrite(fileno(stdout), rbuf, amt);

		debugmsg(DM_MISC, "[readchild(%s, %d, %d) write done]",
			 child->c_name, child->c_pid, child->c_readfd);
	}

	debugmsg(DM_MISC, "readchild(%s, %d, %d) done: amt = %zd errno = %d\n",
		 child->c_name, child->c_pid, child->c_readfd, amt, errno);

	/* 
	 * See if we've reached EOF 
	 */
	if (amt == 0)
		debugmsg(DM_MISC, "readchild(%s, %d, %d) at EOF\n",
			 child->c_name, child->c_pid, child->c_readfd);
}
Exemplo n.º 14
0
void mission_start::place_npc_software(mission *miss)
{
 npc* dev = g->find_npc(miss->npc_id);
 if (dev == NULL) {
  debugmsg("Couldn't find NPC! %d", miss->npc_id);
  return;
 }
 g->u.i_add( item("usb_drive", 0) );
 add_msg(_("%s gave you a USB drive."), dev->name.c_str());

 std::string type = "house";

 switch (dev->myclass) {
 case NC_HACKER:
  miss->item_id = "software_hacking";
  break;
 case NC_DOCTOR:
  miss->item_id = "software_medical";
  type = "s_pharm";
  miss->follow_up = MISSION_GET_ZOMBIE_BLOOD_ANAL;
  break;
 case NC_SCIENTIST:
  miss->item_id = "software_math";
  break;
 default:
  miss->item_id = "software_useless";
 }

    int dist = 0;
    point place;
    if (type == "house") {
        int city_id = g->cur_om->closest_city( g->om_location() );
        place = g->cur_om->random_house_in_city(city_id);
        // make it global coordinates
        place.x += g->cur_om->pos().x * OMAPX;
        place.y += g->cur_om->pos().y * OMAPY;
    } else {
        place = overmap_buffer.find_closest(g->om_global_location(), type, dist, false);
    }
    miss->target = place;
    overmap_buffer.reveal(place, 6, g->levz);

 tinymap compmap;
 compmap.load_abs(place.x * 2, place.y * 2, g->levz, false);
 point comppoint;

    oter_id oter = g->cur_om->ter(place.x, place.y, 0);
    if (oter == "house_north" || oter == "house_east"
            || oter == "house_south" || oter == "house_west") {
        std::vector<point> valid;
        for (int x = 0; x < SEEX * 2; x++) {
            for (int y = 0; y < SEEY * 2; y++) {
                if (compmap.ter(x, y) == t_floor && compmap.furn(x, y) == f_null) {
                    bool okay = false;
                    for (int x2 = x - 1; x2 <= x + 1 && !okay; x2++) {
                        for (int y2 = y - 1; y2 <= y + 1 && !okay; y2++) {
                            if (compmap.furn(x2, y2) == f_bed || compmap.furn(x2, y2) == f_dresser) {
                                okay = true;
                                valid.push_back( point(x, y) );
                            }
                        }
                    }
                }
            }
        }
        if (valid.empty()) {
            comppoint = point( rng(6, SEEX * 2 - 7), rng(6, SEEY * 2 - 7) );
        } else {
            comppoint = valid[rng(0, valid.size() - 1)];
        }
    } else if (oter == "s_pharm_north") {
        bool found = false;
        for (int x = SEEX * 2 - 1; x > 0 && !found; x--) {
            for (int y = SEEY * 2 - 1; y > 0 && !found; y--) {
                if (compmap.ter(x, y) == t_floor) {
                    found = true;
                    comppoint = point(x, y);
                }
            }
        }
    } else if (oter == "s_pharm_east") {
        bool found = false;
        for (int x = 0; x < SEEX * 2 && !found; x++) {
            for (int y = SEEY * 2 - 1; y > 0 && !found; y--) {
                if (compmap.ter(x, y) == t_floor) {
                    found = true;
                    comppoint = point(x, y);
                }
            }
        }
    } else if (oter == "s_pharm_south") {
        bool found = false;
        for (int x = 0; x < SEEX * 2 && !found; x++) {
            for (int y = 0; y < SEEY * 2 && !found; y++) {
                if (compmap.ter(x, y) == t_floor) {
                    found = true;
                    comppoint = point(x, y);
                }
            }
        }
    } else if (oter == "s_pharm_west") {
        bool found = false;
        for (int x = SEEX * 2 - 1; x > 0 && !found; x--) {
            for (int y = 0; y < SEEY * 2 && !found; y++) {
                if (compmap.ter(x, y) == t_floor) {
                    found = true;
                    comppoint = point(x, y);
                }
            }
        }
    }

 compmap.ter_set(comppoint.x, comppoint.y, t_console);
 computer *tmpcomp = compmap.add_computer(comppoint.x, comppoint.y, string_format(_("%s's Terminal"), dev->name.c_str()), 0);
 tmpcomp->mission_id = miss->uid;
 tmpcomp->add_option(_("Download Software"), COMPACT_DOWNLOAD_SOFTWARE, 0);
 compmap.save();
}
Exemplo n.º 15
0
void monfactions::finalize()
{
    if( faction_list.empty() ) {
        debugmsg( "No monster factions found." );
        return;
    }

    // Create a tree of faction dependence
    std::multimap< mfaction_id, mfaction_id > child_map;
    std::set< mfaction_id > unloaded; // To check if cycles exist
    std::queue< mfaction_id > queue;
    for( auto &faction : faction_list ) {
        unloaded.insert( faction.loadid );
        if( faction.loadid == faction.base_faction ) {
            // No parent = root of the (a?) tree
            queue.push( faction.loadid );
            continue;
        }

        // Point parent to children
        if( faction.base_faction >= 0 ) {
            child_map.insert( std::make_pair( faction.base_faction, faction.loadid ) );
        }

        // Set faction as friendly to itself if not explicitly set to anything
        if( faction.attitude_map.count( faction.loadid ) == 0 ) {
            faction.attitude_map[faction.loadid] = MFA_FRIENDLY;
        }
    }

    if( queue.empty() && !faction_list.empty() ) {
        debugmsg( "No valid root monster faction!" );
        return;
    }

    // Set uninitialized factions to be children of the root.
    // If more than one root exists, use the first one.
    const auto root = queue.front();
    for( auto &faction : faction_list ) {
        if( faction.base_faction < 0 ) {
            faction.base_faction = root;
            // If it is the (new) root, connecting it to own parent (self) would create a cycle.
            // So only try to connect it to the parent if it isn't own parent.
            if( faction.base_faction != faction.loadid ) {
                child_map.insert( std::make_pair( faction.base_faction, faction.loadid ) );
            }
        }
    }

    // Traverse the tree (breadth-first), starting from root
    while( !queue.empty() ) {
        mfaction_id cur = queue.front();
        queue.pop();
        if( unloaded.count( cur ) != 0 ) {
            unloaded.erase( cur );
        } else {
            debugmsg( "Tried to load monster faction %s more than once", cur.obj().id.c_str() );
            continue;
        }
        auto children = child_map.equal_range( cur );
        for( auto &it = children.first; it != children.second; ++it ) {
            // Copy attributes to child
            apply_base_faction( cur, it->second );
            queue.push( it->second );
        }
    }

    // Bad json
    if( !unloaded.empty() ) {
        std::string names;
        for( auto &fac : unloaded ) {
            names.append( fac.id().str() );
            names.append( " " );
            auto &the_faction = faction_list[fac];
            the_faction.base_faction = root;
        }

        debugmsg( "Cycle encountered when processing monster factions. Bad factions:\n %s", names.c_str() );
    }

    faction_list.shrink_to_fit(); // Save a couple of bytes
}
Exemplo n.º 16
0
void game::init_vehicles()
{
    vehicle *veh;
    int index = 0;
    int pi;
    vtypes.push_back(new vehicle(this, (vhtype_id)index++)); // veh_null
    vtypes.push_back(new vehicle(this, (vhtype_id)index++)); // veh_custom

#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); }

    //        name
    VEHICLE (_("Bicycle"));
    //    o
    //    #
    //    o

    //   dx, dy,    part_id
    PART (0, 0,     vp_frame_v2);
    PART (0, 0,     vp_saddle);
    PART (0, 0,     vp_controls);
    PART (0, 0,     vp_engine_foot_crank);
    PART (1, 0,     vp_wheel_bicycle);
    PART (-1, 0,    vp_wheel_bicycle);
    PART (-1, 0,    vp_cargo_box);

    //        name
    VEHICLE (_("Motorcycle Chassis"));
    //    o
    //    ^
    //    #
    //    o

    //   dx, dy,    part_id
    PART (0, 0,     vp_frame_v2);
    PART (0, 0,     vp_saddle);
    PART (1, 0,     vp_frame_handle);
    PART (1, 0,     vp_fuel_tank_gas);
    PART (-1, 0,    vp_wheel_motorbike);
    //        name
    VEHICLE (_("Motorcycle"));
    //    o
    //    ^
    //    #
    //    o

    //   dx, dy,    part_id
    PART (0, 0,     vp_frame_v2);
    PART (0, 0,     vp_saddle);
    PART (0, 0,     vp_controls);
    PART (0, 0,     vp_engine_gas_v2);
    PART (1, 0,     vp_frame_handle);
    PART (1, 0,     vp_head_light);
    PART (1, 0,     vp_fuel_tank_gas);
    PART (2, 0,     vp_wheel_motorbike);
    PART (-1, 0,    vp_wheel_motorbike);
    PART (-1, 0,    vp_cargo_box);

    //        name
    VEHICLE (_("Quad Bike"));
    //   0^0
    //    #
    //   0H0

    //   dx, dy,    part_id
    PART (0, 0,     vp_frame_v2);
    PART (0, 0,     vp_saddle);
    PART (0, 0,     vp_controls);
    PART (1, 0,     vp_frame_cover);
    PART (1, 0,     vp_engine_gas_v2);
    PART (1, 0,     vp_head_light);
    PART (1, 0,     vp_fuel_tank_gas);
    PART (1, 0,     vp_steel_plate);
    PART (-1,0,     vp_frame_h);
    PART (-1,0,     vp_cargo_trunk);
    PART (-1,0,     vp_steel_plate);
    PART (1, -1,    vp_wheel_motorbike);
    PART (1,  1,    vp_wheel_motorbike);
    PART (-1,-1,    vp_wheel_motorbike);
    PART (-1, 1,    vp_wheel_motorbike);

        //        name
    VEHICLE (_("Quad Bike Chassis"));
    //   0^0
    //    #
    //   0H0

    //   dx, dy,    part_id
    PART (0, 0,     vp_frame_v2);
    PART (0, 0,     vp_saddle);
    PART (1, 0,     vp_frame_cover);
    PART (-1,0,     vp_frame_h);
    PART (1, -1,    vp_wheel_motorbike);
    PART (-1,-1,    vp_wheel_motorbike);
    PART (-1, 1,    vp_wheel_motorbike);

    //        name
    VEHICLE (_("Car"));
    //   o--o
    //   |""|
    //   +##+
    //   +##+
    //   |HH|
    //   o++o

    //   dx, dy,    part_id
    PART (0, 0,     vp_frame_v2);
    PART (0, 0,     vp_seat);
    PART (0, 0,     vp_seatbelt);
    PART (0, 0,     vp_controls);
    PART (0, 0,     vp_roof);
    PART (0, 1,     vp_frame_v2);
    PART (0, 1,     vp_seat);
    PART (0, 1,     vp_seatbelt);
    PART (0, 1,     vp_roof);
    PART (0, -1,    vp_door);
    PART (0, 2,     vp_door);
    PART (-1, 0,     vp_frame_v2);
    PART (-1, 0,     vp_seat);
    PART (-1, 0,     vp_seatbelt);
    PART (-1, 0,     vp_roof);
    PART (-1, 1,     vp_frame_v2);
    PART (-1, 1,     vp_seat);
    PART (-1, 1,     vp_seatbelt);
    PART (-1, 1,     vp_roof);
    PART (-1, -1,    vp_door);
    PART (-1, 2,     vp_door);
    PART (1, 0,     vp_frame_h);
    PART (1, 0,     vp_window);
    PART (1, 0,     vp_head_light);
    PART (1, 1,     vp_frame_h);
    PART (1, 1,     vp_window);
    PART (1, 1,     vp_head_light);
    PART (1, -1,    vp_frame_v);
    PART (1, 2,     vp_frame_v);
    PART (2, 0,     vp_frame_h);
    PART (2, 0,     vp_engine_gas_v6);
    PART (2, 1,     vp_frame_h);
    PART (2, -1,    vp_wheel);
    PART (2, 2,     vp_wheel);
    PART (-2, 0,     vp_frame_v);
    PART (-2, 0,     vp_cargo_trunk);
    PART (-2, 0,     vp_muffler);
    PART (-2, 0,     vp_roof);
    PART (-2, 1,     vp_frame_v);
    PART (-2, 1,     vp_cargo_trunk);
    PART (-2, 1,     vp_roof);
    PART (-2, -1,    vp_board_v);
    PART (-2, -1,    vp_fuel_tank_gas);
    PART (-2, 2,     vp_board_v);
    PART (-3, -1,    vp_wheel);
    PART (-3, 0,     vp_door);
    PART (-3, 1,     vp_door);
    PART (-3, 2,     vp_wheel);

    //        name
    VEHICLE (_("Car Chassis"));
    //   o--o
    //   |""|
    //   +##+
    //   +##+
    //   |HH|
    //   o++o

    //   dx, dy,    part_id
    PART (0, 0,     vp_frame_v2);
    PART (0, 0,     vp_seat);
    PART (0, 1,     vp_frame_v2);
    PART (-1, 0,    vp_frame_v2);
    PART (-1, 1,    vp_frame_v2);
    PART (1, 0,     vp_frame_h);
    PART (1, 1,     vp_frame_h);
    PART (1, -1,    vp_frame_v);
    PART (1, 2,     vp_frame_v);
    PART (2, 0,     vp_frame_h);
    PART (2, 1,     vp_frame_h);
    PART (2, -1,    vp_wheel);
    PART (2, 2,     vp_wheel);
    PART (-2, 0,     vp_frame_v2);
    PART (-2, 1,     vp_frame_v2);
    PART (-2, -1,    vp_board_v);
    PART (-2, -1,    vp_fuel_tank_gas);
    PART (-2, 2,     vp_board_v);
    PART (-3, -1,    vp_wheel);
    PART (-3, 2,     vp_wheel);
    //        name
    VEHICLE (_("Flatbed Truck"));
    // 0-^-0
    // |"""|
    // +###+
    // |"""|
    // |HHH|
    // 0HHH0

    PART (0, 0,     vp_frame_v);
    PART (0, 0,     vp_cargo_box);
    PART (0, 0,     vp_roof);
//    PART (0, 0,     vp_seatbelt);
    PART (0, -1,    vp_frame_v2);
    PART (0, -1,    vp_seat);
    PART (0, -1,    vp_seatbelt);
    PART (0, -1,     vp_roof);
    PART (0, 1,     vp_frame_v2);
    PART (0, 1,     vp_seat);
    PART (0, 1,     vp_seatbelt);
    PART (0, 1,     vp_roof);
    PART (0, -2,    vp_door);
    PART (0, 2,     vp_door);
    PART (0, -1,     vp_controls);

    PART (1, 0,     vp_frame_h);
    PART (1, 0,     vp_window);
    PART (1, -1,    vp_frame_h);
    PART (1, -1,    vp_window);
    PART (1, -1,    vp_head_light);
    PART (1, 1,     vp_frame_h);
    PART (1, 1,     vp_window);
    PART (1, 1,    vp_head_light);
    PART (1, -2,    vp_frame_v);
    PART (1, 2,     vp_frame_v);

    PART (2, -1,    vp_frame_h);
    PART (2, 0,     vp_frame_cover);
    PART (2, 0,     vp_engine_gas_v6);
    PART (2, 1,     vp_frame_h);
    PART (2, -2,    vp_wheel_wide);
    PART (2,  2,    vp_wheel_wide);

    PART (-1, -1,   vp_frame_h);
    PART (-1, -1,   vp_window);
    PART (-1, 0,    vp_frame_h);
    PART (-1, 0,    vp_window);
    PART (-1, 1,    vp_frame_h);
    PART (-1, 1,    vp_window);
    PART (-1, -2,   vp_board_b);
    PART (-1, -2,   vp_fuel_tank_gas);
    PART (-1, 2,    vp_board_n);
    PART (-1, 2,    vp_fuel_tank_gas);

    PART (-2, -1,   vp_frame_v);
    PART (-2, -1,   vp_cargo_trunk);
    PART (-2, 0,    vp_frame_v);
    PART (-2, 0,    vp_cargo_trunk);
    PART (-2, 1,    vp_frame_v);
    PART (-2, 1,    vp_cargo_trunk);
    PART (-2, -2,   vp_board_v);
    PART (-2, 2,    vp_board_v);

    PART (-3, -1,   vp_frame_h);
    PART (-3, -1,   vp_cargo_trunk);
    PART (-3, 0,    vp_frame_h);
    PART (-3, 0,    vp_cargo_trunk);
    PART (-3, 1,    vp_frame_h);
    PART (-3, 1,    vp_cargo_trunk);
    PART (-3, -2,   vp_wheel_wide);
    PART (-3, 2,    vp_wheel_wide);

	VEHICLE (_("Semi Truck"));
	// semitrucksleeper
    // |=^^=|
    // O-HH-O
    // |""""|
    // +#oo#+
    // |--+-|
    // |#oo#|
    // |----|
    //  H||H
    // OO++OO
    // OO++OO
	// Based loosely on a Peterbilt Semi. 6L engine and 4 fuel tanks. 2 seater. Sleeper cab has zero visibility when opaque door is closed.

    // dx, dy, part_id
	PART (0, 0, vp_frame_v2);
	PART (0, 0, vp_cargo_box);
	PART (0, 0, vp_roof);
	PART (0, 1, vp_frame_v2);
	PART (0, 1, vp_bed);
	PART (0, 1, vp_roof);
	PART (0, -1, vp_frame_v2);
	PART (0, -1, vp_cargo_box);
	PART (0, -1, vp_roof);
	PART (0, 2, vp_board_v);
	PART (0, 2, vp_fuel_tank_gas);
	PART (0, -2, vp_frame_v2);
	PART (0, -2, vp_bed);
	PART (0, -2, vp_roof);
	PART (0, -3, vp_board_v);
	PART (0, -3, vp_fuel_tank_gas);

	PART (1, 0, vp_door_i);
	PART (1, -1, vp_board_h);
	PART (1, 1, vp_board_h);
	PART (1, -2, vp_board_h);
	PART (1, 2, vp_board_v);
	PART (1, 2, vp_fuel_tank_gas);
	PART (1, -3, vp_board_v);
	PART (1, -3, vp_fuel_tank_gas);

	PART (-1, 0, vp_board_h);
	PART (-1, 1, vp_board_h);
	PART (-1, -1, vp_board_h);
	PART (-1, -2, vp_board_h);
	PART (-1, 2, vp_board_n);
	PART (-1, -3, vp_board_b);

	PART (2, -1, vp_frame_h);
	PART (2, -1, vp_cargo_box);
	PART (2, -1, vp_roof);
	PART (2, 1, vp_frame_v2);
	PART (2, 1, vp_seat);
	PART (2, 1, vp_seatbelt);
	PART (2, 1, vp_roof);
	PART (2, -2, vp_frame_v2);
	PART (2, -2, vp_seat);
	PART (2, -2, vp_seatbelt);
	PART (2, -2, vp_roof);
	PART (2, 0, vp_frame_h);
	PART (2, 0, vp_cargo_box);
	PART (2, 0, vp_roof);
	PART (2, 2, vp_door);
	PART (2, -3, vp_door);
	PART (2, -2, vp_controls);

	PART (-2, 0, vp_frame_v);
	PART (-2, -1, vp_frame_v);
	PART (-2, 1, vp_frame_v2);
	PART (-2, 1, vp_cargo_trunk);
	PART (-2, -2, vp_frame_v2);
	PART (-2, -2, vp_cargo_trunk);


	PART (3, 0, vp_frame_h);
	PART (3, 0, vp_window);
	PART (3, -1, vp_frame_h);
	PART (3, -1, vp_window);
	PART (3, 1, vp_frame_h);
	PART (3, 1, vp_window);
	PART (3, -2, vp_frame_h);
	PART (3, -2, vp_window);
	PART (3, 2, vp_board_v);
	PART (3, -3, vp_board_v);

	PART (-3, 0, vp_frame_c);
	PART (-3, -1, vp_frame_c);
	PART (-3, 1, vp_wheel_wide);
	PART (-3, -2, vp_wheel_wide);
	PART (-3, 2, vp_wheel_wide);
	PART (-3, -3, vp_wheel_wide);

	PART (4, 0, vp_frame_v2);
	PART (4, -1, vp_frame_v2);
	PART (4, -1, vp_engine_gas_v8);
	PART (4, 1, vp_frame_h);
	PART (4, 1, vp_head_light);
	PART (4, -2, vp_frame_h);
	PART (4, -2, vp_head_light);
	PART (4, 2, vp_wheel_wide);
	PART (4, -3, vp_wheel_wide);

	PART (-4, 0, vp_frame_c);
	PART (-4, -1, vp_frame_c);
	PART (-4, 1, vp_wheel_wide);
	PART (-4, -2, vp_wheel_wide);
	PART (-4, 2, vp_wheel_wide);
	PART (-4, -3, vp_wheel_wide);

	PART (5, 0, vp_frame_cover);
	PART (5, -1, vp_frame_cover);
	PART (5, 1, vp_frame_h2);
	PART (5, -2, vp_frame_h2);
	PART (5, 2, vp_frame_u);
	PART (5, -3, vp_frame_y);

	VEHICLE (_("Truck Trailer"));
	// trucktrailer
    // |----|
    // |-++-|
    // |-++-|
    // |----|
    // |-HH-|
    // |----|
    // OO++OO
    // OO++OO
	// |----|
    // |-++-|
	// Pelletier trailer. Awaiting hitching of vehicles to each other...

	// dx, dy, part_id
	PART (0, 0, vp_frame_v2);
	PART (0, -1, vp_frame_v2);
	PART (0, 1, vp_frame_h);
	PART (0, -2, vp_frame_h);
	PART (0, 2, vp_board_v);
	PART (0, -3, vp_board_v);

	PART (1, 0, vp_frame_h);
	PART (1, -1, vp_frame_h);
	PART (1, 1, vp_frame_h);
	PART (1, -2, vp_frame_h);
	PART (1, 2, vp_board_v);
	PART (1, -3, vp_board_v);

	PART (-1, 0, vp_frame_c);
	PART (-1, -1, vp_frame_c);
	PART (-1, 1, vp_wheel_wide);
	PART (-1, -2, vp_wheel_wide);
	PART (-1, 2, vp_wheel_wide);
	PART (-1, -3, vp_wheel_wide);

	PART (2, 0, vp_frame_h);
	PART (2, -1, vp_frame_h);
	PART (2, 1, vp_frame_h);
	PART (2, -2, vp_frame_h);
	PART (2, 2, vp_board_v);
	PART (2, -3, vp_board_v);

	PART (-2, 0, vp_frame_c);
	PART (-2, -1, vp_frame_c);
	PART (-2, 1, vp_wheel_wide);
	PART (-2, -2, vp_wheel_wide);
	PART (-2, 2, vp_wheel_wide);
	PART (-2, -3, vp_wheel_wide);

	PART (3, 0, vp_frame_h);
	PART (3, -1, vp_frame_h);
	PART (3, 1, vp_frame_h);
	PART (3, -2, vp_frame_h);
	PART (3, 2, vp_board_v);
	PART (3, -3, vp_board_v);

	PART (-3, 0, vp_frame_h);
	PART (-3, -1, vp_frame_h);
	PART (-3, 1, vp_frame_h);
	PART (-3, -2, vp_frame_h);
	PART (-3, 2, vp_board_v);
	PART (-3, -3, vp_board_v);

	PART (4, 0, vp_frame_c);
	PART (4, -1, vp_frame_c);
	PART (4, 1, vp_frame_h);
	PART (4, -2, vp_frame_h);
	PART (4, 2, vp_board_v);
	PART (4, -3, vp_board_v);

	PART (-4, 0, vp_door_o);
	PART (-4, -1, vp_door_o);
	PART (-4, 1, vp_board_h);
	PART (-4, -2, vp_board_h);
	PART (-4, 2, vp_board_n);
	PART (-4, -3, vp_board_b);

	PART (5, 0, vp_board_h);
	PART (5, -1, vp_board_h);
	PART (5, 1, vp_board_h);
	PART (5, -2, vp_board_h);
	PART (5, 2, vp_board_u);
	PART (5, -3, vp_board_y);

        VEHICLE (_("Wagon"));
    // HHH
    // HHH
    // HHH

        PART (0, 0, vp_frame_v2);
        PART (0, 1, vp_frame_v2);
        PART (0, -1, vp_frame_v2);
        PART (1, 0, vp_frame_v2);
        PART (1, 1, vp_frame_v2);
        PART (1, -1, vp_frame_v2);
	PART (-1, 0, vp_frame_v2);
        PART (-1, 1, vp_frame_v2);
        PART (-1, -1, vp_frame_v2);

	VEHICLE (_("Beetle"));
	// vwbug
    // oHHo
    // |--|
    // +HH+
    // o\/o
	//Volkswagen Bug. Removed back seats entirely to make it feel smaller. Engine in back and cargo/fuel in front.

	// dx, dy, part_id
	PART (0, 0, vp_frame_v2);
	PART (0, 0, vp_seat);
	PART (0, 0, vp_seatbelt);
	PART (0, 0, vp_roof);
	PART (0, 0, vp_controls);
	PART (0, 1, vp_frame_v2);
	PART (0, 1, vp_seat);
	PART (0, 1, vp_seatbelt);
	PART (0, 1, vp_roof);
	PART (0, -1, vp_door);
	PART (0, 2, vp_door);

	PART (1, 0, vp_frame_h);
	PART (1, 0, vp_window);
        PART (1, 0, vp_head_light);
	PART (1, 1, vp_frame_h);
	PART (1, 1, vp_window);
        PART (1, 1, vp_head_light);
	PART (1, -1, vp_board_v);
	PART (1, 2, vp_board_v);

	PART (-1, 0, vp_frame_u);
	PART (-1, 0, vp_engine_gas_i4);
	PART (-1, 1, vp_board_y);
	PART (-1, -1, vp_wheel);
	PART (-1, 2, vp_wheel);

	PART (2, 0, vp_frame_v2);
	PART (2, 0, vp_cargo_trunk);
	PART (2, 1, vp_frame_v2);
	PART (2, 1, vp_fuel_tank_gas);
	PART (2, -1, vp_wheel);
	PART (2, 2, vp_wheel);

	VEHICLE (_("Bubble Car"));
    //  |-|
    // |o#o|
    // |###|
    // |oHo|
    //  +-+

	// dx, dy, part_id
	PART (0, 0, vp_frame_v2);
	PART (0, 0, vp_seat);
	PART (0, 0, vp_engine_motor);
	PART (0, 0, vp_fuel_tank_plut);
	PART (0, 0, vp_seatbelt);
	PART (0, 0, vp_roof);
	PART (0, 1, vp_frame_v2);
	PART (0, 1, vp_seat);
	PART (0, 1, vp_seatbelt);
	PART (0, 1, vp_roof);
	PART (0, -1, vp_frame_v2);
	PART (0, -1, vp_seat);
	PART (0, -1, vp_seatbelt);
	PART (0, -1, vp_roof);
	PART (0, 2, vp_frame_v);
	PART (0, 2, vp_window);
	PART (0, -2, vp_frame_v);
	PART (0, -2, vp_window);

	PART (1, 0, vp_frame_h);
	PART (1, 0, vp_seat);
	PART (1, 0, vp_seatbelt);
	PART (1, 0, vp_roof);
	PART (1, 0, vp_controls);
        PART (0, 0, vp_head_light);
	PART (1, 1, vp_wheel);
	PART (1, 1, vp_window);
	PART (1, -1, vp_wheel);
	PART (1, -1, vp_window);
	PART (1, 2, vp_frame_u);
	PART (1, 2, vp_window);
	PART (1, -2, vp_frame_y);
	PART (1, -2, vp_window);

	PART (-1, 0, vp_frame_h);
	PART (-1, 0, vp_cargo_trunk);
	PART (-1, 1, vp_wheel);
	PART (-1, 1, vp_window);
	PART (-1, -1, vp_wheel);
	PART (-1, -1, vp_window);
	PART (-1, 2, vp_door);
	PART (-1, -2, vp_door);

	PART (2, 0, vp_frame_h);
	PART (2, 0, vp_window);
	PART (2, 1, vp_frame_u);
	PART (2, 1, vp_window);
	PART (2, -1, vp_frame_y);
	PART (2, -1, vp_window);

	PART (-2, 0, vp_frame_h);
	PART (-2, 0, vp_window);
	PART (-2, 1, vp_frame_n);
	PART (-2, 1, vp_window);
	PART (-2, -1, vp_frame_b);
	PART (-2, -1, vp_window);

	VEHICLE (_("Golf Cart"));
	// Yamaha golf cart
    // oo
    // --
    // oo
	// Just an electric golf cart.

    // dx, dy, part_id
	PART (0, 0, vp_frame_h);
	PART (0, 0, vp_seat);
	PART (0, 0, vp_roof);
	PART (0, 0, vp_engine_motor);
	PART (0, 0, vp_controls);
	PART (0, 1, vp_frame_h);
	PART (0, 1, vp_seat);
	PART (0, 1, vp_roof);
	PART (0, 1, vp_fuel_tank_batt);

	PART (1, 0, vp_wheel_small);
	PART (1, 1, vp_wheel_small);

	PART (-1, 0, vp_wheel_small);
	PART (-1, 1, vp_wheel_small);

	VEHICLE (_("Scooter"));
	// Vespa scooter
    // o
    // ^
    // o
	// Just an underpowered gas scooter.

    // dx, dy, part_id
	PART (0, 0, vp_frame_handle);
	PART (0, 0, vp_head_light);
	PART (0, 0, vp_saddle);
	PART (0, 0, vp_engine_gas_1cyl);
	PART (0, 0, vp_fuel_tank_gas);
	PART (0, 0, vp_controls);

	PART (1, 0, vp_wheel_small);

	PART (-1, 0, vp_wheel_small);

	VEHICLE (_("Military Cargo Truck"));
	// Army M35A2 2.5 ton cargo truck
    // |^^^|
    // O-H-O
    // |"""|
    // +###+
    // |"""|
    // |#-#|
    // OO-OO
    // OO-OO
    // |#-#|
	// 3 seater. 6L engine default.

    // dx, dy, part_id
	PART (0, 0, vp_frame_v2);
	PART (0, 0, vp_window);
	PART (0, -1, vp_frame_h);
	PART (0, -1, vp_window);
	PART (0, 1, vp_frame_h);
	PART (0, 1, vp_window);
	PART (0, -2, vp_board_v);
	PART (0, 2, vp_board_v);

	PART (1, 0, vp_frame_v2);
	PART (1, 0, vp_seat);
	PART (1, 0, vp_fuel_tank_gas);
// 	PART (1, 0, vp_fuel_tank_hydrogen);
	PART (1, 0, vp_seatbelt);
	PART (1, 0, vp_roof);
	PART (1, -1, vp_frame_v2);
	PART (1, -1, vp_seat);
	PART (1, -1, vp_fuel_tank_gas);
//	PART (1, -1, vp_fuel_tank_hydrogen);
	PART (1, -1, vp_seatbelt);
	PART (1, -1, vp_roof);
	PART (1, -1, vp_controls);
	PART (1, 1, vp_frame_v2);
	PART (1, 1, vp_seat);
	PART (1, 1, vp_fuel_tank_gas);
//	PART (1, 1, vp_fuel_tank_hydrogen);
	PART (1, 1, vp_seatbelt);
	PART (1, 1, vp_roof);
	PART (1, -2, vp_door);
	PART (1, 2, vp_door);

	PART (-1, 0, vp_frame_h);
	PART (-1, -1, vp_frame_v2);
	PART (-1, -1, vp_seat);
	PART (-1, 1, vp_frame_v2);
	PART (-1, 1, vp_seat);
	PART (-1, -2, vp_frame_v);
	PART (-1, 2, vp_frame_v);

	PART (2, 0, vp_frame_h);
	PART (2, 0, vp_window);
	PART (2, -1, vp_frame_h);
	PART (2, -1, vp_window);
	PART (2, 1, vp_frame_h);
	PART (2, 1, vp_window);
	PART (2, -2, vp_frame_v);
	PART (2, 2, vp_frame_v);

	PART (-2, 0, vp_frame_h);
	PART (-2, -1, vp_wheel_wide);
	PART (-2, -1, vp_seat);
	PART (-2, -1, vp_steel_plate);
	PART (-2, 1, vp_wheel_wide);
	PART (-2, 1, vp_seat);
	PART (-2, 1, vp_steel_plate);
	PART (-2, -2, vp_wheel_wide);
	PART (-2, -2, vp_steel_plate);
	PART (-2, 2, vp_wheel_wide);
	PART (-2, 2, vp_steel_plate);

	PART (3, 0, vp_frame_v2);
	PART (3, -1, vp_frame_h);
	PART (3, -1, vp_head_light);
	PART (3, 1, vp_frame_h);
	PART (3, 1, vp_head_light);
	PART (3, 0, vp_engine_gas_v8);
	PART (3, 0, vp_steel_plate);
//	switch for hydrogen fuel or use both and change (3,0) to (3,1) and (3,-1)
//	PART (3, 0, vp_engine_plasma);
	PART (3, -2, vp_wheel_wide);
	PART (3, -2, vp_steel_plate);
	PART (3, 2, vp_wheel_wide);
	PART (3, 2, vp_steel_plate);

	PART (-3, 0, vp_frame_h);
	PART (-3, -1, vp_wheel_wide);
	PART (-3, -1, vp_seat);
	PART (-3, -1, vp_steel_plate);
	PART (-3, 1, vp_wheel_wide);
	PART (-3, 1, vp_seat);
	PART (-3, 1, vp_steel_plate);
	PART (-3, -2, vp_wheel_wide);
	PART (-3, -2, vp_steel_plate);
	PART (-3, 2, vp_wheel_wide);
	PART (-3, 2, vp_steel_plate);

	PART (4, 0, vp_frame_h2);
	PART (4, 0, vp_steel_plate);
	PART (4, -1, vp_frame_h2);
	PART (4, -1, vp_steel_plate);
	PART (4, 1, vp_frame_h2);
	PART (4, 1, vp_steel_plate);
	PART (4, -2, vp_frame_y);
	PART (4, -2, vp_steel_plate);
	PART (4, 2, vp_frame_u);
	PART (4, 2, vp_steel_plate);

	PART (-4, 0, vp_frame_h);
	PART (-4, -1, vp_frame_v2);
	PART (-4, -1, vp_seat);
	PART (-4, 1, vp_frame_v2);
	PART (-4, 1, vp_seat);
	PART (-4, -2, vp_frame_v);
	PART (-4, 2, vp_frame_v);

	VEHICLE (_("Schoolbus"));
	// Schoolbus
	// O=^=O
	// """""
	// "#..+
	// "#.#"
	// "#.#"
	// "#.#"
	// "#.#"
	// "#.#"
	// O#.#O
	// "#.#"
	// ""+""

    // dx, dy, part_id
	PART ( 0, 0, vp_frame_v2);
  PART ( 0, 0, vp_aisle_v2);
	PART ( 0, 0, vp_roof);
	PART ( 0, 1, vp_frame_v2);
  PART ( 0, 1, vp_aisle_h2);
	PART ( 0, 1, vp_roof);
	PART ( 0, 2, vp_door);
	PART ( 0, -1, vp_frame_v2);
	PART ( 0, -1, vp_seat);
	PART ( 0, -1, vp_controls);
	PART ( 0, -1, vp_roof);
	PART ( 0, -2, vp_frame_v);
	PART ( 0, -2, vp_window);

	PART ( 1, -2, vp_frame_h);
	PART ( 1, -2, vp_window);
	PART ( 1, -1, vp_frame_h);
	PART ( 1, -1, vp_window);
	PART ( 1, 0, vp_frame_h);
	PART ( 1, 0, vp_window);
	PART ( 1, 1, vp_frame_h);
	PART ( 1, 1, vp_window);
	PART ( 1, 2, vp_frame_h);
	PART ( 1, 2, vp_window);

	PART ( 2, -2, vp_wheel_wide);
	PART ( 2, -1, vp_frame_h2);
	PART ( 2, -1, vp_head_light);
	PART ( 2, 0, vp_frame_cover);
	PART ( 2, 0, vp_engine_gas_v8);
	PART ( 2, 1, vp_frame_h2);
	PART ( 2, 1, vp_head_light);
	PART ( 2, 2, vp_wheel_wide);

	PART ( -1, -2, vp_frame_v);
	PART ( -1, -2, vp_window);
	PART ( -1, -1, vp_frame_h2);
	PART ( -1, -1, vp_seat);
	PART ( -1, -1, vp_roof);
	PART ( -1, 0, vp_frame_v2);
  PART ( -1, 0, vp_aisle_v2);
	PART ( -1, 0, vp_roof);
	PART ( -1, 1, vp_frame_h2);
	PART ( -1, 1, vp_seat);
	PART ( -1, 1, vp_roof);
	PART ( -1, 2, vp_frame_v);
	PART ( -1, 2, vp_window);
	PART ( -1, 2, vp_fuel_tank_gas);

	PART ( -2, -2, vp_frame_v);
	PART ( -2, -2, vp_window);
	PART ( -2, -1, vp_frame_h2);
	PART ( -2, -1, vp_seat);
	PART ( -2, -1, vp_roof);
	PART ( -2, 0, vp_frame_v2);
  PART ( -2, 0, vp_floor_trunk);
	PART ( -2, 0, vp_roof);
	PART ( -2, 1, vp_frame_h2);
	PART ( -2, 1, vp_seat);
	PART ( -2, 1, vp_roof);
	PART ( -2, 2, vp_frame_v);
	PART ( -2, 2, vp_window);
	PART ( -2, 2, vp_fuel_tank_gas);

	PART ( -3, -2, vp_frame_v);
	PART ( -3, -2, vp_window);
	PART ( -3, -1, vp_frame_h2);
	PART ( -3, -1, vp_seat);
	PART ( -3, -1, vp_roof);
	PART ( -3, 0, vp_frame_v2);
  PART ( -3, 0, vp_aisle_v2);
	PART ( -3, 0, vp_roof);
	PART ( -3, 1, vp_frame_h2);
	PART ( -3, 1, vp_seat);
	PART ( -3, 1, vp_roof);
	PART ( -3, 2, vp_frame_v);
	PART ( -3, 2, vp_window);

	PART ( -4, -2, vp_frame_v);
	PART ( -4, -2, vp_window);
	PART ( -4, -1, vp_frame_h2);
	PART ( -4, -1, vp_seat);
	PART ( -4, -1, vp_roof);
	PART ( -4, 0, vp_frame_v2);
  PART ( -4, 0, vp_aisle_v2);
	PART ( -4, 0, vp_roof);
	PART ( -4, 1, vp_frame_h2);
	PART ( -4, 1, vp_seat);
	PART ( -4, 1, vp_roof);
	PART ( -4, 2, vp_frame_v);
	PART ( -4, 2, vp_window);

	PART ( -5, -2, vp_frame_v);
	PART ( -5, -2, vp_window);
	PART ( -5, -1, vp_frame_h2);
	PART ( -5, -1, vp_seat);
	PART ( -5, -1, vp_roof);
	PART ( -5, 0, vp_frame_v2);
  PART ( -5, 0, vp_floor_trunk);
	PART ( -5, 0, vp_roof);
	PART ( -5, 1, vp_frame_h2);
	PART ( -5, 1, vp_seat);
	PART ( -5, 1, vp_roof);
	PART ( -5, 2, vp_frame_v);
	PART ( -5, 2, vp_window);

	PART ( -6, -2, vp_wheel_wide);
	//	PART ( -6, -2, vp_window);
	PART ( -6, -1, vp_frame_h2);
	PART ( -6, -1, vp_seat);
	PART ( -6, -1, vp_roof);
	PART ( -6, 0, vp_frame_v2);
  PART ( -6, 0, vp_aisle_v2);
	PART ( -6, 0, vp_roof);
	PART ( -6, 1, vp_frame_h2);
	PART ( -6, 1, vp_seat);
	PART ( -6, 1, vp_roof);
	PART ( -6, 2, vp_wheel_wide);
	//	PART ( -6, 2, vp_window);

	PART ( -7, -2, vp_frame_v);
	PART ( -7, -2, vp_window);
	PART ( -7, -1, vp_frame_h2);
	PART ( -7, -1, vp_seat);
	PART ( -7, -1, vp_roof);
	PART ( -7, 0, vp_frame_v2);
  PART ( -7, 0, vp_aisle_v2);
	PART ( -7, 0, vp_roof);
	PART ( -7, 1, vp_frame_h2);
	PART ( -7, 1, vp_seat);
	PART ( -7, 1, vp_roof);
	PART ( -7, 2, vp_frame_v);
	PART ( -7, 2, vp_window);

	PART ( -8, -2, vp_frame_h);
	PART ( -8, -2, vp_window);
	PART ( -8, -1, vp_frame_h);
	PART ( -8, -1, vp_window);
	PART ( -8, 0, vp_door);
	PART ( -8, 1, vp_frame_h);
	PART ( -8, 1, vp_window);
	PART ( -8, 2, vp_frame_h);
	PART ( -8, 2, vp_window);

    //        name
    VEHICLE (_("Car"));
    //   o--o
    //   |""|
    //   +##+
    //   +##+
    //   #HH#
    //   o++o

    //   dx, dy,    part_id
    PART (0, 0,     vp_frame_v2);
    PART (0, 0,     vp_seat);
    PART (0, 0,     vp_seatbelt);
    PART (0, 0,     vp_controls);
    PART (0, 0,     vp_roof);
    PART (0, 1,     vp_frame_v2);
    PART (0, 1,     vp_seat);
    PART (0, 1,     vp_seatbelt);
    PART (0, 1,     vp_roof);
    PART (0, -1,    vp_door);
    PART (0, 2,     vp_door);
    PART (-1, 0,     vp_frame_v2);
    PART (-1, 0,     vp_seat);
    PART (-1, 0,     vp_seatbelt);
    PART (-1, 0,     vp_roof);
    PART (-1, 1,     vp_frame_v2);
    PART (-1, 1,     vp_seat);
    PART (-1, 1,     vp_seatbelt);
    PART (-1, 1,     vp_roof);
    PART (-1, -1,    vp_door);
    PART (-1, 2,     vp_door);
    PART (1, 0,     vp_frame_h);
    PART (1, 0,     vp_window);
    PART (1, 0,     vp_head_light);
    PART (1, 1,     vp_frame_h);
    PART (1, 1,     vp_window);
    PART (1, 1,     vp_head_light);
    PART (1, -1,    vp_frame_v);
    PART (1, 2,     vp_frame_v);
    PART (2, 0,     vp_frame_h);
    PART (2, 0,     vp_engine_motor_large);
    PART (2, 1,     vp_frame_h);
    PART (2, -1,    vp_wheel);
    PART (2, 2,     vp_wheel);
    PART (-2, 0,     vp_frame_v);
    PART (-2, 0,     vp_cargo_trunk);
    PART (-2, 0,     vp_roof);
    PART (-2, 1,     vp_frame_v);
    PART (-2, 1,     vp_cargo_trunk);
    PART (-2, 1,     vp_roof);
    PART (-2, -1,    vp_board_v);
    PART (-2, -1,    vp_fuel_tank_batt);
    PART (-2, -1,    vp_solar_panel);
    PART (-2, 2,     vp_board_v);
    PART (-2, 2,     vp_fuel_tank_batt);
    PART (-2, 2,     vp_solar_panel);
    PART (-3, -1,    vp_wheel);
    PART (-3, 0,     vp_door);
    PART (-3, 1,     vp_door);
    PART (-3, 2,     vp_wheel);

    if (vtypes.size() != num_vehicles)
        debugmsg("%d vehicles, %d types", vtypes.size(), num_vehicles);
}
Exemplo n.º 17
0
// If we're not using lua, need to define Use_function in a way to always call the C++ function
int use_function::call(player* player_instance, item* item_instance, bool active) {
    if(function_type == USE_FUNCTION_CPP) {
        // If it's a C++ function, simply call it with the given arguments.
        iuse tmp;
        return (tmp.*cpp_function)(player_instance, item_instance, active);
    } else {
        #ifdef LUA

        // We'll be using lua_state a lot!
        lua_State* L = lua_state;

        // If it's a lua function, the arguments have to be wrapped in
        // lua userdata's and passed on the lua stack.
        // We will now call the function f(player, item, active)

        update_globals(L);

        // Push the lua function on top of the stack
        lua_rawgeti(L, LUA_REGISTRYINDEX, lua_function);

        // Push the item on top of the stack.
        int item_in_registry;
        {
            item** item_userdata = (item**) lua_newuserdata(L, sizeof(item*));
            *item_userdata = item_instance;

            // Save a reference to the item in the registry so that we can deallocate it
            // when we're done.
            item_in_registry = luah_store_in_registry(L, -1);

            // Set the metatable for the item.
            luah_setmetatable(L, "item_metatable");
        }

        // Push the "active" parameter on top of the stack.
        lua_pushboolean(L, active);

        // Call the iuse function
        int err = lua_pcall(L, 3, 1, 0);
        if(err) {
            // Error handling.
            const char* error = lua_tostring(L, -1);
            debugmsg("Error in lua iuse function: %s", error);
        }

        // Make sure the now outdated parameters we passed to lua aren't
        // being used anymore by setting a metatable that will error on
        // access.
        luah_remove_from_registry(L, item_in_registry);
        luah_setmetatable(L, "outdated_metatable");

        return lua_tointeger(L, -1);

        #else

        // If LUA isn't defined and for some reason we registered a lua function,
        // simply do nothing.
        return 0;

        #endif

    }
}
Exemplo n.º 18
0
bool player::install_bionics(game *g, it_bionic* type)
{
 if (type == NULL) {
  debugmsg("Tried to install NULL bionic");
  return false;
 }
 std::string bio_name = type->name.substr(5);	// Strip off "CBM: "
 WINDOW* w = newwin(25, 80, 0, 0);

 int pl_skill = int_cur +
   skillLevel("electronics").level() * 4 +
   skillLevel("firstaid").level()    * 3 +
   skillLevel("mechanics").level()   * 2;

 int skint = int(pl_skill / 4);
 int skdec = int((pl_skill * 10) / 4) % 10;

// Header text
 mvwprintz(w, 0,  0, c_white, "Installing bionics:");
 mvwprintz(w, 0, 20, type->color, bio_name.c_str());

// Dividing bars
 for (int i = 0; i < 80; i++) {
  mvwputch(w,  1, i, c_ltgray, LINE_OXOX);
  mvwputch(w, 21, i, c_ltgray, LINE_OXOX);
 }
// Init the list of bionics
 for (unsigned int i = 1; i < type->options.size(); i++) {
  bionic_id id = type->options[i];
  mvwprintz(w, i + 2, 0, (has_bionic(id) ? c_ltred : c_ltblue),
            bionics[id].name.c_str());
 }
// Helper text
 mvwprintz(w, 2, 40, c_white,        "Difficulty of this module: %d",
           type->difficulty);
 mvwprintz(w, 3, 40, c_white,        "Your installation skill:   %d.%d",
           skint, skdec);
 mvwprintz(w, 4, 40, c_white,       "Installation requires high intelligence,");
 mvwprintz(w, 5, 40, c_white,       "and skill in electronics, first aid, and");
 mvwprintz(w, 6, 40, c_white,       "mechanics (in that order of importance).");

 int chance_of_success = int((100 * pl_skill) /
                             (pl_skill + 4 * type->difficulty));

 mvwprintz(w, 8, 40, c_white,        "Chance of success:");

 nc_color col_suc;
 if (chance_of_success >= 95)
  col_suc = c_green;
 else if (chance_of_success >= 80)
  col_suc = c_ltgreen;
 else if (chance_of_success >= 60)
  col_suc = c_yellow;
 else if (chance_of_success >= 35)
  col_suc = c_ltred;
 else
  col_suc = c_red;

 mvwprintz(w, 8, 59, col_suc, "%d%%%%", chance_of_success);

 mvwprintz(w, 10, 40, c_white,       "Failure may result in crippling damage,");
 mvwprintz(w, 11, 40, c_white,       "loss of existing bionics, genetic damage");
 mvwprintz(w, 12, 40, c_white,       "or faulty installation.");
 wrefresh(w);

 if (type->id == itm_bionics_battery) {	// No selection list; just confirm
  mvwprintz(w,  2, 0, h_ltblue, "Battery Level +%d", BATTERY_AMOUNT);
  mvwprintz(w, 22, 0, c_ltblue, "\
Installing this bionic will increase your total battery capacity by %d.\n\
Batteries are necessary for most bionics to function.  They also require a\n\
charge mechanism, which must be installed from another CBM.", BATTERY_AMOUNT);
  char ch;
  wrefresh(w);
  do
   ch = getch();
  while (ch != 'q' && ch != '\n' && ch != KEY_ESCAPE);
  if (ch == '\n') {
   practice("electronics", (100 - chance_of_success) * 1.5);
   practice("firstaid", (100 - chance_of_success) * 1.0);
   practice("mechanics", (100 - chance_of_success) * 0.5);
   int success = chance_of_success - rng(1, 100);
   if (success > 0) {
    g->add_msg("Successfully installed batteries.");
    max_power_level += BATTERY_AMOUNT;
   } else
    bionics_install_failure(g, this, success);
   werase(w);
   delwin(w);
   g->refresh_all();
   return true;
  }
  werase(w);
  delwin(w);
  g->refresh_all();
  return false;
 }
Exemplo n.º 19
0
void game::wishitem( player *p, int x, int y, int z)
{
    if ( p == NULL && x <= 0 ) {
        debugmsg("game::wishitem(): invalid parameters");
        return;
    }
    const std::vector<std::string> standard_itype_ids = item_controller->get_all_itype_ids();
    int prev_amount, amount = 1;
    uimenu wmenu;
    wmenu.w_x = 0;
    wmenu.w_width = TERMX;
    wmenu.pad_right = ( TERMX / 2 > 40 ? TERMX - 40 : TERMX / 2 );
    wmenu.return_invalid = true;
    wmenu.selected = uistate.wishitem_selected;
    wish_item_callback *cb = new wish_item_callback( standard_itype_ids );
    wmenu.callback = cb;

    for (size_t i = 0; i < standard_itype_ids.size(); i++) {
        item ity( standard_itype_ids[i], 0 );
        wmenu.addentry( i, true, 0, string_format( _( "%.*s" ), wmenu.pad_right - 5,
                                                   ity.tname( 1, false ).c_str() ) );
        wmenu.entries[i].extratxt.txt = string_format("%c", ity.symbol());
        wmenu.entries[i].extratxt.color = ity.color();
        wmenu.entries[i].extratxt.left = 1;
    }
    do {
        wmenu.query();
        if ( wmenu.ret >= 0 ) {
            item granted(standard_itype_ids[wmenu.ret], calendar::turn);
            prev_amount = amount;
            if (p != NULL) {
                amount = std::atoi(
                             string_input_popup(_("How many?"), 20, to_string( amount ),
                                                granted.tname()).c_str());
            }
            if (dynamic_cast<wish_item_callback *>(wmenu.callback)->incontainer) {
                granted = granted.in_its_container();
            }
            if ( p != NULL ) {
                for (int i = 0; i < amount; i++) {
                    p->i_add(granted);
                }
                p->invalidate_crafting_inventory();
            } else if ( x >= 0 && y >= 0 ) {
                m.add_item_or_charges( tripoint( x, y, z ), granted);
                wmenu.keypress = 'q';
            }
            if ( amount > 0 ) {
                dynamic_cast<wish_item_callback *>(wmenu.callback)->msg =
                    _("Wish granted. Wish for more or hit 'q' to quit.");
            }
            uistate.wishitem_selected = wmenu.ret;
            if ( !amount ) {
                amount = prev_amount;
            }
        }
    } while ( wmenu.keypress != 'q' && wmenu.keypress != KEY_ESCAPE && wmenu.keypress != ' ' );
    delete wmenu.callback;
    wmenu.callback = NULL;
    return;
}
Exemplo n.º 20
0
std::vector<item> game::multidrop()
{
 u.inv.sort();
 u.inv.restack(&u);
 WINDOW* w_inv = newwin(((VIEWY < 12) ? 25 : VIEWY*2+1), ((VIEWX < 12) ? 80 : VIEWX*2+56), VIEW_OFFSET_Y, VIEW_OFFSET_X);
 const int maxitems = (VIEWY < 12) ? 20 : VIEWY*2-4;    // Number of items to show at one time.
 std::map<char, int> dropping; // Count of how many we'll drop from each stack
 int count = 0; // The current count
 std::vector<char> weapon_and_armor; // Always single, not counted
 bool warned_about_bionic = false; // Printed add_msg re: dropping bionics
 print_inv_statics(this, w_inv, "Multidrop:", weapon_and_armor);
 int base_weight = u.weight_carried();
 int base_volume = u.volume_carried();

 int ch = (int)'.';
 int start = 0, cur_it;
 invslice stacks = u.inv.slice(0, u.inv.size());
 std::vector<int> firsts = find_firsts(stacks);
 do {
  inventory drop_subset = u.inv.subset(dropping);
  int new_weight = base_weight - drop_subset.weight();
  int new_volume = base_volume - drop_subset.volume();
  for (int i = 0; i < weapon_and_armor.size(); ++i) {
   new_weight -= u.i_at(weapon_and_armor[i]).weight();
  }
  print_inv_weight_vol(this, w_inv, new_weight, new_volume);
  if (( ch == '<' || ch == KEY_PPAGE ) && start > 0) {
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
   start -= maxitems;
   if (start < 0)
    start = 0;
   mvwprintw(w_inv, maxitems + 4, 0, "         ");
  }
  if (( ch == '>' || ch == KEY_NPAGE ) && cur_it < u.inv.size()) {
   start = cur_it;
   mvwprintw(w_inv, maxitems + 4, 12, "            ");
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
  }
  int cur_line = 2;
  for (cur_it = start; cur_it < start + maxitems && cur_line < maxitems+3; cur_it++) {
// Clear the current line;
   mvwprintw(w_inv, cur_line, 0, "                                             ");
// Print category header
   for (int i = 1; i < iCategorieNum; i++) {
    if (cur_it == firsts[i-1]) {
     mvwprintz(w_inv, cur_line, 0, c_magenta, CATEGORIES[i].c_str());
     cur_line++;
    }
   }
   if (cur_it < stacks.size()) {
    item& it = stacks[cur_it]->front();
    mvwputch (w_inv, cur_line, 0, c_white, it.invlet);
    char icon = '-';
    if (dropping[it.invlet] >= (it.count_by_charges() ? it.charges : stacks[cur_it]->size()))
     icon = '+';
    else if (dropping[it.invlet] > 0)
     icon = '#';
    nc_color col = (dropping[it.invlet] == 0 ? c_ltgray : c_white);
    mvwprintz(w_inv, cur_line, 1, col, " %c %s", icon,
              it.tname(this).c_str());
    if (stacks[cur_it]->size() > 1)
     wprintz(w_inv, col, " [%d]", stacks[cur_it]->size());
    if (it.charges > 0)
     wprintz(w_inv, col, " (%d)", it.charges);
    else if (it.contents.size() == 1 &&
             it.contents[0].charges > 0)
     wprintw(w_inv, " (%d)", it.contents[0].charges);
   }
   cur_line++;
  }
  if (start > 0)
   mvwprintw(w_inv, maxitems + 4, 0, "< Go Back");
  if (cur_it < u.inv.size())
   mvwprintw(w_inv, maxitems + 4, 12, "> More items");
  wrefresh(w_inv);
  ch = input();
  if (ch >= '0'&& ch <= '9') {
   ch = (char)ch - '0';
   count *= 10;
   count += ch;
  } else if (u.has_item(ch)) {
   item& it = u.inv.item_by_letter(ch);
   if (it.is_null()) { // Not from inventory
    int found = false;
    for (int i = 0; i < weapon_and_armor.size() && !found; i++) {
     if (weapon_and_armor[i] == ch) {
      weapon_and_armor.erase(weapon_and_armor.begin() + i);
      found = true;
      print_inv_statics(this, w_inv, "Multidrop:", weapon_and_armor);
     }
    }
    if (!found) {
     if ( ch == u.weapon.invlet &&
          std::find(unreal_itype_ids.begin(), unreal_itype_ids.end(), u.weapon.type->id) != unreal_itype_ids.end()){
      if (!warned_about_bionic)
       add_msg("You cannot drop your %s.", u.weapon.tname(this).c_str());
      warned_about_bionic = true;
     } else {
      weapon_and_armor.push_back(ch);
      print_inv_statics(this, w_inv, "Multidrop:", weapon_and_armor);
     }
    }
   } else {
    int index = -1;
    for (int i = 0; i < stacks.size(); ++i) {
     if (stacks[i]->front().invlet == it.invlet) {
      index = i;
      break;
     }
    }
    if (index == -1) {
     debugmsg("Inventory got out of sync with inventory slice?");
    }
    if (count == 0) {
    if (it.count_by_charges())
      {
       if (dropping[it.invlet] == 0)
        dropping[it.invlet] = -1;
       else
        dropping[it.invlet] = 0;
      }
    else
      {
       if (dropping[it.invlet] == 0)
        dropping[it.invlet] = stacks[index]->size();
       else
        dropping[it.invlet] = 0;
      }
    }

    else if (count >= stacks[index]->size() && !it.count_by_charges())
       dropping[it.invlet] = stacks[index]->size();
    else
      dropping[it.invlet] = count;

   count = 0;
  }
  }
 } while (ch != '\n' && ch != KEY_ESCAPE && ch != ' ');
 werase(w_inv);
 delwin(w_inv);
 erase();
 refresh_all();

 std::vector<item> ret;

 if (ch != '\n')
  return ret; // Canceled!

 for (std::map<char,int>::iterator it = dropping.begin(); it != dropping.end(); it++) {
  if (it->second == -1)
   ret.push_back( u.inv.remove_item_by_letter( it->first));
  else if (it->second && u.inv.item_by_letter( it->first).count_by_charges()) {
   int charges = u.inv.item_by_letter( it->first).charges;// >= it->second ? : it->second;
   ret.push_back( u.inv.remove_item_by_charges( it->first, it->second > charges ? charges : it->second));
  } else if (it->second) 
   for (int j = it->second; j > 0; j--)
    ret.push_back( u.inv.remove_item_by_letter( it->first));
 }

 for (int i = 0; i < weapon_and_armor.size(); i++)
  ret.push_back(u.i_rem(weapon_and_armor[i]));

 return ret;
}
Exemplo n.º 21
0
void mapbuffer::load()
{
    if (!master_game) {
        debugmsg("Can't load mapbuffer without a master_game");
        return;
    }
    std::map<tripoint, submap*>::iterator it;
    std::ifstream fin;
    fin.open("save/maps.txt");
    if (!fin.is_open())
        return;

    int itx, ity, t, d, a, num_submaps, num_loaded = 0;
    item it_tmp;
    std::string databuff;
    fin >> num_submaps;

    while (!fin.eof()) {
        if (num_loaded % 100 == 0)
            popup_nowait(_("Please wait as the map loads [%d/%d]"),
                         num_loaded, num_submaps);
        int locx, locy, locz, turn;
        submap* sm = new submap;
        fin >> locx >> locy >> locz >> turn;
        sm->turn_last_touched = turn;
        int turndif = (master_game ? int(master_game->turn) - turn : 0);
        if (turndif < 0)
            turndif = 0;
// Load terrain
        for (int j = 0; j < SEEY; j++) {
            for (int i = 0; i < SEEX; i++) {
                int tmpter;
                fin >> tmpter;
                sm->ter[i][j] = ter_id(tmpter);
                sm->frn[i][j] = f_null;
                sm->itm[i][j].clear();
                sm->trp[i][j] = tr_null;
                //sm->fld[i][j] = field(); //not needed now
                sm->graf[i][j] = graffiti();
            }
        }
// Load irradiation
        for (int j = 0; j < SEEY; j++) {
            for (int i = 0; i < SEEX; i++) {
                int radtmp;
                fin >> radtmp;
                radtmp -= int(turndif / 100);	// Radiation slowly decays
                if (radtmp < 0)
                    radtmp = 0;
                sm->rad[i][j] = radtmp;
            }
        }
// Load items and traps and fields and spawn points and vehicles
        std::string string_identifier;
        do {
            fin >> string_identifier; // "----" indicates end of this submap
            t = 0;
            if (string_identifier == "I") {
                fin >> itx >> ity;
                getline(fin, databuff); // Clear out the endline
                getline(fin, databuff);
                it_tmp.load_info(databuff, master_game);
                sm->itm[itx][ity].push_back(it_tmp);
                if (it_tmp.active)
                    sm->active_item_count++;
            } else if (string_identifier == "C") {
                getline(fin, databuff); // Clear out the endline
                getline(fin, databuff);
                int index = sm->itm[itx][ity].size() - 1;
                it_tmp.load_info(databuff, master_game);
                sm->itm[itx][ity][index].put_in(it_tmp);
                if (it_tmp.active)
                    sm->active_item_count++;
            } else if (string_identifier == "T") {
                fin >> itx >> ity >> t;
                sm->trp[itx][ity] = trap_id(t);
            } else if (string_identifier == "f") {
Exemplo n.º 22
0
int item::pick_reload_ammo(player &u, bool interactive)
{
 if( is_null() )
  return false;

 if (!type->is_gun() && !type->is_tool()) {
  debugmsg("RELOADING NON-GUN NON-TOOL");
  return false;
 }
 int has_spare_mag = has_gunmod (itm_spare_mag);

 std::vector<int> am;	// List of indicies of valid ammo

 if (type->is_gun()) {
  if(charges <= 0 && has_spare_mag != -1 && contents[has_spare_mag].charges > 0) {
   // Special return to use magazine for reloading.
   return -2;
  }
  it_gun* tmp = dynamic_cast<it_gun*>(type);

  // If there's room to load more ammo into the gun or a spare mag, stash the ammo.
  // If the gun is partially loaded make sure the ammo matches.
  // If the gun is empty, either the spre mag is empty too and anything goes,
  // or the spare mag is loaded and we're doing a tactical reload.
  if (charges < clip_size() ||
      (has_spare_mag != -1 && contents[has_spare_mag].charges < tmp->clip)) {
   std::vector<int> tmpammo = u.has_ammo(ammo_type());
   for (int i = 0; i < tmpammo.size(); i++)
    if (charges >= 0 || u.inv[tmpammo[i]].typeId() == curammo->id)
      am.push_back(tmpammo[i]);
  }

  // ammo for gun attachments (shotgun attachments, grenade attachments, etc.)
  // for each attachment, find its associated ammo & append it to the ammo vector
  for (int i = 0; i < contents.size(); i++)
   if (contents[i].is_gunmod() && contents[i].has_flag(IF_MODE_AUX) &&
       contents[i].charges < (dynamic_cast<it_gunmod*>(contents[i].type))->clip) {
    std::vector<int> tmpammo = u.has_ammo((dynamic_cast<it_gunmod*>(contents[i].type))->newtype);
    for(int j = 0; j < tmpammo.size(); j++)
     if (contents[i].charges >= 0 ||
         u.inv[tmpammo[j]].typeId() == contents[i].curammo->id)
      am.push_back(tmpammo[j]);
   }
 } else { //non-gun.
  am = u.has_ammo(ammo_type());
 }

 int index = -1;

 if (am.size() > 1 && interactive) {// More than one option; list 'em and pick
   WINDOW* w_ammo = newwin(am.size() + 1, 80, 0, 0);
   char ch;
   clear();
   it_ammo* ammo_type;
   mvwprintw(w_ammo, 0, 0, "\
Choose ammo type:         Damage     Armor Pierce     Range     Accuracy");
   for (int i = 0; i < am.size(); i++) {
    ammo_type = dynamic_cast<it_ammo*>(u.inv[am[i]].type);
    mvwaddch(w_ammo, i + 1, 1, i + 'a');
    mvwprintw(w_ammo, i + 1, 3, "%s (%d)", u.inv[am[i]].tname().c_str(),
                                           u.inv[am[i]].charges);
    mvwprintw(w_ammo, i + 1, 27, "%d", ammo_type->damage);
    mvwprintw(w_ammo, i + 1, 38, "%d", ammo_type->pierce);
    mvwprintw(w_ammo, i + 1, 55, "%d", ammo_type->range);
    mvwprintw(w_ammo, i + 1, 65, "%d", 100 - ammo_type->accuracy);
   }
   refresh();
   wrefresh(w_ammo);
   do
    ch = getch();
   while ((ch < 'a' || ch - 'a' > am.size() - 1) && ch != ' ' && ch != 27);
   werase(w_ammo);
   delwin(w_ammo);
   erase();
   if (ch == ' ' || ch == 27)
    index = -1;
   else
    index = am[ch - 'a'];
 }
bool sokoban_game::parse_level()
{
    /*
    # Wall
    $ Package
    space Floor
    . Goal
    * Package on Goal
    @ Sokoban
    + Sokoban on Goal
    */

    iCurrentLevel = 0;
    iNumLevel = 0;

    vLevel.clear();
    vUndo.clear();
    vLevelDone.clear();

    std::ifstream fin;
    fin.open("data/raw/sokoban.txt");
    if(!fin.is_open()) {
        fin.close();
        debugmsg("Could not read ./data/raw/sokoban.txt");
        return false;
    }

    std::string sLine;
    while(!fin.eof()) {
        getline(fin, sLine);

        if (sLine.substr(0, 3) == "; #") {
            iNumLevel++;
            continue;
        } else if (sLine[0] == ';') {
            continue;
        }

        if (sLine == "") {
            //Find level start
            vLevel.resize(iNumLevel + 1);
            vLevelDone.resize(iNumLevel + 1);
            mLevelInfo[iNumLevel]["MaxLevelY"] = 0;
            mLevelInfo[iNumLevel]["MaxLevelX"] = 0;
            mLevelInfo[iNumLevel]["PlayerY"] = 0;
            mLevelInfo[iNumLevel]["PlayerX"] = 0;
            continue;
        }

        if (mLevelInfo[iNumLevel]["MaxLevelX"] < sLine.length()) {
            mLevelInfo[iNumLevel]["MaxLevelX"] = sLine.length();
        }

        for (int i = 0; i < sLine.length(); i++) {
            if ( sLine[i] == '@' ) {
                if (mLevelInfo[iNumLevel]["PlayerY"] == 0 && mLevelInfo[iNumLevel]["PlayerX"] == 0) {
                    mLevelInfo[iNumLevel]["PlayerY"] = mLevelInfo[iNumLevel]["MaxLevelY"];
                    mLevelInfo[iNumLevel]["PlayerX"] = i;
                } else {
                    //2 @ found error!
                    fin.close();
                    return false;
                }
            }

            if (sLine[i] == '.' || sLine[i] == '*' || sLine[i] == '+') {
                vLevelDone[iNumLevel].push_back(std::make_pair(mLevelInfo[iNumLevel]["MaxLevelY"], i));
            }

            vLevel[iNumLevel][mLevelInfo[iNumLevel]["MaxLevelY"]][i] = sLine[i];
        }

        mLevelInfo[iNumLevel]["MaxLevelY"]++;
    }

    fin.close();

    return true;
}
Exemplo n.º 24
0
Path Pathfinder::path_a_star(Tripoint start, Tripoint end)
{
  int x_size = map.get_size_x();
  int y_size = map.get_size_y();
  int z_size = map.get_size_z();

  start.x -= map.x_offset;
  start.y -= map.y_offset;
  start.z -= map.z_offset;
  end.x   -= map.x_offset;
  end.y   -= map.y_offset;
  end.z   -= map.z_offset;

  if (x_size == 0 || y_size == 0 || z_size == 0) {
    debugmsg("A* generated; %s => %s (size %d, %d, %d)",
             start.str().c_str(), end.str().c_str(),
             x_size, y_size, z_size);
    return Path();
  }

  std::vector<Tripoint> open_points;
  A_star_status status[x_size][y_size][z_size];
  int           gscore[x_size][y_size][z_size];
  int           hscore[x_size][y_size][z_size];
  Tripoint      parent[x_size][y_size][z_size];

  if (border > 0) {
    int x0 = (start.x < end.x ? start.x : end.x);
    int y0 = (start.y < end.y ? start.y : end.y);
    int z0 = (start.z < end.z ? start.z : end.z);
    int x1 = (start.x > end.x ? start.x : end.x);
    int y1 = (start.y > end.y ? start.y : end.y);
    int z1 = (start.z > end.z ? start.z : end.z);

    set_bounds(x0 - border, y0 - border, z0 - border,
               x1 + border, y1 + border, z1 + border);
  }

// Init everything to 0
  for (int x = 0; x < x_size; x++) {
    for (int y = 0; y < y_size; y++) {
      for (int z = 0; z < z_size; z++) {
        status[x][y][z] = ASTAR_NONE;
        gscore[x][y][z] = 0;
        hscore[x][y][z] = 0;
        parent[x][y][z] = Tripoint(-1, -1, -1);
      }
    }
  }

  status[start.x][start.y][start.z] = ASTAR_OPEN;
  open_points.push_back(start);

  bool done = false;


  while (!done && !open_points.empty()) {
// 1) Find the lowest cost in open_points, and set (current) to that point
// (if multiple points are tied, randomly select one)
    int lowest_cost = -1, point_index = -1;
    Tripoint current;
    int current_g = 0;
    std::vector<int> lowest_indices;
    for (int i = 0; i < open_points.size(); i++) {
      Tripoint p = open_points[i];
      int score = gscore[p.x][p.y][p.z] + hscore[p.x][p.y][p.z];
      if (i == 0 || score < lowest_cost) {
        lowest_cost = score;
        lowest_indices.clear();
        lowest_indices.push_back(i);
      } else if (score == lowest_cost) {
        lowest_indices.push_back(i);
      }
    }
    if (lowest_indices.empty()) { // Should never happen
      point_index = 0;
    } else {
      point_index = lowest_indices[ rng(0, lowest_indices.size() - 1) ];
    }
    current = open_points[point_index];
    current_g = gscore[current.x][current.y][current.z];
// 2) Check if (current) is the endpoint
    if (current == end) {
      done = true;
    } else {
// 3) Set (current) to be closed
      open_points.erase(open_points.begin() + point_index);
      status[current.x][current.y][current.z] = ASTAR_CLOSED;
// 4) Examine all adjacent points on the same z-level
      for (int x = current.x - 1; x <= current.x + 1; x++) {
        for (int y = current.y - 1; y <= current.y + 1; y++) {
          if (x == current.x && y == current.y) {
            y++; // Skip the current tile
          }
          int z = current.z;
// If it's not diagonal, or diagonals are allowed...
// ...and if it's in-bounds and not blocked...
          if ((allow_diag || x == current.x || y == current.y) &&
              (in_bounds(x, y, z) && !map.blocked(x, y, z))) {
            int g = current_g + map.get_cost(x, y, z);
// If it's unexamined, make it open and set its values
            if (status[x][y][z] == ASTAR_NONE) {
              status[x][y][z] = ASTAR_OPEN;
              gscore[x][y][z] = g;
              if (allow_diag) {
                hscore[x][y][z] = map.get_cost(x, y, z) *
                                  rl_dist(x, y, z, end.x, end.y, end.z);
              } else {
                hscore[x][y][z] = map.get_cost(x, y, z) *
                                  manhattan_dist(x, y, z, end.x, end.y, end.z);
              }
              parent[x][y][z] = current;
              open_points.push_back( Tripoint(x, y, z) );
// Otherwise, if it's open and we're a better parent, make us the parent
            } else if (status[x][y][z] == ASTAR_OPEN && g < gscore[x][y][z]) {
              gscore[x][y][z] = g;
              parent[x][y][z] = current;
            }
          }
        }
      }
// 5.  Examine adjacent points on adjacent Z-levels
// TODO: Allow diagonal movement across Z-levels? For flying monsters?
// Examine above
      if (map.allow_z_up(current)) {
        int z = current.z + 1;
        int x = current.x, y = current.y;
        if ((in_bounds(x, y, z) && !map.blocked(x, y, z))) {
          int g = current_g + map.get_cost(x, y, z);
// If it's unexamined, make it open and set its values
          if (status[x][y][z] == ASTAR_NONE) {
            status[x][y][z] = ASTAR_OPEN;
            gscore[x][y][z] = g;
            if (allow_diag) {
              hscore[x][y][z] = map.get_cost(x, y, z) *
                                rl_dist(x, y, z, end.x, end.y, end.z);
            } else {
              hscore[x][y][z] = map.get_cost(x, y, z) *
                                manhattan_dist(x, y, z, end.x, end.y, end.z);
            }
            parent[x][y][z] = current;
            open_points.push_back( Tripoint(x, y, z) );
// If it's open and we're a better parent, make us the parent
          } else if (status[x][y][z] == ASTAR_OPEN && g < gscore[x][y][z]) {
            gscore[x][y][z] = g;
            parent[x][y][z] = current;
          }
        }
      }
// Examine below (code duplication, sorry mom)
      if (map.allow_z_down(current)) {
        int z = current.z - 1;
        int x = current.x, y = current.y;
        if ((in_bounds(x, y, z) && !map.blocked(x, y, z))) {
          int g = current_g + map.get_cost(x, y, z);
// If it's unexamined, make it open and set its values
          if (status[x][y][z] == ASTAR_NONE) {
debugmsg("A*'d over Z-level");
            status[x][y][z] = ASTAR_OPEN;
            gscore[x][y][z] = g;
            if (allow_diag) {
              hscore[x][y][z] = map.get_cost(x, y, z) *
                                rl_dist(x, y, z, end.x, end.y, end.z);
            } else {
              hscore[x][y][z] = map.get_cost(x, y, z) *
                                manhattan_dist(x, y, z, end.x, end.y, end.z);
            }
            parent[x][y][z] = current;
            open_points.push_back( Tripoint(x, y, z) );
// If it's open and we're a better parent, make us the parent
          } else if (status[x][y][z] == ASTAR_OPEN && g < gscore[x][y][z]) {
            gscore[x][y][z] = g;
            parent[x][y][z] = current;
          }
        }
      }
    }
  }

  Path ret;
  if (open_points.empty()) {
    return ret;
  }
  Tripoint cur = end;
  ret.add_step(cur, map.get_cost(cur));
  while (parent[cur.x][cur.y][cur.z] != start) {
    cur = parent[cur.x][cur.y][cur.z];
    ret.add_step(cur, map.get_cost(cur));
  }
  ret.reverse();
// Add the offsets back in.
  ret.offset(map.x_offset, map.y_offset, map.z_offset);

  return ret;
}
Exemplo n.º 25
0
mission_type_id mission_type::from_legacy( int old_id )
{
    static const std::vector<mission_type_id> old_id_vec = {{
            mission_type_id( "MISSION_NULL" ),
            mission_type_id( "MISSION_GET_ANTIBIOTICS" ),
            mission_type_id( "MISSION_GET_SOFTWARE" ),
            mission_type_id( "MISSION_GET_ZOMBIE_BLOOD_ANAL" ),
            mission_type_id( "MISSION_RESCUE_DOG" ),
            mission_type_id( "MISSION_KILL_ZOMBIE_MOM" ),
            mission_type_id( "MISSION_REACH_SAFETY" ),
            mission_type_id( "MISSION_GET_FLAG" ),
            mission_type_id( "MISSION_GET_BLACK_BOX" ),
            mission_type_id( "MISSION_GET_BLACK_BOX_TRANSCRIPT" ),
            mission_type_id( "MISSION_EXPLORE_SARCOPHAGUS" ),
            mission_type_id( "MISSION_GET_RELIC" ),
            mission_type_id( "MISSION_RECOVER_PRIEST_DIARY" ),
            mission_type_id( "MISSION_INVESTIGATE_CULT" ),
            mission_type_id( "MISSION_INVESTIGATE_PRISON_VISIONARY" ),
            mission_type_id( "MISSION_GET_RECORD_WEATHER" ),
            mission_type_id( "MISSION_GET_RECORD_PATIENT" ),
            mission_type_id( "MISSION_REACH_FEMA_CAMP" ),
            mission_type_id( "MISSION_REACH_FARM_HOUSE" ),
            mission_type_id( "MISSION_GET_RECORD_ACCOUNTING" ),
            mission_type_id( "MISSION_GET_SAFE_BOX" ),
            mission_type_id( "MISSION_GET_DEPUTY_BADGE" ),
            mission_type_id( "MISSION_KILL_JABBERWOCK" ),
            mission_type_id( "MISSION_KILL_100_Z" ),
            mission_type_id( "MISSION_KILL_HORDE_MASTER" ),
            mission_type_id( "MISSION_RECRUIT_TRACKER" ),
            mission_type_id( "MISSION_JOIN_TRACKER" ),
            mission_type_id( "MISSION_FREE_MERCHANTS_EVAC_1" ),
            mission_type_id( "MISSION_FREE_MERCHANTS_EVAC_2" ),
            mission_type_id( "MISSION_FREE_MERCHANTS_EVAC_4" ),
            mission_type_id( "MISSION_OLD_GUARD_REP_1" ),
            mission_type_id( "MISSION_OLD_GUARD_REP_2" ),
            mission_type_id( "MISSION_OLD_GUARD_REP_3" ),
            mission_type_id( "MISSION_OLD_GUARD_REP_4" ),
            mission_type_id( "MISSION_OLD_GUARD_NEC_1" ),
            mission_type_id( "MISSION_OLD_GUARD_NEC_2" ),
            mission_type_id( "MISSION_OLD_GUARD_NEC_COMMO_1" ),
            mission_type_id( "MISSION_OLD_GUARD_NEC_COMMO_2" ),
            mission_type_id( "MISSION_OLD_GUARD_NEC_COMMO_3" ),
            mission_type_id( "MISSION_OLD_GUARD_NEC_COMMO_4" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_1" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_2" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_3" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_4" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_5" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_6" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_7" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_8" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_9" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_10" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_11" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_12" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_13" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_14" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_15" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_16" ),
            mission_type_id( "MISSION_RANCH_FOREMAN_17" ),
            mission_type_id( "MISSION_RANCH_NURSE_1" ),
            mission_type_id( "MISSION_RANCH_NURSE_2" ),
            mission_type_id( "MISSION_RANCH_NURSE_3" ),
            mission_type_id( "MISSION_RANCH_NURSE_4" ),
            mission_type_id( "MISSION_RANCH_NURSE_5" ),
            mission_type_id( "MISSION_RANCH_NURSE_6" ),
            mission_type_id( "MISSION_RANCH_NURSE_7" ),
            mission_type_id( "MISSION_RANCH_NURSE_8" ),
            mission_type_id( "MISSION_RANCH_NURSE_9" ),
            mission_type_id( "MISSION_RANCH_NURSE_10" ),
            mission_type_id( "MISSION_RANCH_NURSE_11" ),
            mission_type_id( "MISSION_RANCH_SCAVENGER_1" ),
            mission_type_id( "MISSION_RANCH_SCAVENGER_2" ),
            mission_type_id( "MISSION_RANCH_SCAVENGER_3" ),
            mission_type_id( "MISSION_RANCH_SCAVENGER_4" ),
            mission_type_id( "MISSION_RANCH_BARTENDER_1" ),
            mission_type_id( "MISSION_RANCH_BARTENDER_2" ),
            mission_type_id( "MISSION_RANCH_BARTENDER_3" ),
            mission_type_id( "MISSION_RANCH_BARTENDER_4" ),
            mission_type_id( "MISSION_RANCH_BARTENDER_5" ),
            mission_type_id( "MISSION_FREE_MERCHANTS_EVAC_3" ),
            // This is to help with the bugged find book mission
            mission_type_id( "MISSION_NULL" )
        }
    };

    if( old_id >= 0 && old_id < static_cast<int>( old_id_vec.size() ) ) {
        return old_id_vec[ old_id ];
    }

    debugmsg( "Invalid legacy mission id: %d", old_id );
    return mission_type_id( "MISSION_NULL" );
}
Exemplo n.º 26
0
void vpart_info::check()
{
    for( auto &vp : vpart_info_all ) {
        auto &part = vp.second;

        // handle legacy parts without requirement data
        // @todo deprecate once requirements are entirely loaded from JSON
        if( part.legacy ) {

            part.install_skills.emplace( skill_mechanics, part.difficulty );
            part.removal_skills.emplace( skill_mechanics, std::max( part.difficulty - 2, 2 ) );
            part.repair_skills.emplace ( skill_mechanics, std::min( part.difficulty + 1, MAX_SKILL ) );

            if( part.has_flag( "TOOL_WRENCH" ) || part.has_flag( "WHEEL" ) ) {
                part.install_reqs = { { requirement_id( "vehicle_bolt" ), 1 } };
                part.removal_reqs = { { requirement_id( "vehicle_bolt" ), 1 } };
                part.repair_reqs  = { { requirement_id( "welding_standard" ), 5 } };

            } else if( part.has_flag( "TOOL_SCREWDRIVER" ) ) {
                part.install_reqs = { { requirement_id( "vehicle_screw" ), 1 } };
                part.removal_reqs = { { requirement_id( "vehicle_screw" ), 1 } };
                part.repair_reqs  = { { requirement_id( "adhesive" ), 1 } };

            } else if( part.has_flag( "NAILABLE" ) ) {
                part.install_reqs = { { requirement_id( "vehicle_nail_install" ), 1 } };
                part.removal_reqs = { { requirement_id( "vehicle_nail_removal" ), 1 } };
                part.repair_reqs  = { { requirement_id( "adhesive" ), 2 } };

            } else if( part.has_flag( "TOOL_NONE" ) ) {
                // no-op

            } else {
                part.install_reqs = { { requirement_id( "welding_standard" ), 5 } };
                part.removal_reqs = { { requirement_id( "vehicle_weld_removal" ), 1 } };
                part.repair_reqs  = { { requirement_id( "welding_standard" ), 5 } };
            }

        } else {
            if( part.has_flag( "REVERSIBLE" ) ) {
                if( !part.removal_reqs.empty() ) {
                    debugmsg( "vehicle part %s specifies both REVERSIBLE and removal", part.id.c_str() );
                }
                part.removal_reqs = part.install_reqs;
            }
        }

        // add the base item to the installation requirements
        // @todo support multiple/alternative base items
        requirement_data ins;
        ins.components.push_back( { { { part.item, 1 } } } );

        std::string ins_id = std::string( "inline_vehins_base_" ) += part.id.str();
        requirement_data::save_requirement( ins, ins_id );
        part.install_reqs.emplace_back( requirement_id( ins_id ), 1 );

        if( part.removal_moves < 0 ) {
            part.removal_moves = part.install_moves / 2;
        }

        for( auto &e : part.install_skills ) {
            if( !e.first.is_valid() ) {
                debugmsg( "vehicle part %s has unknown install skill %s", part.id.c_str(), e.first.c_str() );
            }
        }

        for( auto &e : part.removal_skills ) {
            if( !e.first.is_valid() ) {
                debugmsg( "vehicle part %s has unknown removal skill %s", part.id.c_str(), e.first.c_str() );
            }
        }

        for( auto &e : part.repair_skills ) {
            if( !e.first.is_valid() ) {
                debugmsg( "vehicle part %s has unknown repair skill %s", part.id.c_str(), e.first.c_str() );
            }
        }

        for( const auto &e : part.install_reqs ) {
            if( !e.first.is_valid() || e.second <= 0 ) {
                debugmsg( "vehicle part %s has unknown or incorrectly specified install requirements %s",
                          part.id.c_str(), e.first.c_str() );
            }
        }

        for( const auto &e : part.install_reqs ) {
            if( !( e.first.is_null() || e.first.is_valid() ) || e.second < 0 ) {
                debugmsg( "vehicle part %s has unknown or incorrectly specified removal requirements %s",
                          part.id.c_str(), e.first.c_str() );
            }
        }

        for( const auto &e : part.repair_reqs ) {
            if( !( e.first.is_null() || e.first.is_valid() ) || e.second < 0 ) {
                debugmsg( "vehicle part %s has unknown or incorrectly specified repair requirements %s",
                          part.id.c_str(), e.first.c_str() );
            }
        }

        if( part.install_moves < 0 ) {
            debugmsg( "vehicle part %s has negative installation time", part.id.c_str() );
        }

        if( part.removal_moves < 0 ) {
            debugmsg( "vehicle part %s has negative removal time", part.id.c_str() );
        }

        if( !item_group::group_is_defined( part.breaks_into_group ) ) {
            debugmsg( "Vehicle part %s breaks into non-existent item group %s.",
                      part.id.c_str(), part.breaks_into_group.c_str() );
        }
        if( part.sym == 0 ) {
            debugmsg( "vehicle part %s does not define a symbol", part.id.c_str() );
        }
        if( part.sym_broken == 0 ) {
            debugmsg( "vehicle part %s does not define a broken symbol", part.id.c_str() );
        }
        if( part.durability <= 0 ) {
            debugmsg( "vehicle part %s has zero or negative durability", part.id.c_str() );
        }
        if( part.dmg_mod < 0 ) {
            debugmsg( "vehicle part %s has negative damage modifier", part.id.c_str() );
        }
        if( part.folded_volume < 0 ) {
            debugmsg( "vehicle part %s has negative folded volume", part.id.c_str() );
        }
        if( part.has_flag( "FOLDABLE" ) && part.folded_volume == 0 ) {
            debugmsg( "vehicle part %s has folding part with zero folded volume", part.name().c_str() );
        }
        if( !item::type_is_defined( part.default_ammo ) ) {
            debugmsg( "vehicle part %s has undefined default ammo %s", part.id.c_str(), part.item.c_str() );
        }
        if( part.size < 0 ) {
            debugmsg( "vehicle part %s has negative size", part.id.c_str() );
        }
        if( !item::type_is_defined( part.item ) ) {
            debugmsg( "vehicle part %s uses undefined item %s", part.id.c_str(), part.item.c_str() );
        }
        const itype &base_item_type = *item::find_type( part.item );
        // Fuel type errors are serious and need fixing now
        if( !item::type_is_defined( part.fuel_type ) ) {
            debugmsg( "vehicle part %s uses undefined fuel %s", part.id.c_str(), part.item.c_str() );
            part.fuel_type = "null";
        } else if( part.fuel_type != "null" && item::find_type( part.fuel_type )->fuel == nullptr &&
                   ( base_item_type.container == nullptr || !base_item_type.container->watertight ) ) {
            // Tanks are allowed to specify non-fuel "fuel",
            // because currently legacy blazemod uses it as a hack to restrict content types
            debugmsg( "non-tank vehicle part %s uses non-fuel item %s as fuel, setting to null",
                      part.id.c_str(), part.fuel_type.c_str() );
            part.fuel_type = "null";
        }
        if( part.has_flag( "TURRET" ) && base_item_type.gun == nullptr ) {
            debugmsg( "vehicle part %s has the TURRET flag, but is not made from a gun item", part.id.c_str() );
        }
        for( auto &q : part.qualities ) {
            if( !q.first.is_valid() ) {
                debugmsg( "vehicle part %s has undefined tool quality %s", part.id.c_str(), q.first.c_str() );
            }
        }
        if( part.has_flag( VPFLAG_ENABLED_DRAINS_EPOWER ) && part.epower == 0 ) {
            debugmsg( "%s is set to drain epower, but has epower == 0", part.id.c_str() );
        }
        // Parts with non-zero epower must have a flag that affects epower usage
        static const std::vector<std::string> handled = {{
            "ENABLED_DRAINS_EPOWER", "SECURITY", "ENGINE",
            "ALTERNATOR", "SOLAR_PANEL", "POWER_TRANSFER",
            "REACTOR"
        }};
        if( part.epower != 0 &&
            std::none_of( handled.begin(), handled.end(), [&part]( const std::string &flag ) {
            return part.has_flag( flag );
        } ) ) {
            std::string warnings_are_good_docs = enumerate_as_string( handled );
            debugmsg( "%s has non-zero epower, but lacks a flag that would make it affect epower (one of %s)",
                      part.id.c_str(), warnings_are_good_docs.c_str() );
        }
    }
}
Exemplo n.º 27
0
void game::compare(int iCompareX, int iCompareY)
{
 int examx, examy;
 int ch = (int)'.';

 if (iCompareX != -999 && iCompareX != -999) {
  examx = iCompareX;
  examy = iCompareY;
 } else {
  mvwprintw(w_terrain, 0, 0, "Compare where? (Direction button)");
  wrefresh(w_terrain);

  ch = input();
  last_action += ch;
  if (ch == KEY_ESCAPE || ch == 'q')
   return;
  if (ch == '\n' || ch == 'I')
   ch = '.';
  get_direction(this, examx, examy, ch);
  if (examx == -2 || examy == -2) {
   add_msg("Invalid direction.");
   return;
  }
 }
 examx += u.posx;
 examy += u.posy;
 std::vector <item> here = m.i_at(examx, examy);
 std::vector <item> grounditems;
 //Filter out items with the same name (keep only one of them)
 std::map <std::string, bool> dups;
 for (int i = 0; i < here.size(); i++) {
  if (!dups[here[i].tname(this).c_str()]) {
   grounditems.push_back(here[i]);
   dups[here[i].tname(this).c_str()] = true;
  }
 }
 //Only the first 10 Items due to numbering 0-9
 const int groundsize = (grounditems.size() > 10 ? 10 : grounditems.size());
 u.inv.sort();
 u.inv.restack(&u);
 
 invslice stacks = u.inv.slice(0, u.inv.size());

 WINDOW* w_inv = newwin(TERMY-VIEW_OFFSET_Y*2, TERMX-VIEW_OFFSET_X*2, VIEW_OFFSET_Y, VIEW_OFFSET_X);
 int maxitems = TERMY-5-VIEW_OFFSET_Y*2;    // Number of items to show at one time.
 std::vector<int> compare_list; // Count of how many we'll drop from each stack
 bool bFirst = false; // First Item selected
 bool bShowCompare = false;
 char cLastCh;
 compare_list.resize(u.inv.size() + groundsize, 0);
 std::vector<char> weapon_and_armor; // Always single, not counted
 print_inv_statics(this, w_inv, "Compare:", weapon_and_armor);
// Gun, ammo, weapon, armor, food, tool, book, other
 std::vector<int> first = find_firsts(stacks);
 std::vector<int> firsts;
 if (groundsize > 0) {
  firsts.push_back(0);
 }
 for (int i = 0; i < first.size(); i++) {
  firsts.push_back((first[i] >= 0) ? first[i]+groundsize : -1);
 }
 ch = '.';
 int start = 0, cur_it;
 do {
  if (( ch == '<' || ch == KEY_PPAGE ) && start > 0) {
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
   start -= maxitems;
   if (start < 0)
    start = 0;
   mvwprintw(w_inv, maxitems + 4, 0, "         ");
  }
  if (( ch == '>' || ch == KEY_NPAGE ) && cur_it < u.inv.size() + groundsize) {
   start = cur_it;
   mvwprintw(w_inv, maxitems + 4, 12, "            ");
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
  }
  int cur_line = 2;
  int iHeaderOffset = (groundsize > 0) ? 0 : 1;

  for (cur_it = start; cur_it < start + maxitems && cur_line < maxitems+3; cur_it++) {
// Clear the current line;
   mvwprintw(w_inv, cur_line, 0, "                                             ");
// Print category header
   for (int i = iHeaderOffset; i < iCategorieNum; i++) {
    if (cur_it == firsts[i-iHeaderOffset]) {
     mvwprintz(w_inv, cur_line, 0, c_magenta, CATEGORIES[i].c_str());
     cur_line++;
    }
   }
   if (cur_it < u.inv.size() + groundsize) {
    char icon = '-';
    if (compare_list[cur_it] == 1)
     icon = '+';
    if (cur_it < groundsize) {
     mvwputch (w_inv, cur_line, 0, c_white, '1'+((cur_it<9) ? cur_it: -1));
     nc_color col = (compare_list[cur_it] == 0 ? c_ltgray : c_white);
     mvwprintz(w_inv, cur_line, 1, col, " %c %s", icon,
               grounditems[cur_it].tname(this).c_str());
    } else {
     item& it = stacks[cur_it-groundsize]->front();
     mvwputch (w_inv, cur_line, 0, c_white, it.invlet);
     nc_color col = (compare_list[cur_it] == 0 ? c_ltgray : c_white);
     mvwprintz(w_inv, cur_line, 1, col, " %c %s", icon,
               it.tname(this).c_str());
     if (stacks[cur_it-groundsize]->size() > 1)
      wprintz(w_inv, col, " [%d]", stacks[cur_it-groundsize]->size());
     if (it.charges > 0)
      wprintz(w_inv, col, " (%d)", it.charges);
     else if (it.contents.size() == 1 &&
              it.contents[0].charges > 0)
      wprintw(w_inv, " (%d)", it.contents[0].charges);
    }
   }
   cur_line++;
  }
  if (start > 0)
   mvwprintw(w_inv, maxitems + 4, 0, "< Go Back");
  if (cur_it < u.inv.size() + groundsize)
   mvwprintw(w_inv, maxitems + 4, 12, "> More items");
  wrefresh(w_inv);
  ch = getch();
  if (u.has_item(ch)) {
   item& it = u.inv.item_by_letter(ch);
   if (it.is_null()) { // Not from inventory
    bool found = false;
    for (int i = 0; i < weapon_and_armor.size() && !found; i++) {
     if (weapon_and_armor[i] == ch) {
      weapon_and_armor.erase(weapon_and_armor.begin() + i);
      found = true;
      bFirst = false;
      print_inv_statics(this, w_inv, "Compare:", weapon_and_armor);
     }
    }
    if (!found) {

     if ( ch == u.weapon.invlet &&
          std::find(unreal_itype_ids.begin(), unreal_itype_ids.end(), u.weapon.type->id) != unreal_itype_ids.end()){
      //Do Bionic stuff here?!
     } else {
      if (!bFirst)
      {
       weapon_and_armor.push_back(ch);
       print_inv_statics(this, w_inv, "Compare:", weapon_and_armor);
       bFirst = true;
       cLastCh = ch;
      } else {
       bShowCompare = true;
      }
     }
    }
   } else {
    int index = -1;
    for (int i = 0; i < stacks.size(); ++i) {
     if (stacks[i]->front().invlet == it.invlet) {
      index = i;
      break;
     }
    }
    if (index == -1) {
     debugmsg("Inventory got out of sync with inventory slice?");
    }
    if (compare_list[index+groundsize] == 1)
    {
     compare_list[index+groundsize] = 0;
     bFirst = false;
    } else {
     if (!bFirst)
     {
      compare_list[index+groundsize] = 1;
      bFirst = true;
      cLastCh = ch;
     } else {
      bShowCompare = true;
     }
    }
   }
  } else if ((ch >= '1' && ch <= '9' && ch-'1' < groundsize) || (ch == '0' && groundsize == 10)) {
   //Ground Items
   int iZero = 0;
   if (ch == '0') {
    iZero = 10;
   }
   if (compare_list[ch-'1'+iZero] == 1)
   {
    compare_list[ch-'1'+iZero] = 0;
    bFirst = false;
   } else {
    if (!bFirst)
    {
     compare_list[ch-'1'+iZero] = 1;
     bFirst = true;
     cLastCh = ch;
    } else {
     bShowCompare = true;
    }
   }
  }
  if (bShowCompare) {
   std::vector<iteminfo> vItemLastCh, vItemCh;
   std::string sItemLastCh, sItemCh;
   if (cLastCh >= '0' && cLastCh <= '9') {
    int iZero = 0;
    if (cLastCh == '0') {
     iZero = 10;
    }

    grounditems[cLastCh-'1'+iZero].info(true, &vItemLastCh);
    sItemLastCh = grounditems[cLastCh-'1'+iZero].tname(this);
   } else {
    u.i_at(cLastCh).info(true, &vItemLastCh);
    sItemLastCh = u.i_at(cLastCh).tname(this);
   }

   if (ch >= '0' && ch <= '9') {
    int iZero = 0;
    if (ch == '0') {
     iZero = 10;
    }

    grounditems[ch-'1'+iZero].info(true, &vItemCh);
    sItemCh = grounditems[ch-'1'+iZero].tname(this);
   } else {
    u.i_at(ch).info(true, &vItemCh);
    sItemCh = u.i_at(ch).tname(this);
   }

   compare_split_screen_popup(0, (TERMX-VIEW_OFFSET_X*2)/2, TERMY-VIEW_OFFSET_Y*2, sItemLastCh, vItemLastCh, vItemCh);
   compare_split_screen_popup((TERMX-VIEW_OFFSET_X*2)/2, (TERMX-VIEW_OFFSET_X*2)/2, TERMY-VIEW_OFFSET_Y*2, sItemCh, vItemCh, vItemLastCh);

   wclear(w_inv);
   print_inv_statics(this, w_inv, "Compare:", weapon_and_armor);
   bShowCompare = false;
  }
 } while (ch != '\n' && ch != KEY_ESCAPE && ch != ' ');
 werase(w_inv);
 delwin(w_inv);
 erase();
 refresh_all();
}
Exemplo n.º 28
0
/**
 *Caches a vehicle definition from a JsonObject to be loaded after itypes is initialized.
 */
void vehicle_prototype::load(JsonObject &jo)
{
    vehicle_prototype &vproto = vtypes[ vproto_id( jo.get_string( "id" ) ) ];
    // If there are already parts defined, this vehicle prototype overrides an existing one.
    // If the json contains a name, it means a completely new prototype (replacing the
    // original one), therefor the old data has to be cleared.
    // If the json does not contain a name (the prototype would have no name), it means appending
    // to the existing prototype (the parts are not cleared).
    if( !vproto.parts.empty() && jo.has_string( "name" ) ) {
        vproto =  vehicle_prototype();
    }
    if( vproto.parts.empty() ) {
        vproto.name = jo.get_string( "name" );
    }

    vgroups[vgroup_id(jo.get_string("id"))].add_vehicle(vproto_id(jo.get_string("id")), 100);

    JsonArray parts = jo.get_array("parts");
    while (parts.has_more()) {
        JsonObject part = parts.next_object();

        part_def pt;
        pt.pos = point( part.get_int( "x" ), part.get_int( "y" ) );
        pt.part = vpart_id( part.get_string( "part" ) );

        assign( part, "ammo", pt.with_ammo, true, 0, 100 );
        assign( part, "ammo_types", pt.ammo_types, true );
        assign( part, "ammo_qty", pt.ammo_qty, true, 0 );
        assign( part, "fuel", pt.fuel, true );

        vproto.parts.push_back( pt );
    }

    JsonArray items = jo.get_array("items");
    while(items.has_more()) {
        JsonObject spawn_info = items.next_object();
        vehicle_item_spawn next_spawn;
        next_spawn.pos.x = spawn_info.get_int("x");
        next_spawn.pos.y = spawn_info.get_int("y");

        next_spawn.chance = spawn_info.get_int("chance");
        if(next_spawn.chance <= 0 || next_spawn.chance > 100) {
            debugmsg("Invalid spawn chance in %s (%d, %d): %d%%",
                     vproto.name.c_str(), next_spawn.pos.x, next_spawn.pos.y, next_spawn.chance);
        }

        // constrain both with_magazine and with_ammo to [0-100]
        next_spawn.with_magazine = std::max( std::min( spawn_info.get_int( "magazine", next_spawn.with_magazine ), 100 ), 0 );
        next_spawn.with_ammo = std::max( std::min( spawn_info.get_int( "ammo", next_spawn.with_ammo ), 100 ), 0 );

        if(spawn_info.has_array("items")) {
            //Array of items that all spawn together (ie jack+tire)
            JsonArray item_group = spawn_info.get_array("items");
            while(item_group.has_more()) {
                next_spawn.item_ids.push_back(item_group.next_string());
            }
        } else if(spawn_info.has_string("items")) {
            //Treat single item as array
            next_spawn.item_ids.push_back(spawn_info.get_string("items"));
        }
        if(spawn_info.has_array("item_groups")) {
            //Pick from a group of items, just like map::place_items
            JsonArray item_group_names = spawn_info.get_array("item_groups");
            while(item_group_names.has_more()) {
                next_spawn.item_groups.push_back(item_group_names.next_string());
            }
        } else if(spawn_info.has_string("item_groups")) {
            next_spawn.item_groups.push_back(spawn_info.get_string("item_groups"));
        }
        vproto.item_spawns.push_back( std::move( next_spawn ) );
    }
}
Exemplo n.º 29
0
void mission_start::place_npc_software(game *g, mission *miss)
{
 npc* dev = g->find_npc(miss->npc_id);
 if (dev == NULL) {
  debugmsg("Couldn't find NPC! %d", miss->npc_id);
  return;
 }
 g->u.i_add( item(g->itypes["usb_drive"], 0) );
 g->add_msg("%s gave you a USB drive.", dev->name.c_str());

 oter_id ter = ot_house_north;

 switch (dev->myclass) {
 case NC_HACKER:
  miss->item_id = "software_hacking";
  break;
 case NC_DOCTOR:
  miss->item_id = "software_medical";
  ter = ot_s_pharm_north;
  miss->follow_up = MISSION_GET_ZOMBIE_BLOOD_ANAL;
  break;
 case NC_SCIENTIST:
  miss->item_id = "software_math";
  break;
 default:
  miss->item_id = "software_useless";
 }

 int dist = 0;
 point place;
 if (ter == ot_house_north) {
  int city_id = g->cur_om->closest_city( g->om_location() );
  place = g->cur_om->random_house_in_city(city_id);
 } else
  place = g->cur_om->find_closest(g->om_location(), ter, 4, dist, false);
 miss->target = place;
// Make it seen on our map
 for (int x = place.x - 6; x <= place.x + 6; x++) {
  for (int y = place.y - 6; y <= place.y + 6; y++)
   g->cur_om->seen(x, y, 0) = true;
 }
 tinymap compmap(&(g->itypes), &(g->mapitems), &(g->traps));
 compmap.load(g, place.x * 2, place.y * 2, 0, false);
 point comppoint;

 switch (g->cur_om->ter(place.x, place.y, 0)) {
 case ot_house_north:
 case ot_house_east:
 case ot_house_west:
 case ot_house_south: {
  std::vector<point> valid;
  for (int x = 0; x < SEEX * 2; x++) {
   for (int y = 0; y < SEEY * 2; y++) {
    if (compmap.ter(x, y) == t_floor) {
     bool okay = false;
     for (int x2 = x - 1; x2 <= x + 1 && !okay; x2++) {
      for (int y2 = y - 1; y2 <= y + 1 && !okay; y2++) {
       if (compmap.ter(x2, y2) == t_bed || compmap.ter(x2, y2) == t_dresser) {
        okay = true;
        valid.push_back( point(x, y) );
       }
      }
     }
    }
   }
  }
  if (valid.empty())
   comppoint = point( rng(6, SEEX * 2 - 7), rng(6, SEEY * 2 - 7) );
  else
   comppoint = valid[rng(0, valid.size() - 1)];
 } break;
 case ot_s_pharm_north: {
  bool found = false;
  for (int x = SEEX * 2 - 1; x > 0 && !found; x--) {
   for (int y = SEEY * 2 - 1; y > 0 && !found; y--) {
    if (compmap.ter(x, y) == t_floor) {
     found = true;
     comppoint = point(x, y);
    }
   }
  }
 } break;
 case ot_s_pharm_east: {
  bool found = false;
  for (int x = 0; x < SEEX * 2 && !found; x++) {
   for (int y = SEEY * 2 - 1; y > 0 && !found; y--) {
    if (compmap.ter(x, y) == t_floor) {
     found = true;
     comppoint = point(x, y);
    }
   }
  }
 } break;
 case ot_s_pharm_south: {
  bool found = false;
  for (int x = 0; x < SEEX * 2 && !found; x++) {
   for (int y = 0; y < SEEY * 2 && !found; y++) {
    if (compmap.ter(x, y) == t_floor) {
     found = true;
     comppoint = point(x, y);
    }
   }
  }
 } break;
 case ot_s_pharm_west: {
  bool found = false;
  for (int x = SEEX * 2 - 1; x > 0 && !found; x--) {
   for (int y = 0; y < SEEY * 2 && !found; y++) {
    if (compmap.ter(x, y) == t_floor) {
     found = true;
     comppoint = point(x, y);
    }
   }
  }
 } break;
 }

 std::stringstream compname;
 compname << dev->name << "'s Terminal";
 compmap.ter_set(comppoint.x, comppoint.y, t_console);
 computer *tmpcomp = compmap.add_computer(comppoint.x, comppoint.y,
                                          compname.str(), 0);
 tmpcomp->mission_id = miss->uid;
 tmpcomp->add_option("Download Software", COMPACT_DOWNLOAD_SOFTWARE, 0);

 compmap.save(g->cur_om, int(g->turn), place.x * 2, place.y * 2, 0);
}
Exemplo n.º 30
0
/**
 *Works through cached vehicle definitions and creates vehicle objects from them.
 */
void vehicle_prototype::finalize()
{
    for( auto &vp : vtypes ) {
        std::unordered_set<point> cargo_spots;
        vehicle_prototype &proto = vp.second;
        const vproto_id &id = vp.first;

        // Calls the default constructor to create an empty vehicle. Calling the constructor with
        // the type as parameter would make it look up the type in the map and copy the
        // (non-existing) blueprint.
        proto.blueprint.reset( new vehicle() );
        vehicle &blueprint = *proto.blueprint;
        blueprint.type = id;
        blueprint.name = _(proto.name.c_str());

        for( auto &pt : proto.parts ) {
            auto base = item::find_type( pt.part->item );

            if( !pt.part.is_valid() ) {
                debugmsg("unknown vehicle part %s in %s", pt.part.c_str(), id.c_str());
                continue;
            }

            if( blueprint.install_part( pt.pos.x, pt.pos.y, pt.part ) < 0 ) {
                debugmsg( "init_vehicles: '%s' part '%s'(%d) can't be installed to %d,%d",
                          blueprint.name.c_str(), pt.part.c_str(),
                          blueprint.parts.size(), pt.pos.x, pt.pos.y );
            }

            if( !base->gun ) {
                if( pt.with_ammo  ) {
                    debugmsg( "init_vehicles: non-turret %s with ammo in %s", pt.part.c_str(), id.c_str() );
                }
                if( !pt.ammo_types.empty() ) {
                    debugmsg( "init_vehicles: non-turret %s with ammo_types in %s", pt.part.c_str(), id.c_str() );
                }
                if( pt.ammo_qty.first > 0 || pt.ammo_qty.second > 0 ) {
                    debugmsg( "init_vehicles: non-turret %s with ammo_qty in %s", pt.part.c_str(), id.c_str() );
                }

            } else {
                for( const auto &e : pt.ammo_types ) {
                    auto ammo = item::find_type( e );
                    if( !ammo->ammo && ammo->ammo->type.count( base->gun->ammo ) ) {
                        debugmsg( "init_vehicles: turret %s has invalid ammo_type %s in %s",
                                  pt.part.c_str(), e.c_str(), id.c_str() );
                    }
                }
                if( pt.ammo_types.empty() ) {
                    pt.ammo_types.insert( default_ammo( base->gun->ammo ) );
                }
            }

            if( base->container ) {
                if( !item::type_is_defined( pt.fuel ) ) {
                    debugmsg( "init_vehicles: tank %s specified invalid fuel in %s", pt.part.c_str(), id.c_str() );
                }
            } else {
                if( pt.fuel != "null" ) {
                    debugmsg( "init_vehicles: non-tank %s with fuel in %s", pt.part.c_str(), id.c_str() );
                }
            }

            if( pt.part.obj().has_flag("CARGO") ) {
                cargo_spots.insert( pt.pos );
            }
        }

        for (auto &i : proto.item_spawns) {
            if( cargo_spots.count( i.pos ) == 0 ) {
                debugmsg("Invalid spawn location (no CARGO vpart) in %s (%d, %d): %d%%",
                         proto.name.c_str(), i.pos.x, i.pos.y, i.chance);
            }
            for (auto &j : i.item_ids) {
                if( !item::type_is_defined( j ) ) {
                    debugmsg("unknown item %s in spawn list of %s", j.c_str(), id.c_str());
                }
            }
            for (auto &j : i.item_groups) {
                if (!item_group::group_is_defined(j)) {
                    debugmsg("unknown item group %s in spawn list of %s", j.c_str(), id.c_str());
                }
            }
        }
    }
}