std::string weather_forecast(game *g, radio_tower tower) { std::stringstream weather_report; // Local conditions city *closest_city = &g->cur_om->cities[g->cur_om->closest_city(point(tower.x, tower.y))]; // Current time weather_report << string_format( _("The current time is %s Eastern Standard Time. At %s in %s, it was %s. The temperature was %s"), g->turn.print_time().c_str(), g->turn.print_time(true).c_str(), closest_city->name.c_str(), weather_data[g->weather].name.c_str(), print_temperature(g->temperature).c_str() ); //weather_report << ", the dewpoint ???, and the relative humidity ???. "; //weather_report << "The wind was <direction> at ? mi/km an hour. "; //weather_report << "The pressure was ??? in/mm and steady/rising/falling."; // Regional conditions (simulated by chosing a random range containing the current conditions). // Adjusted for weather volatility based on how many weather changes are coming up. //weather_report << "Across <region>, skies ranged from <cloudiest> to <clearest>. "; // TODO: Add fake reports for nearby cities // TODO: weather forecast // forecasting periods are divided into 12-hour periods, day (6-18) and night (19-5) // Accumulate percentages for each period of various weather statistics, and report that // (with fuzz) as the weather chances. int weather_proportions[NUM_WEATHER_TYPES] = {0}; signed char high = 0; signed char low = 0; calendar start_time = g->turn; int period_start = g->turn.hours(); // TODO wind direction and speed for(std::map<int, weather_segment>::iterator it = g->weather_log.lower_bound( int(g->turn) ); it != g->weather_log.end(); ++it ) { weather_segment * period = &(it->second); int period_deadline = period->deadline.hours(); signed char period_temperature = period->temperature; weather_type period_weather = period->weather; bool start_day = period_start >= 6 && period_start <= 18; bool end_day = period_deadline >= 6 && period_deadline <= 18; high = std::max(high, period_temperature); low = std::min(low, period_temperature); if(start_day != end_day) // Assume a period doesn't last over 12 hrs? { weather_proportions[period_weather] += end_day ? 6 : 18 - period_start; int weather_duration = 0; int predominant_weather = 0; std::string day; if( g->turn.days() == period->deadline.days() ) { if( start_day ) { day = _("Today"); } else { day = _("Tonight"); } } else { std::string dayofweak = start_time.day_of_week(); if( !start_day ) { day = rmp_format(_("<Mon Night>%s Night"), dayofweak.c_str()); } else { day = dayofweak; } } for( int i = WEATHER_CLEAR; i < NUM_WEATHER_TYPES; i++) { if( weather_proportions[i] > weather_duration) { weather_duration = weather_proportions[i]; predominant_weather = i; } } // Print forecast weather_report << string_format( _("%s...%s. Highs of %s. Lows of %s. "), day.c_str(), weather_data[predominant_weather].name.c_str(), print_temperature(high).c_str(), print_temperature(low).c_str() ); low = period_temperature; high = period_temperature; weather_proportions[period_weather] += end_day ? 6 : 18 - period_start; } else { weather_proportions[period_weather] += period_deadline - period_start; } start_time = period->deadline; period_start = period_deadline; } return weather_report.str(); }
itype* new_natural_artifact(itypemap &itypes, artifact_natural_property prop) { // Natural artifacts are always tools. it_artifact_tool *art = new it_artifact_tool(); // Pick a form artifact_natural_shape shape = artifact_natural_shape(rng(ARTSHAPE_NULL + 1, ARTSHAPE_MAX - 1)); artifact_shape_datum *shape_data = &(artifact_shape_data[shape]); // Pick a property artifact_natural_property property = (prop > ARTPROP_NULL ? prop : artifact_natural_property(rng(ARTPROP_NULL + 1, ARTPROP_MAX - 1))); artifact_property_datum *property_data = &(artifact_property_data[property]); art->sym = ':'; art->color = c_yellow; art->m1 = "stone"; art->m2 = "null"; art->volume = rng(shape_data->volume_min, shape_data->volume_max); art->weight = rng(shape_data->weight_min, shape_data->weight_max); art->melee_dam = 0; art->melee_cut = 0; art->m_to_hit = 0; art->name = rmp_format(_("<artifact_name>%1$s %2$s"), property_data->name.c_str(), shape_data->name.c_str()); art->description = rmp_format(_("<artifact_desc>This %1$s %2$s."), shape_data->desc.c_str(), property_data->desc.c_str()); // Add line breaks to the description as necessary /* size_t pos = 76; while (art->description.length() - pos >= 76) { pos = art->description.find_last_of(' ', pos); if (pos == std::string::npos) pos = art->description.length(); else { art->description[pos] = '\n'; pos += 76; } }*/ // Three possibilities: good passive + bad passive, good active + bad active, // and bad passive + good active bool good_passive = false, bad_passive = false, good_active = false, bad_active = false; switch (rng(1, 3)) { case 1: good_passive = true; bad_passive = true; break; case 2: good_active = true; bad_active = true; break; case 3: bad_passive = true; good_active = true; break; } int value_to_reach = 0; // This is slowly incremented, allowing for better arts int value = 0; art_effect_passive aep_good = AEP_NULL, aep_bad = AEP_NULL; art_effect_active aea_good = AEA_NULL, aea_bad = AEA_NULL; do { if (good_passive) { aep_good = property_data->passive_good[ rng(0, 3) ]; if (aep_good == AEP_NULL || one_in(4)) aep_good = art_effect_passive(rng(AEP_NULL + 1, AEP_SPLIT - 1)); } if (bad_passive) { aep_bad = property_data->passive_bad[ rng(0, 3) ]; if (aep_bad == AEP_NULL || one_in(4)) aep_bad = art_effect_passive(rng(AEP_SPLIT + 1, NUM_AEAS - 1)); } if (good_active) { aea_good = property_data->active_good[ rng(0, 3) ]; if (aea_good == AEA_NULL || one_in(4)) aea_good = art_effect_active(rng(AEA_NULL + 1, AEA_SPLIT - 1)); } if (bad_active) { aea_bad = property_data->active_bad[ rng(0, 3) ]; if (aea_bad == AEA_NULL || one_in(4)) aea_bad = art_effect_active(rng(AEA_SPLIT + 1, NUM_AEAS - 1)); } value = passive_effect_cost[aep_good] + passive_effect_cost[aep_bad] + active_effect_cost[aea_good] + active_effect_cost[aea_bad]; value_to_reach++; // Yes, it is intentional that this is 1 the first check } while (value > value_to_reach); if (aep_good != AEP_NULL) art->effects_carried.push_back(aep_good); if (aep_bad != AEP_NULL) art->effects_carried.push_back(aep_bad); if (aea_good != AEA_NULL) art->effects_activated.push_back(aea_good); if (aea_bad != AEA_NULL) art->effects_activated.push_back(aea_bad); // Natural artifacts ALWAYS can recharge // (When "implanting" them in a mundane item, this ability may be lost if (!art->effects_activated.empty()) { art->max_charges = rng(1, 4); art->def_charges = art->max_charges; art->rand_charges.push_back(art->max_charges); art->charge_type = art_charge( rng(ARTC_NULL + 1, NUM_ARTCS - 1) ); } artifact_itype_ids.push_back(art->id); itypes[art->id] = art; return art; }
int vehicle::automatic_fire_turret( vehicle_part &pt ) { item &gun = pt.base; tripoint pos = global_part_pos3( pt ); npc tmp; tmp.set_fake( true ); tmp.add_effect( effect_on_roof, 1 ); tmp.name = rmp_format( _( "<veh_player>The %s" ), pt.name().c_str() ); tmp.set_skill_level( gun.gun_skill(), 8 ); tmp.set_skill_level( skill_id( "gun" ), 4 ); tmp.recoil = abs( velocity ) / 100 / 4; tmp.setpos( pos ); tmp.str_cur = 16; tmp.dex_cur = 8; tmp.per_cur = 12; // Assume vehicle turrets are defending the player. tmp.attitude = NPCATT_DEFEND; int area = aoe_size( gun.ammo_effects() ); if( area > 0 ) { area += area == 1 ? 1 : 2; // Pad a bit for less friendly fire } tripoint targ = pos; auto &target = pt.target; if( target.first == target.second ) { // Manual target not set, find one automatically const bool u_see = g->u.sees( pos ); int boo_hoo; // @todo calculate chance to hit and cap range based upon this int range = std::min( gun.gun_range(), 12 ); Creature *auto_target = tmp.auto_find_hostile_target( range, boo_hoo, area ); if( auto_target == nullptr ) { if( u_see && boo_hoo ) { add_msg( m_warning, ngettext( "%s points in your direction and emits an IFF warning beep.", "%s points in your direction and emits %d annoyed sounding beeps.", boo_hoo ), tmp.name.c_str(), boo_hoo ); } return 0; } targ = auto_target->pos(); } else if( target.first != target.second ) { // Target set manually // Make sure we didn't move between aiming and firing (it's a bug if we did) if( targ != target.first ) { target.second = target.first; return 0; } targ = target.second; // Remove the target target.second = target.first; } else { // Shouldn't happen target.first = target.second; return 0; } // notify player if player can see the shot if( g->u.sees( pos ) ) { add_msg( _( "The %1$s fires its %2$s!" ), name.c_str(), pt.name().c_str() ); } auto mode = gun.gun_current_mode(); return tmp.fire_gun( targ, mode.qty, *mode ); }
/** * Generate textual weather forecast for the specified radio tower. */ std::string weather_forecast( point const &abs_sm_pos ) { std::ostringstream weather_report; // Local conditions const auto cref = overmap_buffer.closest_city( tripoint( abs_sm_pos, 0 ) ); const std::string city_name = cref ? cref.city->name : std::string( _( "middle of nowhere" ) ); // Current time weather_report << string_format( _("The current time is %s Eastern Standard Time. At %s in %s, it was %s. The temperature was %s. "), calendar::turn.print_time().c_str(), calendar::turn.print_time(true).c_str(), city_name.c_str(), weather_data(g->weather).name.c_str(), print_temperature(g->temperature).c_str() ); //weather_report << ", the dewpoint ???, and the relative humidity ???. "; //weather_report << "The wind was <direction> at ? mi/km an hour. "; //weather_report << "The pressure was ??? in/mm and steady/rising/falling."; // Regional conditions (simulated by choosing a random range containing the current conditions). // Adjusted for weather volatility based on how many weather changes are coming up. //weather_report << "Across <region>, skies ranged from <cloudiest> to <clearest>. "; // TODO: Add fake reports for nearby cities // TODO: weather forecast // forecasting periods are divided into 12-hour periods, day (6-18) and night (19-5) // Accumulate percentages for each period of various weather statistics, and report that // (with fuzz) as the weather chances. // int weather_proportions[NUM_WEATHER_TYPES] = {0}; double high = -100.0; double low = 100.0; point const abs_ms_pos = overmapbuffer::sm_to_ms_copy( abs_sm_pos ); // TODO wind direction and speed int last_hour = calendar::turn - ( calendar::turn % HOURS(1) ); for(int d = 0; d < 6; d++) { weather_type forecast = WEATHER_NULL; for(calendar i(last_hour + 7200 * d); i < last_hour + 7200 * (d + 1); i += 600) { w_point w = g->weather_gen->get_weather( abs_ms_pos, i ); forecast = std::max(forecast, g->weather_gen->get_weather_conditions(w)); high = std::max(high, w.temperature); low = std::min(low, w.temperature); } std::string day; bool started_at_night; calendar c(last_hour + 7200 * d); if(d == 0 && c.is_night()) { day = _("Tonight"); started_at_night = true; } else { day = _("Today"); started_at_night = false; } if(d > 0 && ((started_at_night && !(d % 2)) || (!started_at_night && d % 2))) { day = rmp_format(_("<Mon Night>%s Night"), c.day_of_week().c_str()); } else { day = c.day_of_week(); } weather_report << string_format( _("%s... %s. Highs of %s. Lows of %s. "), day.c_str(), weather_data(forecast).name.c_str(), print_temperature(high).c_str(), print_temperature(low).c_str() ); } return weather_report.str(); }
std::string new_natural_artifact(artifact_natural_property prop) { // Natural artifacts are always tools. it_artifact_tool *art = new it_artifact_tool(); // Pick a form artifact_natural_shape shape = artifact_natural_shape(rng(ARTSHAPE_NULL + 1, ARTSHAPE_MAX - 1)); artifact_shape_datum *shape_data = &(artifact_shape_data[shape]); // Pick a property artifact_natural_property property = (prop > ARTPROP_NULL ? prop : artifact_natural_property(rng(ARTPROP_NULL + 1, ARTPROP_MAX - 1))); artifact_property_datum *property_data = &(artifact_property_data[property]); art->sym = ':'; art->color = c_yellow; art->materials.push_back("stone"); art->volume = rng(shape_data->volume_min, shape_data->volume_max); art->weight = rng(shape_data->weight_min, shape_data->weight_max); art->melee_dam = 0; art->melee_cut = 0; art->m_to_hit = 0; art->create_name(property_data->name, shape_data->name); art->description = rmp_format(_("<artifact_desc>This %1$s %2$s."), shape_data->desc.c_str(), property_data->desc.c_str()); // Three possibilities: good passive + bad passive, good active + bad active, // and bad passive + good active bool good_passive = false, bad_passive = false, good_active = false, bad_active = false; switch (rng(1, 3)) { case 1: good_passive = true; bad_passive = true; break; case 2: good_active = true; bad_active = true; break; case 3: bad_passive = true; good_active = true; break; } int value_to_reach = 0; // This is slowly incremented, allowing for better arts int value = 0; art_effect_passive aep_good = AEP_NULL, aep_bad = AEP_NULL; art_effect_active aea_good = AEA_NULL, aea_bad = AEA_NULL; do { if (good_passive) { aep_good = property_data->passive_good[ rng(0, 3) ]; if (aep_good == AEP_NULL || one_in(4)) { aep_good = art_effect_passive(rng(AEP_NULL + 1, AEP_SPLIT - 1)); } } if (bad_passive) { aep_bad = property_data->passive_bad[ rng(0, 3) ]; if (aep_bad == AEP_NULL || one_in(4)) { aep_bad = art_effect_passive(rng(AEP_SPLIT + 1, NUM_AEAS - 1)); } } if (good_active) { aea_good = property_data->active_good[ rng(0, 3) ]; if (aea_good == AEA_NULL || one_in(4)) { aea_good = art_effect_active(rng(AEA_NULL + 1, AEA_SPLIT - 1)); } } if (bad_active) { aea_bad = property_data->active_bad[ rng(0, 3) ]; if (aea_bad == AEA_NULL || one_in(4)) { aea_bad = art_effect_active(rng(AEA_SPLIT + 1, NUM_AEAS - 1)); } } value = passive_effect_cost[aep_good] + passive_effect_cost[aep_bad] + active_effect_cost[aea_good] + active_effect_cost[aea_bad]; value_to_reach++; // Yes, it is intentional that this is 1 the first check } while (value > value_to_reach); if (aep_good != AEP_NULL) { art->effects_carried.push_back(aep_good); } if (aep_bad != AEP_NULL) { art->effects_carried.push_back(aep_bad); } if (aea_good != AEA_NULL) { art->effects_activated.push_back(aea_good); } if (aea_bad != AEA_NULL) { art->effects_activated.push_back(aea_bad); } // Natural artifacts ALWAYS can recharge // (When "implanting" them in a mundane item, this ability may be lost if (!art->effects_activated.empty()) { art->max_charges = rng(1, 4); art->def_charges = art->max_charges; art->rand_charges.push_back(art->max_charges); art->charge_type = art_charge( rng(ARTC_NULL + 1, NUM_ARTCS - 1) ); } item_controller->add_item_type( art ); return art->id; }
void it_artifact_tool::create_name(const std::string &property_name, const std::string &shape_name) { name = rmp_format(_("<artifact_name>%1$s %2$s"), property_name.c_str(), shape_name.c_str()); name_plural = name; }