Esempio n. 1
0
bool overmapbuffer::reveal_route( const tripoint &source, const tripoint &dest, int radius )
{
    static const int RADIUS = 4;            // Maximal radius of search (in overmaps)
    static const int OX = RADIUS * OMAPX;   // half-width of the area to search in
    static const int OY = RADIUS * OMAPY;   // half-height of the area to search in

    const tripoint start( OX, OY, source.z );   // Local source - center of the local area
    const tripoint base( source - start );      // To convert local coordinates to global ones
    const tripoint finish( dest - base );       // Local destination - relative to source

    const auto estimate = [ this, &base, &finish ]( const pf::node &, const pf::node &cur ) {
        int res = 0;
        int omx = base.x + cur.x;
        int omy = base.y + cur.y;

        const auto &oter = get_om_global( omx, omy ).get_ter( omx, omy, base.z );

        if( !is_ot_type( "road", oter ) && !is_ot_type ( "bridge", oter ) && !is_ot_type( "hiway", oter ) ) {
            if( is_river( oter ) ) {
                return -1; // Can't walk on water
            }
            // Allow going slightly off-road to overcome small obstacles (e.g. craters),
            // but heavily penalize that to make roads preferable
            res += 250;
        }

        res += std::abs( finish.x - cur.x ) +
               std::abs( finish.y - cur.y );

        return res;
    };

    const auto path = pf::find_path( start, finish, 2*OX, 2*OY, estimate );

    if( path.empty() ) {
        return false;
    }

    for( const auto &node : path ) {
        reveal( base + tripoint( node.x, node.y, base.z ), radius );
    }

    return true;
}
Esempio n. 2
0
int get_rot_since( const int startturn, const int endturn, const tripoint &location )
{
    // Ensure food doesn't rot in ice labs, where the
    // temperature is much less than the weather specifies.
    tripoint const omt_pos = overmapbuffer::ms_to_omt_copy( location );
    oter_id const & oter = overmap_buffer.ter( omt_pos );
    // TODO: extract this into a property of the overmap terrain
    if (is_ot_type("ice_lab", oter)) {
        return 0;
    }
    // TODO: maybe have different rotting speed when underground?
    int ret = 0;
    for (calendar i(startturn); i.get_turn() < endturn; i += 600) {
        w_point w = g->weather_gen->get_weather(location, i);
        ret += std::min(600, endturn - i.get_turn()) * get_hourly_rotpoints_at_temp(w.temperature) / 600;
    }
    return ret;
}
Esempio n. 3
0
/**
 * Retroactively determine weather-related rotting effects.
 * Applies rot based on the temperatures incurred between a turn range.
 */
int get_rot_since( const int since, const int endturn, const point &location )
{
    // Hack: Ensure food doesn't rot in ice labs, where the
    // temperature is much less than the weather specifies.
    // http://github.com/CleverRaven/Cataclysm-DDA/issues/9162
    // Bug with this hack: Rot is prevented even when it's above
    // freezing on the ground floor.
    oter_id oter = overmap_buffer.ter(g->om_global_location());
    if (is_ot_type("ice_lab", oter)) {
        return 0;
    }
    int ret = 0;
    for (calendar i(since); i.get_turn() < endturn; i += 600) {
        w_point w = g->weatherGen.get_weather(location, i);
        ret += std::min(600, endturn - i.get_turn()) * get_hourly_rotpoints_at_temp(w.temperature) / 600;
    }
    return ret;
}
Esempio n. 4
0
bool mission::is_complete( const int _npc_id ) const
{
    if( status == mission_status::success ) {
        return true;
    }

    auto &u = g->u;
    switch( type->goal ) {
        case MGOAL_GO_TO: {
            const tripoint cur_pos = g->u.global_omt_location();
            return ( rl_dist( cur_pos, target ) <= 1 );
        }

        case MGOAL_GO_TO_TYPE: {
            const auto cur_ter = overmap_buffer.ter( g->u.global_omt_location() );
            return is_ot_type( type->target_id.str(), cur_ter );
        }

        case MGOAL_FIND_ITEM_GROUP: {
            inventory tmp_inv = u.crafting_inventory();
            std::vector<item *> items = std::vector<item *>();
            tmp_inv.dump( items );
            Group_tag grp_type = type->group_id;
            itype_id container = type->container_id;
            bool specific_container_required = container.compare( "null" ) != 0;

            std::map<itype_id, int> matches = std::map<itype_id, int>();
            get_all_item_group_matches(
                items, grp_type, matches,
                container, itype_id( "null" ), specific_container_required );

            int total_match = std::accumulate( matches.begin(), matches.end(), 0,
            []( const std::size_t previous, const std::pair<const std::string, std::size_t> &p ) {
                return previous + p.second;
            } );

            if( total_match >= ( type->item_count ) ) {
                return true;

            }
        }
        return false;

        case MGOAL_FIND_ITEM: {
            if( npc_id != -1 && npc_id != _npc_id ) {
                return false;
            }
            inventory tmp_inv = u.crafting_inventory();
            // TODO: check for count_by_charges and use appropriate player::has_* function
            if( !tmp_inv.has_amount( type->item_id, item_count ) ) {
                return tmp_inv.has_amount( type->item_id, 1 ) && tmp_inv.has_charges( type->item_id, item_count );
            }
        }
        return true;

        case MGOAL_FIND_ANY_ITEM:
            return u.has_mission_item( uid ) && ( npc_id == -1 || npc_id == _npc_id );

        case MGOAL_FIND_MONSTER:
            if( npc_id != -1 && npc_id != _npc_id ) {
                return false;
            }
            return g->get_creature_if( [&]( const Creature & critter ) {
                const monster *const mon_ptr = dynamic_cast<const monster *>( &critter );
                return mon_ptr && mon_ptr->mission_id == uid;
            } );

        case MGOAL_RECRUIT_NPC: {
            npc *p = g->find_npc( target_npc_id );
            return p != nullptr && p->get_attitude() == NPCATT_FOLLOW;
        }

        case MGOAL_RECRUIT_NPC_CLASS: {
            const auto npcs = overmap_buffer.get_npcs_near_player( 100 );
            for( auto &npc : npcs ) {
                if( npc->myclass == recruit_class && npc->get_attitude() == NPCATT_FOLLOW ) {
                    return true;
                }
            }
            return false;
        }

        case MGOAL_FIND_NPC:
            return npc_id == _npc_id;

        case MGOAL_ASSASSINATE:
            return step >= 1;

        case MGOAL_KILL_MONSTER:
            return step >= 1;

        case MGOAL_KILL_MONSTER_TYPE:
            return g->kill_count( monster_type ) >= kill_count_to_reach;

        case MGOAL_KILL_MONSTER_SPEC:
            return g->kill_count( monster_species ) >= kill_count_to_reach;

        case MGOAL_COMPUTER_TOGGLE:
            return step >= 1;

        default:
            return false;
    }
}
Esempio n. 5
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( is_ot_type("house", oter) || is_ot_type("s_pharm", oter) || oter == "" ) {
        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;
                    int wall = 0;
                    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 ( compmap.has_flag_ter("WALL", x2, y2) ) {
                                wall++;
                            }
                        }
                    }
                    if ( wall == 5 ) {
                        if ( compmap.is_last_ter_wall( true, x, y, SEEX * 2, SEEY * 2, NORTH ) &&
                             compmap.is_last_ter_wall( true, x, y, SEEX * 2, SEEY * 2, SOUTH ) &&
                             compmap.is_last_ter_wall( true, x, y, SEEX * 2, SEEY * 2, WEST ) &&
                             compmap.is_last_ter_wall( true, x, y, SEEX * 2, SEEY * 2, EAST ) ) {
                            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)];
        }
    }

 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();
}
Esempio n. 6
0
bool mission::is_complete( const int _npc_id ) const
{
    if( status == mission_status::success ) {
        return true;
    }

    auto &u = g->u;
    switch( type->goal ) {
        case MGOAL_GO_TO:
            {
                const tripoint cur_pos = g->u.global_omt_location();
                return ( rl_dist( cur_pos, target ) <= 1 );
            }
            break;

        case MGOAL_GO_TO_TYPE:
            {
                const auto cur_ter = overmap_buffer.ter( g->u.global_omt_location() );
                return is_ot_type( type->target_id.str(), cur_ter );
            }
            break;

        case MGOAL_FIND_ITEM:
        {
            inventory tmp_inv = u.crafting_inventory();
            // TODO: check for count_by_charges and use appropriate player::has_* function
            if (!tmp_inv.has_amount(type->item_id, item_count)) {
                return tmp_inv.has_amount( type->item_id, 1 ) && tmp_inv.has_charges( type->item_id, item_count );
            }
            if( npc_id != -1 && npc_id != _npc_id ) {
                return false;
            }
        }
            return true;

        case MGOAL_FIND_ANY_ITEM:
            return u.has_mission_item( uid ) && ( npc_id == -1 || npc_id == _npc_id );

        case MGOAL_FIND_MONSTER:
            if( npc_id != -1 && npc_id != _npc_id ) {
                return false;
            }
            for( size_t i = 0; i < g->num_zombies(); i++ ) {
                if( g->zombie( i ).mission_id == uid ) {
                    return true;
                }
            }
            return false;

        case MGOAL_RECRUIT_NPC:
            {
                npc *p = g->find_npc( target_npc_id );
                return p != nullptr && p->attitude == NPCATT_FOLLOW;
            }

        case MGOAL_RECRUIT_NPC_CLASS:
            {
                const auto npcs = overmap_buffer.get_npcs_near_player( 100 );
                for( auto & npc : npcs ) {
                    if( npc->myclass == recruit_class && npc->attitude == NPCATT_FOLLOW ) {
                        return true;
                    }
                }
                return false;
            }

        case MGOAL_FIND_NPC:
            return npc_id == _npc_id;

        case MGOAL_ASSASSINATE:
            return step >= 1;

        case MGOAL_KILL_MONSTER:
            return step >= 1;

        case MGOAL_KILL_MONSTER_TYPE:
            return g->kill_count( mtype_id( monster_type ) ) >= monster_kill_goal;

        case MGOAL_COMPUTER_TOGGLE:
            return step >= 1;

        default:
            return false;
    }
    return false;
}